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

153 lines
3.7 KiB
Go

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
}