package service import ( "context" "time" "git.nobla.cn/golang/aeus-admin/models" "git.nobla.cn/golang/aeus-admin/pb" "git.nobla.cn/golang/aeus-admin/types" "git.nobla.cn/golang/aeus/metadata" "git.nobla.cn/golang/aeus/pkg/errors" jwt "github.com/golang-jwt/jwt/v5" "github.com/mssola/useragent" "gorm.io/gorm" ) type ( authOptions struct { db *gorm.DB secret []byte method string ttl int64 } AuthOption func(o *authOptions) AuthService struct { opts *authOptions } ) func WithAuthDB(db *gorm.DB) AuthOption { return func(o *authOptions) { o.db = db } } func WithAuthSecret(secret []byte) AuthOption { return func(o *authOptions) { o.secret = secret } } func WithAuthMethod(method string) AuthOption { return func(o *authOptions) { o.method = method } } func WithAuthTTL(ttl int64) AuthOption { return func(o *authOptions) { o.ttl = ttl } } func (s *AuthService) Login(ctx context.Context, req *pb.LoginRequest) (res *pb.LoginResponse, err error) { model := &models.User{} tx := s.opts.db.WithContext(ctx) if err = req.Validate(); err != nil { return nil, errors.Format(errors.Invalid, err.Error()) } if err = model.FindOne(tx, "uid=?", req.Username); err != nil { return nil, errors.ErrAccessDenied } if model.Status != types.UserStatusNormal { return nil, errors.ErrAccessDenied } if model.Password != req.Password { return nil, errors.ErrAccessDenied } claims := types.Claims{ Uid: model.Uid, Role: model.Role, IssuedAt: time.Now().Unix(), ExpirationAt: time.Now().Add(time.Second * time.Duration(s.opts.ttl)).Unix(), } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) res = &pb.LoginResponse{} if res.Token, err = token.SignedString(s.opts.secret); err == nil { res.Uid = model.Uid res.Username = model.Username res.Expires = s.opts.ttl } loginModel := &models.Login{} loginModel.Uid = model.Uid loginModel.AccessToken = res.Token md := metadata.FromContext(ctx) if userAgent, ok := md.Get("User-Agent"); ok { ua := useragent.New(userAgent) loginModel.Os = ua.OS() loginModel.Platform = ua.Platform() loginModel.UserAgent = userAgent browser, browserVersion := ua.Browser() loginModel.Browser = browser + "/" + browserVersion tx.Save(loginModel) } return } func (s *AuthService) Logout(ctx context.Context, req *pb.LogoutRequest) (res *pb.LogoutResponse, err error) { return } func NewAuthService(cbs ...AuthOption) *AuthService { opts := &authOptions{ ttl: 7200, } for _, cb := range cbs { cb(opts) } return &AuthService{ opts: opts, } }