Help us shape the future of Go! Take the 2026 Go Developer Survey

api

package
v0.45.0 Latest Latest
Warning

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

Go to latest
Published: Sep 25, 2026 License: MIT Imports: 60 Imported by: 0

Documentation

Overview

Package api — demo_guard.go

The read-only guard for a public demo.

Package api wires the HTTP routes onto a chi router.

All handlers receive a Deps struct so they have access to the same shared services (Store, Worker, Search, Capability, Pipeline). New handlers should be added here in BuildRouter — never spawned via init() or globals.

Index

Constants

View Source
const UserUIPrefix = "/drive"

UserUIPrefix is the neutral, end-user mount point for the same SPA the admin panel is served from. See wireStatic and GitHub #14.

Variables

This section is empty.

Functions

func APINoStore

func APINoStore(next http.Handler) http.Handler

APINoStore makes every /api response uncacheable unless its handler sets a Cache-Control of its own. Handlers override it with Header().Set — never Add: no-store beside a max-age cancels the max-age.

⚠ Without it a JSON answer carried no Cache-Control at all, and a CDN rule that caches everything took that as permission. Measured behind Cloudflare (2026-09-24): a zone rule written for the tenant's website, with no host condition, kept GET /api/auth/me for two hours and handed one administrator's identity to everyone who asked, an anonymous curl included. Signing out and in as someone else still showed the administrator, because the identity request never reached filex. Per-user data has no business in a shared cache, nor in the browser's after sign-out.

⚠⚠ The ONE deliberate exception is the four answers that say who this instance is — GET /api/branding, /api/appearance, /api/public/branding and /api/public/ui-locales/{code}. They are the same for every visitor of a host and are meant to be KEPT and revalidated (`public, no-cache` + a strong ETag, so an unchanged page load costs a 304): handlers/public_cache.go. They are mounted outside every auth chain, so no principal reaches them, and writePublicJSON downgrades itself to `private` should anybody ever call it with one. TestAPICache_PublicOnlyOnTheInstanceIdentity walks the whole route table and fails on a fifth `public` answer.

The other policies a handler sets are per-person or unstored: thumbnails, file content and share downloads say `private, …`; archives, OnlyOffice and the OIDC bounce say `no-store` themselves.

func BuildRouter

func BuildRouter(d *Deps) http.Handler

BuildRouter constructs the chi router with all routes wired up.

func DemoGuard

func DemoGuard(enabled bool) func(http.Handler) http.Handler

DemoGuard refuses state-changing requests on a public demo.

enabled is config.Demo.Mode. When it is false this middleware is a pass-through with a single boolean test, so an ordinary install carries no behaviour change at all.

func JSONError

func JSONError(w http.ResponseWriter, status int, msg string)

JSONError is a small JSON 4xx/5xx helper used by handlers.

func JSONOk

func JSONOk(w http.ResponseWriter, body any)

JSONOk writes a 200 JSON body.

func Logger

func Logger(next http.Handler) http.Handler

Logger emits one structured log per request.

Beyond method, path, status, ip and duration it names the caller when one was established — `user_id`, `token_id` (the API token's row id, never its secret) and the multi-tenant `tenant` slug — and, on the file manager's one path, WHICH verb was asked (`action`). Before, a line read `method=POST path=/api/files/manager status=500`: every file operation shares that path, one account often backs several tokens (a desktop, a CLI, a proxy), and "which client failed doing what" had no answer.

⚠ The query string is never logged, and must not be. It carries thumbnail and OnlyOffice signatures (`sig`), WebSocket tickets, share PINs, OIDC codes, S3 presigned credentials on /s3, and people's search text. `action` is the one value taken from it, only on /api/files/manager, and only as one of the manager's own verbs (managerAction).

func Recoverer

func Recoverer(next http.Handler) http.Handler

Recoverer returns 500 JSON on panic and prints the stack to slog.

Types

type Deps

type Deps struct {
	Cfg    config.Config
	Store  db.Store
	Worker *syncpkg.Worker
	Index  *search.Index
	Caps   *capability.Service
	// External resolves the live `external_services` rows. It is what makes an
	// admin-UI change to OnlyOffice / drawio / the converter take effect
	// without a restart (issue #17). Constructed in BuildRouter when nil.
	External        *external.Resolver
	Thumbs          *thumb.Pipeline
	Share           *share.Service
	OnlyOffice      *onlyoffice.Service
	Ops             *ops.Service
	Trash           *trash.Service
	Quota           *quota.Service
	Versions        *versioning.Service
	Queue           queue.Driver
	Notify          notify.Service
	ReplicaService  *replica.Service
	ReplicaCron     *replica.CronScheduler
	ReplicaReloader *replica.RulesReloader
	StorageResolver func(int64) (storage.Driver, error)
	// ForgetStorage drops the process-wide cached driver for a storage id.
	// The resolver above builds a driver once and keeps it for the life of
	// the process, so without this an edited storage keeps being served
	// through the connection built from the configuration it had at boot.
	// Nil is legal: it means nothing is cached (tests, embedders).
	ForgetStorage func(int64)
	// Plugins manages out-of-process storage drivers (internal/plugin). Nil
	// when FILEX_PLUGINS_DISABLED — the admin routes then answer 503.
	Plugins *plugin.Manager
	// AppPlugins runs in-process WebAssembly app plugins (internal/wasmplugin).
	// Nil when FILEX_APP_PLUGINS_DISABLED or the CPU architecture has no
	// wazero compiler — the user routes then answer 404, the admin ones 503
	// with AppPluginsDisabledReason.
	AppPlugins               *wasmplugin.Registry
	AppPluginsDisabledReason string
	Embed                    embed.FS // web/dist + admin
	LocalAuth                auth.LoginDriver
	OIDCAuth                 auth.OIDCDriver
	// AuthLive is the running set of sign-in providers (internal/authsetup):
	// the Identity providers page changes it, and LocalAuth / OIDCAuth /
	// Directory are its proxies, so a change applies without a restart.
	AuthLive *authsetup.Live
	// Directory is the external password authority the FILE PROTOCOLS consult
	// (the LDAP driver, when configured and not switched off with
	// auth.ldap.protocol_login). Nil = local passwords only.
	//
	// ⚠ It is set on ProtocolAuth below rather than passed to the login
	// handler: the browser path reaches the same driver through LocalAuth's
	// login chain, and a directory login there mints a session, which is
	// precisely what a per-request protocol login must NOT do.
	Directory protocolauth.Directory
	// ACL resolves per-user/per-item grants (RBAC feature). Constructed in
	// BuildRouter from Store when nil.
	ACL *acl.Resolver
	// ProtocolAuth is the one door every non-HTTP protocol resolves its caller
	// through (WebDAV today; S3, SFTP, FTPS, NFS and FUSE next). ONE instance is
	// shared on purpose: a resolver per protocol would mean a credential cache
	// per protocol, and therefore a different answer to "how long does a revoked
	// password keep working" on each of them. Constructed in BuildRouter when
	// nil.
	ProtocolAuth *protocolauth.Resolver
	// FTPSAddr reports the address the FTPS listener actually bound.
	//
	// ⚠⚠ A function, not a string, and read at REQUEST time. Config may say
	// `:0` ("any free port") — and it does in the test harness — so the only
	// place the real port exists is the running listener, which is created
	// after this router. A guide that printed the configured value would tell
	// somebody to connect to port 0. Nil falls back to the configured address.
	FTPSAddr func() string
	// Mailer sends invite/share notices (optional; nil → links shown on-screen).
	Mailer *mailer.Service
	// ZipCache caches folder-share ZIPs (shared with the background warmer).
	ZipCache *sharezip.Cache
	// FileCache holds the locally prepared copies of big files that live on
	// slow storages (internal/filecache). Nil = no caching; every read then
	// goes to the driver exactly as it did before the cache existed.
	FileCache *filecache.Cache
	/* koru:k2 av */
	// AVScan enqueues an async ClamAV scan for a freshly written node
	// (v0.4 "Koru"). Wired by the server bootstrap only when a ClamAV
	// binary and the persistent queue are both available; nil disables
	// scanning entirely.
	AVScan func(ctx context.Context, n *model.Node)

	// AVScanAfterSave is the DEBOUNCED twin of AVScan, used only by the text
	// editor's save-over-an-existing-file path: it schedules one scan per
	// file per editing window instead of one per Ctrl+S. nil falls back to
	// AVScan (scan immediately) rather than to no scan.
	AVScanAfterSave func(ctx context.Context, n *model.Node)
	// Updater tracks published releases and (on installs that own their
	// binary) applies them. Nil = the feature is off; the admin endpoints then
	// report a "disabled" status instead of disappearing. See docs/UPDATES.md.
	Updater *update.Service
	// Staging is the on-disk staging area for resumable uploads. Constructed
	// in BuildRouter from Cfg.Upload.StagingDir when nil.
	Staging *staging.Area
	// StagedUploads is filled in BY BuildRouter so the server bootstrap can
	// run the staging sweeper against the same handler the routes use.
	StagedUploads *handlers.StagedUpload
	/* wiring:e2 */
	// E2EEscrow is the installation's E2E key-escrow PUBLIC key, or nil when
	// escrow is off (the default). It is published in /api/capabilities so the
	// browser can wrap new folders' master keys to it, and it seals the
	// proof-of-possession challenge in handlers.E2E. The server never has the
	// private half — see internal/e2e/escrow.go.
	E2EEscrow *e2e.EscrowKey
	// Body resolves where a file's bytes are — the storage driver, or the
	// staging area while a staged upload is still being transferred. Built in
	// BuildRouter from Store+Staging when nil, and filled back in here so the
	// bootstrap can hand the SAME resolver to the surfaces that live outside
	// the router (WebDAV, thumbnails, versioning, the queue workers).
	Body *filebody.Resolver
}

Deps is the bundle of services every handler needs.

Directories

Path Synopsis
Package handlers — account_rules.go
Package handlers — account_rules.go

Jump to

Keyboard shortcuts

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