//! The HTTP wire contract of filebrowser-ng in one place. //! //! Both the server (axum) and the web frontend (wasm `fetch`) import these //! endpoint paths, query params and serde types, so the two sides cannot //! drift apart. Serde only — no axum, no wasm dependencies. use serde::{Deserialize, Serialize}; // --------------------------------------------------------------------------- // Endpoint paths (single source of truth for the route table and the client) // --------------------------------------------------------------------------- pub const AUTH_LOGIN: &str = "/api/auth/login"; pub const AUTH_LOGOUT: &str = "/api/auth/logout"; pub const AUTH_ME: &str = "/api/auth/me"; pub const AUTH_SETUP: &str = "/api/auth/setup"; /// File operations: `{FILES}/{root_id}` and `{FILES}/{root_id}/{path...}`. pub const FILES: &str = "/api/files"; /// Share management (authenticated): `{SHARES}` and `{SHARES}/{id}`. pub const SHARES: &str = "/api/shares"; /// Public share resolve (no login): `{SHARE}/{token}`. pub const SHARE: &str = "/api/share"; /// Suffix on `{SHARE}/{token}`: submit the password of a protected share. pub const SHARE_UNLOCK_SUFFIX: &str = "/unlock"; /// `GET /api/search` — name and/or content search, streamed as SSE. pub const SEARCH: &str = "/api/search"; /// WebDAV mount of the signed-in user's roots: `{DAV}` and `{DAV}/{path...}`. pub const DAV: &str = "/dav"; /// WebDAV mount of one public share: `{DAV_SHARE}/{token}/{path...}`. /// /// A separate top-level path, not a segment under [`DAV`]: there, the first /// segment is a root's display name, which a reserved word could collide with. pub const DAV_SHARE: &str = "/dav-share"; /// Admin user management: `{ADMIN_USERS}` and `{ADMIN_USERS}/{id}`. pub const ADMIN_USERS: &str = "/api/admin/users"; pub const ADMIN_SETTINGS: &str = "/api/admin/settings"; /// Pseudo root id every signed-in admin has on the files API: the whole /// server root, read-only (the admin folder picker browses it). Real root /// ids are positive database ids. Not listed in `/me`. pub const ADMIN_ROOT: i64 = -1; // --------------------------------------------------------------------------- // Query params // --------------------------------------------------------------------------- /// `?action=...` on file URLs; without it the route lists the directory. pub const P_ACTION: &str = "action"; pub const ACTION_DOWNLOAD: &str = "download"; pub const ACTION_PREVIEW: &str = "preview"; pub const ACTION_CONTENT: &str = "content"; pub const ACTION_THUMB: &str = "thumb"; /// `POST {FILES}/...?action=mkdir` — create a folder. Explicit, because the /// POST route also carries uploads and mutations. pub const ACTION_MKDIR: &str = "mkdir"; /// `POST {FILES}/...?action=create-file` — create an empty file. Explicit /// like `mkdir`, for the same reason. pub const ACTION_CREATE_FILE: &str = "create-file"; /// `?format=...` for folder downloads (values: see `server::archive::ArchiveFormat`). pub const P_FORMAT: &str = "format"; /// `?share=` — authenticate file calls with a public share token. pub const P_SHARE: &str = "share"; /// Search query text (`GET {SEARCH}`). pub const P_Q: &str = "q"; /// Which index to search: `name`, `content` or `both`. pub const P_SCOPE: &str = "scope"; /// Root id to search; omitted = the caller's first root. pub const P_ROOT: &str = "root"; /// Folder inside the root to start a search in (relative to the root); /// omitted or empty = the whole root. pub const P_PATH: &str = "path"; /// `?overwrite=true|1` on mutations and uploads. pub const P_OVERWRITE: &str = "overwrite"; // --------------------------------------------------------------------------- // Wire enums // --------------------------------------------------------------------------- /// Access mode of a root or a share. /// /// The serde names are also the values stored in the SQLite `mode` columns, /// so renaming a variant would break existing databases. The round-trip test /// below pins them. #[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq)] #[serde(rename_all = "lowercase")] pub enum Mode { Rw, Ro, } impl Mode { /// The only question callers ask: may this root be written to? pub fn is_writable(self) -> bool { matches!(self, Mode::Rw) } /// The wire/database spelling, for `