diff --git a/server/internal/app/users.go b/server/internal/app/users.go index 6004fd67..e0ce4dfa 100644 --- a/server/internal/app/users.go +++ b/server/internal/app/users.go @@ -2,11 +2,15 @@ package app import ( "context" + "errors" + "github.com/jackc/pgx/v5" "github.com/shroff/phylum/server/internal/cryptutil" "github.com/shroff/phylum/server/internal/sql" ) +var ErrUserNotFound = errors.New("user not found") + type User interface { ID() int32 Username() string @@ -48,9 +52,27 @@ func (a App) ListUsers(ctx context.Context) ([]User, error) { return users, nil } -func (a App) FindUser(ctx context.Context, username string) (User, error) { +func (a App) UserByUsername(ctx context.Context, username string) (User, error) { result, err := a.Db.Queries().UserByUsername(ctx, username) if err != nil { + if errors.Is(err, pgx.ErrNoRows) { + err = ErrUserNotFound + } + return nil, err + } + return user{ + id: result.ID, + username: result.Username, + displayName: result.DisplayName, + }, nil +} + +func (a App) UserByID(ctx context.Context, userID int32) (User, error) { + result, err := a.Db.Queries().UserByID(ctx, userID) + if err != nil { + if errors.Is(err, pgx.ErrNoRows) { + err = ErrUserNotFound + } return nil, err } return user{ diff --git a/server/internal/command/appcmd/admincmd/resource.go b/server/internal/command/appcmd/admincmd/resource.go index 6a89c010..d358e3b0 100644 --- a/server/internal/command/appcmd/admincmd/resource.go +++ b/server/internal/command/appcmd/admincmd/resource.go @@ -12,28 +12,32 @@ import ( "github.com/spf13/cobra" ) +var userID int32 + func setupResourceCommand() *cobra.Command { cmd := &cobra.Command{ Use: "resource", Short: "Resource Management", } + cmd.AddCommand([]*cobra.Command{ setupResourceMkdirCommand(), setupResourceRmCommand(), - setupSiloListCommand(), - setupSiloDeleteCommand(), }...) return cmd } func setupResourceMkdirCommand() *cobra.Command { - return &cobra.Command{ + cmd := cobra.Command{ Use: "mkdir path", Short: "Create Directory", Args: cobra.ExactArgs(1), + PreRun: func(cmd *cobra.Command, args []string) { + readUserIDFromFlagsreadUsername(cmd) + }, Run: func(cmd *cobra.Command, args []string) { path := args[0] - fs, err := app.Default.OpenFileSystem(context.Background(), 0) + fs, err := app.Default.OpenFileSystem(context.Background(), userID) if err != nil { logrus.Fatal(err) } @@ -59,6 +63,9 @@ func setupResourceMkdirCommand() *cobra.Command { } }, } + setupUsernameFlags(&cmd) + + return &cmd } func setupResourceRmCommand() *cobra.Command { @@ -66,9 +73,12 @@ func setupResourceRmCommand() *cobra.Command { Use: "rm path", Short: "Delete Resource", Args: cobra.ExactArgs(1), + PreRun: func(cmd *cobra.Command, args []string) { + readUserIDFromFlagsreadUsername(cmd) + }, Run: func(cmd *cobra.Command, args []string) { path := args[0] - fs, err := app.Default.OpenFileSystem(context.Background(), 0) + fs, err := app.Default.OpenFileSystem(context.Background(), userID) if err != nil { logrus.Fatal(err) } @@ -92,26 +102,38 @@ func setupResourceRmCommand() *cobra.Command { } flags := cmd.Flags() flags.BoolP("recursive", "r", false, "Recursively delete resource (required for collections)") + setupUsernameFlags(&cmd) return &cmd } -func setupSiloListCommand() *cobra.Command { - return &cobra.Command{ - Use: "list", - Short: "List Silos", - Args: cobra.ExactArgs(0), - Run: func(cmd *cobra.Command, args []string) { - }, +func readUserIDFromFlagsreadUsername(cmd *cobra.Command) { + if value, err := cmd.Flags().GetInt32("user"); err != nil { + logrus.Fatal(err) + } else if value != 0 { + if user, err := app.Default.UserByID(context.Background(), value); err != nil { + logrus.Fatal(err) + } else { + userID = user.ID() + return + } } + + if value, err := cmd.Flags().GetString("username"); err != nil { + logrus.Fatal(err) + } else { + if user, err := app.Default.UserByUsername(context.Background(), value); err != nil { + logrus.Fatal(err) + } else { + userID = user.ID() + } + } + } -func setupSiloDeleteCommand() *cobra.Command { - return &cobra.Command{ - Use: "delete id", - Short: "Delete Silo", - Args: cobra.ExactArgs(1), - Run: func(cmd *cobra.Command, args []string) { - }, - } +func setupUsernameFlags(cmd *cobra.Command) { + flags := cmd.Flags() + flags.Int32P("user", "u", 0, "Specify User ID for resource operations (cannot be used with -U)") + flags.StringP("username", "U", "root", "Specify Username for resource operations (cannot be used with -u)") + } diff --git a/server/internal/sql/users.sql.go b/server/internal/sql/users.sql.go index d9a6e5a5..ac7d95be 100644 --- a/server/internal/sql/users.sql.go +++ b/server/internal/sql/users.sql.go @@ -58,6 +58,23 @@ func (q *Queries) ListUsers(ctx context.Context) ([]User, error) { return items, nil } +const userByID = `-- name: UserByID :one +SELECT id, username, display_name, password_hash, deleted from users WHERE id = $1 +` + +func (q *Queries) UserByID(ctx context.Context, id int32) (User, error) { + row := q.db.QueryRow(ctx, userByID, id) + var i User + err := row.Scan( + &i.ID, + &i.Username, + &i.DisplayName, + &i.PasswordHash, + &i.Deleted, + ) + return i, err +} + const userByUsername = `-- name: UserByUsername :one SELECT id, username, display_name, password_hash, deleted from users WHERE username = $1 ` diff --git a/server/sql/queries/users.sql b/server/sql/queries/users.sql index 6bf1e36b..1d26e7dc 100644 --- a/server/sql/queries/users.sql +++ b/server/sql/queries/users.sql @@ -8,5 +8,8 @@ INSERT INTO users( -- name: UserByUsername :one SELECT * from users WHERE username = $1; +-- name: UserByID :one +SELECT * from users WHERE id = $1; + -- name: ListUsers :many SELECT * from users WHERE deleted IS NULL; \ No newline at end of file