live-sfu-demo/internal/auth/auth.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)
}