TinySkin/service/admin.go
2023-11-24 15:51:55 +08:00

202 lines
4.8 KiB
Go

package service
import (
"context"
"errors"
"fmt"
"strconv"
"github.com/xmdhs/authlib-skin/config"
"github.com/xmdhs/authlib-skin/db/cache"
"github.com/xmdhs/authlib-skin/db/ent"
"github.com/xmdhs/authlib-skin/db/ent/predicate"
"github.com/xmdhs/authlib-skin/db/ent/user"
"github.com/xmdhs/authlib-skin/db/ent/userprofile"
"github.com/xmdhs/authlib-skin/db/ent/usertoken"
"github.com/xmdhs/authlib-skin/model"
"github.com/xmdhs/authlib-skin/model/yggdrasil"
"github.com/xmdhs/authlib-skin/service/auth"
utilsService "github.com/xmdhs/authlib-skin/service/utils"
"github.com/xmdhs/authlib-skin/utils"
)
type AdminService struct {
authService *auth.AuthService
client *ent.Client
config config.Config
cache cache.Cache
}
func NewAdminService(authService *auth.AuthService, client *ent.Client,
config config.Config, cache cache.Cache) *AdminService {
return &AdminService{
authService: authService,
client: client,
config: config,
cache: cache,
}
}
var ErrNotAdmin = errors.New("无权限")
func (w *AdminService) Auth(ctx context.Context, token string) (*model.TokenClaims, error) {
t, err := w.authService.Auth(ctx, yggdrasil.ValidateToken{AccessToken: token}, false)
if err != nil {
return nil, fmt.Errorf("WebService.Auth: %w", err)
}
return t, nil
}
func (w *AdminService) IsAdmin(ctx context.Context, t *model.TokenClaims) error {
u, err := w.client.User.Query().Where(user.ID(t.UID)).First(ctx)
if err != nil {
return fmt.Errorf("IsAdmin: %w", err)
}
if !auth.IsAdmin(u.State) {
return fmt.Errorf("IsAdmin: %w", ErrNotAdmin)
}
return nil
}
func (w *AdminService) ListUser(ctx context.Context, page int, email, name string) ([]model.UserList, int, error) {
whereL := []predicate.User{}
if email != "" {
whereL = append(whereL, user.EmailHasPrefix(email))
}
if name != "" {
whereL = append(whereL, user.HasProfileWith(userprofile.NameHasPrefix(name)))
}
u, err := w.client.User.Query().WithProfile().
Where(user.And(whereL...)).
Limit(20).Offset((page - 1) * 20).All(ctx)
if err != nil {
return nil, 0, fmt.Errorf("ListUser: %w", err)
}
ul := make([]model.UserList, 0, len(u))
for _, v := range u {
if v.Edges.Profile == nil {
continue
}
ul = append(ul, model.UserList{
UserInfo: model.UserInfo{
UID: v.ID,
UUID: v.Edges.Profile.UUID,
IsAdmin: auth.IsAdmin(v.State),
},
Email: v.Email,
RegIp: v.RegIP,
Name: v.Edges.Profile.Name,
IsDisable: auth.IsDisable(v.State),
})
}
uc, err := w.client.User.Query().Where(user.And(whereL...)).Count(ctx)
if err != nil {
return nil, 0, fmt.Errorf("ListUser: %w", err)
}
return ul, uc, nil
}
func (w *AdminService) EditUser(ctx context.Context, u model.EditUser, uid int) error {
uuid := ""
changePasswd := false
err := utils.WithTx(ctx, w.client, func(tx *ent.Tx) error {
upUser := tx.User.UpdateOneID(uid)
if u.Email != "" {
c, err := tx.User.Query().Where(user.Email(u.Email)).Count(ctx)
if err != nil {
return err
}
if c != 0 {
return ErrExistUser
}
upUser = upUser.SetEmail(u.Email)
}
if u.Name != "" {
c, err := tx.UserProfile.Query().Where(userprofile.Name(u.Name)).Count(ctx)
if err != nil {
return err
}
if c != 0 {
return ErrExitsName
}
err = tx.UserProfile.Update().Where(userprofile.HasUserWith(user.ID(uid))).SetName(u.Name).Exec(ctx)
if err != nil {
return err
}
}
if u.DelTextures {
userProfile, err := tx.UserProfile.Query().Where(userprofile.ID(uid)).First(ctx)
if err != nil {
return err
}
uuid = userProfile.UUID
tl := []string{"skin", "cape"}
for _, v := range tl {
err := utilsService.DelTexture(ctx, userProfile.ID, v, tx.Client(), w.config.TexturePath)
if err != nil {
return err
}
}
}
aUser, err := tx.User.Get(ctx, uid)
if err != nil {
return err
}
state := aUser.State
if u.IsAdmin != nil {
state = auth.SetAdmin(state, *u.IsAdmin)
}
if u.IsDisable != nil {
if *u.IsDisable {
changePasswd = true
}
state = auth.SetDisable(state, *u.IsDisable)
}
if state != aUser.State {
upUser = upUser.SetState(state)
}
if u.Password != "" {
pass, salt := utils.Argon2ID(u.Password)
upUser = upUser.SetPassword(pass).SetSalt(salt)
changePasswd = true
}
err = upUser.Exec(ctx)
if err != nil {
return err
}
if changePasswd {
err = tx.UserToken.Update().Where(usertoken.HasUserWith(user.ID(uid))).AddTokenID(1).Exec(ctx)
if err != nil {
return err
}
}
return nil
})
if err != nil {
return fmt.Errorf("EditUser: %w", err)
}
if uuid != "" {
err = w.cache.Del([]byte("Profile" + uuid))
if err != nil {
return fmt.Errorf("EditUser: %w", err)
}
}
if changePasswd {
err = w.cache.Del([]byte("auth" + strconv.Itoa(uid)))
if err != nil {
return fmt.Errorf("EditUser: %w", err)
}
}
return nil
}