Fix /settings redirect issue and add OAuth admin support
- Convert require_admin_access to proper decorator pattern - Fix redirect loop that was sending all users to / - Add is_admin flag handling for OAuth users (checks groups) - Update SETTING_METADATA with all 102 settings from config.py - Improve API admin check with type hints Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
+5
-1
@@ -24,9 +24,13 @@ logger = logging.getLogger(__name__)
|
||||
router = APIRouter(prefix="/settings", tags=["settings"])
|
||||
|
||||
|
||||
def require_admin(request: Request):
|
||||
def require_admin(request: Request) -> dict:
|
||||
"""
|
||||
Dependency to ensure the user is an admin.
|
||||
Raises HTTPException if not admin.
|
||||
|
||||
Returns:
|
||||
User dict from session
|
||||
"""
|
||||
user = request.session.get("user")
|
||||
if not user or not user.get("is_admin"):
|
||||
|
||||
+13
-1
@@ -114,10 +114,22 @@ if AUTH_ENABLED:
|
||||
if not user_data.get("picture") and user_data.get("email"):
|
||||
user_data["picture"] = get_gravatar_url(user_data["email"])
|
||||
|
||||
# Check if user is admin based on OAuth groups or specific email
|
||||
# You can customize this logic based on your OAuth provider's attributes
|
||||
# For example, check if user has an "admin" group or specific email domain
|
||||
is_admin = False
|
||||
if "groups" in user_data:
|
||||
# Check if user is in admin group
|
||||
groups = user_data.get("groups", [])
|
||||
is_admin = "admin" in groups or "administrators" in groups
|
||||
|
||||
# Set is_admin flag (defaults to False for OAuth users unless they're in admin group)
|
||||
user_data["is_admin"] = is_admin
|
||||
|
||||
request.session["user"] = user_data
|
||||
|
||||
# Log the successful authentication
|
||||
print(f"User authenticated via OAuth: {user_data.get('email', 'No email')}")
|
||||
print(f"User authenticated via OAuth: {user_data.get('email', 'No email')} (admin: {is_admin})")
|
||||
|
||||
# Redirect to original destination or default
|
||||
redirect_url = request.session.pop("redirect_after_login", "/upload")
|
||||
|
||||
+721
-11
@@ -48,7 +48,7 @@ SETTING_METADATA = {
|
||||
"description": "External hostname for the application (e.g., docuelevate.example.com)",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": True,
|
||||
"required": False,
|
||||
"restart_required": True,
|
||||
},
|
||||
"debug": {
|
||||
@@ -59,14 +59,6 @@ SETTING_METADATA = {
|
||||
"required": False,
|
||||
"restart_required": True,
|
||||
},
|
||||
"allow_file_delete": {
|
||||
"category": "Core",
|
||||
"description": "Allow deleting files from the database",
|
||||
"type": "boolean",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"gotenberg_url": {
|
||||
"category": "Core",
|
||||
"description": "Gotenberg service URL for document conversion",
|
||||
@@ -90,7 +82,7 @@ SETTING_METADATA = {
|
||||
"description": "Secret key for session encryption (min 32 characters)",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": True,
|
||||
"required": False,
|
||||
"restart_required": True,
|
||||
},
|
||||
"admin_username": {
|
||||
@@ -109,6 +101,38 @@ SETTING_METADATA = {
|
||||
"required": False,
|
||||
"restart_required": True,
|
||||
},
|
||||
"authentik_client_id": {
|
||||
"category": "Authentication",
|
||||
"description": "Authentik OAuth2 client ID",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": True,
|
||||
},
|
||||
"authentik_client_secret": {
|
||||
"category": "Authentication",
|
||||
"description": "Authentik OAuth2 client secret",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": True,
|
||||
},
|
||||
"authentik_config_url": {
|
||||
"category": "Authentication",
|
||||
"description": "Authentik OpenID Connect configuration URL",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": True,
|
||||
},
|
||||
"oauth_provider_name": {
|
||||
"category": "Authentication",
|
||||
"description": "Display name for OAuth provider (e.g., 'Authentik', 'Keycloak')",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": True,
|
||||
},
|
||||
|
||||
# AI Services
|
||||
"openai_api_key": {
|
||||
@@ -160,7 +184,693 @@ SETTING_METADATA = {
|
||||
"restart_required": False,
|
||||
},
|
||||
|
||||
# Add more settings metadata as needed...
|
||||
# Storage Providers - Dropbox
|
||||
"dropbox_app_key": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Dropbox app key for OAuth authentication",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"dropbox_app_secret": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Dropbox app secret for OAuth authentication",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"dropbox_folder": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Dropbox folder path for document storage",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"dropbox_refresh_token": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Dropbox OAuth refresh token",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
|
||||
# Storage Providers - Nextcloud
|
||||
"nextcloud_upload_url": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Nextcloud WebDAV upload URL",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"nextcloud_username": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Nextcloud username for authentication",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"nextcloud_password": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Nextcloud password or app password",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"nextcloud_folder": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Nextcloud folder path for document storage",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
|
||||
# Storage Providers - Paperless-ngx
|
||||
"paperless_ngx_api_token": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Paperless-ngx API authentication token",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"paperless_host": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Paperless-ngx host URL (e.g., https://paperless.example.com)",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
|
||||
# Storage Providers - Google Drive
|
||||
"google_drive_credentials_json": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Google Drive service account credentials JSON",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"google_drive_folder_id": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Google Drive folder ID for document storage",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"google_drive_delegate_to": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Optional delegated user email for Google Drive service account",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"google_drive_use_oauth": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Use OAuth instead of service account for Google Drive",
|
||||
"type": "boolean",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"google_drive_client_id": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Google Drive OAuth client ID",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"google_drive_client_secret": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Google Drive OAuth client secret",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"google_drive_refresh_token": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Google Drive OAuth refresh token",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
|
||||
# Storage Providers - OneDrive
|
||||
"onedrive_client_id": {
|
||||
"category": "Storage Providers",
|
||||
"description": "OneDrive OAuth client ID",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"onedrive_client_secret": {
|
||||
"category": "Storage Providers",
|
||||
"description": "OneDrive OAuth client secret",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"onedrive_tenant_id": {
|
||||
"category": "Storage Providers",
|
||||
"description": "OneDrive tenant ID (use 'common' for personal accounts)",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"onedrive_refresh_token": {
|
||||
"category": "Storage Providers",
|
||||
"description": "OneDrive OAuth refresh token",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"onedrive_folder_path": {
|
||||
"category": "Storage Providers",
|
||||
"description": "OneDrive folder path for document storage",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
|
||||
# Storage Providers - WebDAV
|
||||
"webdav_url": {
|
||||
"category": "Storage Providers",
|
||||
"description": "WebDAV server URL",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"webdav_username": {
|
||||
"category": "Storage Providers",
|
||||
"description": "WebDAV username for authentication",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"webdav_password": {
|
||||
"category": "Storage Providers",
|
||||
"description": "WebDAV password for authentication",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"webdav_folder": {
|
||||
"category": "Storage Providers",
|
||||
"description": "WebDAV folder path for document storage",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"webdav_verify_ssl": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Verify SSL certificates for WebDAV connections",
|
||||
"type": "boolean",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
|
||||
# Storage Providers - FTP
|
||||
"ftp_host": {
|
||||
"category": "Storage Providers",
|
||||
"description": "FTP server hostname or IP address",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"ftp_port": {
|
||||
"category": "Storage Providers",
|
||||
"description": "FTP server port (default: 21)",
|
||||
"type": "integer",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"ftp_username": {
|
||||
"category": "Storage Providers",
|
||||
"description": "FTP username for authentication",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"ftp_password": {
|
||||
"category": "Storage Providers",
|
||||
"description": "FTP password for authentication",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"ftp_folder": {
|
||||
"category": "Storage Providers",
|
||||
"description": "FTP folder path for document storage",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"ftp_use_tls": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Use TLS encryption for FTP connections (FTPS)",
|
||||
"type": "boolean",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"ftp_allow_plaintext": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Allow fallback to plaintext FTP if TLS fails",
|
||||
"type": "boolean",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
|
||||
# Storage Providers - SFTP
|
||||
"sftp_host": {
|
||||
"category": "Storage Providers",
|
||||
"description": "SFTP server hostname or IP address",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"sftp_port": {
|
||||
"category": "Storage Providers",
|
||||
"description": "SFTP server port (default: 22)",
|
||||
"type": "integer",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"sftp_username": {
|
||||
"category": "Storage Providers",
|
||||
"description": "SFTP username for authentication",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"sftp_password": {
|
||||
"category": "Storage Providers",
|
||||
"description": "SFTP password for authentication",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"sftp_folder": {
|
||||
"category": "Storage Providers",
|
||||
"description": "SFTP folder path for document storage",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"sftp_private_key": {
|
||||
"category": "Storage Providers",
|
||||
"description": "SFTP private key for key-based authentication",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"sftp_private_key_passphrase": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Passphrase for encrypted SFTP private key",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"sftp_disable_host_key_verification": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Disable host key verification (not recommended for production)",
|
||||
"type": "boolean",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
|
||||
# Storage Providers - AWS S3
|
||||
"aws_access_key_id": {
|
||||
"category": "Storage Providers",
|
||||
"description": "AWS access key ID for S3",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"aws_secret_access_key": {
|
||||
"category": "Storage Providers",
|
||||
"description": "AWS secret access key for S3",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"aws_region": {
|
||||
"category": "Storage Providers",
|
||||
"description": "AWS region for S3 bucket (default: us-east-1)",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"s3_bucket_name": {
|
||||
"category": "Storage Providers",
|
||||
"description": "S3 bucket name for document storage",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"s3_folder_prefix": {
|
||||
"category": "Storage Providers",
|
||||
"description": "Optional folder prefix in S3 bucket (e.g., 'uploads/')",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"s3_storage_class": {
|
||||
"category": "Storage Providers",
|
||||
"description": "S3 storage class (e.g., STANDARD, INTELLIGENT_TIERING)",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"s3_acl": {
|
||||
"category": "Storage Providers",
|
||||
"description": "S3 object ACL (e.g., private, public-read)",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
|
||||
# Email Settings
|
||||
"email_host": {
|
||||
"category": "Email",
|
||||
"description": "SMTP server hostname",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"email_port": {
|
||||
"category": "Email",
|
||||
"description": "SMTP server port (default: 587)",
|
||||
"type": "integer",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"email_username": {
|
||||
"category": "Email",
|
||||
"description": "SMTP username for authentication",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"email_password": {
|
||||
"category": "Email",
|
||||
"description": "SMTP password for authentication",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"email_use_tls": {
|
||||
"category": "Email",
|
||||
"description": "Use TLS encryption for SMTP",
|
||||
"type": "boolean",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"email_sender": {
|
||||
"category": "Email",
|
||||
"description": "From address for outgoing emails (defaults to email_username)",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"email_default_recipient": {
|
||||
"category": "Email",
|
||||
"description": "Default recipient email address",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
|
||||
# IMAP Settings - Account 1
|
||||
"imap1_host": {
|
||||
"category": "IMAP",
|
||||
"description": "IMAP server hostname for account 1",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"imap1_port": {
|
||||
"category": "IMAP",
|
||||
"description": "IMAP server port for account 1 (default: 993)",
|
||||
"type": "integer",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"imap1_username": {
|
||||
"category": "IMAP",
|
||||
"description": "IMAP username for account 1",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"imap1_password": {
|
||||
"category": "IMAP",
|
||||
"description": "IMAP password for account 1",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"imap1_ssl": {
|
||||
"category": "IMAP",
|
||||
"description": "Use SSL for IMAP account 1",
|
||||
"type": "boolean",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"imap1_poll_interval_minutes": {
|
||||
"category": "IMAP",
|
||||
"description": "Poll interval in minutes for IMAP account 1 (default: 5)",
|
||||
"type": "integer",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"imap1_delete_after_process": {
|
||||
"category": "IMAP",
|
||||
"description": "Delete emails after processing for IMAP account 1",
|
||||
"type": "boolean",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
|
||||
# IMAP Settings - Account 2
|
||||
"imap2_host": {
|
||||
"category": "IMAP",
|
||||
"description": "IMAP server hostname for account 2",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"imap2_port": {
|
||||
"category": "IMAP",
|
||||
"description": "IMAP server port for account 2 (default: 993)",
|
||||
"type": "integer",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"imap2_username": {
|
||||
"category": "IMAP",
|
||||
"description": "IMAP username for account 2",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"imap2_password": {
|
||||
"category": "IMAP",
|
||||
"description": "IMAP password for account 2",
|
||||
"type": "string",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"imap2_ssl": {
|
||||
"category": "IMAP",
|
||||
"description": "Use SSL for IMAP account 2",
|
||||
"type": "boolean",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"imap2_poll_interval_minutes": {
|
||||
"category": "IMAP",
|
||||
"description": "Poll interval in minutes for IMAP account 2 (default: 10)",
|
||||
"type": "integer",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"imap2_delete_after_process": {
|
||||
"category": "IMAP",
|
||||
"description": "Delete emails after processing for IMAP account 2",
|
||||
"type": "boolean",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
|
||||
# Monitoring - Uptime Kuma
|
||||
"uptime_kuma_url": {
|
||||
"category": "Monitoring",
|
||||
"description": "Uptime Kuma push monitor URL",
|
||||
"type": "string",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"uptime_kuma_ping_interval": {
|
||||
"category": "Monitoring",
|
||||
"description": "Uptime Kuma ping interval in minutes (default: 5)",
|
||||
"type": "integer",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
|
||||
# Processing Settings
|
||||
"http_request_timeout": {
|
||||
"category": "Processing",
|
||||
"description": "Timeout for HTTP requests in seconds (default: 120)",
|
||||
"type": "integer",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"processall_throttle_threshold": {
|
||||
"category": "Processing",
|
||||
"description": "Number of files above which throttling is applied in /processall",
|
||||
"type": "integer",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"processall_throttle_delay": {
|
||||
"category": "Processing",
|
||||
"description": "Delay in seconds between task submissions when throttling in /processall",
|
||||
"type": "integer",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
|
||||
# Notifications Settings
|
||||
"notification_urls": {
|
||||
"category": "Notifications",
|
||||
"description": "Comma-separated list of Apprise notification URLs (e.g., discord://, telegram://)",
|
||||
"type": "list",
|
||||
"sensitive": True,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"notify_on_task_failure": {
|
||||
"category": "Notifications",
|
||||
"description": "Send notifications when Celery tasks fail",
|
||||
"type": "boolean",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"notify_on_credential_failure": {
|
||||
"category": "Notifications",
|
||||
"description": "Send notifications when credential checks fail",
|
||||
"type": "boolean",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"notify_on_startup": {
|
||||
"category": "Notifications",
|
||||
"description": "Send notifications when application starts",
|
||||
"type": "boolean",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"notify_on_shutdown": {
|
||||
"category": "Notifications",
|
||||
"description": "Send notifications when application shuts down",
|
||||
"type": "boolean",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
"notify_on_file_processed": {
|
||||
"category": "Notifications",
|
||||
"description": "Send notifications when files are successfully processed",
|
||||
"type": "boolean",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
|
||||
# Feature Flags
|
||||
"allow_file_delete": {
|
||||
"category": "Feature Flags",
|
||||
"description": "Allow deleting files from the database",
|
||||
"type": "boolean",
|
||||
"sensitive": False,
|
||||
"required": False,
|
||||
"restart_required": False,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
+18
-11
@@ -3,6 +3,8 @@ Settings management views for the application.
|
||||
"""
|
||||
|
||||
import logging
|
||||
import inspect
|
||||
from functools import wraps
|
||||
from fastapi import Request, Depends, HTTPException, status
|
||||
from fastapi.responses import RedirectResponse
|
||||
from sqlalchemy.orm import Session
|
||||
@@ -15,25 +17,30 @@ logger = logging.getLogger(__name__)
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
def require_admin_access(request: Request):
|
||||
"""Check if user is admin and redirect if not"""
|
||||
user = request.session.get("user")
|
||||
if not user or not user.get("is_admin"):
|
||||
logger.warning(f"Non-admin user attempted to access settings page")
|
||||
return RedirectResponse(url="/", status_code=status.HTTP_302_FOUND)
|
||||
return None
|
||||
def require_admin_access(func):
|
||||
"""Decorator to require admin access for a route"""
|
||||
@wraps(func)
|
||||
async def wrapper(request: Request, *args, **kwargs):
|
||||
user = request.session.get("user")
|
||||
if not user or not user.get("is_admin"):
|
||||
logger.warning(f"Non-admin user attempted to access settings page")
|
||||
return RedirectResponse(url="/", status_code=status.HTTP_302_FOUND)
|
||||
|
||||
# Check if the wrapped function is a coroutine function
|
||||
if inspect.iscoroutinefunction(func):
|
||||
return await func(request, *args, **kwargs)
|
||||
else:
|
||||
return func(request, *args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
|
||||
@router.get("/settings")
|
||||
@require_login
|
||||
@require_admin_access
|
||||
async def settings_page(request: Request, db: Session = Depends(get_db)):
|
||||
"""
|
||||
Settings management page - admin only.
|
||||
"""
|
||||
# Check admin access
|
||||
redirect = require_admin_access(request)
|
||||
if redirect:
|
||||
return redirect
|
||||
|
||||
try:
|
||||
# Get settings organized by category
|
||||
|
||||
Reference in New Issue
Block a user