diff options
| author | 2023-03-27 16:02:26 +0200 | |
|---|---|---|
| committer | 2023-03-27 16:02:26 +0200 | |
| commit | 7d098633937a219aa96f1574fa9cc15aec1dd9fe (patch) | |
| tree | 0e52f09ea8f461e6fa4264aa7eac7337f28c9af2 | |
| parent | [chore]: Bump github.com/tdewolff/minify/v2 from 2.12.4 to 2.12.5 (#1649) (diff) | |
| download | gotosocial-7d098633937a219aa96f1574fa9cc15aec1dd9fe.tar.xz | |
[feature] Add list command to admin account (#1648)
* [feature] Add list command to admin account
Relates to: #388
* Print booleans as yes/no too
| -rw-r--r-- | cmd/gotosocial/action/admin/account/account.go | 47 | ||||
| -rw-r--r-- | cmd/gotosocial/admin.go | 12 | ||||
| -rw-r--r-- | internal/db/bundb/user.go | 14 | ||||
| -rw-r--r-- | internal/db/bundb/user_test.go | 6 | ||||
| -rw-r--r-- | internal/db/user.go | 2 | 
5 files changed, 81 insertions, 0 deletions
diff --git a/cmd/gotosocial/action/admin/account/account.go b/cmd/gotosocial/action/admin/account/account.go index 4871d89e8..4f45fd1b2 100644 --- a/cmd/gotosocial/action/admin/account/account.go +++ b/cmd/gotosocial/action/admin/account/account.go @@ -21,6 +21,8 @@ import (  	"context"  	"errors"  	"fmt" +	"os" +	"text/tabwriter"  	"time"  	"github.com/superseriousbusiness/gotosocial/cmd/gotosocial/action" @@ -93,6 +95,51 @@ var Create action.GTSAction = func(ctx context.Context) error {  	return dbConn.Stop(ctx)  } +// List returns all existing local accounts. +var List action.GTSAction = func(ctx context.Context) error { +	var state state.State +	state.Caches.Init() +	state.Workers.Start() + +	dbConn, err := bundb.NewBunDBService(ctx, &state) +	if err != nil { +		return fmt.Errorf("error creating dbservice: %s", err) +	} + +	// Set the state DB connection +	state.DB = dbConn + +	users, err := dbConn.GetAllUsers(ctx) +	if err != nil { +		return err +	} + +	fmtBool := func(b *bool) string { +		if b == nil { +			return "unknown" +		} +		if *b { +			return "yes" +		} +		return "no" +	} + +	fmtDate := func(t time.Time) string { +		if t.Equal(time.Time{}) { +			return "no" +		} +		return "yes" +	} + +	w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', 0) +	fmt.Fprintln(w, "user\taccount\tapproved\tadmin\tmoderator\tsuspended\tconfirmed") +	for _, u := range users { +		fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\t%s\t%s\n", u.Account.Username, u.AccountID, fmtBool(u.Approved), fmtBool(u.Admin), fmtBool(u.Moderator), fmtDate(u.Account.SuspendedAt), fmtDate(u.ConfirmedAt)) +	} +	w.Flush() +	return nil +} +  // Confirm sets a user to Approved, sets Email to the current UnconfirmedEmail value, and sets ConfirmedAt to now.  var Confirm action.GTSAction = func(ctx context.Context) error {  	var state state.State diff --git a/cmd/gotosocial/admin.go b/cmd/gotosocial/admin.go index 185880e3d..810d57e54 100644 --- a/cmd/gotosocial/admin.go +++ b/cmd/gotosocial/admin.go @@ -54,6 +54,18 @@ func adminCommands() *cobra.Command {  	config.AddAdminAccountCreate(adminAccountCreateCmd)  	adminAccountCmd.AddCommand(adminAccountCreateCmd) +	adminAccountListCmd := &cobra.Command{ +		Use:   "list", +		Short: "list all existing local accounts", +		PreRunE: func(cmd *cobra.Command, args []string) error { +			return preRun(preRunArgs{cmd: cmd}) +		}, +		RunE: func(cmd *cobra.Command, args []string) error { +			return run(cmd.Context(), account.List) +		}, +	} +	adminAccountCmd.AddCommand(adminAccountListCmd) +  	adminAccountConfirmCmd := &cobra.Command{  		Use:   "confirm",  		Short: "confirm an existing local account manually, thereby skipping email confirmation", diff --git a/internal/db/bundb/user.go b/internal/db/bundb/user.go index 68fdb0652..b5dae1573 100644 --- a/internal/db/bundb/user.go +++ b/internal/db/bundb/user.go @@ -122,6 +122,20 @@ func (u *userDB) GetUserByConfirmationToken(ctx context.Context, confirmationTok  	}, confirmationToken)  } +func (u *userDB) GetAllUsers(ctx context.Context) ([]*gtsmodel.User, db.Error) { +	var users []*gtsmodel.User +	q := u.conn. +		NewSelect(). +		Model(&users). +		Relation("Account") + +	if err := q.Scan(ctx); err != nil { +		return nil, u.conn.ProcessError(err) +	} + +	return users, nil +} +  func (u *userDB) PutUser(ctx context.Context, user *gtsmodel.User) db.Error {  	return u.state.Caches.GTS.User().Store(user, func() error {  		_, err := u.conn. diff --git a/internal/db/bundb/user_test.go b/internal/db/bundb/user_test.go index f2ce434c1..870a1af91 100644 --- a/internal/db/bundb/user_test.go +++ b/internal/db/bundb/user_test.go @@ -29,6 +29,12 @@ type UserTestSuite struct {  	BunDBStandardTestSuite  } +func (suite *UserTestSuite) TestGetAllUsers() { +	users, err := suite.db.GetAllUsers(context.Background()) +	suite.NoError(err) +	suite.Len(users, len(suite.testUsers)) +} +  func (suite *UserTestSuite) TestGetUser() {  	user, err := suite.db.GetUserByID(context.Background(), suite.testUsers["local_account_1"].ID)  	suite.NoError(err) diff --git a/internal/db/user.go b/internal/db/user.go index e93ac4529..15165d0be 100644 --- a/internal/db/user.go +++ b/internal/db/user.go @@ -25,6 +25,8 @@ import (  // User contains functions related to user getting/setting/creation.  type User interface { +	// GetAllUsers returns all local user accounts, or an error if something goes wrong. +	GetAllUsers(ctx context.Context) ([]*gtsmodel.User, Error)  	// GetUserByID returns one user with the given ID, or an error if something goes wrong.  	GetUserByID(ctx context.Context, id string) (*gtsmodel.User, Error)  	// GetUserByAccountID returns one user by its account ID, or an error if something goes wrong.  | 
