Skip to content

Commit 87ca09f

Browse files
authored
Merge pull request #409 from ilyam8/feat_login1_methods_to_get_properties
login1: add methods to get session/user properties
2 parents 1d04472 + d3e99ab commit 87ca09f

File tree

2 files changed

+172
-14
lines changed

2 files changed

+172
-14
lines changed

login1/dbus.go

Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,11 @@ import (
2626
)
2727

2828
const (
29-
dbusDest = "org.freedesktop.login1"
30-
dbusInterface = "org.freedesktop.login1.Manager"
31-
dbusPath = "/org/freedesktop/login1"
29+
dbusDest = "org.freedesktop.login1"
30+
dbusManagerInterface = "org.freedesktop.login1.Manager"
31+
dbusSessionInterface = "org.freedesktop.login1.Session"
32+
dbusUserInterface = "org.freedesktop.login1.User"
33+
dbusPath = "/org/freedesktop/login1"
3234
)
3335

3436
// Conn is a connection to systemds dbus endpoint.
@@ -166,7 +168,7 @@ func userFromInterfaces(user []interface{}) (*User, error) {
166168
// GetActiveSession may be used to get the session object path for the current active session
167169
func (c *Conn) GetActiveSession() (dbus.ObjectPath, error) {
168170
var seat0Path dbus.ObjectPath
169-
if err := c.object.Call(dbusInterface+".GetSeat", 0, "seat0").Store(&seat0Path); err != nil {
171+
if err := c.object.Call(dbusManagerInterface+".GetSeat", 0, "seat0").Store(&seat0Path); err != nil {
170172
return "", err
171173
}
172174

@@ -242,7 +244,7 @@ func (c *Conn) GetSessionDisplay(sessionPath dbus.ObjectPath) (string, error) {
242244
// GetSession may be used to get the session object path for the session with the specified ID.
243245
func (c *Conn) GetSession(id string) (dbus.ObjectPath, error) {
244246
var out interface{}
245-
if err := c.object.Call(dbusInterface+".GetSession", 0, id).Store(&out); err != nil {
247+
if err := c.object.Call(dbusManagerInterface+".GetSession", 0, id).Store(&out); err != nil {
246248
return "", err
247249
}
248250

@@ -262,7 +264,7 @@ func (c *Conn) ListSessions() ([]Session, error) {
262264
// ListSessionsContext returns an array with all current sessions.
263265
func (c *Conn) ListSessionsContext(ctx context.Context) ([]Session, error) {
264266
out := [][]interface{}{}
265-
if err := c.object.CallWithContext(ctx, dbusInterface+".ListSessions", 0).Store(&out); err != nil {
267+
if err := c.object.CallWithContext(ctx, dbusManagerInterface+".ListSessions", 0).Store(&out); err != nil {
266268
return nil, err
267269
}
268270

@@ -285,7 +287,7 @@ func (c *Conn) ListUsers() ([]User, error) {
285287
// ListUsersContext returns an array with all currently logged-in users.
286288
func (c *Conn) ListUsersContext(ctx context.Context) ([]User, error) {
287289
out := [][]interface{}{}
288-
if err := c.object.CallWithContext(ctx, dbusInterface+".ListUsers", 0).Store(&out); err != nil {
290+
if err := c.object.CallWithContext(ctx, dbusManagerInterface+".ListUsers", 0).Store(&out); err != nil {
289291
return nil, err
290292
}
291293

@@ -300,36 +302,56 @@ func (c *Conn) ListUsersContext(ctx context.Context) ([]User, error) {
300302
return ret, nil
301303
}
302304

305+
// GetSessionPropertiesContext takes a session path and returns all of its dbus object properties.
306+
func (c *Conn) GetSessionPropertiesContext(ctx context.Context, sessionPath dbus.ObjectPath) (map[string]dbus.Variant, error) {
307+
return c.getProperties(ctx, sessionPath, dbusSessionInterface)
308+
}
309+
310+
// GetSessionPropertyContext takes a session path and a property name and returns the property value.
311+
func (c *Conn) GetSessionPropertyContext(ctx context.Context, sessionPath dbus.ObjectPath, property string) (*dbus.Variant, error) {
312+
return c.getProperty(ctx, sessionPath, dbusSessionInterface, property)
313+
}
314+
315+
// GetUserPropertiesContext takes a user path and returns all of its dbus object properties.
316+
func (c *Conn) GetUserPropertiesContext(ctx context.Context, userPath dbus.ObjectPath) (map[string]dbus.Variant, error) {
317+
return c.getProperties(ctx, userPath, dbusUserInterface)
318+
}
319+
320+
// GetUserPropertyContext takes a user path and a property name and returns the property value.
321+
func (c *Conn) GetUserPropertyContext(ctx context.Context, userPath dbus.ObjectPath, property string) (*dbus.Variant, error) {
322+
return c.getProperty(ctx, userPath, dbusUserInterface, property)
323+
}
324+
303325
// LockSession asks the session with the specified ID to activate the screen lock.
304326
func (c *Conn) LockSession(id string) {
305-
c.object.Call(dbusInterface+".LockSession", 0, id)
327+
c.object.Call(dbusManagerInterface+".LockSession", 0, id)
306328
}
307329

308330
// LockSessions asks all sessions to activate the screen locks. This may be used to lock any access to the machine in one action.
309331
func (c *Conn) LockSessions() {
310-
c.object.Call(dbusInterface+".LockSessions", 0)
332+
c.object.Call(dbusManagerInterface+".LockSessions", 0)
311333
}
312334

313335
// TerminateSession forcibly terminate one specific session.
314336
func (c *Conn) TerminateSession(id string) {
315-
c.object.Call(dbusInterface+".TerminateSession", 0, id)
337+
c.object.Call(dbusManagerInterface+".TerminateSession", 0, id)
316338
}
317339

318340
// TerminateUser forcibly terminates all processes of a user.
319341
func (c *Conn) TerminateUser(uid uint32) {
320-
c.object.Call(dbusInterface+".TerminateUser", 0, uid)
342+
c.object.Call(dbusManagerInterface+".TerminateUser", 0, uid)
321343
}
322344

323345
// Reboot asks logind for a reboot optionally asking for auth.
324346
func (c *Conn) Reboot(askForAuth bool) {
325-
c.object.Call(dbusInterface+".Reboot", 0, askForAuth)
347+
c.object.Call(dbusManagerInterface+".Reboot", 0, askForAuth)
326348
}
327349

328350
// Inhibit takes inhibition lock in logind.
329351
func (c *Conn) Inhibit(what, who, why, mode string) (*os.File, error) {
330352
var fd dbus.UnixFD
331353

332-
err := c.object.Call(dbusInterface+".Inhibit", 0, what, who, why, mode).Store(&fd)
354+
err := c.object.Call(dbusManagerInterface+".Inhibit", 0, what, who, why, mode).Store(&fd)
333355
if err != nil {
334356
return nil, err
335357
}
@@ -350,5 +372,37 @@ func (c *Conn) Subscribe(members ...string) chan *dbus.Signal {
350372

351373
// PowerOff asks logind for a power off optionally asking for auth.
352374
func (c *Conn) PowerOff(askForAuth bool) {
353-
c.object.Call(dbusInterface+".PowerOff", 0, askForAuth)
375+
c.object.Call(dbusManagerInterface+".PowerOff", 0, askForAuth)
376+
}
377+
378+
func (c *Conn) getProperties(ctx context.Context, path dbus.ObjectPath, dbusInterface string) (map[string]dbus.Variant, error) {
379+
if !path.IsValid() {
380+
return nil, fmt.Errorf("invalid object path (%s)", path)
381+
}
382+
383+
obj := c.conn.Object(dbusDest, path)
384+
385+
var props map[string]dbus.Variant
386+
err := obj.CallWithContext(ctx, "org.freedesktop.DBus.Properties.GetAll", 0, dbusInterface).Store(&props)
387+
if err != nil {
388+
return nil, err
389+
}
390+
391+
return props, nil
392+
}
393+
394+
func (c *Conn) getProperty(ctx context.Context, path dbus.ObjectPath, dbusInterface, property string) (*dbus.Variant, error) {
395+
if !path.IsValid() {
396+
return nil, fmt.Errorf("invalid object path (%s)", path)
397+
}
398+
399+
obj := c.conn.Object(dbusDest, path)
400+
401+
var prop dbus.Variant
402+
err := obj.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, dbusInterface, property).Store(&prop)
403+
if err != nil {
404+
return nil, err
405+
}
406+
407+
return &prop, nil
354408
}

login1/dbus_test.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
package login1
1616

1717
import (
18+
"context"
1819
"fmt"
1920
"os/user"
2021
"regexp"
2122
"testing"
23+
"time"
2224
)
2325

2426
// TestNew ensures that New() works without errors.
@@ -87,3 +89,105 @@ func TestListUsers(t *testing.T) {
8789
}
8890
}
8991
}
92+
93+
func TestConn_GetSessionPropertiesContext(t *testing.T) {
94+
c, err := New()
95+
if err != nil {
96+
t.Fatal(err)
97+
}
98+
99+
sessions, err := c.ListSessions()
100+
if err != nil {
101+
t.Fatal(err)
102+
}
103+
104+
for _, s := range sessions {
105+
func() {
106+
ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
107+
defer cancel()
108+
109+
props, err := c.GetSessionPropertiesContext(ctx, s.Path)
110+
if err != nil {
111+
t.Fatal(err)
112+
}
113+
if len(props) == 0 {
114+
t.Fatal("no properties returned")
115+
}
116+
}()
117+
}
118+
}
119+
120+
func TestConn_GetSessionPropertyContext(t *testing.T) {
121+
c, err := New()
122+
if err != nil {
123+
t.Fatal(err)
124+
}
125+
126+
sessions, err := c.ListSessions()
127+
if err != nil {
128+
t.Fatal(err)
129+
}
130+
131+
for _, s := range sessions {
132+
func() {
133+
ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
134+
defer cancel()
135+
136+
_, err := c.GetSessionPropertyContext(ctx, s.Path, "Remote")
137+
if err != nil {
138+
t.Fatal(err)
139+
}
140+
}()
141+
}
142+
}
143+
144+
func TestConn_GetUserPropertiesContext(t *testing.T) {
145+
c, err := New()
146+
if err != nil {
147+
t.Fatal(err)
148+
}
149+
150+
users, err := c.ListUsers()
151+
if err != nil {
152+
t.Fatal(err)
153+
}
154+
155+
for _, u := range users {
156+
func() {
157+
ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
158+
defer cancel()
159+
160+
props, err := c.GetUserPropertiesContext(ctx, u.Path)
161+
if err != nil {
162+
t.Fatal(err)
163+
}
164+
if len(props) == 0 {
165+
t.Fatal("no properties returned")
166+
}
167+
}()
168+
}
169+
}
170+
171+
func TestConn_GetUserPropertyContext(t *testing.T) {
172+
c, err := New()
173+
if err != nil {
174+
t.Fatal(err)
175+
}
176+
177+
users, err := c.ListUsers()
178+
if err != nil {
179+
t.Fatal(err)
180+
}
181+
182+
for _, u := range users {
183+
func() {
184+
ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)
185+
defer cancel()
186+
187+
_, err := c.GetUserPropertyContext(ctx, u.Path, "State")
188+
if err != nil {
189+
t.Fatal(err)
190+
}
191+
}()
192+
}
193+
}

0 commit comments

Comments
 (0)