Documentation
¶
Index ¶
- Constants
- func AdminHomeURL(r *http.Request) string
- func Breadcrumbs(breadcrumbs []Breadcrumb) hb.TagInterface
- func Endpoint(r *http.Request) string
- func ErrorAlert(message string) string
- func ErrorPopup(errorMessage string) hb.TagInterface
- func FlashError(flashRedirect FlashRedirectFunc, w http.ResponseWriter, r *http.Request, ...) string
- func FlashSuccess(flashRedirect FlashRedirectFunc, w http.ResponseWriter, r *http.Request, ...) string
- func JSEscapeString(s string) string
- func Layout(w http.ResponseWriter, r *http.Request, webpageTitle, webpageHtml string, ...) string
- func SuccessPopup(successMessage string) hb.TagInterface
- func SuccessPopupWithRedirect(successMessage string, redirectUrl string, redirectSeconds int) hb.TagInterface
- func URL(endpoint string, controller string, params map[string]string) string
- func URLR(r *http.Request, controller string, params map[string]string) string
- func UserAdminURL(r *http.Request) string
- func UserHomeURL(r *http.Request) string
- func VueLoaderScript() hb.TagInterface
- type Breadcrumb
- type FlashRedirectFunc
- type Links
- func (l *Links) Home(params map[string]string) string
- func (l *Links) UserCreate(params map[string]string) string
- func (l *Links) UserDelete(params map[string]string) string
- func (l *Links) UserImpersonate(params map[string]string) string
- func (l *Links) UserManager(params map[string]string) string
- func (l *Links) UserUpdate(params map[string]string) string
- type UiBase
- func (u UiBase) AuthUser(r *http.Request) userstore.UserInterface
- func (u UiBase) BlindIndexEmail() blindindexstore.StoreInterface
- func (u UiBase) BlindIndexFirstName() blindindexstore.StoreInterface
- func (u UiBase) BlindIndexLastName() blindindexstore.StoreInterface
- func (u UiBase) BlindIndexRebuildTaskAlias() string
- func (u UiBase) FlashRedirect() FlashRedirectFunc
- func (u UiBase) GeoStore() geostore.StoreInterface
- func (u UiBase) Layout(w http.ResponseWriter, r *http.Request, webpageTitle, webpageHtml string, ...) string
- func (u UiBase) Logger() *slog.Logger
- func (u UiBase) SecureCookie() bool
- func (u UiBase) SessionStore() sessionstore.StoreInterface
- func (u UiBase) TaskStore() taskstore.StoreInterface
- func (u UiBase) UserStore() userstore.StoreInterface
- func (u UiBase) VaultTokenizer() VaultTokenizer
- type UiConfig
- type UiInterface
- type VaultTokenizer
Constants ¶
const ( CONTROLLER_USER_MANAGER = "user-manager" CONTROLLER_USER_CREATE = "user-create" CONTROLLER_USER_DELETE = "user-delete" CONTROLLER_USER_UPDATE = "user-update" CONTROLLER_USER_IMPERSONATE = "user-impersonate" )
Controller names used in the ?controller= query parameter
const CatchAll = "/*"
CatchAll is the catch-all route suffix
const ERROR_LOGGER_IS_NIL = "logger cannot be nil"
const ERROR_USER_STORE_IS_NIL = "user store cannot be nil"
Error messages
const KeyAdminHomeURL = "admin_home_url"
const KeyEndpoint = "endpoint"
Context keys for config values injected by Handle()
const KeyUserAdminURL = "user_admin_url"
const KeyUserHomeURL = "user_home_url"
const VueLoaderJS = `` /* 479-byte string literal not displayed */
VueLoaderJS is a JavaScript snippet that defines loadVueIfNeeded(). It checks whether Vue is already loaded (e.g. by the layout) and, if not, loads it from the CDN dynamically before invoking the callback.
Every controller that needs Vue includes this snippet once (via the layout or directly). Component JS files then wrap their mount call in:
loadVueIfNeeded((err) => {
if (err) { console.error('Vue load failed:', err); return; }
const { createApp } = Vue;
const el = document.getElementById('my-app');
if (el) createApp(MyApp).mount('#my-app');
});
This avoids double-loading Vue when the layout already provides it.
Variables ¶
This section is empty.
Functions ¶
func AdminHomeURL ¶
AdminHomeURL returns the admin home URL from request context
func Breadcrumbs ¶
func Breadcrumbs(breadcrumbs []Breadcrumb) hb.TagInterface
Breadcrumbs renders a breadcrumb navigation from the given items
func ErrorAlert ¶
ErrorAlert returns an inline HTML error alert for the given message. This replaces the former ToFlashError flash-message pattern, which required a cache store and a /flash route handler that did not exist in the standalone module.
func ErrorPopup ¶
func ErrorPopup(errorMessage string) hb.TagInterface
ErrorPopup returns a SweetAlert2 error popup tag.
func FlashError ¶
func FlashError(flashRedirect FlashRedirectFunc, w http.ResponseWriter, r *http.Request, message, redirectURL string, seconds int) string
FlashError performs a flash redirect for an error message. If flashRedirect is nil, it falls back to a plain http.Redirect.
func FlashSuccess ¶
func FlashSuccess(flashRedirect FlashRedirectFunc, w http.ResponseWriter, r *http.Request, message, redirectURL string, seconds int) string
FlashSuccess performs a flash redirect for a success message. If flashRedirect is nil, it falls back to a plain http.Redirect.
func JSEscapeString ¶
JSEscapeString escapes a string for safe embedding inside a JavaScript single-quoted string literal. It escapes backslash, single quote, and newlines so that user-supplied values (e.g. user IDs from URL params) cannot break out of the string context.
func Layout ¶
func Layout(w http.ResponseWriter, r *http.Request, webpageTitle, webpageHtml string, options struct { Styles []string StyleURLs []string Scripts []string ScriptURLs []string }) string
Layout is the default layout renderer. It builds a complete HTML page using hb.NewWebpage() with Bootstrap + Vue CDN, matching the blogadmin/shopadmin pattern. If a FuncLayout is provided in AdminOptions, it takes precedence over this default.
func SuccessPopup ¶
func SuccessPopup(successMessage string) hb.TagInterface
SuccessPopup returns a SweetAlert2 success popup tag.
func SuccessPopupWithRedirect ¶
func SuccessPopupWithRedirect(successMessage string, redirectUrl string, redirectSeconds int) hb.TagInterface
SuccessPopupWithRedirect returns a SweetAlert2 success popup with an optional redirect. If redirectUrl is empty, no redirect is configured.
func URL ¶
URL builds a URL for the given endpoint and controller with params. The controller is placed in the params map under the "controller" key. The params map is copied before mutation (does not modify caller's map).
func UserAdminURL ¶
UserAdminURL returns the user admin base URL from request context
func UserHomeURL ¶
UserHomeURL returns the user home URL from request context. Used by the impersonate controller to redirect after a successful impersonation.
func VueLoaderScript ¶
func VueLoaderScript() hb.TagInterface
VueLoaderScript returns the loadVueIfNeeded definition as an hb.Tag so controllers can inject it into their container divs. This ensures the guard is available even when a host project provides a custom FuncLayout that does not include VueLoaderJS.
Types ¶
type Breadcrumb ¶
Breadcrumb represents a single breadcrumb navigation item
type FlashRedirectFunc ¶
type FlashRedirectFunc func(w http.ResponseWriter, r *http.Request, messageType, message, redirectURL string, seconds int) string
FlashRedirectFunc redirects the user with a flash message. Host projects that have a flash-message system (cache store + /flash route) provide this callback so useradmin can surface messages across redirects. If nil, useradmin falls back to a plain http.Redirect and the message is dropped.
messageType is one of "error", "success", "info", "warning".
type Links ¶
type Links struct {
// contains filtered or unexported fields
}
Links provides URL helpers for useradmin controllers. The base URL is read from request context (injected by Handle()), not hardcoded. This follows the blogadmin/shopadmin pattern.
func NewLinks ¶
NewLinks creates a Links helper with the given base URL. If baseURL is empty, defaults to "/admin/users".
func NewLinksFromRequest ¶
NewLinksFromRequest creates a Links helper using the user admin URL from the request context.
func (*Links) UserCreate ¶
UserCreate builds the URL for the user create controller
func (*Links) UserDelete ¶
UserDelete builds the URL for the user delete controller
func (*Links) UserImpersonate ¶
UserImpersonate builds the URL for the user impersonate controller
func (*Links) UserManager ¶
UserManager builds the URL for the user manager controller
type UiBase ¶
type UiBase struct {
UserStoreField userstore.StoreInterface
GeoStoreField geostore.StoreInterface
LoggerField *slog.Logger
SessionStoreField sessionstore.StoreInterface
BlindIndexFirstNameField blindindexstore.StoreInterface
BlindIndexLastNameField blindindexstore.StoreInterface
BlindIndexEmailField blindindexstore.StoreInterface
TaskStoreField taskstore.StoreInterface
BlindIndexRebuildTaskAliasField string
VaultTokenizerField VaultTokenizer
AuthUserField func(r *http.Request) userstore.UserInterface
FlashRedirectField FlashRedirectFunc
SecureCookieField bool
LayoutField func(w http.ResponseWriter, r *http.Request, webpageTitle, webpageHtml string, options struct {
Styles []string
StyleURLs []string
Scripts []string
ScriptURLs []string
}) string
}
UiBase is a base struct that implements shared.UiInterface. Subcontroller ui structs can embed this to get all the accessor methods for free, following the blogadmin/shopadmin pattern.
func (UiBase) BlindIndexEmail ¶
func (u UiBase) BlindIndexEmail() blindindexstore.StoreInterface
func (UiBase) BlindIndexFirstName ¶
func (u UiBase) BlindIndexFirstName() blindindexstore.StoreInterface
func (UiBase) BlindIndexLastName ¶
func (u UiBase) BlindIndexLastName() blindindexstore.StoreInterface
func (UiBase) BlindIndexRebuildTaskAlias ¶
func (UiBase) FlashRedirect ¶
func (u UiBase) FlashRedirect() FlashRedirectFunc
func (UiBase) GeoStore ¶
func (u UiBase) GeoStore() geostore.StoreInterface
func (UiBase) SecureCookie ¶
func (UiBase) SessionStore ¶
func (u UiBase) SessionStore() sessionstore.StoreInterface
func (UiBase) TaskStore ¶
func (u UiBase) TaskStore() taskstore.StoreInterface
func (UiBase) UserStore ¶
func (u UiBase) UserStore() userstore.StoreInterface
func (UiBase) VaultTokenizer ¶
func (u UiBase) VaultTokenizer() VaultTokenizer
type UiConfig ¶
type UiConfig struct {
UserStore userstore.StoreInterface
GeoStore geostore.StoreInterface
Logger *slog.Logger
// SessionStore is required for the impersonate controller.
SessionStore sessionstore.StoreInterface
// BlindIndexFirstName/LastName/Email enable filtered search by
// the corresponding field. Optional.
BlindIndexFirstName blindindexstore.StoreInterface
BlindIndexLastName blindindexstore.StoreInterface
BlindIndexEmail blindindexstore.StoreInterface
// TaskStore is used to enqueue a blind index rebuild when a user's
// email changes and vault tokenization is enabled. Optional.
TaskStore taskstore.StoreInterface
// BlindIndexRebuildTaskAlias is the task alias enqueued on email
// change. If empty, the enqueue is skipped.
BlindIndexRebuildTaskAlias string
// VaultTokenizer abstracts vault tokenization. Optional — when
// nil, user fields are treated as plain text.
VaultTokenizer VaultTokenizer
// AuthUser returns the authenticated user from the request, or
// nil if unauthenticated. Used by the create/delete/impersonate
// controllers for authorization checks.
AuthUser func(r *http.Request) userstore.UserInterface
// FlashRedirect redirects with a flash message. Optional — when
// nil, plain http.Redirect is used.
FlashRedirect FlashRedirectFunc
// SecureCookie controls whether the impersonation cookie is marked
// Secure. Set to false for HTTP (development), true for HTTPS
// (production). Defaults to true.
SecureCookie bool
// Layout is the layout renderer callback.
Layout func(w http.ResponseWriter, r *http.Request, webpageTitle, webpageHtml string, options struct {
Styles []string
StyleURLs []string
Scripts []string
ScriptURLs []string
}) string
}
UiConfig holds the dependencies passed to subcontroller UI factories. This follows the blogadmin/shopadmin pattern.
UserStore, GeoStore, and Logger are required for core controllers. SessionStore is required for the impersonate controller. The blind index stores are optional — when nil, the corresponding search filter is disabled. VaultTokenizer is optional — when nil, user fields are treated as plain text. TaskStore is optional — when nil, blind index rebuild enqueue on email change is skipped.
type UiInterface ¶
type UiInterface interface {
UserStore() userstore.StoreInterface
GeoStore() geostore.StoreInterface
Logger() *slog.Logger
SessionStore() sessionstore.StoreInterface
BlindIndexFirstName() blindindexstore.StoreInterface
BlindIndexLastName() blindindexstore.StoreInterface
BlindIndexEmail() blindindexstore.StoreInterface
TaskStore() taskstore.StoreInterface
BlindIndexRebuildTaskAlias() string
VaultTokenizer() VaultTokenizer
AuthUser(r *http.Request) userstore.UserInterface
FlashRedirect() FlashRedirectFunc
SecureCookie() bool
Layout(w http.ResponseWriter, r *http.Request, webpageTitle, webpageHtml string, options struct {
Styles []string
StyleURLs []string
Scripts []string
ScriptURLs []string
}) string
}
UiInterface defines the methods every subcontroller UI must implement. This follows the blogadmin/shopadmin pattern.
type VaultTokenizer ¶
type VaultTokenizer interface {
// Tokenize upserts tokens for the given user fields and returns
// the resulting token strings to store on the user record.
Tokenize(
ctx context.Context,
user userstore.UserInterface,
firstName, lastName, email, phone, businessName string,
) (firstNameToken, lastNameToken, emailToken, phoneToken, businessNameToken string, err error)
// Untokenize resolves the tokenized fields on the given user back
// to their plain-text values.
Untokenize(
ctx context.Context,
user userstore.UserInterface,
) (firstName, lastName, email, phone, businessName string, err error)
}
VaultTokenizer abstracts vault tokenization/untokenization of user fields (first name, last name, email, phone, business name).
Host projects that use a vault store provide an implementation so useradmin can read and write tokenized user data without depending on any specific vault config or key management. If nil, useradmin treats user fields as plain text.