From cbad50a987b81d584d1f6691ec93604fe12feba5 Mon Sep 17 00:00:00 2001 From: Lars Date: Fri, 20 Mar 2026 12:57:29 +0100 Subject: [PATCH] fix: add missing feature check endpoint and features Critical fixes for feature enforcement: - Add GET /api/features/{feature_id}/check-access endpoint (was missing!) - Add migration for missing features: data_export, csv_import - These features were used in frontend but didn't exist in DB This fixes: - "No analysis available" when setting KI limit - Export features not working - Frontend calling non-existent API endpoint Co-Authored-By: Claude Opus 4.6 --- backend/migrations/v9c_fix_features.sql | 33 +++++++++++++++++++++++++ backend/routers/features.py | 19 +++++++++++++- 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 backend/migrations/v9c_fix_features.sql diff --git a/backend/migrations/v9c_fix_features.sql b/backend/migrations/v9c_fix_features.sql new file mode 100644 index 0000000..74382a2 --- /dev/null +++ b/backend/migrations/v9c_fix_features.sql @@ -0,0 +1,33 @@ +-- Fix missing features for v9c feature enforcement +-- 2026-03-20 + +-- Add missing features +INSERT INTO features (id, name, description, category, limit_type, reset_period, default_limit, active) VALUES + ('data_export', 'Daten exportieren', 'CSV/JSON/ZIP Export', 'export', 'count', 'monthly', 0, true), + ('csv_import', 'CSV importieren', 'FDDB/Apple Health CSV Import + ZIP Backup Import', 'import', 'count', 'monthly', 0, true) +ON CONFLICT (id) DO NOTHING; + +-- Add tier limits for new features +-- FREE tier +INSERT INTO tier_limits (tier_id, feature_id, limit_value) VALUES + ('free', 'data_export', 0), -- Kein Export + ('free', 'csv_import', 0) -- Kein Import +ON CONFLICT (tier_id, feature_id) DO NOTHING; + +-- BASIC tier +INSERT INTO tier_limits (tier_id, feature_id, limit_value) VALUES + ('basic', 'data_export', 5), -- 5 Exporte/Monat + ('basic', 'csv_import', 3) -- 3 Imports/Monat +ON CONFLICT (tier_id, feature_id) DO NOTHING; + +-- PREMIUM tier +INSERT INTO tier_limits (tier_id, feature_id, limit_value) VALUES + ('premium', 'data_export', NULL), -- Unbegrenzt + ('premium', 'csv_import', NULL) -- Unbegrenzt +ON CONFLICT (tier_id, feature_id) DO NOTHING; + +-- SELFHOSTED tier +INSERT INTO tier_limits (tier_id, feature_id, limit_value) VALUES + ('selfhosted', 'data_export', NULL), -- Unbegrenzt + ('selfhosted', 'csv_import', NULL) -- Unbegrenzt +ON CONFLICT (tier_id, feature_id) DO NOTHING; diff --git a/backend/routers/features.py b/backend/routers/features.py index 458e8e8..2932bda 100644 --- a/backend/routers/features.py +++ b/backend/routers/features.py @@ -6,7 +6,7 @@ Admin-only CRUD for features registry. from fastapi import APIRouter, HTTPException, Depends from db import get_db, get_cursor, r2d -from auth import require_admin +from auth import require_admin, require_auth, check_feature_access router = APIRouter(prefix="/api/features", tags=["features"]) @@ -119,3 +119,20 @@ def delete_feature(feature_id: str, session: dict = Depends(require_admin)): cur.execute("UPDATE features SET active = false WHERE id = %s", (feature_id,)) conn.commit() return {"ok": True} + + +@router.get("/{feature_id}/check-access") +def check_access(feature_id: str, session: dict = Depends(require_auth)): + """ + User: Check if current user can access a feature. + + Returns: + - allowed: bool - whether user can use the feature + - limit: int|null - total limit (null = unlimited) + - used: int - current usage + - remaining: int|null - remaining uses (null = unlimited) + - reason: str - why access is granted/denied + """ + profile_id = session['profile_id'] + result = check_feature_access(profile_id, feature_id) + return result