gitee.com/woood2/luca@v1.0.4/internal/service/app.go (about) 1 package service 2 3 import ( 4 "context" 5 "gitee.com/woood2/luca/internal/cache" 6 "gitee.com/woood2/luca/internal/errcode" 7 "gitee.com/woood2/luca/internal/layer" 8 "gitee.com/woood2/luca/internal/repository" 9 "go.uber.org/zap" 10 "gorm.io/gorm" 11 "time" 12 ) 13 14 type App struct { 15 ID int 16 Appkey string 17 Secret string 18 Name string 19 Url string 20 Logo string 21 Contacts string 22 Disabled int 23 Createtime time.Time 24 Updatetime time.Time 25 Remark string 26 } 27 28 type AppService interface { 29 //errcode.AppKeyAlreadyExists 30 //errcode.AppNameAlreadyExists 31 Create(ctx context.Context, dto *App) (id int, err error) 32 33 Twins(ctx context.Context) error 34 35 //errcode.AppNotExists 36 //errcode.AppNotAllowedToDelete 37 DeleteByKey(ctx context.Context, appkey string) error 38 39 //errcode.AppNotExists 40 //errcode.AppNotAllowedToChangeDisabled 41 Enable(ctx context.Context, appkey string) error 42 43 //errcode.AppNotExists 44 //errcode.AppNotAllowedToChangeDisabled 45 Disable(ctx context.Context, appkey string) error 46 47 //errcode.AppNotExists 48 //errcode.AppNameAlreadyExists 49 EditByKey(ctx context.Context, appkey string, dto *App) error 50 51 //errcode.AppNotExists 52 GetByKey(ctx context.Context, appkey string) (*App, error) 53 54 //errcode.AppNotExists 55 GetByKeyFromCache(ctx context.Context, c cache.Cache, appkey string) (*App, error) 56 57 //errcode.AppNotExists 58 GetByKeyFromCacheSafely(ctx context.Context, c cache.Cache, appkey string) (*App, error) 59 60 List(ctx context.Context, appkey string, name string) ([]*App, error) 61 } 62 63 func NewAppServiceImpl(logger *zap.Logger, db *gorm.DB, 64 repoFactory repository.AppRepoFactory) *AppServiceImpl { 65 return &AppServiceImpl{ 66 Service: layer.Service{Logger: logger}, 67 repo: repoFactory.Produce(logger, db), 68 repoFactory: repoFactory, 69 db: db, 70 } 71 } 72 73 type AppServiceImpl struct { 74 layer.Service 75 repo repository.AppRepo 76 repoFactory repository.AppRepoFactory 77 db *gorm.DB 78 } 79 80 func (svc *AppServiceImpl) Create(ctx context.Context, dto *App) (id int, err error) { 81 if ok, err := svc.repo.ExistByKey(ctx, dto.Appkey); err != nil { 82 return 0, err 83 } else if ok { 84 return 0, errcode.AppKeyAlreadyExists 85 } 86 if ok, err := svc.repo.ExistByName(ctx, dto.Name); err != nil { 87 return 0, err 88 } else if ok { 89 return 0, errcode.AppNameAlreadyExists 90 } 91 app := &repository.App{ 92 Appkey: dto.Appkey, 93 Secret: dto.Secret, 94 Name: dto.Name, 95 Url: dto.Url, 96 Logo: dto.Logo, 97 Contacts: dto.Contacts, 98 Disabled: dto.Disabled, 99 Remark: dto.Remark, 100 } 101 id, err = svc.repo.Create(ctx, app) 102 return 103 } 104 105 func (svc *AppServiceImpl) Twins(ctx context.Context) error { 106 saga := &repository.App{ 107 Appkey: "saga", 108 Secret: "13", 109 Name: "撒加", 110 } 111 kanon := &repository.App{ 112 Appkey: "kanon", 113 Secret: "North Atlantic", 114 Name: "加隆", 115 } 116 err := svc.db.Transaction(func(tx *gorm.DB) error { 117 repo := svc.repoFactory.Produce(svc.Logger, tx) 118 if _, err := repo.Create(ctx, saga); err != nil { 119 return err 120 } 121 if _, err := repo.Create(ctx, kanon); err != nil { 122 return err 123 } 124 return nil 125 }) 126 return err 127 } 128 129 func (svc *AppServiceImpl) DeleteByKey(ctx context.Context, appkey string) error { 130 app, err := svc.repo.GetByKey(ctx, appkey) 131 if err != nil { 132 return err 133 } 134 if time.Now().After(app.Createtime.Add(2 * time.Hour)) { 135 return errcode.AppNotAllowedToDelete 136 } 137 return svc.repo.Delete(ctx, app) 138 } 139 140 func (svc *AppServiceImpl) Enable(ctx context.Context, appkey string) error { 141 user, err := svc.repo.GetByKey(ctx, appkey) 142 if err != nil { 143 return err 144 } 145 if user.Disabled == 0 { 146 return errcode.AppNotAllowedToChangeDisabled 147 } 148 return svc.repo.SetDisabled(ctx, appkey, 0) 149 } 150 151 func (svc *AppServiceImpl) Disable(ctx context.Context, appkey string) error { 152 user, err := svc.repo.GetByKey(ctx, appkey) 153 if err != nil { 154 return err 155 } 156 if user.Disabled == 1 { 157 return errcode.AppNotAllowedToChangeDisabled 158 } 159 return svc.repo.SetDisabled(ctx, appkey, 1) 160 } 161 162 func (svc *AppServiceImpl) EditByKey(ctx context.Context, appkey string, dto *App) error { 163 app, err := svc.repo.GetByKey(ctx, appkey) 164 if err != nil { 165 return err 166 } 167 if dto.Name != app.Name { 168 if ok, err := svc.repo.ExistByName(ctx, dto.Name); err != nil { 169 return err 170 } else if ok { 171 return errcode.AppNameAlreadyExists 172 } 173 } 174 now := time.Now() 175 app.Updatetime = now 176 177 app.Secret = dto.Secret 178 app.Name = dto.Name 179 app.Url = dto.Url 180 app.Logo = dto.Logo 181 app.Contacts = dto.Contacts 182 app.Remark = dto.Remark 183 184 return svc.repo.Edit(ctx, app) 185 } 186 187 func (svc *AppServiceImpl) GetByKey(ctx context.Context, appkey string) (*App, error) { 188 app, err := svc.repo.GetByKey(ctx, appkey) 189 if err != nil { 190 return nil, err 191 } 192 193 return &App{ 194 ID: app.ID, 195 Appkey: app.Appkey, 196 Secret: app.Secret, 197 Name: app.Name, 198 Url: app.Url, 199 Logo: app.Logo, 200 Contacts: app.Contacts, 201 Disabled: app.Disabled, 202 Createtime: app.Createtime, 203 Updatetime: app.Updatetime, 204 Remark: app.Remark, 205 }, nil 206 } 207 208 /** 209 Mainly used in auth scene 210 [error] 211 errcode.AppNotExists not exist in DB 212 ...other errors 213 */ 214 func (svc *AppServiceImpl) GetByKeyFromCache(ctx context.Context, c cache.Cache, appkey string) (*App, error) { 215 k := cache.App.BuildKey(appkey) 216 var v *App 217 if e := c.Get(k, &v); e != nil { 218 //miss 219 if e == c.Miss() { 220 //exist 221 app, err := svc.GetByKey(ctx, appkey) 222 if err == nil { 223 if err := c.Set(k, app, cache.App.Duration); err != nil { 224 return nil, err 225 } else { 226 return app, nil 227 } 228 } 229 //not exist 230 if err == errcode.AppNotExists { 231 if err := c.Set(k, nil, cache.App.Duration); err != nil { 232 return nil, err 233 } else { 234 return nil, errcode.AppNotExists 235 } 236 } 237 //other errors 238 return nil, err 239 } 240 //other errors 241 return nil, e 242 } 243 //hit 244 if v == nil { 245 return nil, errcode.AppNotExists 246 } 247 return v, nil 248 } 249 250 /** 251 Mainly used in auth scene 252 Safe mode to prevent avalanches 253 [error] 254 errcode.AppNotExists not exist in DB 255 ...other errors 256 */ 257 func (svc *AppServiceImpl) GetByKeyFromCacheSafely(ctx context.Context, c cache.Cache, appkey string) (*App, error) { 258 k := cache.App.BuildKey(appkey) 259 var v *App 260 if e := c.Get(k, &v); e != nil { 261 //miss 262 if e == c.Miss() { 263 ok, ch, er := c.ApplyToSet(k) 264 if er != nil { 265 return nil, er 266 } 267 if ok { 268 defer func() { 269 close(ch) 270 c.Release(k) 271 }() 272 app, err := svc.GetByKey(ctx, appkey) 273 //exist 274 if err == nil { 275 if err := c.Set(k, app, cache.App.Duration); err != nil { 276 return nil, err 277 } 278 return app, nil 279 } 280 //not exist 281 if err == errcode.AppNotExists { 282 if err := c.Set(k, nil, cache.App.Duration); err != nil { 283 return nil, err 284 } 285 return nil, errcode.AppNotExists 286 } 287 //other errors 288 return nil, err 289 } 290 <-ch 291 var v *App 292 if e := c.Get(k, &v); e != nil { 293 return nil, e 294 } 295 if v == nil { 296 return nil, errcode.AppNotExists 297 } 298 return v, nil 299 } 300 //other errors 301 return nil, e 302 } 303 //hit 304 if v == nil { 305 return nil, errcode.AppNotExists 306 } 307 return v, nil 308 } 309 310 func (svc *AppServiceImpl) List(ctx context.Context, appkey string, name string) ([]*App, error) { 311 apps, err := svc.repo.List(ctx, appkey, name) 312 if err != nil { 313 return nil, err 314 } 315 316 var dtos []*App 317 for _, app := range apps { 318 dtos = append(dtos, &App{ 319 ID: app.ID, 320 Appkey: app.Appkey, 321 Secret: app.Secret, 322 Name: app.Name, 323 Url: app.Url, 324 Logo: app.Logo, 325 Contacts: app.Contacts, 326 Disabled: app.Disabled, 327 Createtime: app.Createtime, 328 Updatetime: app.Updatetime, 329 Remark: app.Remark, 330 }) 331 } 332 return dtos, nil 333 }