uos

package module
v0.0.0-...-2fd3322 Latest Latest
Warning

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

Go to latest
Published: Dec 26, 2023 License: MIT Imports: 40 Imported by: 1

README

Golang web "framework". Name provided by Github suggestion - logo provided by DALL-E. Thanks.

Documentation

Overview

Package uos implements a web application framework.

The framework aims to reduce the amount of required boilerplate code to create simple web applications. It provides several common building blocks.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrorFragmentNotFound is returned if the requested fragment is not available
	ErrorFragmentNotFound = errors.New("fragment not found")
	// ErrorFragmentInvalidRequest is returned if the fragment request parameters are invalid
	ErrorFragmentInvalidRequest = errors.New("invalid fragment request")

	// ErrorFormItemNotFound is returned if the requested item was not found (by 'id')
	ErrorFormItemNotFound = errors.New("form item not found")
	// ErrorFormInvalidRequest is returned if the form request parameters are invalid
	ErrorFormInvalidRequest = errors.New("invalid form request")

	// ErrorTableInvaliRequest is returned if the table request parameters are invalid
	ErrorTableInvalidRequest = errors.New("invalid table request")

	// ErrorInvalidPassword is returned if user authentication credentials are invalid
	ErrorInvalidPassword = errors.New("invalid user credentials")
)
View Source
var Config = AppConfiguration{}
View Source
var DB *gorm.DB

DB provides access to the Gorm database connection.

View Source
var Log *internalLogger

Log provides the application logger

View Source
var Metrics *metricsRegistry

Metrics allows to publish application metrics

Functions

func ComponentCleanup

func ComponentCleanup()

ComponentCleanup frees all initializes framework resources. Should be called on program termination, eg. in a defer call.

func ComponentSetup

func ComponentSetup(configFilePath ...string)

ComponentSetup initializes web application framework using the specified configuration file. Uses the default configuration file name ("app_config.json") if called without parameters. Otherwise, the first parameter is used. Panics if anything fails.

func IsCSRFtokenValid

func IsCSRFtokenValid(r *http.Request, token string) bool

func ReadFile

func ReadFile(path string) ([]byte, error)

ReadFile reads the specified file (using 'os.ReadFile'). It checks, whether the given path is contained in the configured base directory (e.g. the current working dir) - if not it returnes an error. Use this function to guard against malicious paths.

func RegisterAppRequestHandler

func RegisterAppRequestHandler(pattern string, handler AppRequestHandler, options AppRequestHandlerOptions)

RegisterAppRequestHandler registers the given handler for a specific URL pattern/path.

func RegisterAppRequestHandlers

func RegisterAppRequestHandlers(handlerList ...AppRequestHandlerMapping)

RegisterAppRequesHandlers registers a list of handler.

func RegisterAppRequestHandlersList

func RegisterAppRequestHandlersList(list []AppRequestHandlerMapping)

RegisterAppRequestHandlersList registers a slice of handler.

func RegisterDBModels

func RegisterDBModels(models ...interface{})

RegisterDBModels executes Gorm auto-migration for all specified models. Determines (and caches) the list of DB columns of each model. Panics if anything fails.

func RegisterDynamicAssets

func RegisterDynamicAssets(route string)

RegisterDynamicAssets provides the configured dynamic asset directory at the specified location.

func RegisterPageConfigurationHook

func RegisterPageConfigurationHook(cb PageConfigurationHandler)

func RegisterStaticAssets

func RegisterStaticAssets(route string, content embed.FS)

RegisterStaticAssets provides the given content file system at the specified location.

func RespondBadRequest

func RespondBadRequest(w http.ResponseWriter)

RespondBadRequest sends "bad request" error.

func RespondInternalServerError

func RespondInternalServerError(w http.ResponseWriter)

RespondInternalServerError sends "internal server error".

func RespondNotFound

func RespondNotFound(w http.ResponseWriter)

RespondNotFound sends "not found" error.

func RespondNotImplemented

func RespondNotImplemented(w http.ResponseWriter)

RespondNotImplemented sends "not implemented" error.

func StartApp

func StartApp()

StartApp starts the web application server. Starts handling requests at the configured port. Blocks. Panics if anything fails.

Types

type ActionSpec

type ActionSpec interface {
	// Name returns the short name of the action. The action can be triggered at "/actions/<name>".
	Name() string
	// Do executes the action. The implementation must ensure logging and an appropriate response.
	// The returned action (optional) is executed afterwards.
	Do(http.ResponseWriter, *http.Request) *ResponseAction
}

ActionSpec describes the interface every web application action must implement.

type AppConfiguration

type AppConfiguration struct {
	// application context information, available as template context
	AppInfo map[string]interface{} `json:"app"`

	// web application port
	Port int `json:"port"`
	// base deployment directory - only files "below" this directory are used.
	// If empty or not defined, the directory of the executable is set.
	BaseDir string `json:"base_dir"`

	Logging    LogConfiguration        `json:"logging"`
	Monitoring MonitoringConfiguration `json:"monitoring"`
	Database   DBConfiguration         `json:"database"`
	Assets     AssetConfiguration      `json:"assets"`
	I18N       I18NConfiguration       `json:"i18n"`

	Auth AuthenticationConfiguration `json:"auth"`

	// page configuration integrated into HTML pages. To define common settings
	// the page "_default" can be specified.
	Pages map[string]PageConfiguration `json:"pages"`

	Tuning   TuningConfiguration  `json:"tuning"`
	Features FeatureConfiguration `json:"-"`
}

AppConfiguration specifies application/framework configuration. Is read from a JSON configuration file in ComponentSetup.

type AppRequestHandler

type AppRequestHandler func(http.ResponseWriter, *http.Request)

AppRequestHandler represents a application specific HTTP handler function.

type AppRequestHandlerMapping

type AppRequestHandlerMapping struct {
	// URL route
	Route string
	// request handler for specified route
	Handler AppRequestHandler
	// options
	Options AppRequestHandlerOptions
}

AppRequestHandlerMapping represents a path pattern and a corresponding handler.

func ActionHandler

func ActionHandler(actions ...ActionSpec) AppRequestHandlerMapping

ActionHandler returns a handler for the "/actions/" route providing the specified actions. The handler can be activated using RegisterAppRequestHandlers.

func DialogHandler

func DialogHandler(dialogs ...DialogSpec) AppRequestHandlerMapping

DialogHandler returns a handler for the "/dialogs/" route providing the specified dialogs. The handler can be activated using RegisterAppRequestHandlers.

func FormHandler

func FormHandler(forms ...FormSpec) AppRequestHandlerMapping

FormHandler returns a handler for the "/forms/" route providing the specified forms. The handler can be activated using RegisterAppRequestHandlers.

func FragmentHandler

func FragmentHandler(fragments ...FragmentSpec) AppRequestHandlerMapping

FragmentHandler returns a handler for the "/fragments/" route providing the specified fragments. Creates default handler for fragments (as defined in templates directory). The handler can be activated using RegisterAppRequestHandlers.

func MarkdownHandler

func MarkdownHandler() AppRequestHandlerMapping

MarkdownHandler returns a handler for the "/markdown/" route providing HTML for the documents in the configured markdown directory. The handler can be activated using RegisterAppRequestHandlers.

func PageHandler

func PageHandler(page ...string) AppRequestHandlerMapping

PageHandler returns a standard GET handler for a template based page.

Called with a single parameter: specifiy the page template name, will be provided at "/<name>".

Calles with two parameters: specify route and page name.

Panics if no or more than two parameters are provided. The returned handler can be activated using RegisterAppRequestHandlers.

func ResourceHandler

func ResourceHandler(resource ResourceSpec) AppRequestHandlerMapping

ResourceHandler returns a request handler for resources. - GET /<name> - GET /<name>/<id>

PUT/POST is not supported, assuming that resources will be created/modified via a form.

func TableHandler

func TableHandler(tables ...TableSpec) AppRequestHandlerMapping

TableHandler returns a handler for the "/tables/" route providing the specified tables. The handler can be activated using RegisterAppRequestHandlers.

func (AppRequestHandlerMapping) AuthPage

AuthPage indicates, that the given request handler provides the authentication page.

func (AppRequestHandlerMapping) Internal

Internal indicates, that the given request handler requires authentication.

func (AppRequestHandlerMapping) NoSitemap

type AppRequestHandlerOptions

type AppRequestHandlerOptions struct {
	// do not expect valid CSRF token on POST/PUT/DELETE
	NoCSRFcheck bool
	// do not include the page in sitemap
	NoSitemap bool

	// redirect to login page if not authenticated
	IsAuthRequired bool
	// login page (target for "authentication required" pages)
	IsAuthPage bool
}

AppRequestHandlerOptions specify meta information about request handling

type AppUser

type AppUser struct {
	gorm.Model

	Name     string `gorm:"unique"`
	Language string

	PasswordHash string
	Salt         string

	IsAdmin bool
	// contains filtered or unexported fields
}

AppUser represents a user account.

func CreateAppUser

func CreateAppUser(name string, password string) (AppUser, error)

CreateAppUser creates, saves and returns a new AppUser object.

func GetAppUser

func GetAppUser(name string, password string) (AppUser, error)

GetAppUser returns an AppUser object. Checks password.

func (AppUser) TableName

func (AppUser) TableName() string

type AssetConfiguration

type AssetConfiguration struct {
	// directory containing "dynamic" assets (= assets that are not included in the executable)
	Dynamic string `json:"dynamic"`
	// directory containing template files for pages, forms, dialogs, fragements.
	Templates string `json:"templates"`
	// directory containing markdown documents
	Markdown string `json:"markdown"`
}

AssetConfiguration specifies directories containing different types of static data.

type AuthenticationConfiguration

type AuthenticationConfiguration struct {
	HashKey  string `json:"hash"`
	BlockKey string `json:"block"`
	// contains filtered or unexported fields
}

AuthenticationConfiguration specifies required keys for cookie handling. If a propertie is changed, existing cookies are invalidated.

type DBConfiguration

type DBConfiguration struct {
	// SQLite database file
	File string `json:"file"`
}

DBConfiguration specifies the database.

type DialogFooter

type DialogFooter struct {
	// left-aligned footer elements
	Left []DialogFooterElement
	// right-aligned footer elements
	Right []DialogFooterElement
}

DialogFooter speficies the footer of a dialog.

type DialogFooterElement

type DialogFooterElement struct {
	// shown as button
	IsButton bool
	// close dialog
	IsClosing bool
	// button submits a form
	IsSaving bool

	// text (button or text label)
	Text string
	// class (button or text label)
	TextClass string

	// referenced form (in combination with IsSaving)
	Form string
}

DialogFooterElement specifies an element shown in a dialog footer. Use the DialogFooter* functions to create elements.

func DialogFooterButton

func DialogFooterButton(text, class string) DialogFooterElement

DialogFooterButton returns a button specification.

func DialogFooterPrimaryButton

func DialogFooterPrimaryButton(text string) DialogFooterElement

DialogFooterPrimaryButton returns a primary button specification.

func DialogFooterText

func DialogFooterText(text, class string) DialogFooterElement

DialogFooterText returns a text label.

func (DialogFooterElement) Closing

Closing sets the IsClosing field and returns the element.

func (DialogFooterElement) Saving

Saving sets the IsSaving field and returns the element.

type DialogSpec

type DialogSpec interface {
	// Name returns the short name of the dialog. The form is available at '/dialogs/<name>'.
	Name() string
	// DisplayTitle returns the title string of the dialog.
	DisplayTitle() string
	// Footer returns a dialog footer specification.
	Footer() DialogFooter
}

DialogSpec describes the interface every web application dialog must implement.

type FeatureConfiguration

type FeatureConfiguration struct {
	Dialogs bool `json:"-"`
}

type FormItem

type FormItem struct {
	ID string

	InputType     string
	InputTypeHTML string

	Name         string
	Value        string
	DefaultValue string

	Constraints *FormItemConstraints

	Class       string
	Placeholder string
	Min         string
	Max         string

	Label string

	Help      string
	HelpClass string

	Message      string
	MessageClass string

	IsHorizontal bool
	IsHidden     bool
	HasFocus     bool
}

FormItem describes a single form entry, e.g. an input box.

type FormItemConstraints

type FormItemConstraints struct {
	IsMandatory bool
	IsNumber    bool

	MinValue float64
	MaxValue float64

	MinLength int
	MaxLength int

	Regexp string
}

type FormItems

type FormItems []FormItem

FormItems is a list of form items.

func DBExtractForm

func DBExtractForm(name string, model interface{}, items FormItems) FormItems

DBExtractForm fills form items with values based on the specified model. The model must be registered using Register DBModels. Panics if "name" specifies an unknown model.

func (*FormItems) Get

func (fi *FormItems) Get(name string) *FormItem

type FormSpec

type FormSpec interface {
	// Name returns the short name of the form. The form is available at '/forms/<name>'.
	Name() string
}

FormSpec describes the interface every web application form must implement.

type FormSpecDelete

type FormSpecDelete interface {
	// Delete removes the specified item from the database.
	Delete(id string) (*ResponseAction, error)
}

FormSpecDelete must be implemented by a web application form to support DELETE requests.

type FormSpecRead

type FormSpecRead interface {
	// Read returns the list of form items. If an id is specified, the form items for an existing
	// entity is returned.
	Read(id string) (FormItems, error)
}

FormSpecRead must be implemented by a web application form to support GET requests.

type FormSpecSave

type FormSpecSave interface {
	// Read returns the list of form items. If an id is specified, the form items for an existing
	// entity is returned.
	Read(id string) (FormItems, error)
	// Save writes the specified items to the database.
	Save(id string, items FormItems) (*ResponseAction, error)
}

FormSpecSave must be implemented by a web application form to support POST requests.

type FragmentSpec

type FragmentSpec interface {
	// Name returns the short name of a fragment. The fragment is available at '/fragments/<name>'
	// and uses the template 'fragment_<name>'.
	Name() string
}

FragmentSpec describes an interface a web application fragment must provide.

type FragmentSpecRead

type FragmentSpecRead interface {
	// GetContextObject returns the fragment template context object for the given URL parameters.
	GetContextObject(params Getter) (interface{}, error)
}

FragmentSpecRead describes an interface a fragment that supports GET requests must provide.

type Getter

type Getter interface {
	Get(string) string
}

type I18NConfiguration

type I18NConfiguration struct {
	// directory containing translations (PO files)
	Locale string `json:"locale"`
	// list of supported languages (first entry is primary language)
	Languages []string `json:"languages"`
}

type LogConfiguration

type LogConfiguration struct {
	// log level (panic, fatal, error, warn, info, debug, trace)
	Level string `json:"level"`
	// write logmessages as colored output to stderr - otherwise log as JSON
	UseConsole bool `json:"use_console"`
}

LogConfiguration specifies logging behaviour.

type LogContext

type LogContext map[string]interface{}

LogContext specifies key-value context information for a log entry.

type MonitoringConfiguration

type MonitoringConfiguration struct {
	// port for pprof web interface
	PortPPROF int `json:"pprof"`
	// port for application metrics (Prometheus)
	PortMetrics int `json:"metrics"`
}

MonitoringConfiguration specifies ports for application monitoring.

type PageConfiguration

type PageConfiguration struct {
	Title       string `json:"title"`
	Description string `json:"description"`
	Author      string `json:"author"`
	URL         string `json:"url"`

	StaticBaseURL string `json:"static_base_url"`

	FavIcon string `json:"favicon"`

	Styles []string `json:"styles"`

	ScriptsHead []string `json:"scripts_head"`
	ScriptsBody []string `json:"scripts_body"`
}

type PageConfigurationHandler

type PageConfigurationHandler func(string, *http.Request, *PageConfiguration)

type ResourceSpec

type ResourceSpec interface {
	// Name returns the short name of a resource. The resource is available at '/<name>'.
	Name() string
}

ResourceSpec describes an interface a web application resource must provide.

type ResourceSpecList

type ResourceSpecList interface {
	// List return a filtered list of resources. Used as context to resource_list_<name> template.
	List(filter string, page, count int) ([]interface{}, error)
}

ResourceSpecRead describes an interface a resource with list access must provide.

type ResourceSpecRead

type ResourceSpecRead interface {
	// Read returns the resource as template context for resource_<name>.
	Read(id string) (interface{}, error)
}

ResourceSpecRead describes an interface a resource with ID access must provide.

type ResponseAction

type ResponseAction struct {
	// contains filtered or unexported fields
}

ResponseAction describes what happens on a successful save or delete form action. Use the FormResponse* functions to create a response action.

func ResponseClearSessionCookie

func ResponseClearSessionCookie() *ResponseAction

ResponseClearSessionCookie clears the session cookie and triggers a full frontend page refresh.

func ResponseCloseDialog

func ResponseCloseDialog() *ResponseAction

ResponseCloseDialog closes an open modal dialog.

func ResponseFormError

func ResponseFormError(message string) *ResponseAction

ResponseFormError renders a form as response - including the specified error message.

func ResponseMessage

func ResponseMessage(message, class string) *ResponseAction

ResponseMessage returns a message element.

func ResponseRefresh

func ResponseRefresh() *ResponseAction

ResponseRefresh triggers a full frontend page refresh.

func ResponseSetSessionCookie

func ResponseSetSessionCookie(userID uint, language string) *ResponseAction

ResponseSetSessionCookie sets a session cookie for the specified user and triggers a full frontend page refresh or a redirect to the given URL.

type TableAction

type TableAction struct {
	// (LineAwesome) icon of the action
	Icon string
	// button text
	Text string
	// button class
	ButtonClass string

	// hx-<method>
	Method string
	// action target, e.g. "/dialogs/..."
	TargetURL string
	// CSS selector for elements to include in the resulting request
	Include string

	// confirmation dialog title, empty: no confirmation required
	ConfirmationTitle string
	// confirmation dialog message
	ConfirmationMessage string
}

TableAction describes a function that can be triggered for a table, e.g. item deletion.

func TableActionButton

func TableActionButton(icon, text, class string) TableAction

TableActionButton returns a table action element with the specified icon, text and button class.

func (TableAction) Confirmation

func (a TableAction) Confirmation(title, message string) TableAction

Confirmation asks for user permission before sending the action

func (TableAction) Dialog

func (a TableAction) Dialog(target string) TableAction

Dialog extends the action to open the specified dialog

func (TableAction) Post

func (a TableAction) Post(target, include string) TableAction

Post adds a HTMX post action to the element

type TableActions

type TableActions []TableAction

type TableColumn

type TableColumn struct {
	// display name
	DisplayName string
	// table supports sorting by this column
	IsSortable bool

	// function to convert raw values to visualization (e.g. for formatting)
	Format TableFormatFunc

	// is current sortfield? (determined automatically)
	IsSortField bool
	// is sorted descending? (determined automatically)
	IsSortDesc bool
	// internal name (determined automatically)
	Name string
}

TableColumn describes properties of a table column.

type TableConfiguration

type TableConfiguration struct {
	// comma separated list of selected columns
	Columns []string

	// sort column
	SortColumn string
	// sort mode (ASC or DESC or empty)
	SortMode string

	// selected page
	Page int
	// number of rows to return
	Rows int
}

TableConfiguration describes a specific table view, e.g. a specific column selection, page or sort column.

func (TableConfiguration) DBQuery

func (c TableConfiguration) DBQuery() *gorm.DB

func (TableConfiguration) LoadTable

func (c TableConfiguration) LoadTable(dest interface{}) error

LoadTable loads table data for the specified model.

type TableData

type TableData [][]interface{}

TableData represents a table with rows and columns.

func DBExtract

func DBExtract(name string, models interface{}, columns []string) TableData

DBExtract returns a table of the specified columns extracted from the given list of models. The model must be registered using RegisterDBModels. Panics if "name" specifies an unknown model or "models" is not a slice.

type TableDisplay

type TableDisplay interface {
	// DisplaySettings returns custom table display settings
	DisplaySettings() TableDisplayProperties
}

TableDisplay describes the interface a web application table must implement to customize the table visualization

type TableDisplayProperties

type TableDisplayProperties struct {
	// show as full element width
	IsFullWidth bool
	// highlight table rows on hover
	IsHoverable bool
	// emphasize every second row
	IsStriped bool
	// show table content as cards on small displays
	IsMobileReady bool
	// rows can be selected
	IsSelectable bool
	// rows can be expanded
	IsExpandable bool
	// last column contains buttons
	HasRowActions bool
}

TableDisplayProperties describes basic table visualization properties. Default: all properties set to false.

type TableFormatFunc

type TableFormatFunc func(interface{}, interface{}) interface{}

TableFormatFunc describes a table cell visualization function. The input parameter are the row id and a raw value read from the database. The returned value is visualized in the frontend. The return value can contain HTML.

type TableSpec

type TableSpec interface {
	// Name returns the short name of the table. The table data is available at '/tables/<name>'.
	Name() string
	// ModelName returns the name of the underlying DB model. Can return "" to indicate a custom table.
	// A returned model must be registered (using RegisterDBModels).
	ModelName() string
	// ResourceName is required if the table IsExpandable (see display properties). The detail rows
	// content will be loaded as the specified resource.
	ResourceName() string

	// LoadData returns the table data according to the specified configuration.
	LoadData(TableConfiguration) (TableData, error)

	// ColumnInfo returns table column information for the selected columns.
	ColumnInfo([]string) []TableColumn
	// ColumnDefault returns list of default columns
	ColumnDefault() []string

	// Actions returns a set of actions related to the table and their contained items.
	Actions() *TableActions
}

TableSpec describes the interface every web application table must implement.

type TableSpecDelete

type TableSpecDelete interface {
	// Delete removes the specified items from the database.
	Delete(ids []uint) (*ResponseAction, error)
}

TableDelete must be implemented by a web application form to support DELETE requests.

type TuningConfiguration

type TuningConfiguration struct {
	ActivateHTMXPreloading bool `json:"htmx_preload"`
}

Jump to

Keyboard shortcuts

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