-
Notifications
You must be signed in to change notification settings - Fork 0
/
auth.go
101 lines (85 loc) · 2.98 KB
/
auth.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package auth
import (
"context"
"encoding/json"
"errors"
authorizationDB "github.com/duyquang6/go-rbac-practice/internal/authorization/database"
userDB "github.com/duyquang6/go-rbac-practice/internal/user/database"
"github.com/gorilla/sessions"
"github.com/duyquang6/go-rbac-practice/pkg/bcrypt"
"github.com/duyquang6/go-rbac-practice/pkg/dto"
"github.com/duyquang6/go-rbac-practice/pkg/logging"
"github.com/duyquang6/go-rbac-practice/pkg/rbac"
)
type AuthService interface {
Login(ctx context.Context, session *sessions.Session, req dto.LoginRequest) error
ClearSession(ctx context.Context, session *sessions.Session)
GetSessionData(ctx context.Context, session *sessions.Session) (SessionData, error)
}
type authService struct {
userRepo userDB.UserRepository
authorizationRepo authorizationDB.AuthorizationRepository
}
func New(userRepo userDB.UserRepository, authorizationRepo authorizationDB.AuthorizationRepository) *authService {
return &authService{
userRepo: userRepo,
authorizationRepo: authorizationRepo,
}
}
func (s *authService) Login(ctx context.Context, session *sessions.Session, req dto.LoginRequest) error {
logger := logging.FromContext(ctx).Named("auth.Login")
user, err := s.userRepo.GetByUsername(ctx, req.Username)
if err != nil {
s.ClearSession(ctx, session)
logger.Error("get user failed: ", err)
return err
}
if !bcrypt.CheckPasswordHash(req.Password, user.Password) {
return errors.New("invalid password")
}
// Get permission
permissionData := make(rbac.PermissionMapping)
permissions, err := s.authorizationRepo.GetPermissionByUserID(ctx, int64(user.ID))
if err != nil {
s.ClearSession(ctx, session)
logger.Error("get permission failed: ", err)
return err
}
for _, perm := range permissions {
permissionData[perm.Object] = rbac.AddImplied(perm.Object, permissionData[perm.Object], perm.Code)
}
// store session
sessionData, err := json.Marshal(&SessionData{
Username: user.Username,
Permission: permissionData,
})
if err != nil {
s.ClearSession(ctx, session)
logger.Error("marshal sesssion data failed: ", err)
return err
}
if err = sessionSet(session, sessionDataKey, sessionData); err != nil {
s.ClearSession(ctx, session)
logger.Error("store session failed: ", err)
return err
}
return nil
}
func (s *authService) GetSessionData(ctx context.Context, session *sessions.Session) (SessionData, error) {
logger := logging.FromContext(ctx).Named("auth.GetSessionData")
data := sessionGet(session, sessionDataKey)
if data == nil {
logger.Error("session data empty")
return SessionData{}, errors.New("session data empty")
}
var sessionData SessionData
if err := json.Unmarshal(data.([]byte), &sessionData); err != nil {
logger.Error("data parse failed:", err)
return SessionData{}, err
}
return sessionData, nil
}
// ClearSession removes any session information for this auth.
func (a *authService) ClearSession(ctx context.Context, session *sessions.Session) {
sessionClear(session, sessionDataKey)
}