Files
pocket-id/backend/internal/authz/principal.go
T

55 lines
1.7 KiB
Go

package authz
import (
"time"
"github.com/gin-gonic/gin"
)
const principalContextKey = "authz.principal"
// Principal is the authenticated caller of a request together with the scopes it holds
type Principal struct {
Kind PrincipalKind
UserID string
Scopes ScopeSet
// WithheldUntilVerified are the scopes the user's role grants but that are withheld until the user verifies their email
WithheldUntilVerified ScopeSet
// AuthenticationMethod and AuthenticationTime describe how the session was established and are only set for KindSession
AuthenticationMethod string
AuthenticationTime time.Time
}
// RestrictUnverified withholds every scope except those a user needs to verify their email, such as signing out or correcting the address
func (p *Principal) RestrictUnverified() {
kept := make(ScopeSet, len(unverifiedScopes))
withheld := make(ScopeSet, len(p.Scopes))
for scope := range p.Scopes {
if unverifiedScopes.Has(scope) {
kept[scope] = struct{}{}
} else {
withheld[scope] = struct{}{}
}
}
p.Scopes = kept
p.WithheldUntilVerified = withheld
}
// PrincipalFrom returns the principal the authorization middleware attached to the request
// Anonymous requests on optional and public routes get the zero Principal, whose UserID is empty
func PrincipalFrom(c *gin.Context) Principal {
value, _ := c.Get(principalContextKey)
if principal, ok := value.(*Principal); ok && principal != nil {
return *principal
}
return Principal{}
}
// SetPrincipal attaches the principal to the request
// The middleware calls it after authorizing a request, and tests use it to call handlers directly
func SetPrincipal(c *gin.Context, principal *Principal) {
c.Set(principalContextKey, principal)
}