diff --git a/app/user_verifications/rpc/internal/logic/searchUserVerificationsLogic.go b/app/user_verifications/rpc/internal/logic/searchUserVerificationsLogic.go index 97cab17..9caefc4 100644 --- a/app/user_verifications/rpc/internal/logic/searchUserVerificationsLogic.go +++ b/app/user_verifications/rpc/internal/logic/searchUserVerificationsLogic.go @@ -4,6 +4,7 @@ import ( "context" "errors" "juwan-backend/app/user_verifications/rpc/internal/models" + "juwan-backend/app/user_verifications/rpc/internal/models/predicate" "juwan-backend/app/user_verifications/rpc/internal/models/userverifications" "juwan-backend/app/user_verifications/rpc/internal/svc" "juwan-backend/app/user_verifications/rpc/pb" @@ -31,7 +32,18 @@ func (l *SearchUserVerificationsLogic) SearchUserVerifications(in *pb.SearchUser logx.Errorf("Limit exceeds max limit: %d", in.Limit) return nil, errors.New("limit exceeds max limit") } - verifications, err := l.svcCtx.UserVeriModelRO.Query().Where(userverifications.UserIDEQ(in.UserId)). + predicates := make([]predicate.UserVerifications, 0, 3) + if in.UserId != 0 { + predicates = append(predicates, userverifications.UserIDEQ(in.UserId)) + } + if in.Role != "" { + predicates = append(predicates, userverifications.RoleEQ(in.Role)) + } + if in.Status != "" { + predicates = append(predicates, userverifications.StatusEQ(in.Status)) + } + + verifications, err := l.svcCtx.UserVeriModelRO.Query().Where(predicates...). Offset(int(in.Page * in.Limit)). Limit(int(in.Limit)). All(l.ctx) diff --git a/app/users/rpc/admin_init.go b/app/users/rpc/admin_init.go new file mode 100644 index 0000000..38b4190 --- /dev/null +++ b/app/users/rpc/admin_init.go @@ -0,0 +1,60 @@ +package main + +import ( + "context" + "os" + "strings" + + "juwan-backend/app/snowflake/rpc/snowflake" + "juwan-backend/app/users/rpc/internal/models/users" + "juwan-backend/app/users/rpc/internal/svc" + "juwan-backend/common/utils/pwdUtils" + + "github.com/zeromicro/go-zero/core/logx" +) + +func initAdmin(svcCtx *svc.ServiceContext) { + username := strings.TrimSpace(os.Getenv("ADMIN_USERNAME")) + password := strings.TrimSpace(os.Getenv("ADMIN_PASSWORD")) + email := strings.TrimSpace(os.Getenv("ADMIN_EMAIL")) + if username == "" || password == "" || email == "" { + return + } + + ctx := context.Background() + exists, _ := svcCtx.UsersModelRW.Users.Query().Where(users.UsernameEQ(username)).Exist(ctx) + if exists { + return + } + + hashedPassword, err := pwdUtils.HashPassword(password) + if err != nil { + logx.Errorf("hash admin password: %v", err) + return + } + + resp, err := svcCtx.Snowflake.NextId(ctx, &snowflake.NextIdReq{}) + if err != nil { + logx.Errorf("generate admin user ID: %v", err) + return + } + + _, err = svcCtx.UsersModelRW.Users.Create(). + SetID(resp.Id). + SetUsername(username). + SetPasswordHash(hashedPassword). + SetEmail(email). + SetPhone(""). + SetBio(""). + SetAvatar(""). + SetCurrentRole("consumer"). + SetNickname(username). + SetIsAdmin(true). + Save(ctx) + if err != nil { + logx.Errorf("create admin user: %v", err) + return + } + + logx.Infof("initialized admin user: %s", username) +} diff --git a/app/users/rpc/internal/logic/updateUsersLogic.go b/app/users/rpc/internal/logic/updateUsersLogic.go index 7fc4034..a84f1ee 100644 --- a/app/users/rpc/internal/logic/updateUsersLogic.go +++ b/app/users/rpc/internal/logic/updateUsersLogic.go @@ -29,7 +29,8 @@ func (l *UpdateUsersLogic) UpdateUsers(in *pb.UpdateUsersReq) (*pb.UpdateUsersRe SetNillableAvatar(in.Avatar). SetNillableBio(in.Bio). SetNillableCurrentRole(in.CurrentRole). - SetNillablePasswordHash(in.PasswordHash) + SetNillablePasswordHash(in.PasswordHash). + SetNillableIsAdmin(in.IsAdmin) if len(in.VerifiedRoles) > 0 { verifiedRoles := types.TextArray{Elements: append([]string{}, in.VerifiedRoles...), Valid: true} updater.SetVerifiedRoles(verifiedRoles) diff --git a/app/users/rpc/pb.go b/app/users/rpc/pb.go index a448628..4943c3f 100644 --- a/app/users/rpc/pb.go +++ b/app/users/rpc/pb.go @@ -25,6 +25,7 @@ func main() { var c config.Config conf.MustLoad(*configFile, &c, conf.UseEnv()) ctx := svc.NewServiceContext(c) + initAdmin(ctx) s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) { pb.RegisterUsercenterServer(grpcServer, server.NewUsercenterServer(ctx)) diff --git a/deploy/dev/.env b/deploy/dev/.env index 65b2ada..0cea1cf 100644 --- a/deploy/dev/.env +++ b/deploy/dev/.env @@ -30,3 +30,8 @@ S3_ACCESS_KEY=changeme S3_SECRET_KEY=changeme S3_BUCKET_NAME=dev-bucket S3_REGION=auto + +# Admin (auto-init on first startup) +ADMIN_USERNAME=admin +ADMIN_PASSWORD=admin123 +ADMIN_EMAIL=admin@juwan.dev diff --git a/deploy/dev/docker-compose.yml b/deploy/dev/docker-compose.yml index e19393a..7f430bd 100644 --- a/deploy/dev/docker-compose.yml +++ b/deploy/dev/docker-compose.yml @@ -118,6 +118,10 @@ services: container_name: juwan-user-rpc restart: unless-stopped env_file: .env + environment: + ADMIN_USERNAME: ${ADMIN_USERNAME} + ADMIN_PASSWORD: ${ADMIN_PASSWORD} + ADMIN_EMAIL: ${ADMIN_EMAIL} depends_on: postgres: condition: service_healthy diff --git a/deploy/dev/envoy.yaml b/deploy/dev/envoy.yaml index 1a94882..69e8176 100644 --- a/deploy/dev/envoy.yaml +++ b/deploy/dev/envoy.yaml @@ -235,6 +235,12 @@ static_resources: cluster: user_api_cluster timeout: 30s + - match: + prefix: /api/v1/admin + route: + cluster: user_api_cluster + timeout: 30s + - match: prefix: /api/v1/users route: