diff --git a/CHANGELOG.md b/CHANGELOG.md
index 40c3697..65744ab 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
# Changelog
+## Changes 4/17
+
+- Generate OpenAPI spec and API HTML docs
+ - Fully auto‑generated OpenAPI spec (`openapi.json`) and interactive HTML docs (`api.html`) powered by Redoc.
+
+---
+
## Changes 4/16 Refactor API endpoints and modularize controllers and models
- Reorganized project structure to separate API logic into dedicated controllers and models:
diff --git a/README.md b/README.md
index 09356a0..c2c9090 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,8 @@ Upload, organize, and share files through a sleek web interface. **FileRise** is
- 🗃️ **Folder Sharing & File Sharing:** Easily share entire folders via secure, expiring public links. Folder shares can be password-protected, and shared folders support file uploads from outside users with a separate, secure upload mechanism. Folder listings are paginated (10 items per page) with navigation controls, and file sizes are displayed in MB for clarity. Share files with others using one-time or expiring public links (with password protection if desired) – convenient for sending individual files without exposing the whole app.
+- 📚 **API Documentation:** Fully auto‑generated OpenAPI spec (`openapi.json`) and interactive HTML docs (`api.html`) powered by Redoc.
+
- 📝 **Built-in Editor & Preview:** View images, videos, audio, and PDFs inline with a preview modal – no need to download just to see them. Edit text/code files right in your browser with a CodeMirror-based editor featuring syntax highlighting and line numbers. Great for config files or notes – tweak and save changes without leaving FileRise.
- 🏷️ **Tags & Search:** Categorize your files with color-coded tags and locate them instantly using our indexed real-time search. Easily switch to Advanced Search mode to enable fuzzy matching not only across file names, tags, and uploader fields but also within the content of text files—helping you find that “important” document even if you make a typo or need to search deep within the file.
diff --git a/public/api.html b/public/api.html
new file mode 100644
index 0000000..a0a13e2
--- /dev/null
+++ b/public/api.html
@@ -0,0 +1,2439 @@
+
+
+
+
+
+ FileRise API
+
+
+
+
+
+
+
+
+
+ FileRise API (1.0.0) Download OpenAPI specification:Download
A lightweight self-hosted file manager API
+
Retrieve admin configuration Returns the admin configuration settings, decrypting the configuration file and providing default values if not set.
+
Responses 200 Configuration retrieved successfully
+500 Failed to decrypt configuration or server error
+get /api/admin/getConfig.php Response samples Content type application/json
Copy
Expand all Collapse all Update admin configuration Updates the admin configuration settings. Requires admin privileges and a valid CSRF token.
+
Request Body schema: application/json
header_title required
oidc required
loginOptions required
globalOtpauthUrl
Responses 200 Configuration updated successfully
+400 Bad Request (e.g., invalid input, incomplete OIDC configuration)
+403 Unauthorized (user not admin or invalid CSRF token)
+500 Server error (failed to write configuration file)
+put /api/admin/updateConfig.php
/api/admin/updateConfig.php
Request samples Content type application/json
Copy
Expand all Collapse all Response samples Content type application/json
Authenticate user Handles user authentication via OIDC or form-based credentials. For OIDC flows, processes callbacks; otherwise, performs standard authentication with optional TOTP verification.
+
Request Body schema: application/json
username required
password required
remember_me totp_code
Responses 200 Login successful; returns user info and status
+400 Bad Request (e.g., missing credentials)
+401 Unauthorized (e.g., invalid credentials, too many attempts)
+429 Too many failed login attempts
+ Request samples Content type application/json
Response samples Content type application/json
Check authentication status Checks if the current session is authenticated. If the users file is missing or empty, returns a setup flag. Also returns information about admin privileges, TOTP status, and folder-only access.
+
Responses 200 Returns authentication status and user details
+get /api/auth/checkAuth.php Response samples Content type application/json
{ "authenticated" : true ,
"isAdmin" : true ,
"totp_enabled" : false ,
"username" : "johndoe" ,
"folderOnly" : false
} Retrieve CSRF token and share URL Returns the current CSRF token along with the configured share URL.
+
Responses 200 CSRF token and share URL
+ Response samples Content type application/json
Authenticate using HTTP Basic Authentication Performs HTTP Basic authentication. If credentials are missing, sends a 401 response prompting for Basic auth. On valid credentials, optionally handles TOTP verification and finalizes session login.
+
Responses 200 Login successful; redirects to index.html
+401 Unauthorized due to missing credentials or invalid credentials.
+get /api/auth/login_basic.php
/api/auth/login_basic.php
Response samples Content type application/json
Logout user Clears the session, removes persistent login tokens, and redirects the user to the login page.
+
Responses 302 Redirects to the login page with a logout flag.
+ Copy files between folders Copies files from a source folder to a destination folder. It validates folder names, handles file renaming if a conflict exists, and updates metadata accordingly.
+
Request Body schema: application/json
source required
destination required
files required
Responses 200 Files copied successfully
+400 Invalid request or input
+403 Invalid CSRF token or read-only permission
+post /api/file/copyFiles.php Request samples Content type application/json
Copy
Expand all Collapse all Response samples Content type application/json
Delete files (move to trash) Moves the specified files from the given folder to the trash and updates metadata accordingly.
+
Request Body schema: application/json
Responses 200 Files moved to Trash successfully
+403 Invalid CSRF token or permission denied
+post /api/file/deleteFiles.php
/api/file/deleteFiles.php
Request samples Content type application/json
Copy
Expand all Collapse all Response samples Content type application/json
Move files between folders Moves files from a source folder to a destination folder, updating metadata accordingly.
+
Request Body schema: application/json
source required
destination required
files required
Responses 200 Files moved successfully
+400 Invalid request or input
+403 Invalid CSRF token or permission denied
+post /api/file/moveFiles.php Request samples Content type application/json
Copy
Expand all Collapse all Response samples Content type application/json
Rename a file Renames a file within a specified folder and updates folder metadata. If a file with the new name exists, a unique name is generated.
+
Request Body schema: application/json
folder required
oldName required
newName required
Responses 200 File renamed successfully
+403 Invalid CSRF token or permission denied
+post /api/file/renameFile.php Request samples Content type application/json
Response samples Content type application/json
Save a file Saves file content to disk in a specified folder and updates metadata accordingly.
+
Request Body schema: application/json
fileName required
content required
folder
Responses 200 File saved successfully
+400 Invalid request data
+403 Invalid CSRF token or read-only permission
+post /api/file/saveFile.php Request samples Content type application/json
{ "fileName" : "document.txt" ,
"content" : "File content here" ,
"folder" : "Documents"
} Response samples Content type application/json
Download a file Downloads a file from a specified folder. The file is served inline for images or as an attachment for other types.
+
query Parameters file required
string
Example: file=example.pdf
The name of the file to download
+
folder string
Example: folder=Documents
The folder in which the file is located. Defaults to root.
+
Responses 200 File downloaded successfully
+get /api/file/download.php Download a ZIP archive of selected files Creates a ZIP archive of the specified files in a folder and serves it for download.
+
Request Body schema: application/json
folder required
files required
Responses 200 ZIP archive created and served
+400 Bad request or invalid input
+post /api/file/downloadZip.php
/api/file/downloadZip.php
Request samples Content type application/json
Copy
Expand all Collapse all Access a shared file Serves a shared file based on a share token. If the file is password protected and no password is provided, a password entry form is returned.
+
query Parameters token required
pass string
The password for the share if required
+
Responses 200 File served or password form rendered
+400 Missing token or invalid request
+403 Link expired, invalid password, or forbidden access
+404 Share link or file not found
+ Create a share link for a file Generates a secure share link token for a specific file with an optional password protection and expiration time.
+
Request Body schema: application/json
folder required
file required
expirationMinutes password
Responses 200 Share link created successfully
+400 Invalid request data
+403 Read-only users are not allowed to create share links
+post /api/file/createShareLink.php
/api/file/createShareLink.php
Request samples Content type application/json
{ "folder" : "Documents" ,
"file" : "report.pdf" ,
"expirationMinutes" : 60 ,
"password" : "secret"
} Response samples Content type application/json
Get trash items Retrieves a list of files that have been moved to Trash, enriched with metadata such as who deleted them and when.
+
Responses 200 Trash items retrieved successfully
+get /api/file/getTrashItems.php
/api/file/getTrashItems.php
Response samples Content type application/json
Copy
Expand all Collapse all Restore trashed files Restores files from Trash based on provided trash file identifiers and updates metadata.
+
Request Body schema: application/json
Responses 200 Files restored successfully
+post /api/file/restoreFiles.php
/api/file/restoreFiles.php
Request samples Content type application/json
Copy
Expand all Collapse all Response samples Content type application/json
Copy
Expand all Collapse all Delete trash files Deletes trash items based on provided trash file identifiers from the trash metadata and removes the files from disk.
+
Request Body schema: application/json
Responses 200 Trash items deleted successfully
+post /api/file/deleteTrashFiles.php
/api/file/deleteTrashFiles.php
Request samples Content type application/json
Copy
Expand all Collapse all Response samples Content type application/json
Copy
Expand all Collapse all Save file tags Saves tag data for a specified file and updates global tag data. For folder-specific tags, saves to the folder's metadata file.
+
Request Body schema: application/json
file required
folder tags required
deleteGlobal tagToDelete
Responses 200 Tag data saved successfully
+400 Invalid request data
+403 Invalid CSRF token or insufficient permissions
+post /api/file/saveFileTag.php
/api/file/saveFileTag.php
Request samples Content type application/json
Copy
Expand all Collapse all { "file" : "document.txt" ,
"folder" : "Documents" ,
"tags" :
[ { "name" : "Important" ,
"color" : "#FF0000"
} ] , "deleteGlobal" : false ,
"tagToDelete" : "OldTag"
} Response samples Content type application/json
Copy
Expand all Collapse all Get file list Retrieves a list of files from a specified folder along with global tags and metadata.
+
query Parameters folder string
Example: folder=Documents
Folder name (defaults to 'root')
+
Responses 200 File list retrieved successfully
+get /api/file/getFileList.php
/api/file/getFileList.php
Response samples Content type application/json
Copy
Expand all Collapse all Create a new folder Creates a new folder in the upload directory (under an optional parent) and creates an associated empty metadata file.
+
Request Body schema: application/json
Responses 200 Folder created successfully
+400 Bad Request (e.g., invalid folder name)
+403 Invalid CSRF token or permission denied
+post /api/folder/createFolder.php
/api/folder/createFolder.php
Request samples Content type application/json
Response samples Content type application/json
Delete an empty folder Deletes a specified folder if it is empty and not the root folder, and also removes its metadata file.
+
Request Body schema: application/json
Responses 200 Folder deleted successfully
+400 Bad Request (e.g., invalid folder name or folder not empty)
+403 Invalid CSRF token or permission denied
+post /api/folder/deleteFolder.php
/api/folder/deleteFolder.php
Request samples Content type application/json
Response samples Content type application/json
Rename a folder Renames an existing folder and updates its associated metadata files.
+
Request Body schema: application/json
oldFolder required
newFolder required
Responses 200 Folder renamed successfully
+400 Invalid folder names or folder does not exist
+403 Invalid CSRF token or permission denied
+post /api/folder/renameFolder.php
/api/folder/renameFolder.php
Request samples Content type application/json
Response samples Content type application/json
Get list of folders Retrieves the list of folders in the upload directory, including file counts and metadata file names for each folder.
+
query Parameters folder string
Example: folder=Documents
Optional folder name to filter the listing
+
Responses 200 Folder list retrieved successfully
+get /api/folder/getFolderList.php
/api/folder/getFolderList.php
Response samples Content type application/json
Copy
Expand all Collapse all Display a shared folder Renders an HTML view of a shared folder's contents. Supports password protection, file listing with pagination, and an upload container if uploads are allowed.
+
query Parameters token required
string
The share token for the folder
+
pass string
The password if the folder is protected
+
page integer
Example: page=1
Page number for pagination
+
Responses 200 Shared folder displayed
+403 Access forbidden (expired link or invalid password)
+404 Share folder not found
+get /api/folder/shareFolder.php
/api/folder/shareFolder.php
Create a share link for a folder Generates a secure share link for a folder along with optional password protection and upload settings.
+
Request Body schema: application/json
folder required
expirationMinutes password allowUpload
Responses 200 Share link created successfully
+403 Read-only users are not allowed to create share links
+post /api/folder/createShareFolderLink.php
/api/folder/createShareFolderLink.php
Request samples Content type application/json
{ "folder" : "Documents" ,
"expirationMinutes" : 60 ,
"password" : "secret" ,
"allowUpload" : 1
} Response samples Content type application/json
{ "token" : "a1b2c3d4..." ,
"expires" : 1623456789 ,
} Download a file from a shared folder Retrieves and serves a file from a shared folder based on a share token.
+
query Parameters token required
file required
string
The filename to download
+
Responses 200 File served successfully
+400 Bad Request (missing parameters, invalid file name, etc.)
+403 Access forbidden (e.g., expired share link)
+get /api/folder/downloadSharedFile.php
/api/folder/downloadSharedFile.php
Upload a file to a shared folder Handles file upload to a shared folder using a share token. Validates file size, extension, and uploads the file to the shared folder, updating metadata accordingly.
+
Request Body schema: multipart/form-data Multipart form data containing the share token and file to upload.
+
token required
fileToUpload required
Responses 302 Redirects to the shared folder page on success.
+400 Bad Request (missing token, file upload error, file type/size not allowed)
+403 Forbidden (share link expired or uploads not allowed)
+500 Server error during file move
+post /api/folder/uploadToSharedFolder.php
/api/folder/uploadToSharedFolder.php
Handle file upload Handles file uploads for both chunked and non-chunked (full) uploads. Validates CSRF, user authentication, and permissions, and processes file uploads accordingly. On success, returns a JSON status for chunked uploads or redirects for full uploads.
+
Request Body schema: multipart/form-data Multipart form data for file upload. For chunked uploads, include fields like 'resumableChunkNumber', 'resumableTotalChunks', 'resumableIdentifier', 'resumableFilename', etc.
+
token required
string
Share token or upload token.
+
fileToUpload required
resumableChunkNumber integer
Chunk number for chunked uploads.
+
resumableTotalChunks integer
Total number of chunks.
+
resumableFilename folder string
Target folder (default 'root').
+
Responses 200 File uploaded successfully (or chunk uploaded status).
+302 Redirection on full upload success.
+400 Bad Request (e.g., missing file, invalid parameters)
+403 Forbidden (e.g., invalid CSRF token, upload disabled)
+500 Server error during file processing
+post /api/upload/upload.php Response samples Content type application/json
{ "success" : "File uploaded successfully" ,
"newFilename" : "5f2d7c123a_example.png" ,
"status" : "chunk uploaded"
} Remove chunked upload temporary directory Removes the temporary directory used for chunked uploads, given a folder name matching the expected resumable pattern.
+
Request Body schema: application/json
Responses 200 Temporary folder removed successfully
+400 Invalid input (e.g., missing folder or invalid folder name)
+post /api/upload/removeChunks.php
/api/upload/removeChunks.php
Request samples Content type application/json
Response samples Content type application/json
Retrieve a list of users Returns a JSON array of users. Only available to authenticated admin users.
+
Responses 200 Successful response with an array of users
+401 Unauthorized: the user is not authenticated or is not an admin
+ Response samples Content type application/json
Copy
Expand all Collapse all [ { "username" : "johndoe" ,
"role" : "admin"
} ] Add a new user Adds a new user to the system. In setup mode, the new user is automatically made admin.
+
Request Body schema: application/json
username required
password required
isAdmin
Responses 200 User added successfully
+ Request samples Content type application/json
Response samples Content type application/json
Remove a user Removes the specified user from the system. Cannot remove the currently logged-in user.
+
Request Body schema: application/json
Responses 200 User removed successfully
+delete /api/removeUser.php Request samples Content type application/json
Response samples Content type application/json
Retrieve user permissions Returns the permissions for the current user, or all permissions if the user is an admin.
+
Responses 200 Successful response with user permissions
+get /api/getUserPermissions.php
/api/getUserPermissions.php
Response samples Content type application/json
Update user permissions Updates permissions for users. Only available to authenticated admin users.
+
Request Body schema: application/json
Responses 200 User permissions updated successfully
+put /api/updateUserPermissions.php
/api/updateUserPermissions.php
Request samples Content type application/json
Copy
Expand all Collapse all { "permissions" :
[ { "username" : "johndoe" ,
"folderOnly" : true ,
"readOnly" : false ,
"disableUpload" : false
} ] } Response samples Content type application/json
Change user password Allows an authenticated user to change their password by verifying the old password and updating to a new one.
+
Request Body schema: application/json
oldPassword required
newPassword required
confirmPassword required
Responses 200 Password updated successfully
+post /api/changePassword.php Request samples Content type application/json
{ "oldPassword" : "oldpass123" ,
"newPassword" : "newpass456" ,
"confirmPassword" : "newpass456"
} Response samples Content type application/json
Update user panel settings Updates user panel settings by disabling TOTP when not enabled. Accessible to authenticated users.
+
Request Body schema: application/json
Responses 200 User panel updated successfully
+put /api/updateUserPanel.php Request samples Content type application/json
Response samples Content type application/json
Disable TOTP for the authenticated user Clears the TOTP secret from the users file for the current user.
+
Responses 200 TOTP disabled successfully
+403 Not authenticated or invalid CSRF token
+500 Failed to disable TOTP
+ Response samples Content type application/json
Recover TOTP Verifies a recovery code to disable TOTP and finalize login.
+
Request Body schema: application/json
Responses 200 Recovery successful
+400 Invalid input or recovery code
+post /api/totp_recover.php Request samples Content type application/json
Response samples Content type application/json
Generate and save a new TOTP recovery code Generates a new TOTP recovery code for the authenticated user, stores its hash, and returns the plain text recovery code.
+
Responses 200 Recovery code generated successfully
+403 Invalid CSRF token or unauthorized
+post /api/totp_saveCode.php Response samples Content type application/json
Set up TOTP and generate a QR code Generates (or retrieves) the TOTP secret for the user and builds a QR code image for scanning.
+
Responses 200 QR code image for TOTP setup
+403 Unauthorized or invalid CSRF token
+ Verify TOTP code Verifies a TOTP code and completes login for pending users or validates TOTP for setup verification.
+
Request Body schema: application/json
Responses 200 TOTP successfully verified
+400 Bad Request (e.g., invalid input)
+403 Not authenticated or invalid CSRF token
+429 Too many attempts. Try again later.
+ Request samples Content type application/json
Response samples Content type application/json
+
+
+
+
\ No newline at end of file
diff --git a/public/openapi.json b/public/openapi.json
new file mode 100644
index 0000000..840f6c7
--- /dev/null
+++ b/public/openapi.json
@@ -0,0 +1,2599 @@
+{
+ "openapi": "3.0.0",
+ "info": {
+ "title": "FileRise API",
+ "description": "A lightweight self-hosted file manager API",
+ "version": "1.0.0"
+ },
+ "paths": {
+ "/api/admin": {},
+ "/api/auth": {},
+ "/api/file": {},
+ "/api/folder": {},
+ "/api/upload": {},
+ "/api": {},
+ "/api/admin/getConfig.php": {
+ "get": {
+ "tags": [
+ "Admin"
+ ],
+ "summary": "Retrieve admin configuration",
+ "description": "Returns the admin configuration settings, decrypting the configuration file and providing default values if not set.",
+ "operationId": "getAdminConfig",
+ "responses": {
+ "200": {
+ "description": "Configuration retrieved successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "header_title": {
+ "type": "string",
+ "example": "FileRise"
+ },
+ "oidc": {
+ "properties": {
+ "providerUrl": {
+ "type": "string",
+ "example": "https://your-oidc-provider.com"
+ },
+ "clientId": {
+ "type": "string",
+ "example": "YOUR_CLIENT_ID"
+ },
+ "clientSecret": {
+ "type": "string",
+ "example": "YOUR_CLIENT_SECRET"
+ },
+ "redirectUri": {
+ "type": "string",
+ "example": "https://yourdomain.com/auth.php?oidc=callback"
+ }
+ },
+ "type": "object"
+ },
+ "loginOptions": {
+ "properties": {
+ "disableFormLogin": {
+ "type": "boolean",
+ "example": false
+ },
+ "disableBasicAuth": {
+ "type": "boolean",
+ "example": false
+ },
+ "disableOIDCLogin": {
+ "type": "boolean",
+ "example": false
+ }
+ },
+ "type": "object"
+ },
+ "globalOtpauthUrl": {
+ "type": "string",
+ "example": ""
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "500": {
+ "description": "Failed to decrypt configuration or server error"
+ }
+ }
+ }
+ },
+ "/api/admin/updateConfig.php": {
+ "put": {
+ "tags": [
+ "Admin"
+ ],
+ "summary": "Update admin configuration",
+ "description": "Updates the admin configuration settings. Requires admin privileges and a valid CSRF token.",
+ "operationId": "updateAdminConfig",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "header_title",
+ "oidc",
+ "loginOptions"
+ ],
+ "properties": {
+ "header_title": {
+ "type": "string",
+ "example": "FileRise"
+ },
+ "oidc": {
+ "properties": {
+ "providerUrl": {
+ "type": "string",
+ "example": "https://your-oidc-provider.com"
+ },
+ "clientId": {
+ "type": "string",
+ "example": "YOUR_CLIENT_ID"
+ },
+ "clientSecret": {
+ "type": "string",
+ "example": "YOUR_CLIENT_SECRET"
+ },
+ "redirectUri": {
+ "type": "string",
+ "example": "https://yourdomain.com/api/auth/auth.php?oidc=callback"
+ }
+ },
+ "type": "object"
+ },
+ "loginOptions": {
+ "properties": {
+ "disableFormLogin": {
+ "type": "boolean",
+ "example": false
+ },
+ "disableBasicAuth": {
+ "type": "boolean",
+ "example": false
+ },
+ "disableOIDCLogin": {
+ "type": "boolean",
+ "example": false
+ }
+ },
+ "type": "object"
+ },
+ "globalOtpauthUrl": {
+ "type": "string",
+ "example": ""
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Configuration updated successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "string",
+ "example": "Configuration updated successfully."
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request (e.g., invalid input, incomplete OIDC configuration)"
+ },
+ "403": {
+ "description": "Unauthorized (user not admin or invalid CSRF token)"
+ },
+ "500": {
+ "description": "Server error (failed to write configuration file)"
+ }
+ }
+ }
+ },
+ "/api/auth/auth.php": {
+ "post": {
+ "tags": [
+ "Auth"
+ ],
+ "summary": "Authenticate user",
+ "description": "Handles user authentication via OIDC or form-based credentials. For OIDC flows, processes callbacks; otherwise, performs standard authentication with optional TOTP verification.",
+ "operationId": "authUser",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "username",
+ "password"
+ ],
+ "properties": {
+ "username": {
+ "type": "string",
+ "example": "johndoe"
+ },
+ "password": {
+ "type": "string",
+ "example": "secretpassword"
+ },
+ "remember_me": {
+ "type": "boolean",
+ "example": true
+ },
+ "totp_code": {
+ "type": "string",
+ "example": "123456"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Login successful; returns user info and status",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "status": {
+ "type": "string",
+ "example": "ok"
+ },
+ "success": {
+ "type": "string",
+ "example": "Login successful"
+ },
+ "username": {
+ "type": "string",
+ "example": "johndoe"
+ },
+ "isAdmin": {
+ "type": "boolean",
+ "example": true
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request (e.g., missing credentials)"
+ },
+ "401": {
+ "description": "Unauthorized (e.g., invalid credentials, too many attempts)"
+ },
+ "429": {
+ "description": "Too many failed login attempts"
+ }
+ }
+ }
+ },
+ "/api/auth/checkAuth.php": {
+ "get": {
+ "tags": [
+ "Auth"
+ ],
+ "summary": "Check authentication status",
+ "description": "Checks if the current session is authenticated. If the users file is missing or empty, returns a setup flag. Also returns information about admin privileges, TOTP status, and folder-only access.",
+ "operationId": "checkAuth",
+ "responses": {
+ "200": {
+ "description": "Returns authentication status and user details",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "authenticated": {
+ "type": "boolean",
+ "example": true
+ },
+ "isAdmin": {
+ "type": "boolean",
+ "example": true
+ },
+ "totp_enabled": {
+ "type": "boolean",
+ "example": false
+ },
+ "username": {
+ "type": "string",
+ "example": "johndoe"
+ },
+ "folderOnly": {
+ "type": "boolean",
+ "example": false
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/auth/token.php": {
+ "get": {
+ "tags": [
+ "Auth"
+ ],
+ "summary": "Retrieve CSRF token and share URL",
+ "description": "Returns the current CSRF token along with the configured share URL.",
+ "operationId": "getToken",
+ "responses": {
+ "200": {
+ "description": "CSRF token and share URL",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "csrf_token": {
+ "type": "string",
+ "example": "0123456789abcdef..."
+ },
+ "share_url": {
+ "type": "string",
+ "example": "https://yourdomain.com/share.php"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/auth/login_basic.php": {
+ "get": {
+ "tags": [
+ "Auth"
+ ],
+ "summary": "Authenticate using HTTP Basic Authentication",
+ "description": "Performs HTTP Basic authentication. If credentials are missing, sends a 401 response prompting for Basic auth. On valid credentials, optionally handles TOTP verification and finalizes session login.",
+ "operationId": "loginBasic",
+ "responses": {
+ "200": {
+ "description": "Login successful; redirects to index.html",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "string",
+ "example": "Login successful"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized due to missing credentials or invalid credentials."
+ }
+ }
+ }
+ },
+ "/api/auth/logout.php": {
+ "post": {
+ "tags": [
+ "Auth"
+ ],
+ "summary": "Logout user",
+ "description": "Clears the session, removes persistent login tokens, and redirects the user to the login page.",
+ "operationId": "logoutUser",
+ "responses": {
+ "302": {
+ "description": "Redirects to the login page with a logout flag."
+ },
+ "401": {
+ "description": "Unauthorized"
+ }
+ }
+ }
+ },
+ "/api/file/copyFiles.php": {
+ "post": {
+ "tags": [
+ "Files"
+ ],
+ "summary": "Copy files between folders",
+ "description": "Copies files from a source folder to a destination folder. It validates folder names, handles file renaming if a conflict exists, and updates metadata accordingly.",
+ "operationId": "copyFiles",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "source",
+ "destination",
+ "files"
+ ],
+ "properties": {
+ "source": {
+ "type": "string",
+ "example": "root"
+ },
+ "destination": {
+ "type": "string",
+ "example": "Documents"
+ },
+ "files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "example": "example.pdf"
+ }
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Files copied successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "string",
+ "example": "Files copied successfully"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid request or input"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Invalid CSRF token or read-only permission"
+ }
+ }
+ }
+ },
+ "/api/file/deleteFiles.php": {
+ "post": {
+ "tags": [
+ "Files"
+ ],
+ "summary": "Delete files (move to trash)",
+ "description": "Moves the specified files from the given folder to the trash and updates metadata accordingly.",
+ "operationId": "deleteFiles",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "files"
+ ],
+ "properties": {
+ "folder": {
+ "type": "string",
+ "example": "Documents"
+ },
+ "files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "example": "example.pdf"
+ }
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Files moved to Trash successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "string",
+ "example": "Files moved to Trash: file1.pdf, file2.doc"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid request"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Invalid CSRF token or permission denied"
+ }
+ }
+ }
+ },
+ "/api/file/moveFiles.php": {
+ "post": {
+ "tags": [
+ "Files"
+ ],
+ "summary": "Move files between folders",
+ "description": "Moves files from a source folder to a destination folder, updating metadata accordingly.",
+ "operationId": "moveFiles",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "source",
+ "destination",
+ "files"
+ ],
+ "properties": {
+ "source": {
+ "type": "string",
+ "example": "root"
+ },
+ "destination": {
+ "type": "string",
+ "example": "Archives"
+ },
+ "files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "example": "report.pdf"
+ }
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Files moved successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "string",
+ "example": "Files moved successfully"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid request or input"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Invalid CSRF token or permission denied"
+ }
+ }
+ }
+ },
+ "/api/file/renameFile.php": {
+ "post": {
+ "tags": [
+ "Files"
+ ],
+ "summary": "Rename a file",
+ "description": "Renames a file within a specified folder and updates folder metadata. If a file with the new name exists, a unique name is generated.",
+ "operationId": "renameFile",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "folder",
+ "oldName",
+ "newName"
+ ],
+ "properties": {
+ "folder": {
+ "type": "string",
+ "example": "Documents"
+ },
+ "oldName": {
+ "type": "string",
+ "example": "oldfile.pdf"
+ },
+ "newName": {
+ "type": "string",
+ "example": "newfile.pdf"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "File renamed successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "string",
+ "example": "File renamed successfully"
+ },
+ "newName": {
+ "type": "string",
+ "example": "newfile.pdf"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid input"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Invalid CSRF token or permission denied"
+ }
+ }
+ }
+ },
+ "/api/file/saveFile.php": {
+ "post": {
+ "tags": [
+ "Files"
+ ],
+ "summary": "Save a file",
+ "description": "Saves file content to disk in a specified folder and updates metadata accordingly.",
+ "operationId": "saveFile",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "fileName",
+ "content"
+ ],
+ "properties": {
+ "fileName": {
+ "type": "string",
+ "example": "document.txt"
+ },
+ "content": {
+ "type": "string",
+ "example": "File content here"
+ },
+ "folder": {
+ "type": "string",
+ "example": "Documents"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "File saved successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "string",
+ "example": "File saved successfully"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid request data"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Invalid CSRF token or read-only permission"
+ }
+ }
+ }
+ },
+ "/api/file/download.php": {
+ "get": {
+ "tags": [
+ "Files"
+ ],
+ "summary": "Download a file",
+ "description": "Downloads a file from a specified folder. The file is served inline for images or as an attachment for other types.",
+ "operationId": "downloadFile",
+ "parameters": [
+ {
+ "name": "file",
+ "in": "query",
+ "description": "The name of the file to download",
+ "required": true,
+ "schema": {
+ "type": "string",
+ "example": "example.pdf"
+ }
+ },
+ {
+ "name": "folder",
+ "in": "query",
+ "description": "The folder in which the file is located. Defaults to root.",
+ "required": false,
+ "schema": {
+ "type": "string",
+ "example": "Documents"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "File downloaded successfully"
+ },
+ "400": {
+ "description": "Bad Request"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Access forbidden"
+ },
+ "404": {
+ "description": "File not found"
+ },
+ "500": {
+ "description": "Server error"
+ }
+ }
+ }
+ },
+ "/api/file/downloadZip.php": {
+ "post": {
+ "tags": [
+ "Files"
+ ],
+ "summary": "Download a ZIP archive of selected files",
+ "description": "Creates a ZIP archive of the specified files in a folder and serves it for download.",
+ "operationId": "downloadZip",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "folder",
+ "files"
+ ],
+ "properties": {
+ "folder": {
+ "type": "string",
+ "example": "Documents"
+ },
+ "files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "example": "example.pdf"
+ }
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "ZIP archive created and served",
+ "content": {
+ "application/zip": {}
+ }
+ },
+ "400": {
+ "description": "Bad request or invalid input"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Invalid CSRF token"
+ },
+ "500": {
+ "description": "Server error"
+ }
+ }
+ }
+ },
+ "/api/file/extractZip.php": {
+ "post": {
+ "tags": [
+ "Files"
+ ],
+ "summary": "Extract ZIP files",
+ "description": "Extracts ZIP archives from a specified folder and updates metadata. Returns a list of extracted files.",
+ "operationId": "extractZip",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "folder",
+ "files"
+ ],
+ "properties": {
+ "folder": {
+ "type": "string",
+ "example": "Documents"
+ },
+ "files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "example": "archive.zip"
+ }
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "ZIP files extracted successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "boolean",
+ "example": true
+ },
+ "extractedFiles": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid input"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Invalid CSRF token"
+ }
+ }
+ }
+ },
+ "/api/file/share.php": {
+ "get": {
+ "tags": [
+ "Files"
+ ],
+ "summary": "Access a shared file",
+ "description": "Serves a shared file based on a share token. If the file is password protected and no password is provided, a password entry form is returned.",
+ "operationId": "shareFile",
+ "parameters": [
+ {
+ "name": "token",
+ "in": "query",
+ "description": "The share token",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "pass",
+ "in": "query",
+ "description": "The password for the share if required",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "File served or password form rendered",
+ "content": {
+ "application/octet-stream": {}
+ }
+ },
+ "400": {
+ "description": "Missing token or invalid request"
+ },
+ "403": {
+ "description": "Link expired, invalid password, or forbidden access"
+ },
+ "404": {
+ "description": "Share link or file not found"
+ }
+ }
+ }
+ },
+ "/api/file/createShareLink.php": {
+ "post": {
+ "tags": [
+ "Files"
+ ],
+ "summary": "Create a share link for a file",
+ "description": "Generates a secure share link token for a specific file with an optional password protection and expiration time.",
+ "operationId": "createShareLink",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "folder",
+ "file"
+ ],
+ "properties": {
+ "folder": {
+ "type": "string",
+ "example": "Documents"
+ },
+ "file": {
+ "type": "string",
+ "example": "report.pdf"
+ },
+ "expirationMinutes": {
+ "type": "integer",
+ "example": 60
+ },
+ "password": {
+ "type": "string",
+ "example": "secret"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Share link created successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "token": {
+ "type": "string",
+ "example": "a1b2c3d4e5f6..."
+ },
+ "expires": {
+ "type": "integer",
+ "example": 1621234567
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid request data"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Read-only users are not allowed to create share links"
+ }
+ }
+ }
+ },
+ "/api/file/getTrashItems.php": {
+ "get": {
+ "tags": [
+ "Files"
+ ],
+ "summary": "Get trash items",
+ "description": "Retrieves a list of files that have been moved to Trash, enriched with metadata such as who deleted them and when.",
+ "operationId": "getTrashItems",
+ "responses": {
+ "200": {
+ "description": "Trash items retrieved successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized"
+ }
+ }
+ }
+ },
+ "/api/file/restoreFiles.php": {
+ "post": {
+ "tags": [
+ "Files"
+ ],
+ "summary": "Restore trashed files",
+ "description": "Restores files from Trash based on provided trash file identifiers and updates metadata.",
+ "operationId": "restoreFiles",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "files"
+ ],
+ "properties": {
+ "files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "example": "trashedFile_1623456789.zip"
+ }
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Files restored successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "string",
+ "example": "Items restored: file1, file2"
+ },
+ "restored": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid request"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Invalid CSRF token"
+ }
+ }
+ }
+ },
+ "/api/file/deleteTrashFiles.php": {
+ "post": {
+ "tags": [
+ "Files"
+ ],
+ "summary": "Delete trash files",
+ "description": "Deletes trash items based on provided trash file identifiers from the trash metadata and removes the files from disk.",
+ "operationId": "deleteTrashFiles",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "oneOf": [
+ {
+ "required": [
+ "deleteAll"
+ ],
+ "properties": {
+ "deleteAll": {
+ "type": "boolean",
+ "example": true
+ }
+ },
+ "type": "object"
+ },
+ {
+ "required": [
+ "files"
+ ],
+ "properties": {
+ "files": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "example": "trashedfile_1234567890"
+ }
+ }
+ },
+ "type": "object"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Trash items deleted successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "deleted": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid input"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Invalid CSRF token"
+ }
+ }
+ }
+ },
+ "/api/file/getFileTag.php": {
+ "get": {
+ "tags": [
+ "Files"
+ ],
+ "summary": "Retrieve file tags",
+ "description": "Retrieves tags from the createdTags.json metadata file.",
+ "operationId": "getFileTags",
+ "responses": {
+ "200": {
+ "description": "File tags retrieved successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "/api/file/saveFileTag.php": {
+ "post": {
+ "tags": [
+ "Files"
+ ],
+ "summary": "Save file tags",
+ "description": "Saves tag data for a specified file and updates global tag data. For folder-specific tags, saves to the folder's metadata file.",
+ "operationId": "saveFileTag",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "file",
+ "tags"
+ ],
+ "properties": {
+ "file": {
+ "type": "string",
+ "example": "document.txt"
+ },
+ "folder": {
+ "type": "string",
+ "example": "Documents"
+ },
+ "tags": {
+ "type": "array",
+ "items": {
+ "properties": {
+ "name": {
+ "type": "string",
+ "example": "Important"
+ },
+ "color": {
+ "type": "string",
+ "example": "#FF0000"
+ }
+ },
+ "type": "object"
+ }
+ },
+ "deleteGlobal": {
+ "type": "boolean",
+ "example": false
+ },
+ "tagToDelete": {
+ "type": "string",
+ "example": "OldTag"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Tag data saved successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "string",
+ "example": "Tag data saved successfully."
+ },
+ "globalTags": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid request data"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Invalid CSRF token or insufficient permissions"
+ }
+ }
+ }
+ },
+ "/api/file/getFileList.php": {
+ "get": {
+ "tags": [
+ "Files"
+ ],
+ "summary": "Get file list",
+ "description": "Retrieves a list of files from a specified folder along with global tags and metadata.",
+ "operationId": "getFileList",
+ "parameters": [
+ {
+ "name": "folder",
+ "in": "query",
+ "description": "Folder name (defaults to 'root')",
+ "required": false,
+ "schema": {
+ "type": "string",
+ "example": "Documents"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "File list retrieved successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "files": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ },
+ "globalTags": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "400": {
+ "description": "Bad Request"
+ }
+ }
+ }
+ },
+ "/api/folder/createFolder.php": {
+ "post": {
+ "tags": [
+ "Folders"
+ ],
+ "summary": "Create a new folder",
+ "description": "Creates a new folder in the upload directory (under an optional parent) and creates an associated empty metadata file.",
+ "operationId": "createFolder",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "folderName"
+ ],
+ "properties": {
+ "folderName": {
+ "type": "string",
+ "example": "NewFolder"
+ },
+ "parent": {
+ "type": "string",
+ "example": "Documents"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Folder created successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "boolean",
+ "example": true
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request (e.g., invalid folder name)"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Invalid CSRF token or permission denied"
+ }
+ }
+ }
+ },
+ "/api/folder/deleteFolder.php": {
+ "post": {
+ "tags": [
+ "Folders"
+ ],
+ "summary": "Delete an empty folder",
+ "description": "Deletes a specified folder if it is empty and not the root folder, and also removes its metadata file.",
+ "operationId": "deleteFolder",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "folder"
+ ],
+ "properties": {
+ "folder": {
+ "type": "string",
+ "example": "Documents/Subfolder"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Folder deleted successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "boolean",
+ "example": true
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request (e.g., invalid folder name or folder not empty)"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Invalid CSRF token or permission denied"
+ }
+ }
+ }
+ },
+ "/api/folder/renameFolder.php": {
+ "post": {
+ "tags": [
+ "Folders"
+ ],
+ "summary": "Rename a folder",
+ "description": "Renames an existing folder and updates its associated metadata files.",
+ "operationId": "renameFolder",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "oldFolder",
+ "newFolder"
+ ],
+ "properties": {
+ "oldFolder": {
+ "type": "string",
+ "example": "Documents/OldFolder"
+ },
+ "newFolder": {
+ "type": "string",
+ "example": "Documents/NewFolder"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Folder renamed successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "boolean",
+ "example": true
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid folder names or folder does not exist"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Invalid CSRF token or permission denied"
+ }
+ }
+ }
+ },
+ "/api/folder/getFolderList.php": {
+ "get": {
+ "tags": [
+ "Folders"
+ ],
+ "summary": "Get list of folders",
+ "description": "Retrieves the list of folders in the upload directory, including file counts and metadata file names for each folder.",
+ "operationId": "getFolderList",
+ "parameters": [
+ {
+ "name": "folder",
+ "in": "query",
+ "description": "Optional folder name to filter the listing",
+ "required": false,
+ "schema": {
+ "type": "string",
+ "example": "Documents"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Folder list retrieved successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "400": {
+ "description": "Bad request"
+ }
+ }
+ }
+ },
+ "/api/folder/shareFolder.php": {
+ "get": {
+ "tags": [
+ "Folders"
+ ],
+ "summary": "Display a shared folder",
+ "description": "Renders an HTML view of a shared folder's contents. Supports password protection, file listing with pagination, and an upload container if uploads are allowed.",
+ "operationId": "shareFolder",
+ "parameters": [
+ {
+ "name": "token",
+ "in": "query",
+ "description": "The share token for the folder",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "pass",
+ "in": "query",
+ "description": "The password if the folder is protected",
+ "required": false,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "page",
+ "in": "query",
+ "description": "Page number for pagination",
+ "required": false,
+ "schema": {
+ "type": "integer",
+ "example": 1
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Shared folder displayed",
+ "content": {
+ "text/html": {}
+ }
+ },
+ "400": {
+ "description": "Invalid request"
+ },
+ "403": {
+ "description": "Access forbidden (expired link or invalid password)"
+ },
+ "404": {
+ "description": "Share folder not found"
+ }
+ }
+ }
+ },
+ "/api/folder/createShareFolderLink.php": {
+ "post": {
+ "tags": [
+ "Folders"
+ ],
+ "summary": "Create a share link for a folder",
+ "description": "Generates a secure share link for a folder along with optional password protection and upload settings.",
+ "operationId": "createShareFolderLink",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "folder"
+ ],
+ "properties": {
+ "folder": {
+ "type": "string",
+ "example": "Documents"
+ },
+ "expirationMinutes": {
+ "type": "integer",
+ "example": 60
+ },
+ "password": {
+ "type": "string",
+ "example": "secret"
+ },
+ "allowUpload": {
+ "type": "integer",
+ "example": 1
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Share link created successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "token": {
+ "type": "string",
+ "example": "a1b2c3d4..."
+ },
+ "expires": {
+ "type": "integer",
+ "example": 1623456789
+ },
+ "link": {
+ "type": "string",
+ "example": "https://yourdomain.com/api/folder/shareFolder.php?token=..."
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid input"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Read-only users are not allowed to create share links"
+ }
+ }
+ }
+ },
+ "/api/folder/downloadSharedFile.php": {
+ "get": {
+ "tags": [
+ "Folders"
+ ],
+ "summary": "Download a file from a shared folder",
+ "description": "Retrieves and serves a file from a shared folder based on a share token.",
+ "operationId": "downloadSharedFile",
+ "parameters": [
+ {
+ "name": "token",
+ "in": "query",
+ "description": "The share folder token",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "file",
+ "in": "query",
+ "description": "The filename to download",
+ "required": true,
+ "schema": {
+ "type": "string"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "File served successfully",
+ "content": {
+ "application/octet-stream": {}
+ }
+ },
+ "400": {
+ "description": "Bad Request (missing parameters, invalid file name, etc.)"
+ },
+ "403": {
+ "description": "Access forbidden (e.g., expired share link)"
+ },
+ "404": {
+ "description": "File not found"
+ }
+ }
+ }
+ },
+ "/api/folder/uploadToSharedFolder.php": {
+ "post": {
+ "tags": [
+ "Folders"
+ ],
+ "summary": "Upload a file to a shared folder",
+ "description": "Handles file upload to a shared folder using a share token. Validates file size, extension, and uploads the file to the shared folder, updating metadata accordingly.",
+ "operationId": "uploadToSharedFolder",
+ "requestBody": {
+ "description": "Multipart form data containing the share token and file to upload.",
+ "required": true,
+ "content": {
+ "multipart/form-data": {
+ "schema": {
+ "required": [
+ "token",
+ "fileToUpload"
+ ],
+ "properties": {
+ "token": {
+ "type": "string"
+ },
+ "fileToUpload": {
+ "type": "string",
+ "format": "binary"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "302": {
+ "description": "Redirects to the shared folder page on success."
+ },
+ "400": {
+ "description": "Bad Request (missing token, file upload error, file type/size not allowed)"
+ },
+ "403": {
+ "description": "Forbidden (share link expired or uploads not allowed)"
+ },
+ "500": {
+ "description": "Server error during file move"
+ }
+ }
+ }
+ },
+ "/api/upload/upload.php": {
+ "post": {
+ "tags": [
+ "Uploads"
+ ],
+ "summary": "Handle file upload",
+ "description": "Handles file uploads for both chunked and non-chunked (full) uploads. Validates CSRF, user authentication, and permissions, and processes file uploads accordingly. On success, returns a JSON status for chunked uploads or redirects for full uploads.",
+ "operationId": "handleUpload",
+ "requestBody": {
+ "description": "Multipart form data for file upload. For chunked uploads, include fields like 'resumableChunkNumber', 'resumableTotalChunks', 'resumableIdentifier', 'resumableFilename', etc.",
+ "required": true,
+ "content": {
+ "multipart/form-data": {
+ "schema": {
+ "required": [
+ "token",
+ "fileToUpload"
+ ],
+ "properties": {
+ "token": {
+ "description": "Share token or upload token.",
+ "type": "string"
+ },
+ "fileToUpload": {
+ "description": "The file to upload.",
+ "type": "string",
+ "format": "binary"
+ },
+ "resumableChunkNumber": {
+ "description": "Chunk number for chunked uploads.",
+ "type": "integer"
+ },
+ "resumableTotalChunks": {
+ "description": "Total number of chunks.",
+ "type": "integer"
+ },
+ "resumableFilename": {
+ "description": "Original filename.",
+ "type": "string"
+ },
+ "folder": {
+ "description": "Target folder (default 'root').",
+ "type": "string"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "File uploaded successfully (or chunk uploaded status).",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "string",
+ "example": "File uploaded successfully"
+ },
+ "newFilename": {
+ "type": "string",
+ "example": "5f2d7c123a_example.png"
+ },
+ "status": {
+ "type": "string",
+ "example": "chunk uploaded"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "302": {
+ "description": "Redirection on full upload success."
+ },
+ "400": {
+ "description": "Bad Request (e.g., missing file, invalid parameters)"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Forbidden (e.g., invalid CSRF token, upload disabled)"
+ },
+ "500": {
+ "description": "Server error during file processing"
+ }
+ }
+ }
+ },
+ "/api/upload/removeChunks.php": {
+ "post": {
+ "tags": [
+ "Uploads"
+ ],
+ "summary": "Remove chunked upload temporary directory",
+ "description": "Removes the temporary directory used for chunked uploads, given a folder name matching the expected resumable pattern.",
+ "operationId": "removeChunks",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "folder"
+ ],
+ "properties": {
+ "folder": {
+ "type": "string",
+ "example": "resumable_myupload123"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Temporary folder removed successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "boolean",
+ "example": true
+ },
+ "message": {
+ "type": "string",
+ "example": "Temporary folder removed."
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid input (e.g., missing folder or invalid folder name)"
+ },
+ "403": {
+ "description": "Invalid CSRF token"
+ }
+ }
+ }
+ },
+ "/api/getUsers.php": {
+ "get": {
+ "tags": [
+ "Users"
+ ],
+ "summary": "Retrieve a list of users",
+ "description": "Returns a JSON array of users. Only available to authenticated admin users.",
+ "operationId": "getUsers",
+ "responses": {
+ "200": {
+ "description": "Successful response with an array of users",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "array",
+ "items": {
+ "properties": {
+ "username": {
+ "type": "string",
+ "example": "johndoe"
+ },
+ "role": {
+ "type": "string",
+ "example": "admin"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized: the user is not authenticated or is not an admin"
+ }
+ }
+ }
+ },
+ "/api/addUser.php": {
+ "post": {
+ "tags": [
+ "Users"
+ ],
+ "summary": "Add a new user",
+ "description": "Adds a new user to the system. In setup mode, the new user is automatically made admin.",
+ "operationId": "addUser",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "username",
+ "password"
+ ],
+ "properties": {
+ "username": {
+ "type": "string",
+ "example": "johndoe"
+ },
+ "password": {
+ "type": "string",
+ "example": "securepassword"
+ },
+ "isAdmin": {
+ "type": "boolean",
+ "example": true
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "User added successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "string",
+ "example": "User added successfully"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request"
+ },
+ "401": {
+ "description": "Unauthorized"
+ }
+ }
+ }
+ },
+ "/api/removeUser.php": {
+ "delete": {
+ "tags": [
+ "Users"
+ ],
+ "summary": "Remove a user",
+ "description": "Removes the specified user from the system. Cannot remove the currently logged-in user.",
+ "operationId": "removeUser",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "username"
+ ],
+ "properties": {
+ "username": {
+ "type": "string",
+ "example": "johndoe"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "User removed successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "string",
+ "example": "User removed successfully"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Invalid CSRF token"
+ }
+ }
+ }
+ },
+ "/api/getUserPermissions.php": {
+ "get": {
+ "tags": [
+ "Users"
+ ],
+ "summary": "Retrieve user permissions",
+ "description": "Returns the permissions for the current user, or all permissions if the user is an admin.",
+ "operationId": "getUserPermissions",
+ "responses": {
+ "200": {
+ "description": "Successful response with user permissions",
+ "content": {
+ "application/json": {
+ "schema": {
+ "type": "object"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized"
+ }
+ }
+ }
+ },
+ "/api/updateUserPermissions.php": {
+ "put": {
+ "tags": [
+ "Users"
+ ],
+ "summary": "Update user permissions",
+ "description": "Updates permissions for users. Only available to authenticated admin users.",
+ "operationId": "updateUserPermissions",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "permissions"
+ ],
+ "properties": {
+ "permissions": {
+ "type": "array",
+ "items": {
+ "properties": {
+ "username": {
+ "type": "string",
+ "example": "johndoe"
+ },
+ "folderOnly": {
+ "type": "boolean",
+ "example": true
+ },
+ "readOnly": {
+ "type": "boolean",
+ "example": false
+ },
+ "disableUpload": {
+ "type": "boolean",
+ "example": false
+ }
+ },
+ "type": "object"
+ }
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "User permissions updated successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "string",
+ "example": "User permissions updated successfully."
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Invalid CSRF token"
+ },
+ "400": {
+ "description": "Bad Request"
+ }
+ }
+ }
+ },
+ "/api/changePassword.php": {
+ "post": {
+ "tags": [
+ "Users"
+ ],
+ "summary": "Change user password",
+ "description": "Allows an authenticated user to change their password by verifying the old password and updating to a new one.",
+ "operationId": "changePassword",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "oldPassword",
+ "newPassword",
+ "confirmPassword"
+ ],
+ "properties": {
+ "oldPassword": {
+ "type": "string",
+ "example": "oldpass123"
+ },
+ "newPassword": {
+ "type": "string",
+ "example": "newpass456"
+ },
+ "confirmPassword": {
+ "type": "string",
+ "example": "newpass456"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Password updated successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "string",
+ "example": "Password updated successfully."
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request"
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Invalid CSRF token"
+ }
+ }
+ }
+ },
+ "/api/updateUserPanel.php": {
+ "put": {
+ "tags": [
+ "Users"
+ ],
+ "summary": "Update user panel settings",
+ "description": "Updates user panel settings by disabling TOTP when not enabled. Accessible to authenticated users.",
+ "operationId": "updateUserPanel",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "totp_enabled"
+ ],
+ "properties": {
+ "totp_enabled": {
+ "type": "boolean",
+ "example": false
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "User panel updated successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "string",
+ "example": "User panel updated: TOTP disabled"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "401": {
+ "description": "Unauthorized"
+ },
+ "403": {
+ "description": "Invalid CSRF token"
+ },
+ "400": {
+ "description": "Bad Request"
+ }
+ }
+ }
+ },
+ "/api/totp_disable.php": {
+ "put": {
+ "tags": [
+ "TOTP"
+ ],
+ "summary": "Disable TOTP for the authenticated user",
+ "description": "Clears the TOTP secret from the users file for the current user.",
+ "operationId": "disableTOTP",
+ "responses": {
+ "200": {
+ "description": "TOTP disabled successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "success": {
+ "type": "boolean",
+ "example": true
+ },
+ "message": {
+ "type": "string",
+ "example": "TOTP disabled successfully."
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "403": {
+ "description": "Not authenticated or invalid CSRF token"
+ },
+ "500": {
+ "description": "Failed to disable TOTP"
+ }
+ }
+ }
+ },
+ "/api/totp_recover.php": {
+ "post": {
+ "tags": [
+ "TOTP"
+ ],
+ "summary": "Recover TOTP",
+ "description": "Verifies a recovery code to disable TOTP and finalize login.",
+ "operationId": "recoverTOTP",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "recovery_code"
+ ],
+ "properties": {
+ "recovery_code": {
+ "type": "string",
+ "example": "ABC123DEF456"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "Recovery successful",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "status": {
+ "type": "string",
+ "example": "ok"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Invalid input or recovery code"
+ },
+ "403": {
+ "description": "Invalid CSRF token"
+ },
+ "405": {
+ "description": "Method not allowed"
+ },
+ "429": {
+ "description": "Too many attempts"
+ }
+ }
+ }
+ },
+ "/api/totp_saveCode.php": {
+ "post": {
+ "tags": [
+ "TOTP"
+ ],
+ "summary": "Generate and save a new TOTP recovery code",
+ "description": "Generates a new TOTP recovery code for the authenticated user, stores its hash, and returns the plain text recovery code.",
+ "operationId": "totpSaveCode",
+ "responses": {
+ "200": {
+ "description": "Recovery code generated successfully",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "status": {
+ "type": "string",
+ "example": "ok"
+ },
+ "recoveryCode": {
+ "type": "string",
+ "example": "ABC123DEF456"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request"
+ },
+ "403": {
+ "description": "Invalid CSRF token or unauthorized"
+ },
+ "405": {
+ "description": "Method not allowed"
+ }
+ }
+ }
+ },
+ "/api/totp_setup.php": {
+ "get": {
+ "tags": [
+ "TOTP"
+ ],
+ "summary": "Set up TOTP and generate a QR code",
+ "description": "Generates (or retrieves) the TOTP secret for the user and builds a QR code image for scanning.",
+ "operationId": "setupTOTP",
+ "responses": {
+ "200": {
+ "description": "QR code image for TOTP setup",
+ "content": {
+ "image/png": {}
+ }
+ },
+ "403": {
+ "description": "Unauthorized or invalid CSRF token"
+ },
+ "500": {
+ "description": "Server error"
+ }
+ }
+ }
+ },
+ "/api/totp_verify.php": {
+ "post": {
+ "tags": [
+ "TOTP"
+ ],
+ "summary": "Verify TOTP code",
+ "description": "Verifies a TOTP code and completes login for pending users or validates TOTP for setup verification.",
+ "operationId": "verifyTOTP",
+ "requestBody": {
+ "required": true,
+ "content": {
+ "application/json": {
+ "schema": {
+ "required": [
+ "totp_code"
+ ],
+ "properties": {
+ "totp_code": {
+ "type": "string",
+ "example": "123456"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "responses": {
+ "200": {
+ "description": "TOTP successfully verified",
+ "content": {
+ "application/json": {
+ "schema": {
+ "properties": {
+ "status": {
+ "type": "string",
+ "example": "ok"
+ },
+ "message": {
+ "type": "string",
+ "example": "Login successful"
+ }
+ },
+ "type": "object"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request (e.g., invalid input)"
+ },
+ "403": {
+ "description": "Not authenticated or invalid CSRF token"
+ },
+ "429": {
+ "description": "Too many attempts. Try again later."
+ }
+ }
+ }
+ }
+ },
+ "tags": [
+ {
+ "name": "Admin",
+ "description": "Admin"
+ },
+ {
+ "name": "Auth",
+ "description": "Auth"
+ },
+ {
+ "name": "Files",
+ "description": "Files"
+ },
+ {
+ "name": "Folders",
+ "description": "Folders"
+ },
+ {
+ "name": "Uploads",
+ "description": "Uploads"
+ },
+ {
+ "name": "Users",
+ "description": "Users"
+ },
+ {
+ "name": "TOTP",
+ "description": "TOTP"
+ }
+ ]
+}
\ No newline at end of file