shared

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 26, 2026 License: AGPL-3.0 Imports: 8 Imported by: 0

Documentation

Index

Constants

View Source
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

View Source
const CatchAll = "/*"

CatchAll is the catch-all route suffix

View Source
const ERROR_LOGGER_IS_NIL = "logger cannot be nil"
View Source
const ERROR_USER_STORE_IS_NIL = "user store cannot be nil"

Error messages

View Source
const KeyAdminHomeURL = "admin_home_url"
View Source
const KeyEndpoint = "endpoint"

Context keys for config values injected by Handle()

View Source
const KeyUserAdminURL = "user_admin_url"
View Source
const KeyUserHomeURL = "user_home_url"
View Source
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

func AdminHomeURL(r *http.Request) string

AdminHomeURL returns the admin home URL from request context

func Breadcrumbs(breadcrumbs []Breadcrumb) hb.TagInterface

Breadcrumbs renders a breadcrumb navigation from the given items

func Endpoint

func Endpoint(r *http.Request) string

Endpoint returns the request endpoint URL from context

func ErrorAlert

func ErrorAlert(message string) string

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

func JSEscapeString(s string) string

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

func URL(endpoint string, controller string, params map[string]string) string

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 URLR

func URLR(r *http.Request, controller string, params map[string]string) string

URLR builds a URL using the endpoint from the request context.

func UserAdminURL

func UserAdminURL(r *http.Request) string

UserAdminURL returns the user admin base URL from request context

func UserHomeURL

func UserHomeURL(r *http.Request) string

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 struct {
	Name string
	URL  string
}

Breadcrumb represents a single breadcrumb navigation item

type Country added in v0.2.0

type Country struct {
	IsoCode2 string
	Name     string
}

Country is a single country entry returned by GeoResolverInterface.

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 GeoResolverInterface added in v0.2.0

type GeoResolverInterface interface {
	// Countries returns all countries.
	Countries(ctx context.Context) ([]Country, error)

	// Timezones returns timezones for the given country code. The
	// country code is optional — pass no argument or an empty string
	// when no country is selected; implementations should return an
	// empty list in that case.
	Timezones(ctx context.Context, countryCode ...string) ([]Timezone, error)
}

GeoResolverInterface provides countries and timezones. The host implements this against whatever geo data source it uses (dracory/geostore, a static list, an external API, etc.).

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(baseURL string) *Links

NewLinks creates a Links helper with the given base URL. If baseURL is empty, defaults to "/admin/users".

func NewLinksFromRequest

func NewLinksFromRequest(r *http.Request) *Links

NewLinksFromRequest creates a Links helper using the user admin URL from the request context.

func (*Links) Home

func (l *Links) Home(params map[string]string) string

Home builds the URL for the user manager controller (default)

func (*Links) UserCreate

func (l *Links) UserCreate(params map[string]string) string

UserCreate builds the URL for the user create controller

func (*Links) UserDelete

func (l *Links) UserDelete(params map[string]string) string

UserDelete builds the URL for the user delete controller

func (*Links) UserImpersonate

func (l *Links) UserImpersonate(params map[string]string) string

UserImpersonate builds the URL for the user impersonate controller

func (*Links) UserManager

func (l *Links) UserManager(params map[string]string) string

UserManager builds the URL for the user manager controller

func (*Links) UserUpdate

func (l *Links) UserUpdate(params map[string]string) string

UserUpdate builds the URL for the user update controller

type OnUserImpersonateFunc added in v0.2.0

type OnUserImpersonateFunc func(w http.ResponseWriter, r *http.Request, userID string) error

OnUserImpersonateFunc is an optional callback invoked when an admin impersonates a user. The host owns the auth mechanism — it can create a session record and set a cookie, issue a JWT, or anything else. When nil, impersonation is disabled.

type OnUserSearchFunc added in v0.2.0

type OnUserSearchFunc func(ctx context.Context, conditions []SearchCondition) ([]string, error)

OnUserSearchFunc is an optional callback for custom user search. The host receives a list of conditions and applies whatever logic it wants (blind index, Elasticsearch, etc.). When nil, useradmin falls back to userstore query-based search.

type OnUserUpdatedFunc added in v0.2.0

type OnUserUpdatedFunc func(ctx context.Context, userID string)

OnUserUpdatedFunc is an optional callback invoked after a user is updated. The host can load the user by ID and react to whatever changed (blind index rebuild, audit log, notifications, etc.). When nil, the callback is skipped.

type SearchCombine added in v0.2.0

type SearchCombine string

SearchCombine defines how a condition combines with the previous one. The first condition's CombineWith is ignored.

const (
	SearchAnd SearchCombine = "AND"
	SearchOr  SearchCombine = "OR"
)

type SearchCondition added in v0.2.0

type SearchCondition struct {
	// Field is the user field to filter on.
	Field SearchField
	// Op is the comparison operator.
	Op SearchOp
	// Value is the value to compare against.
	Value string
	// CombineWith specifies how this condition combines with the
	// previous one. Defaults to AND. Ignored for the first condition.
	CombineWith SearchCombine
}

SearchCondition is a single filter criterion passed to OnUserSearch.

type SearchField added in v0.2.0

type SearchField string

SearchField constants identify the user fields that can be filtered.

const (
	SearchFieldFirstName    SearchField = "first_name"
	SearchFieldLastName     SearchField = "last_name"
	SearchFieldEmail        SearchField = "email"
	SearchFieldPhone        SearchField = "phone"
	SearchFieldBusinessName SearchField = "business_name"
)

type SearchOp added in v0.2.0

type SearchOp string

SearchOp defines the comparison operator for a SearchCondition.

const (
	SearchOpEquals      SearchOp = "eq"
	SearchOpContains    SearchOp = "contains"
	SearchOpNotContains SearchOp = "not_contains"
	SearchOpStartsWith  SearchOp = "starts_with"
)

type Timezone added in v0.2.0

type Timezone struct {
	Code string
}

Timezone is a single timezone entry returned by GeoResolverInterface.

type UiBase

type UiBase struct {
	UserStoreField         userstore.StoreInterface
	GeoResolverField       GeoResolverInterface
	LoggerField            *slog.Logger
	OnUserImpersonateField OnUserImpersonateFunc
	OnUserSearchField      OnUserSearchFunc
	OnUserUpdatedField     OnUserUpdatedFunc
	UserPiiSealField       UserPiiSealFunc
	UserPiiUnsealField     UserPiiUnsealFunc
	UsersPiiUnsealField    UsersPiiUnsealFunc
	FlashRedirectField     FlashRedirectFunc
	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 NewUiBase

func NewUiBase(config UiConfig) UiBase

NewUiBase creates a UiBase from a UiConfig

func (UiBase) FlashRedirect

func (u UiBase) FlashRedirect() FlashRedirectFunc

func (UiBase) GeoResolver added in v0.2.0

func (u UiBase) GeoResolver() GeoResolverInterface

func (UiBase) Layout

func (u UiBase) Layout(w http.ResponseWriter, r *http.Request, webpageTitle, webpageHtml string, options struct {
	Styles     []string
	StyleURLs  []string
	Scripts    []string
	ScriptURLs []string
}) string

func (UiBase) Logger

func (u UiBase) Logger() *slog.Logger

func (UiBase) OnUserImpersonate added in v0.2.0

func (u UiBase) OnUserImpersonate() OnUserImpersonateFunc

func (UiBase) OnUserSearch added in v0.2.0

func (u UiBase) OnUserSearch() OnUserSearchFunc

func (UiBase) OnUserUpdated added in v0.2.0

func (u UiBase) OnUserUpdated() OnUserUpdatedFunc

func (UiBase) UserPiiSeal added in v0.2.0

func (u UiBase) UserPiiSeal() UserPiiSealFunc

func (UiBase) UserPiiUnseal added in v0.2.0

func (u UiBase) UserPiiUnseal() UserPiiUnsealFunc

func (UiBase) UserStore

func (u UiBase) UserStore() userstore.StoreInterface

func (UiBase) UsersPiiUnseal added in v0.2.0

func (u UiBase) UsersPiiUnseal() UsersPiiUnsealFunc

type UiConfig

type UiConfig struct {
	UserStore   userstore.StoreInterface
	GeoResolver GeoResolverInterface
	Logger      *slog.Logger

	// OnUserImpersonate is optional — when nil, the impersonate
	// button is hidden and the impersonate route is not registered.
	OnUserImpersonate OnUserImpersonateFunc

	// OnUserSearch is an optional callback for custom user search
	// (e.g. blind index, Elasticsearch). When nil, useradmin falls
	// back to userstore query-based search.
	OnUserSearch OnUserSearchFunc

	// OnUserUpdated is an optional callback invoked after a user is
	// updated. The host can use it to trigger side effects (blind
	// index rebuild, audit log, notifications, etc.). When nil, the
	// callback is skipped.
	OnUserUpdated OnUserUpdatedFunc

	// UserPiiSeal transforms a user from display representation to
	// storage representation (e.g. tokenize, encrypt PII). Optional —
	// when nil, the user is stored as-is (plain text).
	UserPiiSeal UserPiiSealFunc

	// UserPiiUnseal transforms a user from storage representation to
	// display representation (e.g. detokenize, decrypt PII). Optional —
	// when nil, the user is used as-is (plain text).
	UserPiiUnseal UserPiiUnsealFunc

	// UsersPiiUnseal is the batch version of UserPiiUnseal. It allows
	// the host to unseal all users in a single call for efficiency.
	// Optional — when nil, useradmin falls back to UserPiiUnseal per
	// user (or plain text when that is also nil).
	UsersPiiUnseal UsersPiiUnsealFunc

	// FlashRedirect redirects with a flash message. Optional — when
	// nil, plain http.Redirect is used.
	FlashRedirect FlashRedirectFunc

	// 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, GeoResolver, and Logger are required for core controllers. OnUserImpersonate is optional — when nil, the impersonate button is hidden and the impersonate route is not registered. OnUserSearch is optional — when nil, useradmin falls back to userstore query-based search. OnUserUpdated is optional — when nil, the callback is skipped. UserPiiSeal/UserPiiUnseal/UsersPiiUnseal are optional — when nil, user fields are treated as plain text.

Authentication and authorization are the host's responsibility — gate the routes with middleware before they reach useradmin.

type UiInterface

type UiInterface interface {
	UserStore() userstore.StoreInterface
	GeoResolver() GeoResolverInterface
	Logger() *slog.Logger
	OnUserImpersonate() OnUserImpersonateFunc
	OnUserSearch() OnUserSearchFunc
	OnUserUpdated() OnUserUpdatedFunc
	UserPiiSeal() UserPiiSealFunc
	UserPiiUnseal() UserPiiUnsealFunc
	UsersPiiUnseal() UsersPiiUnsealFunc
	FlashRedirect() FlashRedirectFunc

	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 UserPiiSealFunc added in v0.2.0

type UserPiiSealFunc func(ctx context.Context, user userstore.UserInterface) (userstore.UserInterface, error)

UserPiiSealFunc transforms a user from display representation to storage representation (e.g. tokenize, encrypt, mask PII fields). The host owns the mechanism. When nil, the user is stored as-is (plain text).

type UserPiiUnsealFunc added in v0.2.0

type UserPiiUnsealFunc func(ctx context.Context, user userstore.UserInterface) (userstore.UserInterface, error)

UserPiiUnsealFunc transforms a user from storage representation to display representation (e.g. detokenize, decrypt, reveal PII fields). The host owns the mechanism. When nil, the user is used as-is (plain text).

type UsersPiiUnsealFunc added in v0.2.0

type UsersPiiUnsealFunc func(ctx context.Context, users []userstore.UserInterface) ([]userstore.UserInterface, error)

UsersPiiUnsealFunc is the batch version of UserPiiUnsealFunc. It allows the host to unseal all users in a single vault batch call for efficiency. When nil, useradmin falls back to calling UserPiiUnsealFunc per user (or plain text when that is also nil).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL