Implement user password checking

This commit is contained in:
Tom Wiesing 2022-11-25 15:06:01 +01:00
parent 8e2d2cce3e
commit 996ecb9f80
No known key found for this signature in database
25 changed files with 10762 additions and 224 deletions

View file

@ -2,7 +2,6 @@ package info
import (
"net/http"
"strings"
"time"
_ "embed"
@ -12,6 +11,7 @@ import (
"github.com/FAU-CDI/wisski-distillery/internal/models"
"github.com/FAU-CDI/wisski-distillery/pkg/httpx"
"github.com/FAU-CDI/wisski-distillery/pkg/lazy"
"github.com/gorilla/mux"
)
//go:embed "html/components.html"
@ -51,12 +51,8 @@ type ingredientsContext struct {
func (info *Info) ingredients(r *http.Request) (cp ingredientsContext, err error) {
cp.Time = time.Now().UTC()
// find the slug as the last component of path!
slug := strings.TrimSuffix(r.URL.Path, "/")
slug = slug[strings.LastIndex(slug, "/")+1:]
// find the instance itself!
instance, err := info.Instances.WissKI(slug)
instance, err := info.Instances.WissKI(mux.Vars(r)["slug"])
if err == instances.ErrWissKINotFound {
return cp, httpx.ErrNotFound
}

View file

@ -176,28 +176,81 @@
</div>
</div>
<div class="pure-u-1 pure-u-xl-2-5">
<div class="pure-u-1-1">
<h2 id="wisski">Users</h2>
</div>
<div class="pure-u-1">
<div class="padding">
<div class="overflow">
<table class="pure-table pure-table-bordered">
<thead>
<tr>
<th colspan="2">
Users
<th>
ID
</th>
<th>
Active
</th>
<th>
Name
</th>
<th>
Email
</th>
<th>
Roles
</th>
<th>
Created
</th>
<th>
Last Login
</th>
<th>
Action
</th>
</tr>
</thead>
<tbody>
{{ $slug := .Instance.Slug }}
{{ range $index, $user := .Info.Users }}
<tr>
<tr {{ if not $user.Status }}style="color:gray"{{ end }}>
<td>
<code>{{ $user }}</code>
<code>{{ $user.UID }}</code>
</td>
<td>
<small>
<button class="remote-link pure-button pure-button-action" role="link" data-action="login" data-params="{{ $slug }} {{ $user }} ">Login in new window</button>
</small>
<code>{{ $user.Status }}</code>
</td>
<td>
<code>{{ $user.Name }}</code>
</td>
<td>
{{ if $user.Mail }}
<a href="mailto:{{ $user.Mail }}">{{ $user.Mail }}</a>
{{ end }}
</td>
<td>
{{ range $role, $unuused := $user.Roles }}
<code>
{{ $role }}
</code>
{{ end }}
</td>
<td>
<code class="date">{{ $user.Created.Time.Format "2006-01-02T15:04:05Z07:00" }}</code>
</td>
<td>
<code class="date">{{ $user.Login.Time.Format "2006-01-02T15:04:05Z07:00" }}</code>
</td>
<td>
<form action="/dis/api/login" method="POST" target="_blank">
<input type="hidden" name="slug" value="{{ $slug }}">
<input type="hidden" name="user" value="{{ $user.Name }}">
<input type="submit" class="pure-button pure-button-action" value="Login in new window">
</form>
</td>
</tr>
{{ end }}

View file

@ -7,6 +7,7 @@ import (
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/exporter"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/exporter/logger"
"github.com/gorilla/mux"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/instances"
"github.com/FAU-CDI/wisski-distillery/pkg/httpx"
@ -27,50 +28,71 @@ type Info struct {
func (*Info) Routes() []string { return []string{"/dis/"} }
func (info *Info) Handler(route string, context context.Context, io stream.IOStream) (http.Handler, error) {
mux := http.NewServeMux()
func (info *Info) Handler(route string, context context.Context, io stream.IOStream) (handler http.Handler, err error) {
router := mux.NewRouter()
{
socket := &httpx.WebSocket{
Context: context,
Fallback: router,
Handler: info.serveSocket,
}
handler = httpx.BasicAuth(socket, "WissKI Distillery Admin", func(user, pass string) bool {
return user == info.Config.DisAdminUser && pass == info.Config.DisAdminPassword
})
}
// handle everything
mux.HandleFunc(route, func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == route {
http.Redirect(w, r, route+"/index", http.StatusTemporaryRedirect)
return
}
http.NotFound(w, r)
router.Path(route).HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, route+"/index", http.StatusTemporaryRedirect)
})
// add a handler for the index page
mux.Handle(route+"index", httpx.HTMLHandler[indexContext]{
router.Path(route + "index").Handler(httpx.HTMLHandler[indexContext]{
Handler: info.index,
Template: indexTemplate,
})
// add a handler for the component page
mux.Handle(route+"components", httpx.HTMLHandler[componentContext]{
router.Path(route + "components").Handler(httpx.HTMLHandler[componentContext]{
Handler: info.components,
Template: componentsTemplate,
})
// add a handler for the component page
mux.Handle(route+"ingredients/", httpx.HTMLHandler[ingredientsContext]{
router.Path(route + "ingredients/{slug}").Handler(httpx.HTMLHandler[ingredientsContext]{
Handler: info.ingredients,
Template: ingredientsTemplate,
})
// add a handler for the instance page
mux.Handle(route+"instance/", httpx.HTMLHandler[instanceContext]{
router.Path(route + "instance/{slug}").Handler(httpx.HTMLHandler[instanceContext]{
Handler: info.instance,
Template: instanceTemplate,
})
handler := &httpx.WebSocket{
Context: context,
Fallback: mux,
Handler: info.serveSocket,
}
router.Path(route + "api/login").Handler(httpx.ClientSideRedirect(func(r *http.Request) (string, error) {
// enforce POST
if r.Method != http.MethodPost {
return "", httpx.ErrMethodNotAllowed
}
// ensure that everyone is logged in!
return httpx.BasicAuth(handler, "WissKI Distillery Admin", func(user, pass string) bool {
return user == info.Config.DisAdminUser && pass == info.Config.DisAdminPassword
}), nil
// parse the form
if err := r.ParseForm(); err != nil {
return "", err
}
// get the instance
instance, err := info.Instances.WissKI(r.PostFormValue("slug"))
if err != nil {
return "", httpx.ErrNotFound
}
target, err := instance.Users().Login(nil, r.PostFormValue("user"))
if err != nil {
return "", err
}
return target.String(), err
}))
return
}

View file

@ -3,7 +3,6 @@ package info
import (
_ "embed"
"net/http"
"strings"
"time"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/control/static"
@ -11,6 +10,7 @@ import (
"github.com/FAU-CDI/wisski-distillery/internal/models"
"github.com/FAU-CDI/wisski-distillery/internal/status"
"github.com/FAU-CDI/wisski-distillery/pkg/httpx"
"github.com/gorilla/mux"
)
//go:embed "html/instance.html"
@ -28,12 +28,8 @@ type instanceContext struct {
}
func (info *Info) instance(r *http.Request) (is instanceContext, err error) {
// find the slug as the last component of path!
slug := strings.TrimSuffix(r.URL.Path, "/")
slug = slug[strings.LastIndex(slug, "/")+1:]
// find the instance itself!
instance, err := info.Instances.WissKI(slug)
instance, err := info.Instances.WissKI(mux.Vars(r)["slug"])
if err == instances.ErrWissKINotFound {
return is, httpx.ErrNotFound
}

View file

@ -47,13 +47,6 @@ var socketInstanceActions = map[string]InstanceAction{
return instance.Drush().Cron(str)
},
},
"login": {
NumParams: 1,
HandleResult: func(_ *Info, instance *wisski.WissKI, params ...string) (any, error) {
link, err := instance.Drush().Login(stream.FromNil(), params[0])
return link, err
},
},
}
func (info *Info) serveSocket(conn httpx.WebSocketConnection) {