package auth import ( "context" "net/http" "go-doc/go-loose/client" ) // User represents an authenticated user from go-loose type User struct { ID string Email string DisplayName string AvatarURL string TenantID string TenantSlug string ApplicationID string Application string Role string Permissions []string } func (u User) Can(permission string) bool { for _, granted := range u.Permissions { if granted == permission { return true } } return false } func (u User) IsAdmin() bool { return u.Role == "admin" || u.Role == "owner" || u.Can("console.read") } type contextKey string const userContextKey = contextKey("go-doc-user") func WithUser(ctx context.Context, user User) context.Context { return context.WithValue(ctx, userContextKey, user) } func UserFromContext(ctx context.Context) (User, bool) { user, ok := ctx.Value(userContextKey).(User) return user, ok } func TenantIDFromContext(ctx context.Context) (string, bool) { user, ok := UserFromContext(ctx) if !ok { return "", false } return user.TenantID, true } func UserIDFromContext(ctx context.Context) (string, bool) { user, ok := UserFromContext(ctx) if !ok { return "", false } return user.ID, true } func ConvertUser(looseUser client.User) User { return User{ ID: looseUser.ID, Email: looseUser.Email, DisplayName: looseUser.DisplayName, AvatarURL: looseUser.AvatarURL, TenantID: looseUser.TenantID, TenantSlug: looseUser.TenantSlug, ApplicationID: looseUser.ApplicationID, Application: looseUser.Application, Role: looseUser.Role, Permissions: looseUser.Permissions, } } func BrowserAuthMiddleware(browserAuth *client.BrowserAuth) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { if browserAuth == nil { return next } return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { browserAuth.Middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if user, ok := client.UserFromContext(r.Context()); ok { r = r.WithContext(WithUser(r.Context(), ConvertUser(user))) } next.ServeHTTP(w, r) })).ServeHTTP(w, r) }) } }