mirror of
https://github.com/Theodor-Springmann-Stiftung/musenalm.git
synced 2025-10-29 17:25:32 +00:00
nutzer einladen + sesssion cache correct clear
This commit is contained in:
@@ -99,6 +99,28 @@ func (c *UserSessionCache) Delete(sessionTokenClear string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *UserSessionCache) DeleteSessionByUserID(uid string) {
|
||||||
|
if uid == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.cache.Range(func(key, value any) bool {
|
||||||
|
entry, ok := value.(*cacheEntry)
|
||||||
|
if !ok {
|
||||||
|
c.cache.Delete(key)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if entry.user.Id == uid {
|
||||||
|
c.cache.Delete(key)
|
||||||
|
c.mu.Lock()
|
||||||
|
c.approximateSize--
|
||||||
|
c.mu.Unlock()
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (c *UserSessionCache) Clear() {
|
func (c *UserSessionCache) Clear() {
|
||||||
c.cache.Clear()
|
c.cache.Clear()
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/Theodor-Springmann-Stiftung/musenalm/middleware"
|
"github.com/Theodor-Springmann-Stiftung/musenalm/middleware"
|
||||||
"github.com/Theodor-Springmann-Stiftung/musenalm/pagemodels"
|
"github.com/Theodor-Springmann-Stiftung/musenalm/pagemodels"
|
||||||
"github.com/Theodor-Springmann-Stiftung/musenalm/templating"
|
"github.com/Theodor-Springmann-Stiftung/musenalm/templating"
|
||||||
|
"github.com/pocketbase/dbx"
|
||||||
"github.com/pocketbase/pocketbase/core"
|
"github.com/pocketbase/pocketbase/core"
|
||||||
"github.com/pocketbase/pocketbase/tools/router"
|
"github.com/pocketbase/pocketbase/tools/router"
|
||||||
)
|
)
|
||||||
@@ -76,6 +77,32 @@ func (p *UserEditPage) GET(engine *templating.Engine, app core.App) HandleFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DeleteSessionsForUser(app core.App, uid string) error {
|
||||||
|
defer middleware.SESSION_CACHE.DeleteSessionByUserID(uid)
|
||||||
|
records := []*core.Record{}
|
||||||
|
err := app.RecordQuery(dbmodels.SESSIONS_TABLE).
|
||||||
|
Where(dbx.HashExp{dbmodels.SESSIONS_USER_FIELD: uid}).
|
||||||
|
All(&records)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = app.RunInTransaction(func(tx core.App) error {
|
||||||
|
for _, r := range records {
|
||||||
|
if err := tx.Delete(r); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func InvalidDataResponse(engine *templating.Engine, e *core.RequestEvent, error string, user *dbmodels.FixedUser) error {
|
func InvalidDataResponse(engine *templating.Engine, e *core.RequestEvent, error string, user *dbmodels.FixedUser) error {
|
||||||
data := make(map[string]any)
|
data := make(map[string]any)
|
||||||
data["error"] = error
|
data["error"] = error
|
||||||
@@ -153,10 +180,12 @@ func (p *UserEditPage) POST(engine *templating.Engine, app core.App) HandleFunc
|
|||||||
user_proxy.SetEmail(formdata.Email)
|
user_proxy.SetEmail(formdata.Email)
|
||||||
user_proxy.SetName(formdata.Name)
|
user_proxy.SetName(formdata.Name)
|
||||||
|
|
||||||
|
rolechanged := false
|
||||||
if formdata.Role != "" && formdata.Role != user_proxy.Role() {
|
if formdata.Role != "" && formdata.Role != user_proxy.Role() {
|
||||||
if user.Role == "Admin" &&
|
if user.Role == "Admin" &&
|
||||||
(formdata.Role == "User" || formdata.Role == "Editor" || formdata.Role == "Admin") {
|
(formdata.Role == "User" || formdata.Role == "Editor" || formdata.Role == "Admin") {
|
||||||
user_proxy.SetRole(formdata.Role)
|
user_proxy.SetRole(formdata.Role)
|
||||||
|
rolechanged = true
|
||||||
} else {
|
} else {
|
||||||
return InvalidDataResponse(engine, e, "Rolle nicht erlaubt", &fu)
|
return InvalidDataResponse(engine, e, "Rolle nicht erlaubt", &fu)
|
||||||
}
|
}
|
||||||
@@ -180,8 +209,16 @@ func (p *UserEditPage) POST(engine *templating.Engine, app core.App) HandleFunc
|
|||||||
return InvalidDataResponse(engine, e, err.Error(), &fu)
|
return InvalidDataResponse(engine, e, err.Error(), &fu)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this is lazy, we just need to delete the sessions of the changed user
|
if rolechanged {
|
||||||
middleware.SESSION_CACHE.Clear()
|
if err := DeleteSessionsForUser(app, user_proxy.Id); err != nil {
|
||||||
|
return InvalidDataResponse(engine, e, "Fehler beim Löschen der Sitzungen: "+err.Error(), &fu)
|
||||||
|
}
|
||||||
|
|
||||||
|
if user_proxy.Id == user.Id {
|
||||||
|
// INFO: user changed his own role, so we log him out
|
||||||
|
return e.Redirect(303, "/login/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fu = user_proxy.Fixed()
|
fu = user_proxy.Fixed()
|
||||||
data["user"] = &fu
|
data["user"] = &fu
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -33,7 +33,7 @@
|
|||||||
{{ end }}
|
{{ end }}
|
||||||
<form class="w-full grid grid-cols-3 gap-4" method="POST" x-data="{ openpw: false }">
|
<form class="w-full grid grid-cols-3 gap-4" method="POST" x-data="{ openpw: false }">
|
||||||
<div
|
<div
|
||||||
class="col-span-3 border-2 border-transparent px-2
|
class="rounded-xs col-span-3 border-2 border-transparent px-3
|
||||||
py-1 pb-1.5 border-l-2 focus-within:border-l-slate-600
|
py-1 pb-1.5 border-l-2 focus-within:border-l-slate-600
|
||||||
bg-slate-200 focus-within:bg-slate-100 transition-all duration-100">
|
bg-slate-200 focus-within:bg-slate-100 transition-all duration-100">
|
||||||
<label for="username" class="text-sm text-gray-700 font-bold">
|
<label for="username" class="text-sm text-gray-700 font-bold">
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
type="text"
|
type="text"
|
||||||
name="name"
|
name="name"
|
||||||
id="name"
|
id="name"
|
||||||
class="mt-1 block w-full rounded-md focus:border-none focus:outline-none"
|
class="mt-1 block w-full focus:border-none focus:outline-none"
|
||||||
placeholder=""
|
placeholder=""
|
||||||
required
|
required
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
autofocus />
|
autofocus />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="col-span-3 border-2 border-transparent px-2
|
class="rounded-xs col-span-3 border-2 border-transparent px-3
|
||||||
py-1 pb-1.5 border-l-2 focus-within:border-l-slate-600
|
py-1 pb-1.5 border-l-2 focus-within:border-l-slate-600
|
||||||
bg-slate-200 focus-within:bg-slate-100 transition-all duration-100">
|
bg-slate-200 focus-within:bg-slate-100 transition-all duration-100">
|
||||||
<label for="username" class="text-sm text-gray-700 font-bold">
|
<label for="username" class="text-sm text-gray-700 font-bold">
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
value="{{ $model.user.Email }}" />
|
value="{{ $model.user.Email }}" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="col-span-3 border-2 border-transparent px-2
|
class="rounded-xs col-span-3 border-2 border-transparent px-3
|
||||||
py-1 pb-1.5 border-l-2 focus-within:border-l-slate-600
|
py-1 pb-1.5 border-l-2 focus-within:border-l-slate-600
|
||||||
bg-slate-200 focus-within:bg-slate-100 transition-all duration-100">
|
bg-slate-200 focus-within:bg-slate-100 transition-all duration-100">
|
||||||
<label for="role" class="text-sm text-gray-700 font-bold">
|
<label for="role" class="text-sm text-gray-700 font-bold">
|
||||||
@@ -94,6 +94,32 @@
|
|||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
{{- if and
|
||||||
|
(eq $model.request.user.Role "Admin")
|
||||||
|
(eq $model.request.user.Id
|
||||||
|
$model.user.Id)
|
||||||
|
-}}
|
||||||
|
<div class="flex flex-row col-span-3">
|
||||||
|
<div class="align-top">
|
||||||
|
<i class="ri-information-line text-gray-700 mt-2 mr-2 align-top"></i>
|
||||||
|
</div>
|
||||||
|
<p class="text-sm text-gray-700 max-w-[80ch]">
|
||||||
|
Achtung! Wenn Sie Ihre eigenen Berechtigungen ändern, verlieren Sie die Möglichkeit,
|
||||||
|
diese Änderungen rückgängig zu machen. Weiter werden Sie von allen laufenden Sitzungen
|
||||||
|
abgemeldet und müssen sich erneut anmelden.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{{- else if (eq $model.request.user.Role "Admin") -}}
|
||||||
|
<div class="flex flex-row col-span-3">
|
||||||
|
<div class="align-top">
|
||||||
|
<i class="ri-information-line text-gray-700 mt-2 mr-2 align-top"></i>
|
||||||
|
</div>
|
||||||
|
<p class="text-sm text-gray-700 max-w-[80ch]">
|
||||||
|
Achtung! Wenn Sie die Rolle eines Benutzers ändern, wird dieser von allen laufenden
|
||||||
|
Sitzungen abgemeldet und muss sich erneut anmelden.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
<div class="col-span-3">
|
<div class="col-span-3">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<input type="checkbox" name="openpw" id="openpw" x-model="openpw" class="mr-2" />
|
<input type="checkbox" name="openpw" id="openpw" x-model="openpw" class="mr-2" />
|
||||||
@@ -105,7 +131,7 @@
|
|||||||
{{- if not (eq $model.request.user.Role "Admin") -}}
|
{{- if not (eq $model.request.user.Role "Admin") -}}
|
||||||
<div
|
<div
|
||||||
x-bind:style="!openpw ? 'display:none' : ''"
|
x-bind:style="!openpw ? 'display:none' : ''"
|
||||||
class="col-span-3 border-2 border-transparent px-2
|
class="rounded-xs col-span-3 border-2 border-transparent px-3
|
||||||
py-1 pb-1.5 border-l-2 focus-within:border-l-slate-600
|
py-1 pb-1.5 border-l-2 focus-within:border-l-slate-600
|
||||||
bg-slate-200 focus-within:bg-slate-100 transition-all duration-100">
|
bg-slate-200 focus-within:bg-slate-100 transition-all duration-100">
|
||||||
<label for="password_old" class="text-sm text-gray-700 font-bold"> Altes Passwort </label>
|
<label for="password_old" class="text-sm text-gray-700 font-bold"> Altes Passwort </label>
|
||||||
@@ -120,7 +146,7 @@
|
|||||||
{{- end -}}
|
{{- end -}}
|
||||||
<div
|
<div
|
||||||
x-bind:style="!openpw ? 'display:none' : ''"
|
x-bind:style="!openpw ? 'display:none' : ''"
|
||||||
class="col-span-3 border-2 border-transparent px-2
|
class="rounded-xs col-span-3 border-2 border-transparent px-3
|
||||||
py-1 pb-1.5 border-l-2 focus-within:border-l-slate-600
|
py-1 pb-1.5 border-l-2 focus-within:border-l-slate-600
|
||||||
bg-slate-200 focus-within:bg-slate-100 transition-all duration-100">
|
bg-slate-200 focus-within:bg-slate-100 transition-all duration-100">
|
||||||
<label for="password" class="text-sm text-gray-700 font-bold"> Neues Passwort </label>
|
<label for="password" class="text-sm text-gray-700 font-bold"> Neues Passwort </label>
|
||||||
@@ -135,7 +161,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
x-bind:style="!openpw ? 'display:none' : ''"
|
x-bind:style="!openpw ? 'display:none' : ''"
|
||||||
class="col-span-3 border-2 border-transparent px-2
|
class="rounded-xs col-span-3 border-2 border-transparent px-3
|
||||||
py-1 pb-1.5 border-l-2 focus-within:border-l-slate-600
|
py-1 pb-1.5 border-l-2 focus-within:border-l-slate-600
|
||||||
bg-slate-200 focus-within:bg-slate-100 transition-all duration-100">
|
bg-slate-200 focus-within:bg-slate-100 transition-all duration-100">
|
||||||
<label for="password_repeat" class="text-sm text-gray-700 font-bold">
|
<label for="password_repeat" class="text-sm text-gray-700 font-bold">
|
||||||
|
|||||||
@@ -88,131 +88,135 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="user-invites flex container-normal mx-auto px-8 mt-4">
|
<div class="user-invites flex container-normal mx-auto px-8 mt-4">
|
||||||
<div class="flex-col max-w-xl w-full">
|
<div class="flex flex-row w-full">
|
||||||
<div
|
<div class="flex-col max-w-xl w-full">
|
||||||
class="col-span-9 grid grid-cols-3 justify-between mb-4 py-1 px-1 border rounded-xs gap-x-2
|
<!-- QR Code -->
|
||||||
bg-slate-200 user-chooser">
|
<div class="mb-4 p-4 border rounded-xs hidden" id="qr"></div>
|
||||||
<a
|
|
||||||
href="/user/management/access/User?redirectTo={{ $model.redirect_url }}"
|
<!-- Access URL and Token -->
|
||||||
class="text-center px-4 text-gray-700 hover:text-slate-950 block"
|
<div class="mb-6 flex flex-col">
|
||||||
{{ if eq $model.role "User" }}aria-current="page"{{ end }}>
|
<div class="flex flex-row">
|
||||||
Benutzer
|
<input
|
||||||
</a>
|
type="text"
|
||||||
<a
|
name="token"
|
||||||
href="/user/management/access/Editor?redirectTo={{ $model.redirect_url }}"
|
id="token"
|
||||||
class="text-gray-700 hover:text-slate-950 block px-4 text-center"
|
class="w-full text-center border border-slate-300 rounded-xs
|
||||||
{{ if eq $model.role "Editor" }}aria-current="page"{{ end }}>
|
|
||||||
Redakteur
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="/user/management/access/Admin?redirectTo={{ $model.redirect_url }}"
|
|
||||||
class="text-gray-700 hover:text-slate-950 text-center px-4 block"
|
|
||||||
{{ if eq $model.role "Admin" }}aria-current="page"{{ end }}>
|
|
||||||
Admin
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<!--
|
|
||||||
<div class="flex justify-center mt-8 items-baseline">
|
|
||||||
<div>
|
|
||||||
<img class="h-20 w-20 border" src="/assets/favicon.png" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
-->
|
|
||||||
<div class="col-span-7 col-start-2 mb-4 p-4 border rounded-xs hidden" id="qr"></div>
|
|
||||||
<div class="col-span-9 mb-6 flex flex-col">
|
|
||||||
<div class="flex flex-row">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
name="token"
|
|
||||||
id="token"
|
|
||||||
class="w-full text-center border border-slate-300 rounded-xs
|
|
||||||
focus:border-slate-500 focus:ring-slate-500 p-1 px-2 overflow-ellipsis"
|
focus:border-slate-500 focus:ring-slate-500 p-1 px-2 overflow-ellipsis"
|
||||||
value="{{ $model.access_url }}"
|
value="{{ $model.access_url }}"
|
||||||
deactive
|
deactive
|
||||||
readonly />
|
readonly />
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="ml-2 inline-flex justify-center py-2 px-3 border border-transparent
|
class="ml-2 inline-flex justify-center py-2 px-3 border border-transparent
|
||||||
rounded-xs
|
rounded-xs
|
||||||
shadow-sm text-sm font-medium text-white bg-slate-700 hover:bg-slate-800 cursor-pointer
|
shadow-sm text-sm font-medium text-white bg-slate-700 hover:bg-slate-800 cursor-pointer
|
||||||
focus:outline-none no-underline
|
focus:outline-none no-underline
|
||||||
focus:ring-2 focus:ring-offset-2 focus:ring-slate-500"
|
focus:ring-2 focus:ring-offset-2 focus:ring-slate-500"
|
||||||
onclick="navigator.clipboard.writeText('{{ $model.access_url }}')">
|
onclick="navigator.clipboard.writeText('{{ $model.access_url }}')">
|
||||||
<i class="ri-file-copy-line"></i>
|
<i class="ri-file-copy-line"></i>
|
||||||
</button>
|
</button>
|
||||||
<a
|
<a
|
||||||
href="{{ $model.relative_url }}"
|
href="{{ $model.relative_url }}"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
class="ml-2 inline-flex justify-center py-2 px-3 border border-transparent
|
class="ml-2 inline-flex justify-center py-2 px-3 border border-transparent
|
||||||
rounded-xs
|
rounded-xs
|
||||||
shadow-sm text-sm font-medium text-white bg-slate-700 hover:bg-slate-800 cursor-pointer
|
shadow-sm text-sm font-medium text-white bg-slate-700 hover:bg-slate-800 cursor-pointer
|
||||||
focus:outline-none no-underline
|
focus:outline-none no-underline
|
||||||
focus:ring-2 focus:ring-offset-2 focus:ring-slate-500">
|
focus:ring-2 focus:ring-offset-2 focus:ring-slate-500">
|
||||||
<i class="ri-external-link-line"></i>
|
<i class="ri-external-link-line"></i>
|
||||||
</a>
|
</a>
|
||||||
<form class="" method="POST">
|
<form class="" method="POST">
|
||||||
<input
|
<input
|
||||||
type="hidden"
|
type="hidden"
|
||||||
name="csrf_nonce"
|
name="csrf_nonce"
|
||||||
id="csrf_nonce"
|
id="csrf_nonce"
|
||||||
required
|
required
|
||||||
value="{{ $model.csrf_nonce }}" />
|
value="{{ $model.csrf_nonce }}" />
|
||||||
<input
|
<input
|
||||||
type="hidden"
|
type="hidden"
|
||||||
name="csrf_token"
|
name="csrf_token"
|
||||||
id="csrf_token"
|
id="csrf_token"
|
||||||
required
|
required
|
||||||
value="{{ $model.csrf_token }}" />
|
value="{{ $model.csrf_token }}" />
|
||||||
|
<div class="col-span-9 flex flex-row items-center justify-center">
|
||||||
<div class="col-span-9 flex flex-row items-center justify-center">
|
<button
|
||||||
<button
|
type="submit"
|
||||||
type="submit"
|
class="ml-2 inline-flex justify-center py-2 px-3 border border-transparent
|
||||||
class="ml-2 inline-flex justify-center py-2 px-3 border border-transparent
|
|
||||||
rounded-xs
|
rounded-xs
|
||||||
shadow-sm text-sm font-medium text-white bg-slate-700 hover:bg-slate-800 cursor-pointer
|
shadow-sm text-sm font-medium text-white bg-slate-700 hover:bg-slate-800 cursor-pointer
|
||||||
focus:outline-none no-underline
|
focus:outline-none no-underline
|
||||||
focus:ring-2 focus:ring-offset-2 focus:ring-slate-500">
|
focus:ring-2 focus:ring-offset-2 focus:ring-slate-500">
|
||||||
<i class="ri-loop-left-line"></i>
|
<i class="ri-loop-left-line"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="text-right text-slate-400 mb-1 mt-3">
|
||||||
|
Gültig bis
|
||||||
|
{{ $model.validUntil }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-9 text-right text-slate-400 mb-1 mt-3">
|
<!-- End of Access URL and Token -->
|
||||||
Gültig bis
|
|
||||||
{{ $model.validUntil }}
|
|
||||||
</div>
|
|
||||||
{{ if eq $model.role "User" }}
|
|
||||||
<div class="max-w-[60ch] mt-1 text-sm text-blue-600 flex flex-row gap-x-2 hyphens-auto">
|
|
||||||
<div>
|
|
||||||
<i class="ri-error-warning-line"></i>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
Benutzer können private Felder und Datensätze einsehen, aber nicht bearbeiten oder
|
|
||||||
löschen.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{ else if eq $model.role "Admin" }}
|
|
||||||
<div class="max-w-[60ch] mt-1 text-sm text-red-600 flex flex-row gap-x-2 hyphens-auto">
|
|
||||||
<div>
|
|
||||||
<i class="ri-error-warning-line"></i>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
Administratoren können alle Felder und Datensätze einsehen, bearbeiten und löschen.
|
|
||||||
Administratoren können Passwörter setzen, Nutzer einladen und deaktivieren.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{ else if eq $model.role "Editor" }}
|
|
||||||
<div class="max-w-[60ch] mt-1 text-sm text-orange-600 flex flex-row gap-x-2 hyphens-auto">
|
|
||||||
<div>
|
|
||||||
<i class="ri-error-warning-line"></i>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
Redakteure können alle Felder und Datensätze der Datenbank einsehen, bearbeiten und
|
|
||||||
löschen.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{- end -}}
|
|
||||||
</div>
|
</div>
|
||||||
|
<!-- End of First Column -->
|
||||||
|
|
||||||
|
<!-- Second column -->
|
||||||
|
<div class="ml-12 flex flex-col">
|
||||||
|
<!-- User Role Chooser -->
|
||||||
|
<div class="user-chooser flex flex-col gap-y-3">
|
||||||
|
<a
|
||||||
|
href="/user/management/access/User?redirectTo={{ $model.redirect_url }}"
|
||||||
|
{{ if eq $model.role "User" }}aria-current="page"{{ end }}>
|
||||||
|
Benutzer
|
||||||
|
</a>
|
||||||
|
{{ if eq $model.role "User" }}
|
||||||
|
<div class="max-w-[60ch] text-sm text-blue-600 flex flex-row gap-x-2 hyphens-auto">
|
||||||
|
<div>
|
||||||
|
<i class="ri-error-warning-line"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Benutzer können private Felder und Datensätze einsehen, aber nicht bearbeiten oder
|
||||||
|
löschen.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
|
<a
|
||||||
|
href="/user/management/access/Editor?redirectTo={{ $model.redirect_url }}"
|
||||||
|
{{ if eq $model.role "Editor" }}aria-current="page"{{ end }}>
|
||||||
|
Redakteur
|
||||||
|
</a>
|
||||||
|
{{- if eq $model.role "Editor" -}}
|
||||||
|
<div class="max-w-[60ch] text-sm text-orange-600 flex flex-row gap-x-2 hyphens-auto">
|
||||||
|
<div>
|
||||||
|
<i class="ri-error-warning-line"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Redakteure können alle Felder und Datensätze der Datenbank einsehen, bearbeiten und
|
||||||
|
löschen.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
|
<a
|
||||||
|
href="/user/management/access/Admin?redirectTo={{ $model.redirect_url }}"
|
||||||
|
{{ if eq $model.role "Admin" }}aria-current="page"{{ end }}>
|
||||||
|
Admin
|
||||||
|
</a>
|
||||||
|
{{- if eq $model.role "Admin" -}}
|
||||||
|
<div class="max-w-[60ch] text-sm text-red-600 flex flex-row gap-x-2 hyphens-auto">
|
||||||
|
<div>
|
||||||
|
<i class="ri-error-warning-line"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Administratoren können alle Felder und Datensätze einsehen, bearbeiten und löschen.
|
||||||
|
Administratoren können Passwörter setzen, Nutzer einladen und deaktivieren.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
|
</div>
|
||||||
|
<!-- End of User Role Chooser -->
|
||||||
|
</div>
|
||||||
|
<!-- End of second column -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
<title>Musenalm – Nutzer einladen</title>
|
||||||
|
|||||||
@@ -512,12 +512,24 @@
|
|||||||
@apply !text-slate-900 bg-stone-50;
|
@apply !text-slate-900 bg-stone-50;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-invites .user-chooser a {
|
.user-chooser a {
|
||||||
@apply py-1 rounded-xs no-underline;
|
@apply px-4 py-2 no-underline text-gray-500 hover:text-slate-900 font-serif font-bold border-l-4 border-transparent hover:bg-slate-100 transition-all duration-75 rounded-xs;
|
||||||
}
|
}
|
||||||
|
|
||||||
.user-invites .user-chooser a[aria-current="page"] {
|
.user-chooser a[aria-current="page"] {
|
||||||
@apply font-bold !bg-stone-50 relative border-b z-20 shadow;
|
@apply text-slate-900 font-bold bg-slate-100 border-slate-900 shadow-sm;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-chooser a[aria-current="page"]:nth-child(1) {
|
||||||
|
@apply border-blue-500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-chooser a[aria-current="page"]:nth-child(2) {
|
||||||
|
@apply border-orange-600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-chooser a[aria-current="page"]:nth-child(3) {
|
||||||
|
@apply border-red-600;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
|
|||||||
Reference in New Issue
Block a user