go: add usr updating [wip]
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
32aa8d8852
commit
5f8548958f
|
@ -58,8 +58,10 @@ func (a *App) SetupRoutes() error {
|
||||||
|
|
||||||
e.GET("/manage/users", handlers.ManageUsers(), handlers.MiddlewareSession)
|
e.GET("/manage/users", handlers.ManageUsers(), handlers.MiddlewareSession)
|
||||||
e.GET("/manage/users/new", handlers.ManageUsers(), handlers.MiddlewareSession)
|
e.GET("/manage/users/new", handlers.ManageUsers(), handlers.MiddlewareSession)
|
||||||
e.GET("/manage/users/:id", handlers.ViewUser(), handlers.MiddlewareSession)
|
|
||||||
e.POST("/manage/users/create", handlers.CreateUser(), handlers.MiddlewareSession)
|
e.POST("/manage/users/create", handlers.CreateUser(), handlers.MiddlewareSession)
|
||||||
|
e.GET("/manage/users/:id", handlers.ViewUser(), handlers.MiddlewareSession)
|
||||||
|
e.GET("/manage/users/:id/edit", handlers.EditUser(), handlers.MiddlewareSession, handlers.MiddlewareCache, compress)
|
||||||
|
e.POST("/manage/users/:id/update", handlers.UpdateUser(), handlers.MiddlewareSession)
|
||||||
|
|
||||||
e.GET("/logout", handlers.Logout(), compress)
|
e.GET("/logout", handlers.Logout(), compress)
|
||||||
e.POST("/logout", handlers.Logout())
|
e.POST("/logout", handlers.Logout())
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"git.dotya.ml/mirre-mt/pcmt/ent"
|
"git.dotya.ml/mirre-mt/pcmt/ent"
|
||||||
moduser "git.dotya.ml/mirre-mt/pcmt/modules/user"
|
moduser "git.dotya.ml/mirre-mt/pcmt/modules/user"
|
||||||
|
@ -306,7 +307,7 @@ func ViewUser() echo.HandlerFunc {
|
||||||
uid := new(userID)
|
uid := new(userID)
|
||||||
|
|
||||||
err := c.Bind(uid)
|
err := c.Bind(uid)
|
||||||
if err == nil {
|
if err == nil { //nolint:dupl
|
||||||
usr, err := getUserByID(ctx, dbclient, uid.ID)
|
usr, err := getUserByID(ctx, dbclient, uid.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, moduser.ErrUserNotFound) { //nolint:gocritic
|
if errors.Is(err, moduser.ErrUserNotFound) { //nolint:gocritic
|
||||||
|
@ -372,3 +373,293 @@ func ViewUser() echo.HandlerFunc {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//nolint:dupl
|
||||||
|
func EditUser() echo.HandlerFunc {
|
||||||
|
return func(c echo.Context) error {
|
||||||
|
addHeaders(c)
|
||||||
|
|
||||||
|
u, ok := c.Get("sessUsr").(moduser.User)
|
||||||
|
if !ok {
|
||||||
|
return renderErrorPage(
|
||||||
|
c,
|
||||||
|
http.StatusUnauthorized,
|
||||||
|
http.StatusText(http.StatusUnauthorized),
|
||||||
|
"username was nil",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !u.IsAdmin {
|
||||||
|
c.Logger().Debug("this is a restricted endpoint")
|
||||||
|
|
||||||
|
status := http.StatusUnauthorized
|
||||||
|
msg := http.StatusText(status)
|
||||||
|
|
||||||
|
return renderErrorPage(
|
||||||
|
c, status, msg+": You should not be here", "Restricted endpoint",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, ok := c.Get("sloggerCtx").(context.Context)
|
||||||
|
if !ok {
|
||||||
|
ctx = context.WithValue(context.Background(), moduser.CtxKey{}, slogger)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := page{
|
||||||
|
AppName: setting.AppName(),
|
||||||
|
AppVer: appver,
|
||||||
|
Title: "Manage Users - Edit User",
|
||||||
|
DevelMode: setting.IsDevel(),
|
||||||
|
Current: "manage-users-edit-user",
|
||||||
|
User: u,
|
||||||
|
}
|
||||||
|
tmpl := "manage/user-edit.tmpl"
|
||||||
|
data := make(map[string]any)
|
||||||
|
id := strings.TrimPrefix(strings.TrimSuffix(c.Request().URL.Path, "/edit"), "/manage/users/")
|
||||||
|
|
||||||
|
usr, err := getUserByID(ctx, dbclient, id)
|
||||||
|
if err != nil {
|
||||||
|
//nolint:dupl
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, moduser.ErrUserNotFound):
|
||||||
|
c.Logger().Errorf("user not found by ID: '%s'", id)
|
||||||
|
|
||||||
|
data["flash"] = fmt.Sprintf("No user found with the UUID: %q", id)
|
||||||
|
p.Data = data
|
||||||
|
|
||||||
|
return c.Render(
|
||||||
|
http.StatusNotFound,
|
||||||
|
tmpl,
|
||||||
|
p,
|
||||||
|
)
|
||||||
|
|
||||||
|
case errors.Is(err, moduser.ErrFailedToQueryUser):
|
||||||
|
c.Logger().Errorf("failed to query user by ID: '%s'", id)
|
||||||
|
|
||||||
|
data["flash"] = fmt.Sprintf("failed to query user by UUID %q", id)
|
||||||
|
p.Data = data
|
||||||
|
|
||||||
|
return c.Render(
|
||||||
|
http.StatusInternalServerError,
|
||||||
|
tmpl,
|
||||||
|
p,
|
||||||
|
)
|
||||||
|
|
||||||
|
case errors.Is(err, moduser.ErrBadUUID):
|
||||||
|
c.Logger().Errorf("Invalid UUID '%s': %q", id, err)
|
||||||
|
|
||||||
|
data["flash"] = fmt.Sprintf("invalid UUID %q", id)
|
||||||
|
p.Data = data
|
||||||
|
|
||||||
|
return c.Render(
|
||||||
|
http.StatusBadRequest,
|
||||||
|
"manage/user-details.tmpl",
|
||||||
|
p,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Logger().Errorf("UUID-related issue for UUID '%s': %q", id, err)
|
||||||
|
|
||||||
|
return renderErrorPage(
|
||||||
|
c,
|
||||||
|
http.StatusInternalServerError,
|
||||||
|
http.StatusText(http.StatusInternalServerError),
|
||||||
|
err.Error(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
data["user"] = usr
|
||||||
|
p.Data = data
|
||||||
|
|
||||||
|
return c.Render(
|
||||||
|
http.StatusOK,
|
||||||
|
tmpl,
|
||||||
|
p,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//nolint:dupl
|
||||||
|
func UpdateUser() echo.HandlerFunc { //nolint:gocognit
|
||||||
|
return func(c echo.Context) error {
|
||||||
|
addHeaders(c)
|
||||||
|
|
||||||
|
u, ok := c.Get("sessUsr").(moduser.User)
|
||||||
|
if !ok {
|
||||||
|
return renderErrorPage(
|
||||||
|
c,
|
||||||
|
http.StatusUnauthorized,
|
||||||
|
http.StatusText(http.StatusUnauthorized),
|
||||||
|
"username was nil",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !u.IsAdmin {
|
||||||
|
c.Logger().Debug("this is a restricted endpoint")
|
||||||
|
|
||||||
|
status := http.StatusUnauthorized
|
||||||
|
msg := http.StatusText(status)
|
||||||
|
|
||||||
|
return renderErrorPage(
|
||||||
|
c, status, msg+": You should not be here", "Restricted endpoint",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, ok := c.Get("sloggerCtx").(context.Context)
|
||||||
|
if !ok {
|
||||||
|
ctx = context.WithValue(context.Background(), moduser.CtxKey{}, slogger)
|
||||||
|
}
|
||||||
|
|
||||||
|
p := page{
|
||||||
|
AppName: setting.AppName(),
|
||||||
|
AppVer: appver,
|
||||||
|
Title: "Manage Users - Edit User",
|
||||||
|
DevelMode: setting.IsDevel(),
|
||||||
|
Current: "manage-users-edit-user",
|
||||||
|
User: u,
|
||||||
|
}
|
||||||
|
tmpl := "manage/user-edit.tmpl"
|
||||||
|
data := make(map[string]any)
|
||||||
|
id := strings.TrimPrefix(strings.TrimSuffix(c.Request().URL.Path, "/update"), "/manage/users/")
|
||||||
|
|
||||||
|
usr, err := getUserByID(ctx, dbclient, id)
|
||||||
|
if err != nil {
|
||||||
|
switch {
|
||||||
|
case errors.Is(err, moduser.ErrUserNotFound):
|
||||||
|
c.Logger().Errorf("user not found by ID: '%s'", id)
|
||||||
|
|
||||||
|
data["flash"] = fmt.Sprintf("No user found with the UUID: %q", id)
|
||||||
|
p.Data = data
|
||||||
|
|
||||||
|
return c.Render(
|
||||||
|
http.StatusNotFound,
|
||||||
|
tmpl,
|
||||||
|
p,
|
||||||
|
)
|
||||||
|
|
||||||
|
case errors.Is(err, moduser.ErrFailedToQueryUser):
|
||||||
|
c.Logger().Errorf("failed to query user by ID: '%s'", id)
|
||||||
|
|
||||||
|
data["flash"] = fmt.Sprintf("failed to query user by UUID %q", id)
|
||||||
|
p.Data = data
|
||||||
|
|
||||||
|
return c.Render(
|
||||||
|
http.StatusInternalServerError,
|
||||||
|
tmpl,
|
||||||
|
p,
|
||||||
|
)
|
||||||
|
|
||||||
|
case errors.Is(err, moduser.ErrBadUUID):
|
||||||
|
c.Logger().Errorf("Invalid UUID '%s': %q", id, err)
|
||||||
|
|
||||||
|
data["flash"] = fmt.Sprintf("invalid UUID %q", id)
|
||||||
|
p.Data = data
|
||||||
|
|
||||||
|
return c.Render(
|
||||||
|
http.StatusBadRequest,
|
||||||
|
"manage/user-details.tmpl",
|
||||||
|
p,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Logger().Errorf("UUID-related issue for UUID '%s': %q", id, err)
|
||||||
|
|
||||||
|
return renderErrorPage(
|
||||||
|
c,
|
||||||
|
http.StatusInternalServerError,
|
||||||
|
http.StatusText(http.StatusInternalServerError),
|
||||||
|
err.Error(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
uu := new(userCreate)
|
||||||
|
|
||||||
|
if err := c.Bind(uu); err != nil {
|
||||||
|
return renderErrorPage(
|
||||||
|
c,
|
||||||
|
http.StatusBadRequest,
|
||||||
|
http.StatusText(http.StatusBadRequest),
|
||||||
|
err.Error(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if uu.Username == "" || uu.Password == "" || uu.RepeatPassword == "" || uu.Password != uu.RepeatPassword {
|
||||||
|
c.Logger().Error("username or password not set, returning to /manage/users/edit")
|
||||||
|
|
||||||
|
msg := "Error: both username and password need to be set"
|
||||||
|
|
||||||
|
if uu.Password != uu.RepeatPassword {
|
||||||
|
msg += "; the same password needs to be passed in twice"
|
||||||
|
}
|
||||||
|
|
||||||
|
data["flash"] = msg
|
||||||
|
data["form"] = uu
|
||||||
|
p.Data = data
|
||||||
|
|
||||||
|
return c.Render(
|
||||||
|
http.StatusBadRequest,
|
||||||
|
"manage/user-edit.tmpl",
|
||||||
|
p,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if usr.Username != uu.Username {
|
||||||
|
exists, err := moduser.UsernameExists(ctx, dbclient, uu.Username)
|
||||||
|
if err != nil {
|
||||||
|
return renderErrorPage(
|
||||||
|
c,
|
||||||
|
http.StatusInternalServerError,
|
||||||
|
http.StatusText(http.StatusInternalServerError),
|
||||||
|
err.Error(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if exists {
|
||||||
|
msg := fmt.Sprintf("Error: username %q is already taken", uu.Username)
|
||||||
|
|
||||||
|
c.Logger().Warn(msg)
|
||||||
|
|
||||||
|
data["flash"] = msg
|
||||||
|
p.Data = data
|
||||||
|
|
||||||
|
return c.Render(
|
||||||
|
http.StatusBadRequest,
|
||||||
|
"manage/user-edit.tmpl",
|
||||||
|
p,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if usr.Email != uu.Email {
|
||||||
|
exists, err := moduser.EmailExists(ctx, dbclient, uu.Email)
|
||||||
|
if err != nil {
|
||||||
|
return renderErrorPage(
|
||||||
|
c,
|
||||||
|
http.StatusInternalServerError,
|
||||||
|
http.StatusText(http.StatusInternalServerError),
|
||||||
|
err.Error(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if exists {
|
||||||
|
msg := fmt.Sprintf("Error: email %q is already taken", uu.Email)
|
||||||
|
|
||||||
|
c.Logger().Error(msg)
|
||||||
|
|
||||||
|
return renderErrorPage(
|
||||||
|
c,
|
||||||
|
http.StatusBadRequest,
|
||||||
|
msg,
|
||||||
|
msg,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now update
|
||||||
|
|
||||||
|
data["user"] = usr
|
||||||
|
p.Data = data
|
||||||
|
|
||||||
|
return c.Redirect(http.StatusSeeOther, fmt.Sprintf("/manage/users/%s/edit", usr.ID))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -153,14 +153,14 @@ func Exists(ctx context.Context, client *ent.Client, username, email string) (bo
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("failed to check whether username is taken", "error", err, "username requested", username)
|
log.Warn("failed to check whether username is taken", "error", err, "username requested", username)
|
||||||
|
|
||||||
return false, fmt.Errorf("failed querying user: %w", err)
|
return false, ErrFailedToQueryUser
|
||||||
}
|
}
|
||||||
|
|
||||||
emailExists, err := EmailExists(ctx, client, email)
|
emailExists, err := EmailExists(ctx, client, email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("failed to check whether user email exists", "error", err, "user email requested", email)
|
log.Warn("failed to check whether user email exists", "error", err, "user email requested", email)
|
||||||
|
|
||||||
return false, fmt.Errorf("failed querying user: %w", err)
|
return false, ErrFailedToQueryUser
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
|
|
@ -12,6 +12,11 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{{if and .Data .Data.user -}}
|
{{if and .Data .Data.user -}}
|
||||||
|
<div class="flex justify-end gap-2 lg:gap-0 place-items-center">
|
||||||
|
<a href="/manage/users/{{- .Data.user.ID -}}/edit" class="w-auto py-1 mt-0 text-center text-blue-500 dark:text-blue-400 md:mx-2 lg:mx-4 hover:underline hover:text-blue-600 dark:hover:text-blue-300">
|
||||||
|
Edit
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
<div class="p-2 mt-3 lg:mx-auto border-2 dark:border-slate-500 rounded-sm space-y-0">
|
<div class="p-2 mt-3 lg:mx-auto border-2 dark:border-slate-500 rounded-sm space-y-0">
|
||||||
<div class="flex max-h-14 place-items-baseline justify-left lg:justify-between overflow-x-auto text-ellipsis hover:bg-gray-100 dark:hover:bg-gray-700">
|
<div class="flex max-h-14 place-items-baseline justify-left lg:justify-between overflow-x-auto text-ellipsis hover:bg-gray-100 dark:hover:bg-gray-700">
|
||||||
<span class="w-24 md:w-32 text-purple-500 dark:text-purple-300">ID:</span>
|
<span class="w-24 md:w-32 text-purple-500 dark:text-purple-300">ID:</span>
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
{{ template "head.tmpl" . }}
|
||||||
|
<body class="h-screen bg-white dark:bg-gray-900">
|
||||||
|
{{ template "navbar.tmpl" . }}
|
||||||
|
<main class="grow min-w-[300px]">
|
||||||
|
<!-- <main class="grow"> -->
|
||||||
|
<!-- <div class="container mx-auto place-items-center px-8 md:px-12 lg:px-14"> -->
|
||||||
|
<!-- {{ if and .Data .Data.flash }} -->
|
||||||
|
<!-- <h2 class="text-xl text-pink-600 dark:text-pink-500 capitalize py-2"> -->
|
||||||
|
<!-- {{- .Data.flash -}} -->
|
||||||
|
<!-- </h2> -->
|
||||||
|
<!-- {{- end}} -->
|
||||||
|
<!-- <div class="flex justify-between place-items-center"> -->
|
||||||
|
<!-- <h1 class="text-xl font-bold text-fuchsia-600 dark:text-fuchsia-400 capitalize py-2"> -->
|
||||||
|
<!-- Edit user -->
|
||||||
|
<!-- </h1> -->
|
||||||
|
<!-- </div> -->
|
||||||
|
<!-- </div> -->
|
||||||
|
<section class="bg-white dark:bg-gray-900">
|
||||||
|
<div class="container mx-auto md:mx-4 px-6 sm:px-0:py-0 md:py-16 lg:py-32">
|
||||||
|
<div class="lg:flex">
|
||||||
|
<div class="lg:w-1/2">
|
||||||
|
<h1 class="mt-4 text-2xl font-medium text-fuchsia-600 dark:text-fuchsia-400 capitalize lg:text-3xl">
|
||||||
|
Edit user
|
||||||
|
</h1>
|
||||||
|
{{ if and .Data .Data.flash }}
|
||||||
|
<h2 class="text-xl text-pink-600 dark:text-pink-500 py-2">
|
||||||
|
{{- .Data.flash -}}
|
||||||
|
</h2>
|
||||||
|
{{- end }}
|
||||||
|
</div>
|
||||||
|
<div class="mt-8 lg:w-1/2 lg:mt-0">
|
||||||
|
{{if and .Data .Data.user -}}
|
||||||
|
<div class="flex justify-end gap-2 lg:gap-0 place-items-center">
|
||||||
|
<a href="/manage/users/{{.Data.user.ID}}" class="w-auto py-1 mt-2 mb-4 text-center text-blue-500 md:mt-0 md:mx-6 lg:mx-4 hover:underline dark:text-blue-400">
|
||||||
|
Back to detail
|
||||||
|
</a>
|
||||||
|
<a href="/manage/users" class="w-auto py-1 mt-2 mb-4 text-center text-blue-500 md:mt-0 md:mx-6 lg:mx-4 hover:underline dark:text-blue-400">
|
||||||
|
⏎ All users
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
<form method="post" action="/manage/users/{{.Data.user.ID}}/update" class="w-full lg:max-w-xl">
|
||||||
|
<input type="hidden" name="_csrf" value="{{- .CSRF -}}">
|
||||||
|
<div class="relative flex items-center">
|
||||||
|
<span class="absolute" role="img" aria-label="person outline icon for username">
|
||||||
|
{{ template "svg-user.tmpl" }}
|
||||||
|
</span>
|
||||||
|
<input name="username" type="text" {{if and .Data.user .Data.user.Username}}value="{{.Data.user.Username}}"{{end}} placeholder="Username" required class="block w-full py-3 valid:border-green-300 required:border-blue-300 text-gray-700 bg-white border rounded-lg px-11 dark:bg-gray-900 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 dark:focus:border-blue-300 focus:ring-blue-300 focus:outline-none focus:ring focus:ring-opacity-40">
|
||||||
|
</div>
|
||||||
|
<div class="relative flex items-center mt-4">
|
||||||
|
<span class="absolute" role="img" aria-label="email icon">
|
||||||
|
{{ template "svg-email.tmpl" }}
|
||||||
|
</span>
|
||||||
|
<input name="email" type="email" {{if and .Data.user .Data.user.Email}}value="{{.Data.user.Email}}"{{end}} placeholder="Email address" required class="peer block w-full px-10 py-3 required:border-blue-300 text-gray-700 bg-white border rounded-lg dark:bg-gray-900 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 dark:focus:border-blue-300 focus:ring-blue-300 focus:outline-none focus:ring focus:ring-opacity-40">
|
||||||
|
<p class="mt-2 mx-4 peer-placeholder-shown:collapse peer-valid:hidden peer-invalid:block text-pink-600 text-sm">
|
||||||
|
Please provide a valid email address.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="relative flex items-center mt-4">
|
||||||
|
<span class="absolute" role="img" aria-label="password lock icon">
|
||||||
|
{{ template "svg-password.tmpl" }}
|
||||||
|
</span>
|
||||||
|
<input name="password" type="password" {{if and .Data.user .Data.user.Password}}value="{{.Data.user.Password}}"{{end}} placeholder="Password" required class="block w-full px-10 py-3 required:border-blue-300 text-gray-700 bg-white border rounded-lg dark:bg-gray-900 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 dark:focus:border-blue-300 focus:ring-blue-300 focus:outline-none focus:ring focus:ring-opacity-40">
|
||||||
|
</div>
|
||||||
|
<div class="relative flex items-center mt-4">
|
||||||
|
<span class="absolute" role="img" aria-label="password lock icon">
|
||||||
|
{{ template "svg-password.tmpl" }}
|
||||||
|
</span>
|
||||||
|
<input name="repeatPassword" type="password" {{if and .Data.user .Data.user.Password}}value="{{.Data.user.Password}}"{{end}} placeholder="Repeat Password" required class="block w-full px-10 py-3 required:border-blue-300 text-gray-700 bg-white border rounded-lg dark:bg-gray-900 dark:text-gray-300 dark:border-gray-600 focus:border-blue-400 dark:focus:border-blue-300 focus:ring-blue-300 focus:outline-none focus:ring focus:ring-opacity-40">
|
||||||
|
</div>
|
||||||
|
<div class="flex pt-2 px-2 items-center justify-center gap-6">
|
||||||
|
<div class="mb-1 block min-h-3">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
value="true"
|
||||||
|
id="isAdmin"
|
||||||
|
name="isAdmin"
|
||||||
|
{{- if and .Data.user .Data.user.IsAdmin}}checked{{ end -}}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
class="inline-block pl-1 hover:cursor-pointer text-gray-700 dark:text-gray-300"
|
||||||
|
for="isAdmin">
|
||||||
|
Is admin?
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="mb-1 block min-h-3">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
value="true"
|
||||||
|
id="isActive"
|
||||||
|
name="isActive"
|
||||||
|
{{- if and .Data.user .Data.user.IsActive}}checked{{ end -}}
|
||||||
|
/>
|
||||||
|
<label
|
||||||
|
class="inline-block pl-1 hover:cursor-pointer text-gray-700 dark:text-gray-300"
|
||||||
|
for="isActive">
|
||||||
|
Is active?
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-8 md:flex md:items-center">
|
||||||
|
<button class="w-full px-6 py-3 text-sm font-medium tracking-wide text-white capitalize transition-colors duration-300 transform bg-blue-500 rounded-lg md:w-1/2 hover:bg-blue-400 focus:outline-none focus:ring focus:ring-blue-300 focus:ring-opacity-50">
|
||||||
|
Update
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
{{ template "footer.tmpl" . }}
|
|
@ -25,11 +25,11 @@
|
||||||
</li>
|
</li>
|
||||||
{{ if and .User .User.IsLoggedIn }}
|
{{ if and .User .User.IsLoggedIn }}
|
||||||
<li>
|
<li>
|
||||||
{{ if or (pageIs .Current "manage-users") (pageIs .Current "manage-users-new") (pageIs .Current "manage-users-user-details") }}
|
{{- if or (pageIs .Current "manage-users") (pageIs .Current "manage-users-new") (pageIs .Current "manage-users-user-details") (pageIs .Current "manage-users-edit-user") -}}
|
||||||
<a href="/manage/users" class="block py-2 pl-3 pr-4 text-white bg-blue-500 rounded md:bg-transparent md:text-blue-700 md:p-0 md:dark:text-blue-500 dark:bg-blue-500 md:dark:bg-transparent" aria-current="page">
|
<a href="/manage/users" class="block py-2 pl-3 pr-4 text-white bg-blue-500 rounded md:bg-transparent md:text-blue-700 md:p-0 md:dark:text-blue-500 dark:bg-blue-500 md:dark:bg-transparent" aria-current="page">
|
||||||
{{ else }}
|
{{else}}
|
||||||
<a href="/manage/users" class="block py-2 pl-3 pr-4 text-gray-900 rounded hover:bg-gray-300 md:hover:bg-transparent md:border-0 md:hover:text-blue-500 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent">
|
<a href="/manage/users" class="block py-2 pl-3 pr-4 text-gray-900 rounded hover:bg-gray-300 md:hover:bg-transparent md:border-0 md:hover:text-blue-500 md:p-0 dark:text-white md:dark:hover:text-blue-500 dark:hover:bg-gray-700 dark:hover:text-white md:dark:hover:bg-transparent">
|
||||||
{{ end }}
|
{{end}}
|
||||||
User management
|
User management
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
Loading…
Reference in New Issue