100 lines
2.4 KiB
Go
100 lines
2.4 KiB
Go
package auth
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
type Manager struct {
|
|
Store *UserStore
|
|
JWT *JWTManager
|
|
Enforcer *EnforcerWrapper
|
|
}
|
|
|
|
func NewManager(jwtSecret string, jwtTTL time.Duration, modelPath, policyPath, userFile string) (*Manager, error) {
|
|
store, err := NewUserStore(userFile)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("init user store: %w", err)
|
|
}
|
|
jwtMgr := NewJWTManager(jwtSecret, jwtTTL)
|
|
enc, err := NewEnforcer(modelPath, policyPath, store)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("init casbin: %w", err)
|
|
}
|
|
m := &Manager{Store: store, JWT: jwtMgr, Enforcer: enc}
|
|
return m, nil
|
|
}
|
|
|
|
func NewManagerWithStore(store *UserStore, jwtSecret string, ttl time.Duration, enforcer *EnforcerWrapper) *Manager {
|
|
return &Manager{
|
|
Store: store,
|
|
JWT: NewJWTManager(jwtSecret, ttl),
|
|
Enforcer: enforcer,
|
|
}
|
|
}
|
|
|
|
func (m *Manager) Login(username, password string) (string, *User, error) {
|
|
u, ok := m.Store.Verify(username, password)
|
|
if !ok {
|
|
return "", nil, fmt.Errorf("invalid credentials")
|
|
}
|
|
_ = m.Enforcer.AddUserRole(u.Username, u.Role)
|
|
token, err := m.JWT.Sign(u.Username, u.Role)
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
ret := &User{Username: u.Username, Role: u.Role, CreatedAt: u.CreatedAt}
|
|
return token, ret, nil
|
|
}
|
|
|
|
func (m *Manager) Register(username, password, role string) (string, *User, error) {
|
|
if role == "" {
|
|
role = RoleViewer
|
|
}
|
|
u, err := m.Store.Create(username, password, role)
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
_ = m.Enforcer.AddUserRole(u.Username, u.Role)
|
|
token, err := m.JWT.Sign(u.Username, u.Role)
|
|
if err != nil {
|
|
return "", nil, err
|
|
}
|
|
return token, u, nil
|
|
}
|
|
|
|
func (m *Manager) VerifyToken(token string) (*Claims, *User, error) {
|
|
claims, err := m.JWT.Verify(token)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
if u, ok := m.Store.Get(claims.Username); ok {
|
|
claims.Role = u.Role
|
|
return claims, &User{Username: u.Username, Role: u.Role, CreatedAt: u.CreatedAt}, nil
|
|
}
|
|
return claims, &User{Username: claims.Username, Role: claims.Role}, nil
|
|
}
|
|
|
|
func (m *Manager) Check(username, role, obj, act string) (bool, error) {
|
|
if role == "" {
|
|
if u, ok := m.Store.Get(username); ok {
|
|
role = u.Role
|
|
} else {
|
|
role = RoleGuest
|
|
}
|
|
}
|
|
sub := username
|
|
if sub == "" {
|
|
sub = role
|
|
}
|
|
return m.Enforcer.Enforce(sub, obj, act)
|
|
}
|
|
|
|
func (m *Manager) UpdateUserRole(targetUser, newRole string) error {
|
|
if err := m.Store.UpdateRole(targetUser, newRole); err != nil {
|
|
return err
|
|
}
|
|
return m.Enforcer.AddUserRole(targetUser, newRole)
|
|
}
|
|
|