[feature/backend] implement /users handler + switch to username + add display name + user management cli
This commit is contained in:
parent
1d712d4e6c
commit
86ab334bc9
38 changed files with 1851 additions and 506 deletions
411
backend/cmd/user.go
Normal file
411
backend/cmd/user.go
Normal file
|
@ -0,0 +1,411 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"text/tabwriter"
|
||||
|
||||
"tss-rocks-be/ent/user"
|
||||
"tss-rocks-be/ent/role"
|
||||
"tss-rocks-be/internal/config"
|
||||
"tss-rocks-be/internal/server"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func GetUserCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "user",
|
||||
Short: "User management commands",
|
||||
Long: `Commands for managing users, including create, delete, password, and role management.`,
|
||||
}
|
||||
|
||||
configPath := cmd.PersistentFlags().String("config", "config/config.yaml", "Path to config file")
|
||||
|
||||
cmd.AddCommand(getCreateUserCmd(*configPath))
|
||||
cmd.AddCommand(getPasswordCmd(*configPath))
|
||||
cmd.AddCommand(getListUsersCmd(*configPath))
|
||||
cmd.AddCommand(getDeleteUserCmd(*configPath))
|
||||
cmd.AddCommand(getRoleCmd(*configPath))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func getCreateUserCmd(configPath string) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "create",
|
||||
Short: "Create a new user",
|
||||
Long: `Create a new user with specified username, email and password.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
username, _ := cmd.Flags().GetString("username")
|
||||
email, _ := cmd.Flags().GetString("email")
|
||||
password, _ := cmd.Flags().GetString("password")
|
||||
|
||||
// 加载配置
|
||||
cfg, err := config.Load(configPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading config: %v", err)
|
||||
}
|
||||
|
||||
// 初始化数据库连接
|
||||
client := server.NewEntClient(cfg)
|
||||
if client == nil {
|
||||
return fmt.Errorf("failed to create database client")
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// 检查用户名是否已存在
|
||||
exists, err := client.User.Query().Where(user.Username(username)).Exist(cmd.Context())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error checking username: %v", err)
|
||||
}
|
||||
if exists {
|
||||
return fmt.Errorf("username '%s' already exists", username)
|
||||
}
|
||||
|
||||
// 检查邮箱是否已存在
|
||||
exists, err = client.User.Query().Where(user.Email(email)).Exist(cmd.Context())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error checking email: %v", err)
|
||||
}
|
||||
if exists {
|
||||
return fmt.Errorf("email '%s' already exists", email)
|
||||
}
|
||||
|
||||
// 生成密码哈希
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error hashing password: %v", err)
|
||||
}
|
||||
|
||||
// 创建用户
|
||||
u, err := client.User.Create().
|
||||
SetUsername(username).
|
||||
SetEmail(email).
|
||||
SetPasswordHash(string(hashedPassword)).
|
||||
SetStatus("active").
|
||||
Save(cmd.Context())
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating user: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully created user '%s' with email '%s'\n", u.Username, u.Email)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// 添加命令行参数
|
||||
cmd.Flags().String("username", "", "username for the new user")
|
||||
cmd.Flags().String("email", "", "email for the new user")
|
||||
cmd.Flags().String("password", "", "password for the new user")
|
||||
|
||||
// 设置必需的参数
|
||||
cmd.MarkFlagRequired("username")
|
||||
cmd.MarkFlagRequired("email")
|
||||
cmd.MarkFlagRequired("password")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func getPasswordCmd(configPath string) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "password",
|
||||
Short: "Change user password",
|
||||
Long: `Change the password for an existing user.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
username, _ := cmd.Flags().GetString("username")
|
||||
password, _ := cmd.Flags().GetString("password")
|
||||
|
||||
// 加载配置
|
||||
cfg, err := config.Load(configPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading config: %v", err)
|
||||
}
|
||||
|
||||
// 初始化数据库连接
|
||||
client := server.NewEntClient(cfg)
|
||||
if client == nil {
|
||||
return fmt.Errorf("failed to create database client")
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// 查找用户
|
||||
u, err := client.User.Query().Where(user.Username(username)).Only(cmd.Context())
|
||||
if err != nil {
|
||||
return fmt.Errorf("user with username '%s' not found", username)
|
||||
}
|
||||
|
||||
// 生成新的密码哈希
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error hashing password: %v", err)
|
||||
}
|
||||
|
||||
// 更新密码
|
||||
_, err = u.Update().SetPasswordHash(string(hashedPassword)).Save(cmd.Context())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error updating password: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully updated password for user '%s'\n", username)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// 添加命令行参数
|
||||
cmd.Flags().String("username", "", "username of the user")
|
||||
cmd.Flags().String("password", "", "new password")
|
||||
|
||||
// 设置必需的参数
|
||||
cmd.MarkFlagRequired("username")
|
||||
cmd.MarkFlagRequired("password")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func getListUsersCmd(configPath string) *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "List all users",
|
||||
Long: `List all users in the system.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
// 加载配置
|
||||
cfg, err := config.Load(configPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading config: %v", err)
|
||||
}
|
||||
|
||||
// 初始化数据库连接
|
||||
client := server.NewEntClient(cfg)
|
||||
if client == nil {
|
||||
return fmt.Errorf("failed to create database client")
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// 获取所有用户
|
||||
users, err := client.User.Query().All(cmd.Context())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error querying users: %v", err)
|
||||
}
|
||||
|
||||
// 创建表格写入器
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||
fmt.Fprintln(w, "USERNAME\tEMAIL\tSTATUS\tCREATED AT")
|
||||
|
||||
// 输出用户信息
|
||||
for _, u := range users {
|
||||
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n",
|
||||
u.Username,
|
||||
u.Email,
|
||||
u.Status,
|
||||
u.CreatedAt.Format("2006-01-02 15:04:05"))
|
||||
}
|
||||
w.Flush()
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func getDeleteUserCmd(configPath string) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "delete",
|
||||
Short: "Delete a user",
|
||||
Long: `Delete an existing user from the system.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
username, _ := cmd.Flags().GetString("username")
|
||||
force, _ := cmd.Flags().GetBool("force")
|
||||
|
||||
// 加载配置
|
||||
cfg, err := config.Load(configPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading config: %v", err)
|
||||
}
|
||||
|
||||
// 初始化数据库连接
|
||||
client := server.NewEntClient(cfg)
|
||||
if client == nil {
|
||||
return fmt.Errorf("failed to create database client")
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// 查找用户
|
||||
u, err := client.User.Query().Where(user.Username(username)).Only(cmd.Context())
|
||||
if err != nil {
|
||||
return fmt.Errorf("user with username '%s' not found", username)
|
||||
}
|
||||
|
||||
// 检查用户的角色
|
||||
hasRoles, err := client.User.QueryRoles(u).Exist(cmd.Context())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error checking user roles: %v", err)
|
||||
}
|
||||
if hasRoles && !force {
|
||||
return fmt.Errorf("user '%s' has roles assigned. Use --force to override", username)
|
||||
}
|
||||
|
||||
// 删除用户
|
||||
err = client.User.DeleteOne(u).Exec(cmd.Context())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error deleting user: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully deleted user '%s'\n", username)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// 添加命令行参数
|
||||
cmd.Flags().String("username", "", "username of the user to delete")
|
||||
cmd.Flags().Bool("force", false, "force delete even if user has roles")
|
||||
|
||||
// 设置必需的参数
|
||||
cmd.MarkFlagRequired("username")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func getRoleCmd(configPath string) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "role",
|
||||
Short: "User role management commands",
|
||||
Long: `Commands for managing user roles, including adding and removing roles.`,
|
||||
}
|
||||
|
||||
cmd.AddCommand(getRoleAddCmd(configPath))
|
||||
cmd.AddCommand(getRoleRemoveCmd(configPath))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func getRoleAddCmd(configPath string) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "add",
|
||||
Short: "Add a role to a user",
|
||||
Long: `Add a role to an existing user.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
username, _ := cmd.Flags().GetString("username")
|
||||
roleName, _ := cmd.Flags().GetString("role")
|
||||
|
||||
// 加载配置
|
||||
cfg, err := config.Load(configPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading config: %v", err)
|
||||
}
|
||||
|
||||
// 初始化数据库连接
|
||||
client := server.NewEntClient(cfg)
|
||||
if client == nil {
|
||||
return fmt.Errorf("failed to create database client")
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// 查找用户
|
||||
u, err := client.User.Query().Where(user.Username(username)).Only(cmd.Context())
|
||||
if err != nil {
|
||||
return fmt.Errorf("user with username '%s' not found", username)
|
||||
}
|
||||
|
||||
// 检查角色是否已存在
|
||||
hasRole, err := client.User.QueryRoles(u).Where(role.Name(roleName)).Exist(cmd.Context())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error checking user roles: %v", err)
|
||||
}
|
||||
if hasRole {
|
||||
return fmt.Errorf("user '%s' already has role '%s'", username, roleName)
|
||||
}
|
||||
|
||||
// 获取要添加的角色
|
||||
r, err := client.Role.Query().Where(role.Name(roleName)).Only(cmd.Context())
|
||||
if err != nil {
|
||||
return fmt.Errorf("role '%s' not found", roleName)
|
||||
}
|
||||
|
||||
// 添加角色
|
||||
err = client.User.UpdateOne(u).AddRoles(r).Exec(cmd.Context())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error adding role: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully added role '%s' to user '%s'\n", roleName, username)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// 添加命令行参数
|
||||
cmd.Flags().String("username", "", "username of the user")
|
||||
cmd.Flags().String("role", "", "role to add (admin/editor/contributor)")
|
||||
|
||||
// 设置必需的参数
|
||||
cmd.MarkFlagRequired("username")
|
||||
cmd.MarkFlagRequired("role")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func getRoleRemoveCmd(configPath string) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "remove",
|
||||
Short: "Remove a role from a user",
|
||||
Long: `Remove a role from an existing user.`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
username, _ := cmd.Flags().GetString("username")
|
||||
roleName, _ := cmd.Flags().GetString("role")
|
||||
|
||||
// 加载配置
|
||||
cfg, err := config.Load(configPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading config: %v", err)
|
||||
}
|
||||
|
||||
// 初始化数据库连接
|
||||
client := server.NewEntClient(cfg)
|
||||
if client == nil {
|
||||
return fmt.Errorf("failed to create database client")
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
// 查找用户
|
||||
u, err := client.User.Query().Where(user.Username(username)).Only(cmd.Context())
|
||||
if err != nil {
|
||||
return fmt.Errorf("user with username '%s' not found", username)
|
||||
}
|
||||
|
||||
// 检查角色是否存在
|
||||
r, err := client.Role.Query().Where(role.Name(roleName)).Only(cmd.Context())
|
||||
if err != nil {
|
||||
return fmt.Errorf("role '%s' not found", roleName)
|
||||
}
|
||||
|
||||
// 检查用户是否有该角色
|
||||
hasRole, err := client.User.QueryRoles(u).Where(role.Name(roleName)).Exist(cmd.Context())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error checking user roles: %v", err)
|
||||
}
|
||||
if !hasRole {
|
||||
return fmt.Errorf("user '%s' does not have role '%s'", username, roleName)
|
||||
}
|
||||
|
||||
// 移除角色
|
||||
err = client.User.UpdateOne(u).RemoveRoles(r).Exec(cmd.Context())
|
||||
if err != nil {
|
||||
return fmt.Errorf("error removing role: %v", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Successfully removed role '%s' from user '%s'\n", roleName, username)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// 添加命令行参数
|
||||
cmd.Flags().String("username", "", "username of the user")
|
||||
cmd.Flags().String("role", "", "role to remove (admin/editor/contributor)")
|
||||
|
||||
// 设置必需的参数
|
||||
cmd.MarkFlagRequired("username")
|
||||
cmd.MarkFlagRequired("role")
|
||||
|
||||
return cmd
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue