diff --git a/internal/config/http.go b/internal/config/http.go
index 5bda9f2..2a56771 100644
--- a/internal/config/http.go
+++ b/internal/config/http.go
@@ -2,12 +2,10 @@ package config
import (
"fmt"
- "net/http"
"net/url"
"strings"
"github.com/FAU-CDI/wisski-distillery/internal/config/validators"
- "github.com/tkw1536/pkglib/httpx"
"golang.org/x/net/idna"
)
@@ -31,26 +29,6 @@ type HTTPConfig struct {
API validators.NullableBool `yaml:"api" validate:"bool" default:"false"`
}
-var apiNotEnabled = httpx.Response{
- StatusCode: http.StatusForbidden,
- Body: []byte(`{"message":"API is not enabled"}`),
-}
-
-func (hcfg HTTPConfig) APIDecorator(methods ...string) func(http.Handler) http.Handler {
- methods = append(methods, "OPTIONS") // always permit the options method!
-
- if !hcfg.API.Value {
- return func(http.Handler) http.Handler {
- return httpx.PermitMethods(apiNotEnabled, methods...)
- }
- }
-
- // permit only the specified methods
- return func(h http.Handler) http.Handler {
- return httpx.PermitMethods(h, methods...)
- }
-}
-
// JoinPath returns the root public url joined with the provided parts.
func (hcfg HTTPConfig) JoinPath(elem ...string) *url.URL {
u := url.URL{
diff --git a/internal/dis/component/auth/api/handler.go b/internal/dis/component/auth/api/handler.go
new file mode 100644
index 0000000..8b321c9
--- /dev/null
+++ b/internal/dis/component/auth/api/handler.go
@@ -0,0 +1,175 @@
+// Package api implements a common handler used by the api routes
+package api
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net/http"
+
+ "github.com/FAU-CDI/wisski-distillery/internal/config"
+ "github.com/FAU-CDI/wisski-distillery/internal/dis/component/auth"
+ "github.com/FAU-CDI/wisski-distillery/internal/dis/component/auth/scopes"
+ "github.com/rs/zerolog"
+ "github.com/tkw1536/pkglib/httpx"
+ "github.com/tkw1536/pkglib/lazy"
+)
+
+// Handler represents an API handler that returns a REST response.
+// The response is automatically marshaled using T.
+type Handler[T any] struct {
+ Config *config.Config
+ Auth *auth.Auth // Handler to handle Auth
+
+ Methods []string // HTTP methods to allow
+ methods lazy.Lazy[map[string]struct{}]
+
+ Scope scopes.Scope
+ ScopeParam func(*http.Request) string
+ Handler func(string, *http.Request) (T, error)
+}
+
+var apiNotEnabled = &Response{
+ Status: http.StatusNotImplemented,
+ Message: "API is not implemented on this server",
+}
+
+var apiMethodNotAllowed = &Response{
+ Status: http.StatusMethodNotAllowed,
+ Message: "method not allowed",
+}
+
+var apiInternalServerError = &Response{
+ Status: http.StatusInternalServerError,
+ Message: "internal server error",
+}
+
+var apiBadRequest = &Response{
+ Status: http.StatusBadRequest,
+ Message: "bad request",
+}
+
+var apiNotFound = &Response{
+ Status: http.StatusNotFound,
+ Message: "not found",
+}
+
+var apiForbidden = &Response{
+ Status: http.StatusForbidden,
+ Message: "forbidden",
+}
+
+// ServeHTTP servers an api call
+func (handler *Handler[T]) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ // check that the api is actually enabled!
+ if !handler.Config.HTTP.API.Value {
+ apiNotEnabled.ServeHTTP(w, r)
+ return
+ }
+
+ // get the permitted methods
+ methods := handler.methods.Get(func() map[string]struct{} {
+ m := make(map[string]struct{}, len(handler.Methods)+1)
+ for _, method := range handler.Methods {
+ m[method] = struct{}{}
+ }
+ m["OPTIONS"] = struct{}{}
+ return m
+ })
+
+ // check that the method is permitted
+ if _, ok := methods[r.Method]; !ok {
+ apiMethodNotAllowed.ServeHTTP(w, r)
+ return
+ }
+
+ // we now delegate to user-level code;
+ // so we now need to make sure that panic()s are caught.
+ var stage string
+ defer func() {
+ // recover any error
+ rec := recover()
+ if rec == nil {
+ return
+ }
+
+ // log the error, and serve the default internal server error
+ zerolog.Ctx(r.Context()).Error().Str("panic", fmt.Sprint(rec)).Str("stage", stage).Str("route", r.URL.RequestURI()).Msg("api handler caused panic()")
+ apiInternalServerError.ServeHTTP(w, r)
+ }()
+
+ // read the parameter
+ stage = "param"
+ var param string
+ if handler.ScopeParam != nil {
+ param = handler.ScopeParam(r)
+ }
+
+ // check that the scope is correct
+ stage = "scope"
+ if err := handler.Auth.CheckScope(param, handler.Scope, r); err != nil {
+ (&Response{
+ Status: http.StatusForbidden,
+ Message: err.Error(),
+ }).ServeHTTP(w, r)
+ return
+ }
+
+ stage = "handler"
+
+ result, err := handler.Handler(param, r)
+ switch true {
+ case err == nil: /* keep going */
+
+ // handle common httpx errors
+ case errors.Is(err, httpx.ErrInternalServerError):
+ apiInternalServerError.ServeHTTP(w, r)
+ return
+ case errors.Is(err, httpx.ErrBadRequest):
+ apiBadRequest.ServeHTTP(w, r)
+ return
+ case errors.Is(err, httpx.ErrNotFound):
+ apiNotFound.ServeHTTP(w, r)
+ return
+ case errors.Is(err, httpx.ErrForbidden):
+ apiForbidden.ServeHTTP(w, r)
+ return
+ case errors.Is(err, httpx.ErrMethodNotAllowed):
+ apiMethodNotAllowed.ServeHTTP(w, r)
+ return
+
+ // generic error
+ default:
+ (&Response{
+ Status: http.StatusInternalServerError,
+ Message: err.Error(),
+ }).ServeHTTP(w, r)
+ return
+ }
+
+ stage = "marshal"
+
+ // encode the result into json and send it as the response
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ json.NewEncoder(w).Encode(result)
+}
+
+// Response represents a generic response to any request.
+// Response objects cache response serialization
+type Response struct {
+ Status int `json:"status"`
+ Message string `json:"message"`
+ res lazy.Lazy[httpx.Response]
+}
+
+func (g *Response) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ g.res.Get(func() httpx.Response {
+ bytes, _ := json.Marshal(g)
+ return httpx.Response{
+ ContentType: "application/json",
+ Body: bytes,
+ StatusCode: g.Status,
+ }
+ }).ServeHTTP(w, r)
+}
diff --git a/internal/dis/component/auth/next/next.go b/internal/dis/component/auth/next/next.go
index 00483e4..9c85c56 100644
--- a/internal/dis/component/auth/next/next.go
+++ b/internal/dis/component/auth/next/next.go
@@ -8,6 +8,7 @@ import (
"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/policy"
+ "github.com/FAU-CDI/wisski-distillery/internal/dis/component/auth/scopes"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/instances"
"github.com/FAU-CDI/wisski-distillery/internal/wisski"
"github.com/FAU-CDI/wisski-distillery/internal/wisski/ingredient/php/users"
@@ -30,7 +31,7 @@ var (
func (next *Next) Routes() component.Routes {
return component.Routes{
Prefix: "/next/",
- Decorator: next.Dependencies.Auth.Require(component.ScopeUserLoggedIn, nil),
+ Decorator: next.Dependencies.Auth.Require(scopes.ScopeUserLoggedIn, nil),
}
}
diff --git a/internal/dis/component/auth/panel/panel.go b/internal/dis/component/auth/panel/panel.go
index 78906ac..f686c91 100644
--- a/internal/dis/component/auth/panel/panel.go
+++ b/internal/dis/component/auth/panel/panel.go
@@ -8,6 +8,7 @@ import (
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/auth"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/auth/next"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/auth/policy"
+ "github.com/FAU-CDI/wisski-distillery/internal/dis/component/auth/scopes"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/instances"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/templating"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/ssh2"
@@ -39,7 +40,7 @@ func (panel *UserPanel) Routes() component.Routes {
return component.Routes{
Prefix: "/user/",
CSRF: true,
- Decorator: panel.Dependencies.Auth.Require(component.ScopeUserLoggedIn, nil),
+ Decorator: panel.Dependencies.Auth.Require(scopes.ScopeUserLoggedIn, nil),
}
}
@@ -115,7 +116,7 @@ func (panel *UserPanel) HandleRoute(ctx context.Context, route string) (http.Han
}
// ensure that the user is logged in!
- return panel.Dependencies.Auth.Protect(router, component.ScopeUserLoggedIn, nil), nil
+ return panel.Dependencies.Auth.Protect(router, scopes.ScopeUserLoggedIn, nil), nil
}
type userFormContext struct {
diff --git a/internal/dis/component/auth/scopes/admin.go b/internal/dis/component/auth/scopes/admin.go
index 3918bc2..2bf1da1 100644
--- a/internal/dis/component/auth/scopes/admin.go
+++ b/internal/dis/component/auth/scopes/admin.go
@@ -18,9 +18,13 @@ var (
_ component.ScopeProvider = (*UserLoggedIn)(nil)
)
+const (
+ ScopeAdminLoggedIn Scope = "login.admin"
+)
+
func (*AdminLoggedIn) Scope() component.ScopeInfo {
return component.ScopeInfo{
- Scope: component.ScopeAdminLoggedIn,
+ Scope: ScopeAdminLoggedIn,
Description: "session has a signed in admin",
DeniedMessage: "user must be signed into an admin account with TOTP enabled",
TakesParam: false,
diff --git a/internal/dis/component/auth/scopes/instances.go b/internal/dis/component/auth/scopes/instances.go
new file mode 100644
index 0000000..1bb7002
--- /dev/null
+++ b/internal/dis/component/auth/scopes/instances.go
@@ -0,0 +1,38 @@
+package scopes
+
+import (
+ "net/http"
+
+ "github.com/FAU-CDI/wisski-distillery/internal/dis/component"
+ "github.com/FAU-CDI/wisski-distillery/internal/dis/component/auth"
+)
+
+type ListInstancesScope struct {
+ component.Base
+ Dependencies struct {
+ Auth *auth.Auth
+ }
+}
+
+var (
+ _ component.ScopeProvider = (*ListInstancesScope)(nil)
+)
+
+const (
+ ScopeInstanceDirectory Scope = "instances.directory"
+)
+
+func (*ListInstancesScope) Scope() component.ScopeInfo {
+ return component.ScopeInfo{
+ Scope: ScopeInstanceDirectory,
+ Description: "get a public directory of instances",
+ DeniedMessage: "",
+ TakesParam: false,
+ }
+}
+
+func (lis *ListInstancesScope) HasScope(param string, r *http.Request) (bool, error) {
+ // TODO: at the moment everyone has this permission
+ // this should change in the future!
+ return true, nil
+}
diff --git a/internal/dis/component/auth/scopes/news.go b/internal/dis/component/auth/scopes/news.go
new file mode 100644
index 0000000..3e38ddd
--- /dev/null
+++ b/internal/dis/component/auth/scopes/news.go
@@ -0,0 +1,37 @@
+package scopes
+
+import (
+ "net/http"
+
+ "github.com/FAU-CDI/wisski-distillery/internal/dis/component"
+ "github.com/FAU-CDI/wisski-distillery/internal/dis/component/auth"
+)
+
+type ListNewsScope struct {
+ component.Base
+ Dependencies struct {
+ Auth *auth.Auth
+ }
+}
+
+var (
+ _ component.ScopeProvider = (*ListNewsScope)(nil)
+)
+
+const (
+ ScopeListNews Scope = "news.list"
+)
+
+func (*ListNewsScope) Scope() component.ScopeInfo {
+ return component.ScopeInfo{
+ Scope: ScopeListNews,
+ Description: "list news items",
+ DeniedMessage: "",
+ TakesParam: false,
+ }
+}
+
+func (lns *ListNewsScope) HasScope(param string, r *http.Request) (bool, error) {
+ // TODO: at the moment everyone has this permission
+ return true, nil
+}
diff --git a/internal/dis/component/auth/scopes/scopes.go b/internal/dis/component/auth/scopes/scopes.go
new file mode 100644
index 0000000..b55fe4a
--- /dev/null
+++ b/internal/dis/component/auth/scopes/scopes.go
@@ -0,0 +1,6 @@
+// Package scopes implements and provides scopes used by the API
+package scopes
+
+import "github.com/FAU-CDI/wisski-distillery/internal/dis/component"
+
+type Scope = component.Scope
diff --git a/internal/dis/component/auth/scopes/user.go b/internal/dis/component/auth/scopes/user.go
index 6d055d5..97c62ec 100644
--- a/internal/dis/component/auth/scopes/user.go
+++ b/internal/dis/component/auth/scopes/user.go
@@ -18,9 +18,13 @@ var (
_ component.ScopeProvider = (*UserLoggedIn)(nil)
)
+const (
+ ScopeUserLoggedIn Scope = "login.user"
+)
+
func (*UserLoggedIn) Scope() component.ScopeInfo {
return component.ScopeInfo{
- Scope: component.ScopeUserLoggedIn,
+ Scope: ScopeUserLoggedIn,
Description: "session has an associated user",
TakesParam: false,
}
diff --git a/internal/dis/component/resolver/resolver.go b/internal/dis/component/resolver/resolver.go
index df9353d..76da377 100644
--- a/internal/dis/component/resolver/resolver.go
+++ b/internal/dis/component/resolver/resolver.go
@@ -11,6 +11,7 @@ import (
"github.com/FAU-CDI/wdresolve/resolvers"
"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/scopes"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/instances"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/assets"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/templating"
@@ -102,7 +103,7 @@ func (resolver *Resolver) HandleRoute(ctx context.Context, route string) (http.H
IndexContext: context,
}
- if resolver.Dependencies.Auth.CheckScope("", component.ScopeUserLoggedIn, r) != nil {
+ if resolver.Dependencies.Auth.CheckScope("", scopes.ScopeUserLoggedIn, r) != nil {
ctx.IndexContext.Prefixes = nil
}
httpx.WriteHTML(tpl.Context(r, ctx), nil, t, "", w, r)
diff --git a/internal/dis/component/scope.go b/internal/dis/component/scope.go
index 08e2489..9912265 100644
--- a/internal/dis/component/scope.go
+++ b/internal/dis/component/scope.go
@@ -51,11 +51,6 @@ func (scope ScopeInfo) CheckError(err error) error {
return CheckError{Scope: scope.Scope, Err: err}
}
-const (
- ScopeUserLoggedIn Scope = "login.user"
- ScopeAdminLoggedIn Scope = "login.admin"
-)
-
// ScopeProvider is a component that can check a specific scope
type ScopeProvider interface {
Component
diff --git a/internal/dis/component/server/admin/admin.go b/internal/dis/component/server/admin/admin.go
index 14e1c00..ece8512 100644
--- a/internal/dis/component/server/admin/admin.go
+++ b/internal/dis/component/server/admin/admin.go
@@ -7,6 +7,7 @@ import (
"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/policy"
+ "github.com/FAU-CDI/wisski-distillery/internal/dis/component/auth/scopes"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/admin/socket"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/templating"
"github.com/julienschmidt/httprouter"
@@ -46,12 +47,12 @@ func (admin *Admin) Routes() component.Routes {
return component.Routes{
Prefix: "/admin/",
CSRF: true,
- Decorator: admin.Dependencies.Auth.Require(component.ScopeAdminLoggedIn, nil),
+ Decorator: admin.Dependencies.Auth.Require(scopes.ScopeAdminLoggedIn, nil),
}
}
func (admin *Admin) Menu(r *http.Request) []component.MenuItem {
- if admin.Dependencies.Auth.CheckScope("", component.ScopeAdminLoggedIn, r) != nil {
+ if admin.Dependencies.Auth.CheckScope("", scopes.ScopeAdminLoggedIn, r) != nil {
return nil
}
return []component.MenuItem{
diff --git a/internal/dis/component/server/home/api.go b/internal/dis/component/server/home/api.go
deleted file mode 100644
index cfb6439..0000000
--- a/internal/dis/component/server/home/api.go
+++ /dev/null
@@ -1,64 +0,0 @@
-package home
-
-import (
- "context"
- "net/http"
- "time"
-
- "github.com/FAU-CDI/wisski-distillery/internal/dis/component"
- "github.com/FAU-CDI/wisski-distillery/internal/status"
- "github.com/tkw1536/pkglib/httpx"
-)
-
-type API struct {
- component.Base
-
- Dependencies struct {
- Home *Home
- }
-}
-
-var (
- _ component.Routeable = (*API)(nil)
-)
-
-func (api *API) Routes() component.Routes {
- return component.Routes{
- Prefix: "/api/v1/systems",
- Exact: true,
- Decorator: api.Config.HTTP.APIDecorator("GET"),
- }
-}
-
-type APISystemInfo struct {
- Slug string
- URL string
- Tagline string
-
- EntityCount int
- BundleCount int
- LastEdit time.Time
-}
-
-func (api *API) HandleRoute(ctx context.Context, path string) (http.Handler, error) {
- return httpx.JSON(func(r *http.Request) ([]APISystemInfo, error) {
- var statuses []status.WissKI
- if api.Dependencies.Home.ShouldShowList(r) {
- statuses = api.Dependencies.Home.homeInstances.Get(nil)
- }
-
- if len(statuses) == 0 {
- return []APISystemInfo{}, nil
- }
-
- infos := make([]APISystemInfo, len(statuses))
- for i, status := range statuses {
- infos[i].Slug = status.Slug
- infos[i].URL = status.URL
- infos[i].EntityCount = status.Statistics.Bundles.TotalCount()
- infos[i].BundleCount = status.Statistics.Bundles.TotalBundles
- infos[i].LastEdit = status.Statistics.Bundles.LastEdit().Time
- }
- return infos, nil
- }), nil
-}
diff --git a/internal/dis/component/server/home/home.go b/internal/dis/component/server/home/home.go
index 3643c0a..4fab5b6 100644
--- a/internal/dis/component/server/home/home.go
+++ b/internal/dis/component/server/home/home.go
@@ -6,23 +6,16 @@ import (
"net/http"
"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/instances"
+ "github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/list"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/server/templating"
- "github.com/FAU-CDI/wisski-distillery/internal/status"
- "github.com/tkw1536/pkglib/lazy"
)
type Home struct {
component.Base
Dependencies struct {
- Templating *templating.Templating
- Instances *instances.Instances
- Auth *auth.Auth
+ ListInstances *list.ListInstances
+ Templating *templating.Templating
}
-
- instanceNames lazy.Lazy[map[string]struct{}] // instance names
- homeInstances lazy.Lazy[[]status.WissKI] // list of home instances (updated via cron)
}
var (
@@ -61,21 +54,8 @@ func (home *Home) HandleRoute(ctx context.Context, route string) (http.Handler,
}), nil
}
-func (home *Home) instanceMap(ctx context.Context) (map[string]struct{}, error) {
- wissKIs, err := home.Dependencies.Instances.All(ctx)
- if err != nil {
- return nil, err
- }
-
- names := make(map[string]struct{}, len(wissKIs))
- for _, w := range wissKIs {
- names[w.Slug] = struct{}{}
- }
- return names, nil
-}
-
func (home *Home) serveWissKI(w http.ResponseWriter, slug string, r *http.Request) {
- if _, ok := home.instanceNames.Get(nil)[slug]; !ok {
+ if _, ok := home.Dependencies.ListInstances.Names()[slug]; !ok {
// Get(nil) guaranteed to work by precondition
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "WissKI %q not found\n", slug)
diff --git a/internal/dis/component/server/home/instances.go b/internal/dis/component/server/home/instances.go
deleted file mode 100644
index 0bceca2..0000000
--- a/internal/dis/component/server/home/instances.go
+++ /dev/null
@@ -1,86 +0,0 @@
-package home
-
-import (
- "context"
-
- "github.com/FAU-CDI/wisski-distillery/internal/dis/component"
- "github.com/FAU-CDI/wisski-distillery/internal/status"
- "golang.org/x/sync/errgroup"
-)
-
-// loadInstances loads all the instances into the home route
-func (home *Home) loadInstances(ctx context.Context) ([]status.WissKI, error) {
- // find all the WissKIs
- wissKIs, err := home.Dependencies.Instances.All(ctx)
- if err != nil {
- return nil, err
- }
-
- instances := make([]status.WissKI, len(wissKIs))
-
- // determine their infos
- var eg errgroup.Group
- for i, instance := range wissKIs {
- i := i
- wissKI := instance
- eg.Go(func() (err error) {
- instances[i], err = wissKI.Info().Information(ctx, false)
- return
- })
- }
- eg.Wait()
-
- // and return the new instances
- return instances, nil
-}
-
-// UpdateInstanceList updates the instances list of the home struct
-type UpdateInstanceList struct {
- component.Base
- Dependencies struct {
- Home *Home
- }
-}
-
-var (
- _ component.Cronable = (*UpdateInstanceList)(nil)
-)
-
-func (*UpdateInstanceList) TaskName() string {
- return "instance list"
-}
-
-func (ul *UpdateInstanceList) Cron(ctx context.Context) error {
- names, err := ul.Dependencies.Home.instanceMap(ctx)
- if err != nil {
- return err
- }
-
- ul.Dependencies.Home.instanceNames.Set(names)
- return nil
-}
-
-type UpdateHome struct {
- component.Base
- Dependencies struct {
- Home *Home
- }
-}
-
-var (
- _ component.Cronable = (*UpdateHome)(nil)
-)
-
-func (ur *UpdateHome) TaskName() string {
- return "home instances fetch"
-}
-
-func (ur *UpdateHome) Cron(ctx context.Context) error {
- instances, err := ur.Dependencies.Home.loadInstances(ctx)
- if err != nil {
- return err
- }
-
- ur.Dependencies.Home.homeInstances.Set(instances)
- return nil
-}
diff --git a/internal/dis/component/server/home/public.go b/internal/dis/component/server/home/public.go
index e0bf880..7b669c8 100644
--- a/internal/dis/component/server/home/public.go
+++ b/internal/dis/component/server/home/public.go
@@ -47,23 +47,6 @@ type publicContext struct {
const logoHTML = template.HTML(``)
-// ShouldShowList determines if the given request should show a WissKI list
-func (home *Home) ShouldShowList(r *http.Request) bool {
- allowPrivate := home.Config.Home.List.Private.Value
- allowPublic := home.Config.Home.List.Public.Value
-
- if allowPrivate == allowPublic {
- return allowPrivate
- }
-
- user, _ := home.Dependencies.Auth.UserOf(r)
- if user == nil {
- return allowPublic
- } else {
- return allowPrivate
- }
-}
-
func (home *Home) publicHandler(ctx context.Context) http.Handler {
title := home.Config.Home.Title
@@ -89,7 +72,7 @@ func (home *Home) publicHandler(ctx context.Context) http.Handler {
// prepare about
pc.aboutContext.Logo = logoHTML
- pc.aboutContext.Instances = home.homeInstances.Get(nil)
+ pc.aboutContext.Instances = home.Dependencies.ListInstances.Infos()
pc.aboutContext.SelfRedirect = home.Config.Home.SelfRedirect.String()
// render the about template
@@ -102,7 +85,7 @@ func (home *Home) publicHandler(ctx context.Context) http.Handler {
pc.About = template.HTML(builder.String())
// check if we should show the list of WissKIs
- pc.ListEnabled = home.ShouldShowList(r)
+ pc.ListEnabled = home.Dependencies.ListInstances.ShouldShowList(r)
// title of the list
pc.ListTitle = home.Config.Home.List.Title
diff --git a/internal/dis/component/server/home/public.html b/internal/dis/component/server/home/public.html
index 8712032..b5a5ac9 100644
--- a/internal/dis/component/server/home/public.html
+++ b/internal/dis/component/server/home/public.html
@@ -6,22 +6,20 @@
{{range .Instances}}
- {{ if and .Running (not .NoPrefixes) }}
-
- {{.URL}}
+ {{.URL}}
-
- {{ .Statistics.Bundles.Summary }}
+ {{.Slug}}
+
+
+ {{ .Statistics.Bundles.Summary }}
- {{ $edit := .Statistics.Bundles.LastEdit }}
- {{ if $edit.Valid }}
-
- last edited {{ $edit.Time.Format "2006-01-02T15:04:05Z07:00" }}
- {{ end }}
-
-
+ last edited {{ $edit.Time.Format "2006-01-02T15:04:05Z07:00" }}
+ {{ end }}
+
+