diff --git a/server/internal/api/routes/auth.go b/server/internal/api/routes/auth.go index 1a1f13d0..97bee4b6 100644 --- a/server/internal/api/routes/auth.go +++ b/server/internal/api/routes/auth.go @@ -20,16 +20,16 @@ func SetupAuthRoutes(r *gin.RouterGroup, a *core.App) { func createLoginRouteHandler(a *core.App) func(c *gin.Context) { return func(c *gin.Context) { - username, ok := c.GetQuery("username") + email, ok := c.GetQuery("email") if !ok { - panic(errors.New(http.StatusBadRequest, "missing_username", "Username Not Specified")) + panic(errors.New(http.StatusBadRequest, "missing_email", "Email Not Specified")) } password, ok := c.GetQuery("password") if !ok { panic(errors.New(http.StatusBadRequest, "missing_password", "Password Not Specified")) } - if user, err := a.VerifyUserPassword(c.Request.Context(), username, password); err != nil { + if user, err := a.VerifyUserPassword(c.Request.Context(), email, password); err != nil { if errors.Is(err, core.ErrCredentialsInvalid) { panic(errors.New(http.StatusUnauthorized, "credentials_invalid", "Invalid Credentials")) } diff --git a/server/internal/api/routes/users.go b/server/internal/api/routes/users.go index db4ac38a..966d76f3 100644 --- a/server/internal/api/routes/users.go +++ b/server/internal/api/routes/users.go @@ -8,8 +8,7 @@ import ( ) type userResponse struct { - UserID int32 `json:"id"` - Username string `json:"username"` + Email string `json:"email"` DisplayName string `json:"name"` Home uuid.UUID `json:"home"` } @@ -25,8 +24,7 @@ func handleUserMeRoute(c *gin.Context) { func responseFromUser(user core.User) userResponse { return userResponse{ - UserID: user.ID(), - Username: user.Username(), + Email: user.Email(), DisplayName: user.DisplayName(), Home: user.Home(), } diff --git a/server/internal/command/appcmd/resource.go b/server/internal/command/appcmd/resource.go index 60a706c1..c81f9945 100644 --- a/server/internal/command/appcmd/resource.go +++ b/server/internal/command/appcmd/resource.go @@ -62,7 +62,7 @@ func setupResourceMkdirCommand() *cobra.Command { } }, } - setupUsernameFlags(&cmd) + setupUserFlags(&cmd) return &cmd } @@ -97,7 +97,7 @@ func setupResourceRmCommand() *cobra.Command { } flags := cmd.Flags() flags.BoolP("recursive", "r", false, "Recursively delete resource (required for collections)") - setupUsernameFlags(&cmd) + setupUserFlags(&cmd) return &cmd } @@ -162,7 +162,7 @@ func setupResourceLsCommand() *cobra.Command { if err != nil { logrus.Fatal(err) } - logrus.Info(fmt.Sprintf("%8.8s (%3.3d): %s", user.Username(), user.ID(), core.PermissionString(p))) + logrus.Info(fmt.Sprintf("%8.8s (%3.3d): %s", user.Email(), user.ID(), core.PermissionString(p))) } } @@ -174,7 +174,7 @@ func setupResourceLsCommand() *cobra.Command { if err != nil { logrus.Fatal(err) } - logrus.Info(fmt.Sprintf("%8.8s (%3.3d): %s", user.Username(), user.ID(), core.PermissionString(p))) + logrus.Info(fmt.Sprintf("%8.8s (%3.3d): %s", user.Email(), user.ID(), core.PermissionString(p))) } } @@ -191,7 +191,7 @@ func setupResourceLsCommand() *cobra.Command { } }, } - setupUsernameFlags(&cmd) + setupUserFlags(&cmd) return &cmd } @@ -206,7 +206,7 @@ func setupResourceChpermCommand() *cobra.Command { }, Run: func(cmd *cobra.Command, args []string) { var user int32 - if u, err := core.Default.UserByUsername(context.Background(), args[0]); err != nil { + if u, err := core.Default.UserByEmail(context.Background(), args[0]); err != nil { logrus.Fatal(err) } else { user = u.ID() @@ -257,7 +257,7 @@ func setupResourceChpermCommand() *cobra.Command { } }, } - setupUsernameFlags(&cmd) + setupUserFlags(&cmd) return &cmd } @@ -267,7 +267,7 @@ func openFileSystemFromFlags(cmd *cobra.Command) { if value, err := cmd.Flags().GetString("user"); err != nil { logrus.Fatal(err) } else { - if u, err := core.Default.UserByUsername(context.Background(), value); err != nil { + if u, err := core.Default.UserByEmail(context.Background(), value); err != nil { logrus.Fatal(err) } else { user = u @@ -282,8 +282,8 @@ func openFileSystemFromFlags(cmd *cobra.Command) { } -func setupUsernameFlags(cmd *cobra.Command) { +func setupUserFlags(cmd *cobra.Command) { flags := cmd.Flags() - flags.StringP("user", "u", "phylum", "Specify Username for resource operations (cannot be used with -u)") + flags.StringP("user", "u", "phylum", "Specify user for resource operations") } diff --git a/server/internal/command/appcmd/user.go b/server/internal/command/appcmd/user.go index 7605e08a..8ae28727 100644 --- a/server/internal/command/appcmd/user.go +++ b/server/internal/command/appcmd/user.go @@ -27,15 +27,15 @@ func setupUserCommand() *cobra.Command { func setupUserAddCommand() *cobra.Command { cmd := &cobra.Command{ - Use: "add username", + Use: "add email", Short: "Add User", Args: cobra.ExactArgs(1), Run: func(cmd *cobra.Command, args []string) { - username := args[0] + email := args[0] displayName, _ := cmd.Flags().GetString("name") if displayName == "" { - displayName = username + displayName = email } password, _ := cmd.Flags().GetString("password") @@ -61,7 +61,7 @@ func setupUserAddCommand() *cobra.Command { } } - if err := core.Default.CreateUser(context.Background(), username, displayName, password, nil); err != nil { + if err := core.Default.CreateUser(context.Background(), email, displayName, password, nil); err != nil { logrus.Fatal(err) } }, @@ -73,13 +73,13 @@ func setupUserAddCommand() *cobra.Command { func setupUserChrootCommand() *cobra.Command { cmd := &cobra.Command{ - Use: "chroot username uuid", + Use: "chroot email uuid", Short: "Set User Root", Args: cobra.ExactArgs(2), Run: func(cmd *cobra.Command, args []string) { - username := args[0] + email := args[0] idOrPath := args[1] - if user, err := core.Default.UserByUsername(context.Background(), username); err != nil { + if user, err := core.Default.UserByEmail(context.Background(), email); err != nil { logrus.Fatal(err) } else { var res core.Resource @@ -111,7 +111,7 @@ func setupUserListCommand() *cobra.Command { logrus.Fatal(err) } for _, user := range users { - logrus.Infof(" %3.3d: %s (%s)", user.ID(), user.Username(), user.DisplayName()) + logrus.Infof(" %3.3d: %s (%s)", user.ID(), user.Email(), user.DisplayName()) logrus.Infof("Root: %s", user.Root()) logrus.Infof("Home: %s", user.Home()) } diff --git a/server/internal/core/app.go b/server/internal/core/app.go index 65e996c2..54708e94 100644 --- a/server/internal/core/app.go +++ b/server/internal/core/app.go @@ -10,7 +10,7 @@ import ( "github.com/shroff/phylum/server/internal/storage" ) -const defaultUserName = "phylum" +const defaultUserEmail = "admin@phylum" type App struct { Debug bool @@ -32,7 +32,7 @@ func Create(ctx context.Context, db *db.DbHandler, cs storage.Storage, debug boo } func (a *App) setupAppData(ctx context.Context) error { - u, err := a.db.UserByUsername(ctx, defaultUserName) + u, err := a.db.UserByEmail(ctx, defaultUserEmail) if errors.Is(err, pgx.ErrNoRows) { u, err = a.populateData(ctx) @@ -76,7 +76,7 @@ func (a *App) populateData(ctx context.Context) (user db.User, e error) { userHome, err := dbh.CreateResource(ctx, db.CreateResourceParams{ ID: uuid.New(), Parent: &home.ID, - Name: defaultUserName, + Name: defaultUserEmail, Dir: true, }) if err != nil { @@ -85,7 +85,7 @@ func (a *App) populateData(ctx context.Context) (user db.User, e error) { // Create phylum user user, err = dbh.CreateUser(ctx, db.CreateUserParams{ - Username: defaultUserName, + Email: defaultUserEmail, DisplayName: "Phylum", PasswordHash: "", Root: root.ID, diff --git a/server/internal/core/auth.go b/server/internal/core/auth.go index 82b440ad..f3c46bf7 100644 --- a/server/internal/core/auth.go +++ b/server/internal/core/auth.go @@ -24,8 +24,8 @@ var ErrCredentialsInvalid = errors.New("credentials invalid") var ErrTokenInvalid = errors.New("token invalid") var ErrTokenExpired = errors.New("token expired") -func (a App) VerifyUserPassword(ctx context.Context, username, password string) (User, error) { - if user, err := a.db.UserByUsername(ctx, username); err != nil { +func (a App) VerifyUserPassword(ctx context.Context, email, password string) (User, error) { + if user, err := a.db.UserByEmail(ctx, email); err != nil { if errors.Is(err, pgx.ErrNoRows) { return nil, ErrCredentialsInvalid } diff --git a/server/internal/core/user.go b/server/internal/core/user.go index 811db05f..fd1e9bb9 100644 --- a/server/internal/core/user.go +++ b/server/internal/core/user.go @@ -4,7 +4,7 @@ import "github.com/google/uuid" type User interface { ID() int32 - Username() string + Email() string DisplayName() string Root() uuid.UUID Home() uuid.UUID @@ -12,14 +12,14 @@ type User interface { type user struct { id int32 - username string + email string displayName string root uuid.UUID home uuid.UUID } func (u user) ID() int32 { return u.id } -func (u user) Username() string { return u.username } +func (u user) Email() string { return u.email } func (u user) DisplayName() string { return u.displayName } func (u user) Root() uuid.UUID { return u.root } func (u user) Home() uuid.UUID { return u.home } diff --git a/server/internal/core/user_manager.go b/server/internal/core/user_manager.go index 8f1d31b8..ef30d1f0 100644 --- a/server/internal/core/user_manager.go +++ b/server/internal/core/user_manager.go @@ -12,7 +12,7 @@ import ( var ErrUserNotFound = errors.New("user not found") -func (a App) CreateUser(ctx context.Context, username, displayName, password string, root *uuid.UUID) error { +func (a App) CreateUser(ctx context.Context, email, displayName, password string, root *uuid.UUID) error { var rootID = a.Rootfs.Root().ID() if root != nil { rootID = *root @@ -22,7 +22,7 @@ func (a App) CreateUser(ctx context.Context, username, displayName, password str if hash, err := cryptutil.GenerateArgon2EncodedHash(password, cryptutil.DefaultArgon2Params()); err != nil { return err } else if u, err := d.CreateUser(ctx, db.CreateUserParams{ - Username: username, + Email: email, DisplayName: displayName, PasswordHash: hash, Root: rootID, @@ -31,7 +31,7 @@ func (a App) CreateUser(ctx context.Context, username, displayName, password str return err } else if home, err := fs.ResourceByPath("/home"); err != nil { return err - } else if userHome, err := fs.CreateMemberResource(home, uuid.New(), username, true); err != nil { + } else if userHome, err := fs.CreateMemberResource(home, uuid.New(), email, true); err != nil { return err } else if err := fs.UpdatePermissions(userHome, u.ID, PermissionReadWriteShare); err != nil { return err @@ -50,7 +50,7 @@ func (a App) ListUsers(ctx context.Context) ([]User, error) { for i, r := range results { users[i] = user{ id: r.ID, - username: r.Username, + email: r.Email, displayName: r.DisplayName, root: r.Root, home: r.Home, @@ -59,8 +59,8 @@ func (a App) ListUsers(ctx context.Context) ([]User, error) { return users, nil } -func (a App) UserByUsername(ctx context.Context, username string) (User, error) { - result, err := a.db.UserByUsername(ctx, username) +func (a App) UserByEmail(ctx context.Context, email string) (User, error) { + result, err := a.db.UserByEmail(ctx, email) if err != nil { if errors.Is(err, pgx.ErrNoRows) { err = ErrUserNotFound @@ -69,7 +69,7 @@ func (a App) UserByUsername(ctx context.Context, username string) (User, error) } return user{ id: result.ID, - username: result.Username, + email: result.Email, displayName: result.DisplayName, root: result.Root, home: result.Home, @@ -86,7 +86,7 @@ func (a App) UserByID(ctx context.Context, userID int32) (User, error) { } return user{ id: result.ID, - username: result.Username, + email: result.Email, displayName: result.DisplayName, root: result.Root, home: result.Home, diff --git a/server/internal/db/migrations/data/002_users.sql b/server/internal/db/migrations/data/002_users.sql index 03816424..2c44e699 100644 --- a/server/internal/db/migrations/data/002_users.sql +++ b/server/internal/db/migrations/data/002_users.sql @@ -1,6 +1,6 @@ CREATE TABLE users( id SERIAL PRIMARY KEY, - username TEXT NOT NULL UNIQUE, + email TEXT NOT NULL UNIQUE, created TIMESTAMP NOT NULL, modified TIMESTAMP NOT NULL, display_name TEXT NOT NULL, diff --git a/server/internal/db/models.go b/server/internal/db/models.go index f66280d8..a4209729 100644 --- a/server/internal/db/models.go +++ b/server/internal/db/models.go @@ -42,7 +42,7 @@ type StorageBackend struct { type User struct { ID int32 - Username string + Email string Created pgtype.Timestamp Modified pgtype.Timestamp DisplayName string diff --git a/server/internal/db/users.sql.go b/server/internal/db/users.sql.go index 40fe64a7..72889bc1 100644 --- a/server/internal/db/users.sql.go +++ b/server/internal/db/users.sql.go @@ -13,14 +13,14 @@ import ( const createUser = `-- name: CreateUser :one INSERT INTO users( - username, created, modified, display_name, password_hash, root, home + email, created, modified, display_name, password_hash, root, home ) VALUES ( $1, NOW(), NOW(), $2, $3, $4, $5 -) RETURNING id, username, created, modified, display_name, password_hash, deleted, root, home +) RETURNING id, email, created, modified, display_name, password_hash, deleted, root, home ` type CreateUserParams struct { - Username string + Email string DisplayName string PasswordHash string Root uuid.UUID @@ -29,7 +29,7 @@ type CreateUserParams struct { func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, error) { row := q.db.QueryRow(ctx, createUser, - arg.Username, + arg.Email, arg.DisplayName, arg.PasswordHash, arg.Root, @@ -38,7 +38,7 @@ func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, e var i User err := row.Scan( &i.ID, - &i.Username, + &i.Email, &i.Created, &i.Modified, &i.DisplayName, @@ -51,7 +51,7 @@ func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, e } const listUsers = `-- name: ListUsers :many -SELECT id, username, created, modified, display_name, password_hash, deleted, root, home from users WHERE deleted IS NULL +SELECT id, email, created, modified, display_name, password_hash, deleted, root, home from users WHERE deleted IS NULL ` func (q *Queries) ListUsers(ctx context.Context) ([]User, error) { @@ -65,7 +65,7 @@ func (q *Queries) ListUsers(ctx context.Context) ([]User, error) { var i User if err := rows.Scan( &i.ID, - &i.Username, + &i.Email, &i.Created, &i.Modified, &i.DisplayName, @@ -156,8 +156,29 @@ func (q *Queries) UpdateUserRoot(ctx context.Context, arg UpdateUserRootParams) return err } +const userByEmail = `-- name: UserByEmail :one +SELECT id, email, created, modified, display_name, password_hash, deleted, root, home from users WHERE email = $1 +` + +func (q *Queries) UserByEmail(ctx context.Context, email string) (User, error) { + row := q.db.QueryRow(ctx, userByEmail, email) + var i User + err := row.Scan( + &i.ID, + &i.Email, + &i.Created, + &i.Modified, + &i.DisplayName, + &i.PasswordHash, + &i.Deleted, + &i.Root, + &i.Home, + ) + return i, err +} + const userByID = `-- name: UserByID :one -SELECT id, username, created, modified, display_name, password_hash, deleted, root, home from users WHERE id = $1 +SELECT id, email, created, modified, display_name, password_hash, deleted, root, home from users WHERE id = $1 ` func (q *Queries) UserByID(ctx context.Context, id int32) (User, error) { @@ -165,28 +186,7 @@ func (q *Queries) UserByID(ctx context.Context, id int32) (User, error) { var i User err := row.Scan( &i.ID, - &i.Username, - &i.Created, - &i.Modified, - &i.DisplayName, - &i.PasswordHash, - &i.Deleted, - &i.Root, - &i.Home, - ) - return i, err -} - -const userByUsername = `-- name: UserByUsername :one -SELECT id, username, created, modified, display_name, password_hash, deleted, root, home from users WHERE username = $1 -` - -func (q *Queries) UserByUsername(ctx context.Context, username string) (User, error) { - row := q.db.QueryRow(ctx, userByUsername, username) - var i User - err := row.Scan( - &i.ID, - &i.Username, + &i.Email, &i.Created, &i.Modified, &i.DisplayName, diff --git a/server/sql/queries/users.sql b/server/sql/queries/users.sql index 6f0642f6..95ad1f0f 100644 --- a/server/sql/queries/users.sql +++ b/server/sql/queries/users.sql @@ -1,12 +1,12 @@ -- name: CreateUser :one INSERT INTO users( - username, created, modified, display_name, password_hash, root, home + email, created, modified, display_name, password_hash, root, home ) VALUES ( $1, NOW(), NOW(), $2, $3, $4, $5 ) RETURNING *; --- name: UserByUsername :one -SELECT * from users WHERE username = $1; +-- name: UserByEmail :one +SELECT * from users WHERE email = $1; -- name: UserByID :one SELECT * from users WHERE id = $1;