package service import ( "context" "errors" "fmt" "strconv" "time" "dsbqj-admin/app/task" "dsbqj-admin/model/mongo/version" "dsbqj-admin/tool" "github.com/kamva/mgm/v3" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" ) const versionExternalReqTimeoutSec = 30 * 60 type VersionReloadService struct { } func (service *VersionReloadService) Reload() error { task.VersionTask.Exec() return nil } type VersionServerService struct { Channel string `json:"channel" binding:"required"` } func (service *VersionServerService) Servers() ([]*version.Version, error) { return task.VersionTask.Servers(service.Channel), nil } type VersionCheckService struct { Version string `json:"version" binding:"required"` Channel string `json:"channel" binding:"required"` EnvVersion string `json:"envVersion"` } func (service *VersionCheckService) Check() (*version.Version, error) { return task.VersionTask.Check(service.Version, service.Channel, service.EnvVersion), nil } type VersionShowService struct { CondPage Channel string `form:"channel" json:"channel"` EnvVersion string `form:"envVersion" json:"envVersion"` } func (service *VersionShowService) List() ([]version.Version, error) { versions := make([]version.Version, 0) var queryDoc = bson.M{} if service.Channel != "" { queryDoc["channel"] = service.Channel } if service.EnvVersion != "" { envVersion := task.NormalizeEnvVersion(service.EnvVersion) if envVersion == "release" { queryDoc["$or"] = []bson.M{ {"envVersion": envVersion}, {"envVersion": ""}, {"envVersion": bson.M{"$exists": false}}, } } else { queryDoc["envVersion"] = envVersion } } err := mgm.Coll(&version.Version{}).SimpleFind(&versions, queryDoc) return versions, err } type VersionCreateService struct { Channel string `json:"channel" binding:"required"` EnvVersion string `json:"envVersion"` Version string `json:"version" binding:"required"` Name string `json:"name" binding:"required"` CDN string `json:"cdn" binding:"required"` Url string `json:"url" binding:"required"` } func (service *VersionCreateService) Create() error { version := new(version.Version) version.Channel = service.Channel version.EnvVersion = task.NormalizeEnvVersion(service.EnvVersion) version.Name = service.Name version.Version = service.Version version.CDN = service.CDN version.Url = service.Url return mgm.Coll(version).Create(version) } type VersionEditService struct { Id string `json:"id" binding:"required"` Channel *string `json:"channel"` EnvVersion *string `json:"envVersion"` Version *string `json:"version"` Name *string `json:"name"` CDN *string `json:"cdn"` Url *string `json:"url"` Default *bool `json:"default"` } func (service *VersionEditService) Edit() error { version := new(version.Version) objectId, _ := primitive.ObjectIDFromHex(service.Id) filterDoc := bson.M{"_id": objectId} updateDoc := bson.M{} if service.Channel != nil { updateDoc["channel"] = service.Channel } if service.EnvVersion != nil { updateDoc["envVersion"] = task.NormalizeEnvVersion(*service.EnvVersion) } if service.Name != nil { updateDoc["name"] = service.Name } if service.Version != nil { updateDoc["version"] = service.Version } if service.CDN != nil { updateDoc["cdn"] = service.CDN } if service.Url != nil { updateDoc["url"] = service.Url } if service.Default != nil { updateDoc["default"] = service.Default } _, err := mgm.Coll(version).UpdateOne(context.Background(), filterDoc, bson.M{"$set": updateDoc}) return err } type VersionProdService struct { Id string `json:"id" binding:"required"` IsProd bool `json:"isProd"` } func (service *VersionProdService) Update() error { objectId, err := primitive.ObjectIDFromHex(service.Id) if err != nil { return err } coll := mgm.Coll(&version.Version{}) var current version.Version if err := coll.FindByID(objectId, ¤t); err != nil { return err } if service.IsProd { if _, err := coll.UpdateMany( context.Background(), bson.M{"_id": bson.M{"$ne": objectId}}, bson.M{"$set": bson.M{"isProd": false}}, ); err != nil { return err } } _, err = coll.UpdateOne( context.Background(), bson.M{"_id": objectId}, bson.M{"$set": bson.M{"isProd": service.IsProd}}, ) return err } type VersionExternalConfigService struct { Channel string `form:"channel" json:"channel" binding:"required"` Version string `form:"version" json:"version" binding:"required"` AbVer *string `form:"abVer" json:"abVer"` MD5 *string `form:"md5" json:"md5"` TimeSec int64 `form:"timesec" json:"timesec" binding:"required"` Sign string `form:"sign" json:"sign" binding:"required"` } func (service *VersionExternalConfigService) Save() error { if service.AbVer == nil && service.MD5 == nil { return errors.New("abVer or md5 is required") } filterDoc := bson.M{ "channel": service.Channel, "version": service.Version, } coll := mgm.Coll(&version.Version{}) var current version.Version if err := coll.First(filterDoc, ¤t); err != nil { return errors.New("version not found") } if current.IsProd { return errors.New("production version does not allow external upload") } updateDoc := bson.M{} if service.AbVer != nil { updateDoc["abVer"] = *service.AbVer } if service.MD5 != nil { updateDoc["md5"] = *service.MD5 } _, err := coll.UpdateOne( context.Background(), bson.M{"_id": current.ID}, bson.M{"$set": updateDoc}, ) return err } func (service *VersionExternalConfigService) ValidateAuth() error { deltaTime := time.Now().Unix() - service.TimeSec if deltaTime < 0 { deltaTime = -deltaTime } if deltaTime > versionExternalReqTimeoutSec { return fmt.Errorf("timesec timeout") } params := map[string]any{ "channel": service.Channel, "version": service.Version, "timesec": strconv.FormatInt(service.TimeSec, 10), } if service.AbVer != nil { params["abVer"] = *service.AbVer } if service.MD5 != nil { params["md5"] = *service.MD5 } sign := tool.GenSign(params) if sign != service.Sign { return fmt.Errorf("sign error") } return nil } type VersionDeleteService struct { Id string `json:"id" binding:"required"` } func (service *VersionDeleteService) Delete() error { version := new(version.Version) objectId, _ := primitive.ObjectIDFromHex(service.Id) filterDoc := bson.M{"_id": objectId} _, err := mgm.Coll(version).DeleteOne(context.Background(), filterDoc) return err }