Update grant page
This commit is contained in:
parent
021fc3cc7e
commit
97f5ac7e1a
10 changed files with 313 additions and 54 deletions
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
|
"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"
|
||||||
|
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/auth/policy"
|
||||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/control/static/custom"
|
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/control/static/custom"
|
||||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/exporter"
|
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/exporter"
|
||||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/exporter/logger"
|
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/exporter/logger"
|
||||||
|
|
@ -28,6 +29,8 @@ type Admin struct {
|
||||||
|
|
||||||
Auth *auth.Auth
|
Auth *auth.Auth
|
||||||
|
|
||||||
|
Policy *policy.Policy
|
||||||
|
|
||||||
Custom *custom.Custom
|
Custom *custom.Custom
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,6 +111,16 @@ func (admin *Admin) HandleRoute(ctx context.Context, route string) (handler http
|
||||||
Template: admin.Dependencies.Custom.Template(instanceTemplate),
|
Template: admin.Dependencies.Custom.Template(instanceTemplate),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// add a router for the grants pages
|
||||||
|
router.Handler(http.MethodGet, route+"grants/:slug", httpx.HTMLHandler[grantsContext]{
|
||||||
|
Handler: admin.getGrants,
|
||||||
|
Template: admin.Dependencies.Custom.Template(grantsTemplate),
|
||||||
|
})
|
||||||
|
router.Handler(http.MethodPost, route+"grants/", httpx.HTMLHandler[grantsContext]{
|
||||||
|
Handler: admin.postGrants,
|
||||||
|
Template: admin.Dependencies.Custom.Template(grantsTemplate),
|
||||||
|
})
|
||||||
|
|
||||||
// add a router for the login page
|
// add a router for the login page
|
||||||
router.Handler(http.MethodPost, route+"login", admin.loginHandler(ctx))
|
router.Handler(http.MethodPost, route+"login", admin.loginHandler(ctx))
|
||||||
|
|
||||||
|
|
|
||||||
152
internal/dis/component/control/admin/grants.go
Normal file
152
internal/dis/component/control/admin/grants.go
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/control/static"
|
||||||
|
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/control/static/custom"
|
||||||
|
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/instances"
|
||||||
|
"github.com/FAU-CDI/wisski-distillery/internal/models"
|
||||||
|
"github.com/FAU-CDI/wisski-distillery/internal/wisski"
|
||||||
|
"github.com/FAU-CDI/wisski-distillery/pkg/httpx"
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
"golang.org/x/exp/maps"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed "html/grants.html"
|
||||||
|
var grantsStr string
|
||||||
|
var grantsTemplate = static.AssetsAdmin.MustParseShared(
|
||||||
|
"grants.html",
|
||||||
|
grantsStr,
|
||||||
|
)
|
||||||
|
|
||||||
|
type grantsContext struct {
|
||||||
|
custom.BaseContext
|
||||||
|
|
||||||
|
Error string
|
||||||
|
|
||||||
|
instance *wisski.WissKI
|
||||||
|
Instance models.Instance // current instance
|
||||||
|
|
||||||
|
Grants []models.Grant // grants that exist for the user
|
||||||
|
Usernames []string // unuused distillery usernames
|
||||||
|
Drupals []string // unusued drupal usernames
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gc *grantsContext) use(r *http.Request, slug string, admin *Admin) (err error) {
|
||||||
|
admin.Dependencies.Custom.Update(gc, r)
|
||||||
|
|
||||||
|
// find the instance itself
|
||||||
|
gc.instance, err = admin.Dependencies.Instances.WissKI(r.Context(), slug)
|
||||||
|
if err == instances.ErrWissKINotFound {
|
||||||
|
return httpx.ErrNotFound
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
gc.Instance = gc.instance.Instance
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (gc *grantsContext) useGrants(r *http.Request, admin *Admin) (err error) {
|
||||||
|
gc.Grants, err = admin.Dependencies.Policy.Instance(r.Context(), gc.Instance.Slug)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
users, err := admin.Dependencies.Auth.Users(r.Context())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a namemap of users, but not those already taken
|
||||||
|
userNameMap := make(map[string]struct{}, len(users))
|
||||||
|
for _, user := range users {
|
||||||
|
userNameMap[user.User.User] = struct{}{}
|
||||||
|
}
|
||||||
|
for _, grant := range gc.Grants {
|
||||||
|
delete(userNameMap, grant.User)
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup the usernames
|
||||||
|
gc.Usernames = maps.Keys(userNameMap)
|
||||||
|
slices.Sort(gc.Usernames)
|
||||||
|
|
||||||
|
// get the drupal usernames
|
||||||
|
drupals, err := gc.instance.Users().All(r.Context(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// and convert them to strings only
|
||||||
|
gc.Drupals = make([]string, len(drupals))
|
||||||
|
for i, drupal := range drupals {
|
||||||
|
gc.Drupals[i] = string(drupal.Name)
|
||||||
|
}
|
||||||
|
slices.Sort(gc.Drupals)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (admin *Admin) getGrants(r *http.Request) (gc grantsContext, err error) {
|
||||||
|
if err := gc.use(r, mux.Vars(r)["slug"], admin); err != nil {
|
||||||
|
return gc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := gc.useGrants(r, admin); err != nil {
|
||||||
|
return gc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return gc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (admin *Admin) postGrants(r *http.Request) (gc grantsContext, err error) {
|
||||||
|
// parse the form
|
||||||
|
if err := r.ParseForm(); err != nil {
|
||||||
|
return gc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// read out the form values
|
||||||
|
var (
|
||||||
|
slug = r.PostFormValue("slug")
|
||||||
|
delete = r.PostFormValue("action") == "delete"
|
||||||
|
distilleryUser = r.PostFormValue("distillery-user")
|
||||||
|
drupalUser = r.PostFormValue("drupal-user")
|
||||||
|
adminRole = r.PostFormValue("admin") == httpx.CheckboxChecked
|
||||||
|
)
|
||||||
|
|
||||||
|
// set the common fields
|
||||||
|
if err := gc.use(r, slug, admin); err != nil {
|
||||||
|
return gc, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if delete {
|
||||||
|
// delete the user grant
|
||||||
|
err := admin.Dependencies.Policy.Remove(r.Context(), distilleryUser, slug)
|
||||||
|
if err != nil {
|
||||||
|
return gc, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// update the grant
|
||||||
|
err := admin.Dependencies.Policy.Set(r.Context(), models.Grant{
|
||||||
|
User: distilleryUser,
|
||||||
|
Slug: slug,
|
||||||
|
|
||||||
|
DrupalUsername: drupalUser,
|
||||||
|
DrupalAdminRole: adminRole,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
gc.Error = fmt.Sprintf("Unable to update grant for user %s: %s", distilleryUser, err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch the grants for the instance
|
||||||
|
if err := gc.useGrants(r, admin); err != nil {
|
||||||
|
return gc, err
|
||||||
|
}
|
||||||
|
return gc, nil
|
||||||
|
}
|
||||||
135
internal/dis/component/control/admin/html/grants.html
Normal file
135
internal/dis/component/control/admin/html/grants.html
Normal file
|
|
@ -0,0 +1,135 @@
|
||||||
|
{{ template "_base.html" . }}
|
||||||
|
{{ define "title" }}Distillery Admin - {{ .Instance.Slug }} - Grants{{ end }}
|
||||||
|
|
||||||
|
{{ define "header"}}
|
||||||
|
<p>
|
||||||
|
<a class="pure-button" href="/admin/index">Control</a> >
|
||||||
|
<a class="pure-button" href="/admin/instance/{{ .Instance.Slug }}">Instance</a> >
|
||||||
|
<a class="pure-button pure-button-primary" href="/admin/grants/{{ .Instance.Slug }}">Grants</a>
|
||||||
|
</p>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
{{ define "content" }}
|
||||||
|
{{ $csrf := .CSRF }}
|
||||||
|
{{ $slug := .Instance.Slug }}
|
||||||
|
<div class="pure-u-1-1">
|
||||||
|
<h2 id="overview">Grants</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
A grant provides access for a specific distillery user to a specific WissKI instance.
|
||||||
|
Only <em>Distillery Administrators</em> can manage grants.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<em>Distillery Users</em> must exist in order to grant them access to a specific instance
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<em>Drupal Users</em> will be automatically created if they do not exist.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
If <em>Admin</em> is checked and a user logs in, they will automatically be given the admin role.
|
||||||
|
For security reasons, an admin role is never automatically removed.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{{ block "form/message" . }}
|
||||||
|
{{ $E := .Error }}
|
||||||
|
{{ if not (eq $E "") }}
|
||||||
|
<div class="pure-form-group">
|
||||||
|
<p class="error-message">
|
||||||
|
{{ $E }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
{{ end }}
|
||||||
|
</div>
|
||||||
|
<div class="pure-u-1">
|
||||||
|
<div class="padding">
|
||||||
|
<div class="overflow">
|
||||||
|
<table class="pure-table pure-table-bordered pure-form">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
Distillery Username
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Drupal Username
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Roles
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Actions
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{ range $id, $grant := .Grants }}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{{ $grant.User }}
|
||||||
|
<input type="hidden" name="distillery-user" value="{{ $grant.User }}" form="update-{{ $id }}">
|
||||||
|
<input type="hidden" name="distillery-user" value="{{ $grant.User }}" form="delete-{{ $id }}">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="drupal-user" list="drupal-users" value="{{ $grant.DrupalUsername }}" form="update-{{ $id }}">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label for="update={{ $id }}-admin">Admin</label>
|
||||||
|
<input type="checkbox" name="admin" id="update-{{ $id }}-admin" {{ if $grant.DrupalAdminRole }}checked{{end}} form="update-{{ $id }}">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="pure-button-group" role="group">
|
||||||
|
<form id="update-{{ $id }}" method="POST" action="/admin/grants/" class="pure-form-group" autocomplete="off">
|
||||||
|
{{ $csrf }}
|
||||||
|
<input type="hidden" name="slug" value="{{ $slug }}">
|
||||||
|
<input type="hidden" name="action" value="update">
|
||||||
|
<input type="submit" class="pure-button" value="Update">
|
||||||
|
</form>
|
||||||
|
<form id="delete-{{ $id }}" method="POST" action="/admin/grants/" class="pure-form-group" autocomplete="off">
|
||||||
|
{{ $csrf }}
|
||||||
|
<input type="hidden" name="action" value="delete">
|
||||||
|
<input type="hidden" name="slug" value="{{ $slug }}">
|
||||||
|
<input type="submit" class="pure-button pure-button-danger" value="Delete">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{ end }}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="distillery-user" list="distillery-users" placeholder="Distillery User" form="add-grant">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input type="text" name="drupal-user" list="drupal-users" placeholder="Drupal User" form="add-grant">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<label form="add-grant-admin">Admin</label>
|
||||||
|
<input type="checkbox" name="admin" id="add-grant-admin" form="add-grant">
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<form id="add-grant" method="POST" action="/admin/grants/" class="pure-form-group">
|
||||||
|
{{ $csrf }}
|
||||||
|
<input type="hidden" name="action" value="update">
|
||||||
|
<input type="hidden" name="slug" value="{{ $slug }}">
|
||||||
|
<input type="submit" class="pure-button" value="Add New">
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<datalist id="distillery-users">
|
||||||
|
{{ range $unused, $user := .Usernames }}
|
||||||
|
<option value="{{ $user }}">
|
||||||
|
{{ end }}
|
||||||
|
</datalist>
|
||||||
|
<datalist id="drupal-users">
|
||||||
|
{{ range $unused, $drupal := .Drupals }}
|
||||||
|
<option value="{{ $drupal }}">
|
||||||
|
{{ end }}
|
||||||
|
</datalist>
|
||||||
|
{{ end }}
|
||||||
|
|
@ -1,14 +1,15 @@
|
||||||
{{ template "_base.html" . }}
|
{{ template "_base.html" . }}
|
||||||
{{ define "title" }}Distillery Admin - {{ .Info.Slug }}{{ end }}
|
{{ define "title" }}Distillery Admin - {{ .Instance.Slug }}{{ end }}
|
||||||
|
|
||||||
{{ define "header"}}
|
{{ define "header"}}
|
||||||
<p>
|
<p>
|
||||||
<a class="pure-button" href="/admin/index">Control</a> >
|
<a class="pure-button" href="/admin/index">Control</a> >
|
||||||
<a class="pure-button pure-button-primary" href="/admin/instance/{{ .Info.Slug }}">Instance</a>
|
<a class="pure-button pure-button-primary" href="/admin/instance/{{ .Instance.Slug }}">Instance</a>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
<div class="pure-button-group" role="group" aria-label="Actions">
|
<div class="pure-button-group" role="group" aria-label="Actions">
|
||||||
<a class="pure-button pure-button-small" href="/admin/ingredients/{{ .Info.Slug }}">Ingredients</a>
|
<a class="pure-button" href="/admin/grants/{{ .Info.Slug }}">Grants</a>
|
||||||
|
<a class="pure-button pure-button-small" href="/admin/ingredients/{{ .Instance.Slug }}">Ingredients</a>
|
||||||
</div>
|
</div>
|
||||||
</p>
|
</p>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
@ -180,7 +181,8 @@
|
||||||
|
|
||||||
|
|
||||||
<div class="pure-u-1-1">
|
<div class="pure-u-1-1">
|
||||||
<h2 id="wisski">(Drupal) Users</h2>
|
<h2 id="wisski">Users (Drupal)</h2>
|
||||||
|
<a class="pure-button" href="/admin/grants/{{ .Info.Slug }}">Manage Grants</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pure-u-1">
|
<div class="pure-u-1">
|
||||||
|
|
@ -265,47 +267,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="pure-u-1-1">
|
|
||||||
<h2 id="distillery">(Distillery) Users</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="pure-u-1">
|
|
||||||
<div class="padding">
|
|
||||||
<div class="overflow">
|
|
||||||
<table class="pure-table pure-table-bordered">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
Distillery User
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
WissKI User
|
|
||||||
</th>
|
|
||||||
<th>
|
|
||||||
Admin
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{{ range $index, $grant := .Info.Grants }}
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<code>{{ $grant.User }}</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<code>{{ $grant.DrupalUsername }}</code>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<code>{{ $grant.DrupalAdminRole }}</code>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{ end }}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="pure-u-1-1">
|
<div class="pure-u-1-1">
|
||||||
<h2 id="wisski">WissKI Data</h2>
|
<h2 id="wisski">WissKI Data</h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@
|
||||||
</form>
|
</form>
|
||||||
<form action="/admin/users/password" method="POST" class="pure-form pure-form-group">
|
<form action="/admin/users/password" method="POST" class="pure-form pure-form-group">
|
||||||
<input type="hidden" name="user" value="{{ .User.User }}">
|
<input type="hidden" name="user" value="{{ .User.User }}">
|
||||||
<input type="password" name="password">
|
<input type="password" name="password" autocomplete="new-password">
|
||||||
<input type="submit" class="pure-button" value="Update Password">
|
<input type="submit" class="pure-button" value="Update Password">
|
||||||
{{ $csrf }}
|
{{ $csrf }}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"github.com/FAU-CDI/wisski-distillery/internal/models"
|
"github.com/FAU-CDI/wisski-distillery/internal/models"
|
||||||
"github.com/FAU-CDI/wisski-distillery/internal/status"
|
"github.com/FAU-CDI/wisski-distillery/internal/status"
|
||||||
"github.com/FAU-CDI/wisski-distillery/pkg/httpx"
|
"github.com/FAU-CDI/wisski-distillery/pkg/httpx"
|
||||||
"github.com/gorilla/csrf"
|
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -31,8 +30,6 @@ type instanceContext struct {
|
||||||
func (admin *Admin) instance(r *http.Request) (is instanceContext, err error) {
|
func (admin *Admin) instance(r *http.Request) (is instanceContext, err error) {
|
||||||
admin.Dependencies.Custom.Update(&is, r)
|
admin.Dependencies.Custom.Update(&is, r)
|
||||||
|
|
||||||
is.CSRF = csrf.TemplateField(r)
|
|
||||||
|
|
||||||
// find the instance itself!
|
// find the instance itself!
|
||||||
instance, err := admin.Dependencies.Instances.WissKI(r.Context(), mux.Vars(r)["slug"])
|
instance, err := admin.Dependencies.Instances.WissKI(r.Context(), mux.Vars(r)["slug"])
|
||||||
if err == instances.ErrWissKINotFound {
|
if err == instances.ErrWissKINotFound {
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ import (
|
||||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/control/static"
|
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/control/static"
|
||||||
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/control/static/custom"
|
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/control/static/custom"
|
||||||
"github.com/FAU-CDI/wisski-distillery/pkg/httpx"
|
"github.com/FAU-CDI/wisski-distillery/pkg/httpx"
|
||||||
"github.com/gorilla/csrf"
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -32,7 +31,6 @@ type userContext struct {
|
||||||
func (admin *Admin) users(r *http.Request) (uc userContext, err error) {
|
func (admin *Admin) users(r *http.Request) (uc userContext, err error) {
|
||||||
admin.Dependencies.Custom.Update(&uc, r)
|
admin.Dependencies.Custom.Update(&uc, r)
|
||||||
|
|
||||||
uc.CSRF = csrf.TemplateField(r)
|
|
||||||
uc.Users, err = admin.Dependencies.Auth.Users(r.Context())
|
uc.Users, err = admin.Dependencies.Auth.Users(r.Context())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -70,7 +68,7 @@ func (admin *Admin) createUser(ctx context.Context) http.Handler {
|
||||||
RenderTemplateContext: admin.Dependencies.Custom.RenderContext,
|
RenderTemplateContext: admin.Dependencies.Custom.RenderContext,
|
||||||
|
|
||||||
Validate: func(r *http.Request, values map[string]string) (cu createUserResult, err error) {
|
Validate: func(r *http.Request, values map[string]string) (cu createUserResult, err error) {
|
||||||
cu.User, cu.Passsword, cu.Admin = values["username"], values["password"], values["admin"] == "on"
|
cu.User, cu.Passsword, cu.Admin = values["username"], values["password"], values["admin"] == httpx.CheckboxChecked
|
||||||
|
|
||||||
if cu.User == "" {
|
if cu.User == "" {
|
||||||
return cu, errCreateInvalidUsername
|
return cu, errCreateInvalidUsername
|
||||||
|
|
|
||||||
|
|
@ -211,3 +211,6 @@ const (
|
||||||
PasswordField InputType = "password"
|
PasswordField InputType = "password"
|
||||||
CheckboxField InputType = "checkbox"
|
CheckboxField InputType = "checkbox"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CheckboxChecked is the default value of a checked checkbox
|
||||||
|
const CheckboxChecked = "on"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
//go:build nominify
|
//go:build !nominify
|
||||||
|
|
||||||
package httpx
|
package httpx
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
//go:build !nominify
|
//go:build nominify
|
||||||
|
|
||||||
package httpx
|
package httpx
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue