From 959baa964f45b40fad239e21a246e3b963f9ca57 Mon Sep 17 00:00:00 2001 From: delthas Date: Tue, 17 Jan 2023 14:25:37 +0100 Subject: [PATCH] service: add user status This lists all the users of the instances, along with the number of networks they have. Limited to 50 users to avoid flooding with thousands of messages on large instances. --- doc/soju.1.scd | 3 +++ service.go | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/doc/soju.1.scd b/doc/soju.1.scd index 8dc65ae..94c0e1e 100644 --- a/doc/soju.1.scd +++ b/doc/soju.1.scd @@ -407,6 +407,9 @@ character. *-network* Select a network. By default, the current network is selected, if any. +*user status* + Show a list of users on this server. Only admins can query this information. + *user create* -username -password [options...] Create a new soju user. Only admin users can create new accounts. The _-username_ and _-password_ flags are mandatory. diff --git a/service.go b/service.go index 5960bd3..c12c156 100644 --- a/service.go +++ b/service.go @@ -272,6 +272,11 @@ func init() { }, "user": { children: serviceCommandSet{ + "status": { + desc: "show a list of users and their current status", + handle: handleUserStatus, + admin: true, + }, "create": { usage: "-username -password [-realname ] [-admin]", desc: "create a new soju user", @@ -874,6 +879,40 @@ func handleServiceSASLReset(ctx *serviceContext, params []string) error { return nil } +func handleUserStatus(ctx *serviceContext, params []string) error { + // Limit to a small amount of users to avoid sending + // thousands of messages on large instances. + users := make([]database.User, 0, 50) + + ctx.user.srv.lock.Lock() + n := len(ctx.user.srv.users) + for _, user := range ctx.user.srv.users { + if len(users) == cap(users) { + break + } + users = append(users, user.User) + } + ctx.user.srv.lock.Unlock() + + for _, user := range users { + line := user.Username + if user.Admin { + line += " (admin)" + } + networks, err := ctx.user.srv.db.ListNetworks(ctx, user.ID) + if err != nil { + return fmt.Errorf("could not get networks of user %q: %v", user.Username, err) + } + line += fmt.Sprintf(": %d networks", len(networks)) + ctx.print(line) + } + if n > len(users) { + ctx.print(fmt.Sprintf("(%d more users omitted)", n-len(users))) + } + + return nil +} + func handleUserCreate(ctx *serviceContext, params []string) error { fs := newFlagSet() username := fs.String("username", "", "")