diff --git a/internal/dis/component/server/admin/admin.go b/internal/dis/component/server/admin/admin.go index bd56c73..a57e02e 100644 --- a/internal/dis/component/server/admin/admin.go +++ b/internal/dis/component/server/admin/admin.go @@ -124,13 +124,13 @@ func (admin *Admin) HandleRoute(ctx context.Context, route string) (handler http { rebuild := admin.instanceRebuild(ctx) - router.Handler(http.MethodGet, route+"rebuild/:slug", rebuild) + router.Handler(http.MethodGet, route+"instance/:slug/rebuild", rebuild) } { - grants := admin.grants(ctx) - router.Handler(http.MethodGet, route+"grants/:slug", grants) - router.Handler(http.MethodPost, route+"grants/", grants) // NOTE(twiesing): This path is intentionally different! + iUsers := admin.instanceUsers(ctx) + router.Handler(http.MethodGet, route+"instance/:slug/users", iUsers) + router.Handler(http.MethodPost, route+"grants/", iUsers) // NOTE(twiesing): This path is intentionally different! } // add a router for the login page diff --git a/internal/dis/component/server/admin/html/instance.html b/internal/dis/component/server/admin/html/instance.html index 4e47d68..5161325 100644 --- a/internal/dis/component/server/admin/html/instance.html +++ b/internal/dis/component/server/admin/html/instance.html @@ -6,7 +6,6 @@
Info & Status Drupal Status Report - Users (Drupal) WissKI Data Statistics SSH Keys @@ -346,93 +345,6 @@
-
-

Users (Drupal)

- Manage Grants -
- -
-
-
- - - - - - - - - - - - - - - - {{ $slug := .Instance.Slug }} - {{ $csrf := .CSRF }} - {{ range $index, $user := .Info.Users }} - - - - - - - - - - - - {{ end }} - -
- ID - - Active - - Name - - Email - - Roles - - Created - - Last Login - - Action -
- {{ $user.UID }} - - {{ $user.Status }} - - {{ $user.Name }} - - {{ if $user.Mail }} - {{ $user.Mail }} - {{ end }} - - {{ range $role, $unuused := $user.Roles }} - - {{ $role }} - - {{ end }} - - {{ $user.Created.Time.Format "2006-01-02T15:04:05Z07:00" }} - - {{ $user.Login.Time.Format "2006-01-02T15:04:05Z07:00" }} - -
- - - - {{ $csrf }} -
-
-
-
-
-

WissKI Data

diff --git a/internal/dis/component/server/admin/html/grants.html b/internal/dis/component/server/admin/html/instance_users.html similarity index 58% rename from internal/dis/component/server/admin/html/grants.html rename to internal/dis/component/server/admin/html/instance_users.html index fa152aa..cdf65ea 100644 --- a/internal/dis/component/server/admin/html/grants.html +++ b/internal/dis/component/server/admin/html/instance_users.html @@ -1,5 +1,102 @@ {{ $csrf := .CSRF }} {{ $slug := .Instance.Slug }} + + +
+

Users

+ +

+ This page provides a list of users found in this Drupal instance. + You can click the login button to authenticate as that user. +
+ Please be aware that these never end an already existing session. + When already logged into drupal, an error message Access denied may appear. + To prevent this, log out of the drupal instance before clicking the button. +

+
+ +
+
+
+ + + + + + + + + + + + + + + + {{ $slug := .Instance.Slug }} + {{ $csrf := .CSRF }} + {{ range $index, $user := .Users }} + + + + + + + + + + + + {{ end }} + +
+ ID + + Active + + Name + + Email + + Roles + + Created + + Last Login + + Action +
+ {{ $user.UID }} + + {{ $user.Status }} + + {{ $user.Name }} + + {{ if $user.Mail }} + {{ $user.Mail }} + {{ end }} + + {{ range $role, $unuused := $user.Roles }} + + {{ $role }} + + {{ end }} + + {{ $user.Created.Time.Format "2006-01-02T15:04:05Z07:00" }} + + {{ $user.Login.Time.Format "2006-01-02T15:04:05Z07:00" }} + +
+ + + + {{ $csrf }} +
+
+
+
+
+

Grants

@@ -116,7 +213,7 @@ {{ end }} - {{ range $unused, $drupal := .Drupals }} - \ No newline at end of file diff --git a/internal/dis/component/server/admin/instance.go b/internal/dis/component/server/admin/instance.go index 961a622..13b7ca9 100644 --- a/internal/dis/component/server/admin/instance.go +++ b/internal/dis/component/server/admin/instance.go @@ -40,10 +40,6 @@ func (admin *Admin) instance(ctx context.Context) http.Handler { menuInstances, menuInstance, ), - templating.Actions( - menuRebuild, - menuGrants, - ), ) return tpl.HTMLHandlerWithFlags(func(r *http.Request) (ic instanceContext, funcs []templating.FlagFunc, err error) { @@ -67,12 +63,36 @@ func (admin *Admin) instance(ctx context.Context) http.Handler { funcs = []templating.FlagFunc{ templating.ReplaceCrumb(menuInstance, component.MenuItem{Title: "Instance", Path: template.URL("/admin/instance/" + slug)}), - templating.ReplaceAction(menuRebuild, component.MenuItem{Title: "Rebuild", Path: template.URL("/admin/rebuild/" + slug)}), - templating.ReplaceAction(menuGrants, component.MenuItem{Title: "Grants", Path: template.URL("/admin/grants/" + slug)}), - templating.Title(instance.Slug), + + admin.instanceTabs(slug, "overview"), } return }) } + +// instanceTabs +func (admin *Admin) instanceTabs(slug string, active string) templating.FlagFunc { + return func(flags templating.Flags, r *http.Request) templating.Flags { + flags.Tabs = []component.MenuItem{ + {Title: "Overview", Path: template.URL("/admin/instance/" + slug), Active: active == "overview"}, + {Title: "Rebuild", Path: template.URL("/admin/instance/" + slug + "/rebuild"), Active: active == "rebuild"}, + {Title: "Users & Grants", Path: template.URL("/admin/instance/" + slug + "/users"), Active: active == "users"}, + + // TODO: These still need to be migrated to their own tabs + // Then we also need to redo the main page + /* + {Title: "Status", Path: template.URL("/instance/" + slug + "/status"), Active: active == "status"}, + {Title: "Database", Path: template.URL("/instance/" + slug + "/database"), Active: active == "database"}, + {Title: "Drupal", Path: template.URL("/instance/" + slug + "/drupal"), Active: active == "drupal"}, + {Title: "Users & Grants", Path: template.URL("/instance/" + slug + "/users"), Active: active == "users"}, + {Title: "Stats", Path: template.URL("/instance/" + slug + "/stats"), Active: active == "stats"}, + {Title: "SSH", Path: template.URL("/instance/" + slug + "/ssh"), Active: active == "ssh"}, + {Title: "Snapshots", Path: template.URL("/instance/" + slug + "/snapshots"), Active: active == "snapshots"}, + {Title: "Danger Zone", Path: template.URL("/instance/" + slug + "/danger"), Active: active == "danger"}, + */ + } + return flags + } +} diff --git a/internal/dis/component/server/admin/instance_rebuild.go b/internal/dis/component/server/admin/instance_rebuild.go index 75ec07c..ad9b226 100644 --- a/internal/dis/component/server/admin/instance_rebuild.go +++ b/internal/dis/component/server/admin/instance_rebuild.go @@ -83,8 +83,9 @@ func (admin *Admin) instanceRebuild(ctx context.Context) http.Handler { // replace the menu item funcs = []templating.FlagFunc{ templating.ReplaceCrumb(menuInstance, component.MenuItem{Title: "Instance", Path: template.URL("/admin/instance/" + instance.Slug)}), - templating.ReplaceCrumb(menuRebuild, component.MenuItem{Title: "Rebuild", Path: template.URL("/admin/rebuild/" + instance.Slug)}), + templating.ReplaceCrumb(menuRebuild, component.MenuItem{Title: "Rebuild", Path: template.URL("/admin/instance/" + instance.Slug + "/rebuild")}), templating.Title(instance.Slug + " - Rebuild"), + admin.instanceTabs(slug, "rebuild"), } isc.prepare(true) diff --git a/internal/dis/component/server/admin/grants.go b/internal/dis/component/server/admin/instance_users.go similarity index 70% rename from internal/dis/component/server/admin/grants.go rename to internal/dis/component/server/admin/instance_users.go index 4743eb9..19935ff 100644 --- a/internal/dis/component/server/admin/grants.go +++ b/internal/dis/component/server/admin/instance_users.go @@ -12,6 +12,7 @@ import ( "github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/assets" "github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/templating" "github.com/FAU-CDI/wisski-distillery/internal/models" + "github.com/FAU-CDI/wisski-distillery/internal/status" "github.com/FAU-CDI/wisski-distillery/internal/wisski" "github.com/tkw1536/pkglib/httpx" "github.com/tkw1536/pkglib/httpx/field" @@ -21,15 +22,15 @@ import ( "golang.org/x/exp/slices" ) -//go:embed "html/grants.html" -var grantsHTML []byte -var grantsTemplate = templating.Parse[grantsContext]( - "grants.html", grantsHTML, nil, +//go:embed "html/instance_users.html" +var instanceUsersHTML []byte +var instanceUsersTemplate = templating.Parse[instanceUsersContext]( + "instance_users.html", instanceUsersHTML, nil, templating.Assets(assets.AssetsAdmin), ) -type grantsContext struct { +type instanceUsersContext struct { templating.RuntimeFlags Error string @@ -37,13 +38,14 @@ type grantsContext struct { instance *wisski.WissKI Instance models.Instance // current instance - Grants []models.Grant // grants that exist for the user + Users []status.DrupalUser // drupal users + Usernames []string // unuused distillery usernames - Drupals []string // unusued drupal usernames + Grants []models.Grant // grants that exist for the user } -func (admin *Admin) grants(ctx context.Context) http.Handler { - tpl := grantsTemplate.Prepare( +func (admin *Admin) instanceUsers(ctx context.Context) http.Handler { + tpl := instanceUsersTemplate.Prepare( admin.dependencies.Templating, templating.Crumbs( menuAdmin, @@ -53,16 +55,16 @@ func (admin *Admin) grants(ctx context.Context) http.Handler { ), ) - return tpl.HTMLHandlerWithFlags(func(r *http.Request) (grantsContext, []templating.FlagFunc, error) { + return tpl.HTMLHandlerWithFlags(func(r *http.Request) (instanceUsersContext, []templating.FlagFunc, error) { if r.Method == http.MethodGet { - return admin.getGrants(r) + return admin.getGrantsUsers(r) } else { - return admin.postGrants(r) + return admin.postInstanceUsers(r) } }) } -func (admin *Admin) getGrants(r *http.Request) (gc grantsContext, funcs []templating.FlagFunc, err error) { +func (admin *Admin) getGrantsUsers(r *http.Request) (gc instanceUsersContext, funcs []templating.FlagFunc, err error) { slug := httprouter.ParamsFromContext(r.Context()).ByName("slug") funcs, err = gc.use(r, slug, admin) @@ -70,14 +72,14 @@ func (admin *Admin) getGrants(r *http.Request) (gc grantsContext, funcs []templa return gc, nil, err } - if err := gc.useGrants(r, admin); err != nil { + if err := gc.useUsers(r, admin); err != nil { return gc, nil, err } return gc, funcs, nil } -func (admin *Admin) postGrants(r *http.Request) (gc grantsContext, funcs []templating.FlagFunc, err error) { +func (admin *Admin) postInstanceUsers(r *http.Request) (gc instanceUsersContext, funcs []templating.FlagFunc, err error) { // parse the form if err := r.ParseForm(); err != nil { return gc, nil, err @@ -119,13 +121,13 @@ func (admin *Admin) postGrants(r *http.Request) (gc grantsContext, funcs []templ } // fetch the grants for the instance - if err := gc.useGrants(r, admin); err != nil { + if err := gc.useUsers(r, admin); err != nil { return gc, nil, err } return gc, funcs, nil } -func (gc *grantsContext) use(r *http.Request, slug string, admin *Admin) (funcs []templating.FlagFunc, err error) { +func (gc *instanceUsersContext) use(r *http.Request, slug string, admin *Admin) (funcs []templating.FlagFunc, err error) { // find the instance itself gc.instance, err = admin.dependencies.Instances.WissKI(r.Context(), slug) if err == instances.ErrWissKINotFound { @@ -139,13 +141,14 @@ func (gc *grantsContext) use(r *http.Request, slug string, admin *Admin) (funcs // replace the functions funcs = []templating.FlagFunc{ templating.ReplaceCrumb(menuInstance, component.MenuItem{Title: "Instance", Path: template.URL("/admin/instance/" + slug)}), - templating.ReplaceCrumb(menuGrants, component.MenuItem{Title: "Grants", Path: template.URL("/admin/grants/" + slug)}), - templating.Title(gc.Instance.Slug + " - Grants"), + templating.ReplaceCrumb(menuGrants, component.MenuItem{Title: "Users & Grants", Path: template.URL("/admin/instance/" + slug + "/users")}), + templating.Title(gc.Instance.Slug + " - Users & Grants"), + admin.instanceTabs(slug, "users"), } return funcs, nil } -func (gc *grantsContext) useGrants(r *http.Request, admin *Admin) (err error) { +func (gc *instanceUsersContext) useUsers(r *http.Request, admin *Admin) (err error) { gc.Grants, err = admin.dependencies.Policy.Instance(r.Context(), gc.Instance.Slug) if err != nil { return err @@ -169,18 +172,14 @@ func (gc *grantsContext) useGrants(r *http.Request, admin *Admin) (err error) { gc.Usernames = maps.Keys(userNameMap) slices.Sort(gc.Usernames) - // get the drupal usernames - drupals, err := gc.instance.Users().All(r.Context(), nil) + // get the drupal user data + gc.Users, 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) + slices.SortFunc(gc.Users, func(a, b status.DrupalUser) int { + return int(b.UID) - int(a.UID) + }) return nil }