Expose user login functionality
This commit is contained in:
parent
97f5ac7e1a
commit
8a5b066839
8 changed files with 246 additions and 8 deletions
109
internal/dis/component/auth/next/next.go
Normal file
109
internal/dis/component/auth/next/next.go
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
package next
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/auth"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/auth/policy"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/instances"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/wisski"
|
||||
"github.com/FAU-CDI/wisski-distillery/internal/wisski/ingredient/php/users"
|
||||
"github.com/FAU-CDI/wisski-distillery/pkg/httpx"
|
||||
)
|
||||
|
||||
type Next struct {
|
||||
component.Base
|
||||
Dependencies struct {
|
||||
Auth *auth.Auth
|
||||
Policy *policy.Policy
|
||||
Instances *instances.Instances
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
_ component.Routeable = (*Next)(nil)
|
||||
)
|
||||
|
||||
func (next *Next) Routes() component.Routes {
|
||||
return component.Routes{
|
||||
Paths: []string{"/next/"},
|
||||
Decorator: next.Dependencies.Auth.Require(auth.User),
|
||||
}
|
||||
}
|
||||
|
||||
// Next returns a url that will forward authorized users to the given slug and path
|
||||
func (next *Next) Next(context context.Context, slug, path string) (string, error) {
|
||||
wisski, err := next.Dependencies.Instances.WissKI(context, slug)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
target := wisski.URL()
|
||||
target.Path = path
|
||||
return "/next/?next=" + url.PathEscape(target.String()), nil
|
||||
|
||||
}
|
||||
|
||||
func (next *Next) getInstance(r *http.Request) (wisski *wisski.WissKI, path string, err error) {
|
||||
// extract the instance
|
||||
url, err := url.Parse(r.URL.Query().Get("next"))
|
||||
if err != nil {
|
||||
return nil, "", httpx.ErrBadRequest
|
||||
}
|
||||
|
||||
// find the slug
|
||||
slug, ok := next.Config.SlugFromHost(url.Host)
|
||||
if slug == "" || !ok {
|
||||
return nil, "", httpx.ErrBadRequest
|
||||
}
|
||||
|
||||
// fetch the instance from the database
|
||||
wisski, err = next.Dependencies.Instances.WissKI(r.Context(), slug)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
// return the wisski and the relative path
|
||||
return wisski, url.Path, nil
|
||||
}
|
||||
|
||||
func (next *Next) HandleRoute(ctx context.Context, path string) (http.Handler, error) {
|
||||
return httpx.RedirectHandler(func(r *http.Request) (string, int, error) {
|
||||
// get the instance and the path
|
||||
instance, path, err := next.getInstance(r)
|
||||
if err != nil {
|
||||
return "", 0, httpx.ErrForbidden
|
||||
}
|
||||
|
||||
// get the user
|
||||
user, err := next.Dependencies.Auth.UserOf(r)
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
|
||||
// check if they have a grant
|
||||
grant, err := next.Dependencies.Policy.Has(r.Context(), user.User.User, instance.Slug)
|
||||
if err == policy.ErrNoAccess {
|
||||
return "", 0, httpx.ErrForbidden
|
||||
}
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
|
||||
// perform the login
|
||||
dest, err := instance.Users().LoginWithOpt(r.Context(), nil, grant.DrupalUsername, users.LoginOptions{
|
||||
Destination: path,
|
||||
CreateIfMissing: true,
|
||||
GrantAdminRole: grant.DrupalAdminRole,
|
||||
})
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
|
||||
// and redirect
|
||||
return dest.String(), http.StatusSeeOther, nil
|
||||
}), nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue