| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486 |
- package service
- import (
- "context"
- "errors"
- "fmt"
- "sort"
- "strconv"
- "strings"
- "time"
- "dsbqj-admin/app/task"
- "dsbqj-admin/model/mongo/abver"
- "dsbqj-admin/model/mongo/md5"
- "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"
- "go.mongodb.org/mongo-driver/mongo"
- "go.mongodb.org/mongo-driver/mongo/options"
- )
- const versionExternalReqTimeoutSec = 30 * 60
- type VersionReloadService struct {
- }
- func (service *VersionReloadService) Reload() error {
- task.VersionTask.Exec()
- return nil
- }
- type VersionServerService struct {
- Platform string `json:"platform"`
- LegacyChannel string `json:"channel"`
- }
- func (service *VersionServerService) Servers() ([]*version.Version, error) {
- platform := resolvePlatform(service.Platform, service.LegacyChannel)
- if platform == "" {
- return nil, errors.New("平台不能为空")
- }
- items := task.VersionTask.Servers(platform)
- result := make([]*version.Version, 0, len(items))
- for _, item := range items {
- result = append(result, versionWithConfig(item, platform, task.NormalizeEnvVersion(item.EnvVersion)))
- }
- return result, nil
- }
- type VersionCheckService struct {
- Version string `json:"version"`
- Platform string `json:"platform"`
- LegacyChannel string `json:"channel"`
- EnvVersion string `json:"envVersion"`
- }
- func (service *VersionCheckService) Check() (*version.Version, error) {
- platform := resolvePlatform(service.Platform, service.LegacyChannel)
- if platform == "" {
- return nil, errors.New("平台不能为空")
- }
- result := task.VersionTask.Check(service.Version, platform, service.EnvVersion)
- if result == nil {
- return nil, nil
- }
- return versionWithConfig(result, platform, task.NormalizeEnvVersion(result.EnvVersion)), nil
- }
- func versionWithConfig(item *version.Version, platform, env string) *version.Version {
- result := *item
- abVer := task.VersionConfigTask.GetAbVer(platform, env)
- md5 := task.VersionConfigTask.GetMD5(platform, env)
- result.AbVer, result.AbVerVersion = abVer.Value, abVer.Version
- result.MD5, result.MD5Version = md5.Value, md5.Version
- return &result
- }
- func resolvePlatform(platform, legacyChannel string) string {
- if value := strings.TrimSpace(platform); value != "" {
- return value
- }
- return strings.TrimSpace(legacyChannel)
- }
- type VersionShowService struct {
- CondPage
- Platform string `form:"platform" json:"platform"`
- EnvVersion string `form:"envVersion" json:"envVersion"`
- }
- func (service *VersionShowService) List() ([]version.Version, error) {
- versions := make([]version.Version, 0)
- var queryDoc = bson.M{}
- clauses := make([]bson.M, 0, 2)
- if service.Platform != "" {
- clauses = append(clauses, bson.M{"$or": []bson.M{{"platform": service.Platform}, {"platform": ""}, {"platform": bson.M{"$exists": false}}}})
- }
- if service.EnvVersion != "" {
- envVersion := task.NormalizeEnvVersion(service.EnvVersion)
- if envVersion == "release" {
- clauses = append(clauses, bson.M{"$or": []bson.M{
- {"envVersion": envVersion},
- {"envVersion": ""},
- {"envVersion": bson.M{"$exists": false}},
- }})
- } else {
- clauses = append(clauses, bson.M{"envVersion": envVersion})
- }
- }
- if len(clauses) > 0 {
- queryDoc["$and"] = clauses
- }
- err := mgm.Coll(&version.Version{}).SimpleFind(&versions, queryDoc)
- return versions, err
- }
- type VersionCreateService struct {
- Platform string `json:"platform" 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 {
- envVersion := task.NormalizeEnvVersion(service.EnvVersion)
- var exists version.Version
- err := mgm.Coll(&version.Version{}).First(versionIdentityFilter(service.Platform, service.Version, envVersion), &exists)
- if err == nil {
- return errors.New("该平台、环境和版本号已存在")
- }
- if !errors.Is(err, mongo.ErrNoDocuments) {
- return err
- }
- version := new(version.Version)
- version.Platform = service.Platform
- version.EnvVersion = envVersion
- version.Name = service.Name
- version.Version = service.Version
- version.CDN = service.CDN
- version.Url = service.Url
- if err := mgm.Coll(version).Create(version); err != nil {
- return err
- }
- task.VersionTask.Exec()
- return nil
- }
- type VersionEditService struct {
- Id string `json:"id" binding:"required"`
- Platform *string `json:"platform"`
- 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 {
- objectId, _ := primitive.ObjectIDFromHex(service.Id)
- coll := mgm.Coll(&version.Version{})
- var current version.Version
- if err := coll.FindByID(objectId, ¤t); err != nil {
- return err
- }
- platform, envVersion, versionNumber := current.Platform, task.NormalizeEnvVersion(current.EnvVersion), current.Version
- if service.Platform != nil {
- platform = strings.TrimSpace(*service.Platform)
- }
- if service.EnvVersion != nil {
- envVersion = task.NormalizeEnvVersion(*service.EnvVersion)
- }
- if service.Version != nil {
- versionNumber = *service.Version
- }
- var duplicate version.Version
- duplicateFilter := versionIdentityFilter(platform, versionNumber, envVersion)
- duplicateFilter["_id"] = bson.M{"$ne": objectId}
- if err := coll.First(duplicateFilter, &duplicate); err == nil {
- return errors.New("该平台、环境和版本号已存在")
- } else if !errors.Is(err, mongo.ErrNoDocuments) {
- return err
- }
- filterDoc := bson.M{"_id": objectId}
- updateDoc := bson.M{}
- if service.Platform != nil {
- updateDoc["platform"] = platform
- }
- 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 := coll.UpdateOne(context.Background(), filterDoc, bson.M{"$set": updateDoc})
- if err != nil {
- return err
- }
- task.VersionTask.Exec()
- return nil
- }
- func versionIdentityFilter(platform, versionNumber, envVersion string) bson.M {
- filter := bson.M{"platform": platform, "version": versionNumber}
- if task.NormalizeEnvVersion(envVersion) == "release" {
- filter["$or"] = []bson.M{{"envVersion": "release"}, {"envVersion": ""}, {"envVersion": bson.M{"$exists": false}}}
- } else {
- filter["envVersion"] = "trial"
- }
- return filter
- }
- 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 {
- scope := versionIdentityFilter(current.Platform, "", current.EnvVersion)
- delete(scope, "version")
- scope["_id"] = bson.M{"$ne": objectId}
- if _, err := coll.UpdateMany(
- context.Background(),
- scope,
- 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 {
- Platform string `form:"platform" json:"platform" 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"`
- }
- type VersionConfigUploadService struct {
- Platform string `form:"platform" json:"platform" binding:"required"`
- Version string `form:"version" json:"version" binding:"required"`
- Value string `form:"value" json:"value" binding:"required"`
- TimeSec int64 `form:"timesec" json:"timesec" binding:"required"`
- Sign string `form:"sign" json:"sign" binding:"required"`
- }
- type VersionConfigManageService struct {
- Type string `json:"type" form:"type" binding:"required"`
- ID string `json:"id"`
- PlatformFilter string `json:"-"`
- Version string `json:"version"`
- Value *string `json:"value"`
- EnvVersions *[]string `json:"envVersions"`
- External *bool `json:"external"`
- }
- func configCollection(configType string) interface{} {
- if configType == "md5" {
- return &md5.MD5{}
- }
- return &abver.AbVer{}
- }
- func (service *VersionConfigManageService) List() (interface{}, error) {
- items := make([]interface{}, 0)
- filter := bson.M{}
- if service.PlatformFilter != "" {
- filter["$or"] = []bson.M{{"platform": service.PlatformFilter}, {"platform": ""}, {"platform": bson.M{"$exists": false}}}
- }
- if service.Type == "md5" {
- result := make([]md5.MD5, 0)
- err := mgm.Coll(&md5.MD5{}).SimpleFind(&result, filter)
- sort.SliceStable(result, func(i, j int) bool {
- return task.CompareConfigVersion(result[i].Version, result[j].Version) > 0
- })
- for i := range result {
- items = append(items, result[i])
- }
- return items, err
- }
- result := make([]abver.AbVer, 0)
- err := mgm.Coll(&abver.AbVer{}).SimpleFind(&result, filter)
- sort.SliceStable(result, func(i, j int) bool {
- return task.CompareConfigVersion(result[i].Version, result[j].Version) > 0
- })
- for i := range result {
- items = append(items, result[i])
- }
- return items, err
- }
- func (service *VersionConfigManageService) Save() error {
- if service.ID == "" {
- return errors.New("配置记录编号不能为空")
- }
- id, err := primitive.ObjectIDFromHex(service.ID)
- if err != nil {
- return err
- }
- update := bson.M{}
- if service.Value != nil {
- update["value"] = *service.Value
- }
- if service.EnvVersions != nil {
- update["envVersions"] = *service.EnvVersions
- }
- if service.External != nil {
- update["external"] = *service.External
- }
- if len(update) == 0 {
- return errors.New("没有需要更新的内容")
- }
- if service.Type == "md5" {
- _, err = mgm.Coll(&md5.MD5{}).UpdateOne(context.Background(), bson.M{"_id": id}, bson.M{"$set": update})
- if err == nil {
- task.VersionConfigTask.Reload()
- }
- return err
- }
- _, err = mgm.Coll(&abver.AbVer{}).UpdateOne(context.Background(), bson.M{"_id": id}, bson.M{"$set": update})
- if err == nil {
- task.VersionConfigTask.Reload()
- }
- return err
- }
- func (service *VersionConfigUploadService) ValidateAuth() error {
- deltaTime := time.Now().Unix() - service.TimeSec
- if deltaTime < 0 {
- deltaTime = -deltaTime
- }
- if deltaTime > versionExternalReqTimeoutSec {
- return errors.New("时间戳已过期")
- }
- params := map[string]any{"platform": service.Platform, "version": service.Version, "value": service.Value, "timesec": strconv.FormatInt(service.TimeSec, 10)}
- if tool.GenSign(params) != service.Sign {
- return errors.New("签名错误")
- }
- return nil
- }
- func (service *VersionConfigUploadService) SaveAbVer() error {
- var exists abver.AbVer
- filter := bson.M{"platform": service.Platform, "version": service.Version}
- if err := mgm.Coll(&abver.AbVer{}).First(filter, &exists); err == nil {
- return errors.New("abVer 配置版本已存在,不能重复上报")
- }
- item := &abver.AbVer{Platform: service.Platform, Version: service.Version, Value: service.Value, External: false}
- _, err := mgm.Coll(item).UpdateOne(context.Background(), filter, bson.M{"$set": item}, options.Update().SetUpsert(true))
- if err == nil {
- task.VersionConfigTask.Reload()
- }
- return err
- }
- func (service *VersionConfigUploadService) SaveMD5() error {
- var exists md5.MD5
- filter := bson.M{"platform": service.Platform, "version": service.Version}
- if err := mgm.Coll(&md5.MD5{}).First(filter, &exists); err == nil {
- return errors.New("md5 配置版本已存在,不能重复上报")
- }
- item := &md5.MD5{Platform: service.Platform, Version: service.Version, Value: service.Value, External: false}
- _, err := mgm.Coll(item).UpdateOne(context.Background(), filter, bson.M{"$set": item}, options.Update().SetUpsert(true))
- if err == nil {
- task.VersionConfigTask.Reload()
- }
- return err
- }
- func (service *VersionExternalConfigService) Save() error {
- if service.AbVer == nil && service.MD5 == nil {
- return errors.New("abVer or md5 is required")
- }
- filterDoc := bson.M{
- "platform": service.Platform,
- "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")
- }
- 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{
- "platform": service.Platform,
- "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)
- if err != nil {
- return err
- }
- task.VersionTask.Exec()
- return nil
- }
|