Files
nextsnap/app/routes/auth.py
kamaji cad4118f72 Add NextSnap PWA with photo gallery viewer and continuous capture
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>
2026-02-07 04:53:13 -06:00

73 lines
2.3 KiB
Python

from flask import Blueprint, request, jsonify, session
from app.services.nextcloud import NextcloudClient
from config import Config
import base64
bp = Blueprint('auth', __name__, url_prefix='/api/auth')
def _encrypt_password(password: str) -> str:
"""Simple base64 encoding for password storage in session."""
return base64.b64encode(password.encode()).decode()
def _decrypt_password(encrypted: str) -> str:
"""Decode base64 encoded password from session."""
return base64.b64decode(encrypted.encode()).decode()
@bp.route('/login', methods=['POST'])
def login():
"""Authenticate user against Nextcloud."""
data = request.get_json()
if not data or 'username' not in data or 'password' not in data:
return jsonify({'error': 'Username and password required'}), 400
username = data['username'].strip()
password = data['password']
if not username or not password:
return jsonify({'error': 'Username and password cannot be empty'}), 400
try:
# Validate credentials by attempting to connect to Nextcloud
nc_client = NextcloudClient(Config.NEXTCLOUD_URL, username, password)
if not nc_client.verify_credentials():
return jsonify({'error': 'Invalid username or password'}), 401
# Check if user is admin
is_admin = nc_client.check_admin()
# Store credentials in session
session['username'] = username
session['password'] = _encrypt_password(password)
session['is_admin'] = is_admin
return jsonify({
'success': True,
'username': username,
'is_admin': is_admin
}), 200
except Exception as e:
return jsonify({'error': f'Authentication failed: {str(e)}'}), 500
@bp.route('/logout', methods=['POST'])
def logout():
"""Clear user session."""
session.clear()
return jsonify({'success': True}), 200
@bp.route('/status', methods=['GET'])
def status():
"""Check current authentication status."""
if 'username' in session:
return jsonify({
'authenticated': True,
'username': session['username'],
'is_admin': session.get('is_admin', False)
}), 200
else:
return jsonify({
'authenticated': False
}), 200