Use authentication for Distillery control page
This commit is contained in:
parent
da32b67981
commit
1caecc0f19
8 changed files with 122 additions and 82 deletions
72
internal/dis/component/auth/protect.go
Normal file
72
internal/dis/component/auth/protect.go
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/httpx"
|
||||
)
|
||||
|
||||
// Permission represents a permission for a user
|
||||
//
|
||||
// The nil permission represents any authenticated user.
|
||||
type Permission func(user *AuthUser, r *http.Request) (ok bool, err error)
|
||||
|
||||
// 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.
|
||||
// If an authenticated user is missing permissions, a Forbidden response is called.
|
||||
// If an authenticated calls the endpoint, and they have the given permissions, the original handler is called.
|
||||
func (auth *Auth) Protect(handler http.Handler, perm Permission) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// load the user in the session
|
||||
user, err := auth.UserOf(r)
|
||||
if err != nil {
|
||||
goto err
|
||||
}
|
||||
|
||||
// if there is no user in the session
|
||||
// we need to login the user
|
||||
if user == nil {
|
||||
// we can't redirect anything other than GET
|
||||
// (because it might be a form)
|
||||
// => so we just return a forbidden
|
||||
if r.Method != http.MethodGet {
|
||||
goto forbidden
|
||||
}
|
||||
|
||||
// redirect the user to the login endpoint, with the original URI as a return
|
||||
dest := "/auth/login?next=" + url.QueryEscape(r.URL.RequestURI())
|
||||
http.Redirect(w, r, dest, http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
|
||||
// if we have a permission check, we need to call it
|
||||
// to find out if the user is actually allowed to access the page
|
||||
if perm != nil {
|
||||
ok, err := perm(user, r)
|
||||
if err != nil {
|
||||
goto err
|
||||
}
|
||||
if !ok {
|
||||
goto forbidden
|
||||
}
|
||||
}
|
||||
|
||||
// store the user into the session
|
||||
r = r.WithContext(context.WithValue(r.Context(), ctxUserKey, user))
|
||||
handler.ServeHTTP(w, r)
|
||||
return
|
||||
forbidden:
|
||||
httpx.HTMLInterceptor.Intercept(w, r, httpx.ErrForbidden)
|
||||
return
|
||||
err:
|
||||
httpx.HTMLInterceptor.Fallback.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// Admin represents a permission that checks if a user is an administrator and has totp enabled.
|
||||
var Admin Permission = func(user *AuthUser, r *http.Request) (ok bool, err error) {
|
||||
return user != nil && user.Admin && user.TOTPEnabled, nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue