March 17 2026: Mobile app phase 1 - fix error

This commit is contained in:
2026-03-17 17:33:00 -04:00
parent 75a7b26695
commit f399537246
3 changed files with 16 additions and 13 deletions
+14 -5
View File
@@ -3,15 +3,17 @@ from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from flask_migrate import Migrate
from flask_mail import Mail
from flask_wtf.csrf import CSRFProtect
from config import config
import os
import logging
from logging.handlers import RotatingFileHandler
db = SQLAlchemy()
db = SQLAlchemy()
login_manager = LoginManager()
migrate = Migrate()
mail = Mail()
migrate = Migrate()
mail = Mail()
csrf = CSRFProtect() # initialized here; .init_app() called in create_app()
def create_app(config_name='default'):
@@ -22,6 +24,7 @@ def create_app(config_name='default'):
login_manager.init_app(app)
migrate.init_app(app, db)
mail.init_app(app)
csrf.init_app(app) # enables CSRF protection for all web routes
login_manager.login_view = 'auth.login'
login_manager.login_message = 'Please log in to access this page.'
@@ -69,6 +72,8 @@ def create_app(config_name='default'):
# Register csrf_token() as an app-wide Jinja2 global so templates that
# render manual forms (no WTForms object) can still inject the CSRF token.
# CSRFProtect (initialized above) is the authoritative guard for web routes;
# the /api/v1 blueprint is exempted below via csrf.exempt().
from flask_wtf.csrf import generate_csrf
app.jinja_env.globals['csrf_token'] = generate_csrf
app.jinja_env.globals['enumerate'] = enumerate
@@ -131,8 +136,12 @@ def create_app(config_name='default'):
app.register_blueprint(customers.bp)
app.register_blueprint(scheduled_reports.bp)
# ── Mobile API ─────────────────────────────────────────────
from app.api import register_api
# ── Mobile API (Phase 7) ─────────────────────────────────────────────────
# The /api/v1 blueprint uses JWT Bearer tokens — no CSRF cookies needed.
# Exempt it from CSRFProtect before registering so POST /api/v1/* routes
# are never rejected for a missing CSRF token.
from app.api import register_api, api_bp
csrf.exempt(api_bp)
register_api(app)
# ── Error handler: 413 Request Entity Too Large ───────────────────────
+1 -1
View File
@@ -57,4 +57,4 @@ def register_api(app):
# api_bp.register_blueprint(notifications_bp)
# api_bp.register_blueprint(photos_bp)
app.register_blueprint(api_bp)
app.register_blueprint(api_bp)
+1 -7
View File
@@ -31,8 +31,6 @@ GET /api/v1/auth/me
import logging
from flask import Blueprint, request, g
from flask_wtf.csrf import csrf_exempt
from app import db
from app.models.user import User
from app.models.api_token import RefreshToken, DeviceToken
@@ -61,7 +59,6 @@ def _user_payload(user: User) -> dict:
# ── Login ─────────────────────────────────────────────────────────────────────
@bp.route('/auth/login', methods=['POST'])
@csrf_exempt
def login():
"""
Authenticate with username + password.
@@ -137,7 +134,6 @@ def login():
# ── Refresh ───────────────────────────────────────────────────────────────────
@bp.route('/auth/refresh', methods=['POST'])
@csrf_exempt
def refresh():
"""
Exchange a valid refresh token for a new access token.
@@ -207,7 +203,6 @@ def refresh():
# ── Logout ────────────────────────────────────────────────────────────────────
@bp.route('/auth/logout', methods=['POST'])
@csrf_exempt
@jwt_required
def logout():
"""
@@ -261,7 +256,6 @@ def me():
# ── Device token registration ─────────────────────────────────────────────────
@bp.route('/devices/register', methods=['POST'])
@csrf_exempt
@jwt_required
def register_device():
"""
@@ -316,4 +310,4 @@ def register_device():
logger.info('API DEVICE REGISTERED | user=%s | device_id=%s | apns_token=...%s',
g.api_user.username, device_id, apns_token[-6:])
return api_ok({'registered': True})
return api_ok({'registered': True})