Offline-first photo capture app for Nextcloud with: - Camera capture with continuous mode (auto-reopens after each photo) - File browser with fullscreen image gallery, swipe navigation, and rename - Upload queue with background sync engine - Admin panel for Nextcloud user management - Service worker for offline-first caching (v13) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
40 lines
1.3 KiB
Python
40 lines
1.3 KiB
Python
from flask import session
|
|
from functools import wraps
|
|
from flask import jsonify
|
|
import base64
|
|
|
|
def _decrypt_password(encrypted: str) -> str:
|
|
"""Decode base64 encoded password from session."""
|
|
return base64.b64decode(encrypted.encode()).decode()
|
|
|
|
def get_current_user():
|
|
"""Get current authenticated user info from session."""
|
|
if 'username' not in session:
|
|
return None
|
|
|
|
return {
|
|
'username': session['username'],
|
|
'password': _decrypt_password(session['password']),
|
|
'is_admin': session.get('is_admin', False)
|
|
}
|
|
|
|
def require_auth(f):
|
|
"""Decorator to require authentication for a route."""
|
|
@wraps(f)
|
|
def decorated_function(*args, **kwargs):
|
|
if 'username' not in session:
|
|
return jsonify({'error': 'Authentication required'}), 401
|
|
return f(*args, **kwargs)
|
|
return decorated_function
|
|
|
|
def require_admin(f):
|
|
"""Decorator to require admin privileges for a route."""
|
|
@wraps(f)
|
|
def decorated_function(*args, **kwargs):
|
|
if 'username' not in session:
|
|
return jsonify({'error': 'Authentication required'}), 401
|
|
if not session.get('is_admin', False):
|
|
return jsonify({'error': 'Admin privileges required'}), 403
|
|
return f(*args, **kwargs)
|
|
return decorated_function
|