first commit
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type Provider interface {
|
||||
ListUsers(ctx context.Context) ([]UserInfo, error)
|
||||
LoginUser(ctx context.Context, username, password string) (*Result, error)
|
||||
SetupUser(ctx context.Context, session, username, preferredUsername, newPassword string) (*UserInfo, error)
|
||||
ValidateToken(ctx context.Context, token string) *UserInfo
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Service struct {
|
||||
Provider Provider
|
||||
|
||||
userListMutex sync.Mutex
|
||||
userList []UserInfo
|
||||
userMap map[string]string
|
||||
userListTime time.Time
|
||||
|
||||
key struct{ Stuff uint64 }
|
||||
key2 struct{ Stuff2 string }
|
||||
}
|
||||
|
||||
func (s *Service) ValidateUser(ctx context.Context, token string) *UserInfo {
|
||||
return s.Provider.ValidateToken(ctx, token)
|
||||
}
|
||||
|
||||
func (s *Service) AddContextUser(ctx context.Context, user UserInfo) context.Context {
|
||||
return context.WithValue(ctx, &s.key, &user)
|
||||
}
|
||||
|
||||
func (s *Service) Users(ctx context.Context) ([]UserInfo, map[string]string, error) {
|
||||
s.userListMutex.Lock()
|
||||
if time.Since(s.userListTime) < time.Minute {
|
||||
m := s.userMap
|
||||
l := s.userList
|
||||
s.userListMutex.Unlock()
|
||||
return l, m, nil
|
||||
}
|
||||
s.userListMutex.Unlock()
|
||||
|
||||
users, err := s.Provider.ListUsers(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
s.userListMutex.Lock()
|
||||
s.userList = users
|
||||
s.userMap = make(map[string]string, len(users))
|
||||
for _, user := range users {
|
||||
s.userMap[user.ID] = user.Name
|
||||
}
|
||||
m := s.userMap
|
||||
s.userListTime = time.Now()
|
||||
s.userListMutex.Unlock()
|
||||
|
||||
return users, m, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetUser(ctx context.Context) *UserInfo {
|
||||
v := ctx.Value(&s.key)
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return v.(*UserInfo)
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type UserInfo struct {
|
||||
User
|
||||
Permissions []string `json:"permissions"`
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
User *UserInfo `json:"user"`
|
||||
Token string `json:"token,omitempty"`
|
||||
Session string `json:"session,omitempty"`
|
||||
PasswordChangeRequired bool `json:"passwordChangeRequired"`
|
||||
}
|
||||
|
||||
func (user *UserInfo) HasIDOrPermission(userID, subject, action string) bool {
|
||||
return user.HasID(userID) || user.HasPermission(subject, action)
|
||||
}
|
||||
|
||||
func (user *UserInfo) HasID(id string) bool {
|
||||
return user != nil && user.ID == id
|
||||
}
|
||||
|
||||
func (user *UserInfo) HasOpPermission(userID, subject, action string) bool {
|
||||
if !user.HasID(userID) && !user.HasPermission(subject, "admin") {
|
||||
return false
|
||||
}
|
||||
|
||||
return user.HasPermission(subject, action)
|
||||
}
|
||||
|
||||
func (user *UserInfo) HasPermission(subject, action string) bool {
|
||||
if user == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
anyAll := "*.*"
|
||||
anyAction := fmt.Sprintf("%s.*", subject)
|
||||
anySubject := fmt.Sprintf("*.%s", action)
|
||||
specific := fmt.Sprintf("%s.%s", subject, action)
|
||||
|
||||
if action == "admin" {
|
||||
anyAction = specific
|
||||
}
|
||||
|
||||
for _, perm := range user.Permissions {
|
||||
if perm == anyAll || perm == anyAction || perm == anySubject || perm == specific {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user