CLI: Add command flag to show deleted user accounts #4570

Signed-off-by: Michael Mayer <michael@photoprism.app>
This commit is contained in:
Michael Mayer
2024-10-11 11:37:11 +02:00
parent 3d220227bb
commit 51bc0f1f5a
7 changed files with 43 additions and 18 deletions

View File

@@ -16,7 +16,7 @@ var AuthListCommand = cli.Command{
Name: "ls",
Usage: "Lists currently authenticated users and clients",
ArgsUsage: "[search]",
Flags: append(report.CliFlags, countFlag, tokensFlag),
Flags: append(report.CliFlags, CountFlag, tokensFlag),
Action: authListAction,
}

View File

@@ -16,7 +16,7 @@ var ClientsListCommand = cli.Command{
Name: "ls",
Usage: "Lists registered client applications",
ArgsUsage: "[search]",
Flags: append(report.CliFlags, countFlag),
Flags: append(report.CliFlags, CountFlag),
Action: clientsListAction,
}

View File

@@ -71,8 +71,8 @@ var PhotoPrism = []cli.Command{
ConnectCommand,
}
// countFlag represents a CLI flag to limit the number of report rows.
var countFlag = cli.UintFlag{
// CountFlag represents a CLI flag to limit the number of report rows.
var CountFlag = cli.UintFlag{
Name: "n",
Usage: "`LIMIT` number of results",
Value: 100,

View File

@@ -79,3 +79,15 @@ var UserFlags = []cli.Flag{
Usage: UserWebDAVUsage,
},
}
// UserTokensFlag is a CLI flag for including security tokens in reports.
var UserTokensFlag = cli.BoolFlag{
Name: "tokens",
Usage: "show user preview and download tokens",
}
// UsersDeletedFlag is a CLI flag for finding deleted user accounts.
var UsersDeletedFlag = cli.BoolFlag{
Name: "deleted, d",
Usage: "show deleted user accounts",
}

View File

@@ -15,7 +15,7 @@ import (
var UsersListCommand = cli.Command{
Name: "ls",
Usage: "Lists registered user accounts",
Flags: append(report.CliFlags, countFlag),
Flags: append(report.CliFlags, CountFlag, UsersDeletedFlag),
Action: usersListAction,
}
@@ -26,8 +26,12 @@ func usersListAction(ctx *cli.Context) error {
cols := []string{"UID", "Username", "Role", "Authentication", "Super Admin", "Web Login", "Last Login", "WebDAV"}
if ctx.Bool("deleted") {
cols = append(cols, "Deleted At")
}
// Fetch users from database.
users, err := query.Users(ctx.Int("n"), 0, "", ctx.Args().First())
users, err := query.Users(ctx.Int("n"), 0, "", ctx.Args().First(), ctx.Bool("deleted"))
if err != nil {
return err
@@ -42,9 +46,6 @@ func usersListAction(ctx *cli.Context) error {
rows = make([][]string, len(users))
// Show log message.
log.Infof("found %s", english.Plural(len(users), "user", "users"))
// Display report.
for i, user := range users {
rows[i] = []string{
@@ -57,6 +58,10 @@ func usersListAction(ctx *cli.Context) error {
report.DateTime(user.LoginAt),
report.Bool(user.CanUseWebDAV(), report.Enabled, report.Disabled),
}
if ctx.Bool("deleted") {
rows[i] = append(rows[i], report.DateTime(user.DeletedAt))
}
}
result, err := report.RenderFormat(rows, cols, report.CliFormat(ctx))

View File

@@ -42,13 +42,14 @@ func CountUsers(registered, active bool, roles, excludeRoles []string) (count in
return count
}
// Users finds users and returns them.
func Users(limit, offset int, sortOrder, search string) (result entity.Users, err error) {
// Users finds user accounts based on the specified parameters.
func Users(limit, offset int, sortOrder, search string, deleted bool) (result entity.Users, err error) {
result = entity.Users{}
stmt := Db()
stmt := UnscopedDb()
search = strings.TrimSpace(search)
// Filter user accounts to be returned.
if search == "all" {
// Don't filter.
} else if id := txt.Int(search); id != 0 {
@@ -61,10 +62,17 @@ func Users(limit, offset int, sortOrder, search string) (result entity.Users, er
stmt = stmt.Where("id > 0")
}
// Hide deleted user accounts?
if !deleted {
stmt = stmt.Where("deleted_at IS NULL")
}
// Set result sort order.
if sortOrder == "" {
sortOrder = "id"
}
// Limit number of results.
if limit > 0 {
stmt = stmt.Limit(limit)

View File

@@ -45,28 +45,28 @@ func TestCountUsers(t *testing.T) {
func TestUsers(t *testing.T) {
t.Run("Default", func(t *testing.T) {
if results, err := Users(0, 0, "", ""); err != nil {
if results, err := Users(0, 0, "", "", false); err != nil {
t.Fatal(err)
} else {
assert.LessOrEqual(t, 2, len(results))
}
})
t.Run("Limit", func(t *testing.T) {
if results, err := Users(1, 0, "", ""); err != nil {
if results, err := Users(1, 0, "", "", false); err != nil {
t.Fatal(err)
} else {
assert.LessOrEqual(t, 1, len(results))
}
})
t.Run("Offset", func(t *testing.T) {
if results, err := Users(0, 1, "", ""); err != nil {
if results, err := Users(0, 1, "", "", false); err != nil {
t.Fatal(err)
} else {
assert.LessOrEqual(t, 2, len(results))
}
})
t.Run("SearchAlice", func(t *testing.T) {
if results, err := Users(100, 0, "", "alice"); err != nil {
if results, err := Users(100, 0, "", "alice", false); err != nil {
t.Fatal(err)
} else {
assert.LessOrEqual(t, 1, len(results))
@@ -78,14 +78,14 @@ func TestUsers(t *testing.T) {
}
})
t.Run("SortByID", func(t *testing.T) {
if results, err := Users(100, 0, "id", ""); err != nil {
if results, err := Users(100, 0, "id", "", false); err != nil {
t.Fatal(err)
} else {
assert.LessOrEqual(t, 2, len(results))
}
})
t.Run("SearchAliceSortByID", func(t *testing.T) {
if results, err := Users(100, 0, "id", "alice"); err != nil {
if results, err := Users(100, 0, "id", "alice", false); err != nil {
t.Fatal(err)
} else {
assert.LessOrEqual(t, 1, len(results))