Files
scheduler-backend/internal/store/mongo/admin_profile_store.go
2026-05-28 00:16:19 +08:00

126 lines
3.1 KiB
Go

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[:])
}