package mongo import ( "context" "errors" "time" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" mongodriver "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" "scheduler-backend/internal/store/model" ) type AdminUserStore struct { collection *mongodriver.Collection } func NewAdminUserStore(db *mongodriver.Database) *AdminUserStore { return &AdminUserStore{ collection: db.Collection("admin_users"), } } func (s *AdminUserStore) List(ctx context.Context) ([]model.AdminUser, error) { findCtx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() cursor, err := s.collection.Find(findCtx, bson.D{}, options.Find().SetSort(bson.D{{Key: "updatedAt", Value: -1}})) if err != nil { return nil, err } defer cursor.Close(findCtx) items := make([]model.AdminUser, 0) for cursor.Next(findCtx) { var item model.AdminUser if err := cursor.Decode(&item); err != nil { return nil, err } items = append(items, item) } if err := cursor.Err(); err != nil { return nil, err } if len(items) == 0 { defaultAdmin := model.AdminUser{ Account: "admin", Nickname: "调度管理员", Status: "active", Role: "super_admin", Remark: "default admin user", PasswordHash: hashPassword(defaultAdminPassword), } if err := s.Create(ctx, &defaultAdmin); err != nil { return nil, err } items = append(items, defaultAdmin) } return items, nil } func (s *AdminUserStore) GetByID(ctx context.Context, id primitive.ObjectID) (*model.AdminUser, error) { findCtx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() var item model.AdminUser err := s.collection.FindOne(findCtx, bson.M{"_id": id}).Decode(&item) if err != nil { if errors.Is(err, mongodriver.ErrNoDocuments) { return nil, nil } return nil, err } return &item, nil } func (s *AdminUserStore) Create(ctx context.Context, item *model.AdminUser) error { insertCtx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() now := time.Now() item.CreatedAt = now item.UpdatedAt = now if item.Status == "" { item.Status = "active" } if item.Role == "" { item.Role = "super_admin" } result, err := s.collection.InsertOne(insertCtx, item) if err != nil { return err } if oid, ok := result.InsertedID.(primitive.ObjectID); ok { item.ID = oid } return nil } func (s *AdminUserStore) Update(ctx context.Context, item *model.AdminUser) error { updateCtx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() item.UpdatedAt = time.Now() _, err := s.collection.UpdateByID(updateCtx, item.ID, bson.M{ "$set": bson.M{ "account": item.Account, "nickname": item.Nickname, "status": item.Status, "role": item.Role, "remark": item.Remark, "updatedAt": item.UpdatedAt, }, }) return err } func (s *AdminUserStore) ChangePassword(ctx context.Context, id primitive.ObjectID, newPassword string) error { updateCtx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() _, err := s.collection.UpdateByID(updateCtx, id, bson.M{ "$set": bson.M{ "passwordHash": hashPassword(newPassword), "updatedAt": time.Now(), }, }) return err } func (s *AdminUserStore) Authenticate(ctx context.Context, account, password string) (*model.AdminUser, error) { findCtx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() var item model.AdminUser err := s.collection.FindOne(findCtx, bson.M{"account": account}).Decode(&item) if err != nil { if errors.Is(err, mongodriver.ErrNoDocuments) { return nil, ErrInvalidPassword } return nil, err } if item.Status == "disabled" || item.PasswordHash != hashPassword(password) { return nil, ErrInvalidPassword } return &item, nil }