mirror of
https://github.com/get-drexa/drive.git
synced 2025-11-30 21:41:39 +00:00
113 lines
2.1 KiB
Go
113 lines
2.1 KiB
Go
|
|
package auth
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"encoding/hex"
|
||
|
|
"errors"
|
||
|
|
|
||
|
|
"github.com/uptrace/bun"
|
||
|
|
)
|
||
|
|
|
||
|
|
type LoginResult struct {
|
||
|
|
User User
|
||
|
|
AccessToken string
|
||
|
|
RefreshToken string
|
||
|
|
}
|
||
|
|
|
||
|
|
var ErrInvalidCredentials = errors.New("invalid credentials")
|
||
|
|
var ErrUserExists = errors.New("user already exists")
|
||
|
|
|
||
|
|
type Service struct {
|
||
|
|
db *bun.DB
|
||
|
|
tokenConfig TokenConfig
|
||
|
|
}
|
||
|
|
|
||
|
|
type registerOptions struct {
|
||
|
|
displayName string
|
||
|
|
email string
|
||
|
|
password string
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewService(db *bun.DB, tokenConfig TokenConfig) *Service {
|
||
|
|
return &Service{
|
||
|
|
db: db,
|
||
|
|
tokenConfig: tokenConfig,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *Service) LoginWithEmailAndPassword(ctx context.Context, email, password string) (*LoginResult, error) {
|
||
|
|
var user User
|
||
|
|
|
||
|
|
err := s.db.NewSelect().Model(&user).Where("email = ?", email).Scan(ctx)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
ok, err := VerifyPassword(password, user.Password)
|
||
|
|
if err != nil || !ok {
|
||
|
|
return nil, ErrInvalidCredentials
|
||
|
|
}
|
||
|
|
|
||
|
|
at, err := GenerateAccessToken(&user, &s.tokenConfig)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
rt, err := GenerateRefreshToken(&user, &s.tokenConfig)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
_, err = s.db.NewInsert().Model(rt).Exec(ctx)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
return &LoginResult{
|
||
|
|
User: user,
|
||
|
|
AccessToken: at,
|
||
|
|
RefreshToken: hex.EncodeToString(rt.Token),
|
||
|
|
}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *Service) Register(ctx context.Context, opts registerOptions) (*LoginResult, error) {
|
||
|
|
user := User{
|
||
|
|
Email: opts.email,
|
||
|
|
DisplayName: opts.displayName,
|
||
|
|
}
|
||
|
|
|
||
|
|
exists, err := s.db.NewSelect().Model(&user).Where("email = ?", opts.email).Exists(ctx)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
if exists {
|
||
|
|
return nil, ErrUserExists
|
||
|
|
}
|
||
|
|
|
||
|
|
user.Password, err = HashPassword(opts.password)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
_, err = s.db.NewInsert().Model(&user).Exec(ctx)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
at, err := GenerateAccessToken(&user, &s.tokenConfig)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
rt, err := GenerateRefreshToken(&user, &s.tokenConfig)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
return &LoginResult{
|
||
|
|
User: user,
|
||
|
|
AccessToken: at,
|
||
|
|
RefreshToken: hex.EncodeToString(rt.Token),
|
||
|
|
}, nil
|
||
|
|
}
|