Add initial implementation of grants

This commit is contained in:
Tom Wiesing 2023-01-02 15:12:06 +01:00
parent b8f1281f78
commit 69b6579de7
No known key found for this signature in database
15 changed files with 308 additions and 73 deletions

View file

@ -2,77 +2,12 @@ package auth
import (
"context"
"errors"
"net/http"
"net/url"
"github.com/FAU-CDI/wisski-distillery/pkg/httpx"
)
// Permission represents a permission granted to a user.
//
// The nil permission represents any authenticated user.
type Permission func(user *AuthUser, r *http.Request) (ok Grant, err error)
// Grant represents an object that either grants or denies access for a certain permission
type Grant interface {
isGranted()
// Granted returns a boolean indicating if permission to the resource in question
// has been granted
Granted() bool
// Denied returns a string containing an error message to display to the user when permission is denied.
// When Granted() returns true, the behaviour is undefined.
Denied() string
}
// Bool2Grant returns a new grant that returns granted for the given boolean, and message as the denied message.
func Bool2Grant(granted bool, message string) Grant {
if granted {
return grantAllow{}
}
return grantDeny(message)
}
type grantAllow struct{}
func (grantAllow) isGranted() {}
func (grantAllow) Granted() bool { return true }
func (grantAllow) Denied() string { return "" }
type grantDeny string
func (grantDeny) isGranted() {}
func (g grantDeny) Granted() bool { return false }
func (g grantDeny) Denied() string {
if g == "" {
return "Forbidden"
}
return string(g)
}
var errPermissionPanic = errors.New("permission: panic()")
// Permit checks if the given user has this permission.
func (perm Permission) Permit(user *AuthUser, r *http.Request) (ok Grant, err error) {
// if there is no permission, then we just check if there is some user
if perm == nil {
return Bool2Grant(user != nil, ""), nil
}
// recover any panic()ed permission call
// to prevent the handler from panic()ing
defer func() {
if p := recover(); p != nil {
ok = Bool2Grant(false, "unknown error")
err = errPermissionPanic
}
}()
return perm(user, r)
}
// Protect returns a new handler which requires a user to be logged in and pass the perm function.
//
// If an unauthenticated user attempts to access the returned handler, they are redirected to the login endpoint.