This commit is contained in:
vet
2026-05-28 00:16:19 +08:00
commit 52446ccf3f
54 changed files with 4617 additions and 0 deletions

View File

@@ -0,0 +1,18 @@
package model
import (
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type AdminProfile struct {
ID primitive.ObjectID `bson:"_id,omitempty" json:"id"`
Account string `bson:"account" json:"account"`
Nickname string `bson:"nickname" json:"nickname"`
Avatar string `bson:"avatar" json:"avatar"`
Remark string `bson:"remark" json:"remark"`
PasswordHash string `bson:"passwordHash" json:"-"`
CreatedAt time.Time `bson:"createdAt" json:"createdAt"`
UpdatedAt time.Time `bson:"updatedAt" json:"updatedAt"`
}

View File

@@ -0,0 +1,19 @@
package model
import (
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type AdminUser struct {
ID primitive.ObjectID `bson:"_id,omitempty" json:"id"`
Account string `bson:"account" json:"account"`
Nickname string `bson:"nickname" json:"nickname"`
Status string `bson:"status" json:"status"`
Role string `bson:"role" json:"role"`
Remark string `bson:"remark" json:"remark"`
PasswordHash string `bson:"passwordHash" json:"-"`
CreatedAt time.Time `bson:"createdAt" json:"createdAt"`
UpdatedAt time.Time `bson:"updatedAt" json:"updatedAt"`
}

View File

@@ -0,0 +1,33 @@
package model
import (
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type JobConfig struct {
ID primitive.ObjectID `bson:"_id,omitempty" json:"id"`
Name string `bson:"name" json:"name"`
HandlerKey string `bson:"handlerKey" json:"handlerKey"`
Enabled bool `bson:"enabled" json:"enabled"`
ScheduleType string `bson:"scheduleType" json:"scheduleType"`
ScheduleValue string `bson:"scheduleValue" json:"scheduleValue"`
DefaultParams string `bson:"defaultParams" json:"defaultParams"`
LastStatus string `bson:"lastStatus" json:"lastStatus"`
LastRunAt *time.Time `bson:"lastRunAt,omitempty" json:"lastRunAt,omitempty"`
NextRunAt *time.Time `bson:"nextRunAt,omitempty" json:"nextRunAt,omitempty"`
CreatedAt time.Time `bson:"createdAt" json:"createdAt"`
UpdatedAt time.Time `bson:"updatedAt" json:"updatedAt"`
}
func NewJobConfig(name, handlerKey string) JobConfig {
now := time.Now()
return JobConfig{
Name: name,
HandlerKey: handlerKey,
LastStatus: "idle",
CreatedAt: now,
UpdatedAt: now,
}
}

View File

@@ -0,0 +1,10 @@
package model
import "testing"
func TestJobConfigDefaultsToIdleStatus(t *testing.T) {
job := NewJobConfig("daily-check", "daily-check")
if job.LastStatus != "idle" {
t.Fatalf("LastStatus = %q, want idle", job.LastStatus)
}
}

View File

@@ -0,0 +1,23 @@
package model
import (
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type JobExecution struct {
ID primitive.ObjectID `bson:"_id,omitempty" json:"id"`
JobConfigID primitive.ObjectID `bson:"jobConfigId" json:"jobConfigId"`
TriggerType string `bson:"triggerType" json:"triggerType"`
Status string `bson:"status" json:"status"`
ParamsSnapshot string `bson:"paramsSnapshot" json:"paramsSnapshot"`
StartedAt *time.Time `bson:"startedAt,omitempty" json:"startedAt,omitempty"`
FinishedAt *time.Time `bson:"finishedAt,omitempty" json:"finishedAt,omitempty"`
DurationMs int64 `bson:"durationMs" json:"durationMs"`
ResultSummary string `bson:"resultSummary" json:"resultSummary"`
ErrorMessage string `bson:"errorMessage" json:"errorMessage"`
LogText string `bson:"logText" json:"logText"`
LogFile string `bson:"logFile,omitempty" json:"logFile,omitempty"`
CreatedAt time.Time `bson:"createdAt" json:"createdAt"`
}

View File

@@ -0,0 +1,19 @@
package model
import (
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type SystemConfig struct {
ID primitive.ObjectID `bson:"_id,omitempty" json:"id"`
Key string `bson:"key" json:"key"`
Title string `bson:"title" json:"title"`
Value string `bson:"value" json:"value"`
ValueType string `bson:"valueType" json:"valueType"`
Description string `bson:"description" json:"description"`
Enabled bool `bson:"enabled" json:"enabled"`
CreatedAt time.Time `bson:"createdAt" json:"createdAt"`
UpdatedAt time.Time `bson:"updatedAt" json:"updatedAt"`
}

View File

@@ -0,0 +1,125 @@
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[:])
}

View File

@@ -0,0 +1,152 @@
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
}

View File

@@ -0,0 +1,37 @@
package mongo
import (
"context"
"time"
mongodriver "go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"scheduler-backend/pkg/config"
)
type Databases struct {
Client *mongodriver.Client
MetaDB *mongodriver.Database
BusinessDB *mongodriver.Database
}
func Connect(ctx context.Context, cfg config.Config) (*Databases, error) {
client, err := mongodriver.Connect(ctx, options.Client().ApplyURI(cfg.MongoURI()))
if err != nil {
return nil, err
}
pingCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
if err := client.Ping(pingCtx, nil); err != nil {
return nil, err
}
return &Databases{
Client: client,
MetaDB: client.Database(cfg.SchedulerMongoDatabase),
BusinessDB: client.Database(cfg.BusinessMongoDatabase),
}, nil
}

View File

@@ -0,0 +1,5 @@
package mongo
import "errors"
var ErrInvalidPassword = errors.New("invalid password")

View File

@@ -0,0 +1,222 @@
package mongo
import (
"context"
"errors"
"time"
"go.mongodb.org/mongo-driver/bson"
mongodriver "go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/bson/primitive"
"scheduler-backend/internal/store/model"
)
type JobConfigStore struct {
collection *mongodriver.Collection
}
func NewJobConfigStore(db *mongodriver.Database) *JobConfigStore {
return &JobConfigStore{
collection: db.Collection("job_configs"),
}
}
func (s *JobConfigStore) List(ctx context.Context) ([]model.JobConfig, 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.JobConfig, 0)
for cursor.Next(findCtx) {
var item model.JobConfig
if err := cursor.Decode(&item); err != nil {
return nil, err
}
items = append(items, item)
}
if err := cursor.Err(); err != nil {
return nil, err
}
return items, nil
}
func (s *JobConfigStore) ListEnabled(ctx context.Context) ([]model.JobConfig, error) {
findCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
cursor, err := s.collection.Find(
findCtx,
bson.M{"enabled": true},
options.Find().SetSort(bson.D{{Key: "updatedAt", Value: -1}}),
)
if err != nil {
return nil, err
}
defer cursor.Close(findCtx)
items := make([]model.JobConfig, 0)
for cursor.Next(findCtx) {
var item model.JobConfig
if err := cursor.Decode(&item); err != nil {
return nil, err
}
items = append(items, item)
}
if err := cursor.Err(); err != nil {
return nil, err
}
return items, nil
}
func (s *JobConfigStore) GetByID(ctx context.Context, id primitive.ObjectID) (*model.JobConfig, error) {
findCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
var item model.JobConfig
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 *JobConfigStore) Create(ctx context.Context, item *model.JobConfig) error {
insertCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
now := time.Now()
item.CreatedAt = now
item.UpdatedAt = now
if item.LastStatus == "" {
item.LastStatus = "idle"
}
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 *JobConfigStore) Update(ctx context.Context, item *model.JobConfig) error {
updateCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
item.UpdatedAt = time.Now()
update := bson.M{
"$set": bson.M{
"name": item.Name,
"handlerKey": item.HandlerKey,
"enabled": item.Enabled,
"scheduleType": item.ScheduleType,
"scheduleValue": item.ScheduleValue,
"defaultParams": item.DefaultParams,
"updatedAt": item.UpdatedAt,
},
}
_, err := s.collection.UpdateByID(updateCtx, item.ID, update)
return err
}
func (s *JobConfigStore) ToggleEnabled(ctx context.Context, id primitive.ObjectID, enabled bool) error {
updateCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
_, err := s.collection.UpdateByID(updateCtx, id, bson.M{
"$set": bson.M{
"enabled": enabled,
"updatedAt": time.Now(),
},
})
return err
}
func (s *JobConfigStore) UpdateRunState(ctx context.Context, id primitive.ObjectID, status string, lastRunAt *time.Time) error {
updateCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
set := bson.M{
"lastStatus": status,
"updatedAt": time.Now(),
}
if lastRunAt != nil {
set["lastRunAt"] = *lastRunAt
}
_, err := s.collection.UpdateByID(updateCtx, id, bson.M{
"$set": set,
})
return err
}
func (s *JobConfigStore) UpsertByHandlerKey(ctx context.Context, item *model.JobConfig) error {
upsertCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
now := time.Now()
_, err := s.collection.UpdateOne(
upsertCtx,
bson.M{"handlerKey": item.HandlerKey},
bson.M{
"$set": bson.M{
"name": item.Name,
"handlerKey": item.HandlerKey,
"scheduleType": item.ScheduleType,
"scheduleValue": item.ScheduleValue,
"defaultParams": item.DefaultParams,
"updatedAt": now,
},
"$setOnInsert": bson.M{
"enabled": false,
"lastStatus": "idle",
"createdAt": now,
},
},
options.Update().SetUpsert(true),
)
return err
}
func (s *JobConfigStore) UpdateNextRunAt(ctx context.Context, id primitive.ObjectID, nextRunAt *time.Time) error {
updateCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
set := bson.M{
"updatedAt": time.Now(),
}
if nextRunAt != nil {
set["nextRunAt"] = *nextRunAt
} else {
set["nextRunAt"] = nil
}
_, err := s.collection.UpdateByID(updateCtx, id, bson.M{
"$set": set,
})
return err
}

View File

@@ -0,0 +1,109 @@
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 JobExecutionStore struct {
collection *mongodriver.Collection
}
func NewJobExecutionStore(db *mongodriver.Database) *JobExecutionStore {
return &JobExecutionStore{
collection: db.Collection("job_executions"),
}
}
func (s *JobExecutionStore) List(ctx context.Context) ([]model.JobExecution, 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: "createdAt", Value: -1}}),
)
if err != nil {
return nil, err
}
defer cursor.Close(findCtx)
items := make([]model.JobExecution, 0)
for cursor.Next(findCtx) {
var item model.JobExecution
if err := cursor.Decode(&item); err != nil {
return nil, err
}
items = append(items, item)
}
if err := cursor.Err(); err != nil {
return nil, err
}
return items, nil
}
func (s *JobExecutionStore) GetByID(ctx context.Context, id primitive.ObjectID) (*model.JobExecution, error) {
findCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
var item model.JobExecution
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 *JobExecutionStore) Create(ctx context.Context, item *model.JobExecution) error {
insertCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
if item.CreatedAt.IsZero() {
item.CreatedAt = time.Now()
}
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 *JobExecutionStore) UpdateResult(ctx context.Context, item *model.JobExecution) error {
updateCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
_, err := s.collection.UpdateByID(updateCtx, item.ID, bson.M{
"$set": bson.M{
"status": item.Status,
"startedAt": item.StartedAt,
"finishedAt": item.FinishedAt,
"durationMs": item.DurationMs,
"resultSummary": item.ResultSummary,
"errorMessage": item.ErrorMessage,
"logText": item.LogText,
"logFile": item.LogFile,
},
})
return err
}

View File

@@ -0,0 +1,113 @@
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 SystemConfigStore struct {
collection *mongodriver.Collection
}
func NewSystemConfigStore(db *mongodriver.Database) *SystemConfigStore {
return &SystemConfigStore{
collection: db.Collection("system_configs"),
}
}
func (s *SystemConfigStore) List(ctx context.Context) ([]model.SystemConfig, 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.SystemConfig, 0)
for cursor.Next(findCtx) {
var item model.SystemConfig
if err := cursor.Decode(&item); err != nil {
return nil, err
}
items = append(items, item)
}
if err := cursor.Err(); err != nil {
return nil, err
}
return items, nil
}
func (s *SystemConfigStore) GetByID(ctx context.Context, id primitive.ObjectID) (*model.SystemConfig, error) {
findCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
var item model.SystemConfig
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 *SystemConfigStore) Create(ctx context.Context, item *model.SystemConfig) error {
insertCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
now := time.Now()
item.CreatedAt = now
item.UpdatedAt = now
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 *SystemConfigStore) Update(ctx context.Context, item *model.SystemConfig) 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{
"key": item.Key,
"title": item.Title,
"value": item.Value,
"valueType": item.ValueType,
"description": item.Description,
"enabled": item.Enabled,
"updatedAt": item.UpdatedAt,
},
})
return err
}
func (s *SystemConfigStore) ToggleEnabled(ctx context.Context, id primitive.ObjectID, enabled bool) error {
updateCtx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
_, err := s.collection.UpdateByID(updateCtx, id, bson.M{
"$set": bson.M{
"enabled": enabled,
"updatedAt": time.Now(),
},
})
return err
}