package mongo import ( "context" "crypto/sha256" "encoding/hex" "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" ) const defaultAdminPassword = "admin123" type AdminProfileStore struct { collection *mongodriver.Collection } func NewAdminProfileStore(db *mongodriver.Database) *AdminProfileStore { return &AdminProfileStore{ collection: db.Collection("admin_profiles"), } } func (s *AdminProfileStore) Get(ctx context.Context) (*model.AdminProfile, error) { findCtx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() var item model.AdminProfile err := s.collection.FindOne(findCtx, bson.D{}, options.FindOne().SetSort(bson.D{{Key: "updatedAt", Value: -1}})).Decode(&item) if err == nil { return &item, nil } if !errors.Is(err, mongodriver.ErrNoDocuments) { return nil, err } now := time.Now() item = model.AdminProfile{ ID: primitive.NewObjectID(), Account: "admin", Nickname: "调度管理员", Avatar: "", Remark: "default admin profile", PasswordHash: hashPassword(defaultAdminPassword), CreatedAt: now, UpdatedAt: now, } if _, err := s.collection.InsertOne(findCtx, item); err != nil { return nil, err } return &item, nil } func (s *AdminProfileStore) Upsert(ctx context.Context, profile *model.AdminProfile) error { updateCtx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() now := time.Now() profile.UpdatedAt = now if profile.CreatedAt.IsZero() { profile.CreatedAt = now } if profile.ID.IsZero() { current, err := s.Get(ctx) if err != nil { return err } profile.ID = current.ID if profile.PasswordHash == "" { profile.PasswordHash = current.PasswordHash } if profile.CreatedAt.IsZero() { profile.CreatedAt = current.CreatedAt } } _, err := s.collection.UpdateByID(updateCtx, profile.ID, bson.M{ "$set": bson.M{ "account": profile.Account, "nickname": profile.Nickname, "avatar": profile.Avatar, "remark": profile.Remark, "passwordHash": profile.PasswordHash, "createdAt": profile.CreatedAt, "updatedAt": profile.UpdatedAt, }, }, options.Update().SetUpsert(true)) return err } func (s *AdminProfileStore) ChangePassword(ctx context.Context, oldPassword, newPassword string) error { current, err := s.Get(ctx) if err != nil { return err } if current.PasswordHash != hashPassword(oldPassword) { return ErrInvalidPassword } current.PasswordHash = hashPassword(newPassword) return s.Upsert(ctx, current) } func (s *AdminProfileStore) Authenticate(ctx context.Context, account, password string) (*model.AdminProfile, error) { current, err := s.Get(ctx) if err != nil { return nil, err } if current.Account != account || current.PasswordHash != hashPassword(password) { return nil, ErrInvalidPassword } return current, nil } func hashPassword(password string) string { sum := sha256.Sum256([]byte(password)) return hex.EncodeToString(sum[:]) }