From ee7b0286b2299666876d665d0f1c3210887ffeeb Mon Sep 17 00:00:00 2001 From: NguyenND Date: Sat, 27 Jun 2026 20:21:33 -0400 Subject: [PATCH] Jun 27 MT-6 --- app/api/inspections.py | 3 +++ app/api/issues.py | 3 +++ app/routes/auth.py | 2 ++ app/routes/facilities.py | 5 +++++ app/routes/inspections.py | 2 ++ app/routes/issues.py | 2 ++ app/routes/scheduled_reports.py | 4 ++++ 7 files changed, 21 insertions(+) diff --git a/app/api/inspections.py b/app/api/inspections.py index b91021a..9363d7c 100644 --- a/app/api/inspections.py +++ b/app/api/inspections.py @@ -26,6 +26,7 @@ from app.models.inspection import Inspection, InspectionTemplate from app.models.facility import Facility, Area from app.api.errors import api_ok, api_error from app.api.decorators import jwt_required +from app.tenancy.gates import feature_required, quota_soft_check from app.utils.audit import log_action, ACTION_CREATE, ACTION_UPDATE from app.utils.notifications import notify_by_matrix from app.utils.time_utils import now_eastern @@ -242,6 +243,8 @@ def list_inspections(): @bp.route('/inspections', methods=['POST']) @jwt_required +@feature_required('mobile_api') +@quota_soft_check('inspections') def create_inspection(): """ Create a new inspection submitted from the iPad app. diff --git a/app/api/issues.py b/app/api/issues.py index 6604370..2c77462 100644 --- a/app/api/issues.py +++ b/app/api/issues.py @@ -32,6 +32,7 @@ from app.models.facility import Facility, Area from app.models.inspection import Inspection from app.api.errors import api_ok, api_error from app.api.decorators import jwt_required +from app.tenancy.gates import feature_required, quota_soft_check from app.utils.audit import log_action, ACTION_CREATE, ACTION_UPDATE from app.utils.notifications import notify_by_matrix from app.utils.time_utils import now_eastern @@ -159,6 +160,8 @@ def list_issues(): @bp.route('/issues', methods=['POST']) @jwt_required +@feature_required('mobile_api') +@quota_soft_check('issues') def create_issue(): """ Create a new issue submitted from the iPad app. diff --git a/app/routes/auth.py b/app/routes/auth.py index 8ae6d2a..ac100dc 100644 --- a/app/routes/auth.py +++ b/app/routes/auth.py @@ -7,6 +7,7 @@ from app.utils.forms import LoginForm, UserForm, ProfileForm, ForgotPasswordForm from app.utils.decorators import admin_required, supervisor_required, safe_redirect_url import logging from app.utils.audit import log_action, ACTION_CREATE, ACTION_UPDATE, ACTION_DELETE, ACTION_LOGIN, ACTION_LOGOUT +from app.tenancy.gates import quota_soft_check logger = logging.getLogger(__name__) @@ -144,6 +145,7 @@ def list_users(): @bp.route('/users/new', methods=['GET', 'POST']) @login_required @admin_required +@quota_soft_check('users') def create_user(): form = UserForm() diff --git a/app/routes/facilities.py b/app/routes/facilities.py index b34c271..cab2bd6 100644 --- a/app/routes/facilities.py +++ b/app/routes/facilities.py @@ -8,6 +8,8 @@ from app.utils.forms import FacilityForm, AreaForm from app.utils.decorators import supervisor_required, admin_required from app.utils.audit import log_action, ACTION_CREATE, ACTION_UPDATE, ACTION_DELETE from app.utils.scope import get_customer_scope, get_inspector_scope +from app.tenancy.gates import quota_soft_check +from app.tenancy.gates import feature_required bp = Blueprint('facilities', __name__, url_prefix='/facilities') @@ -15,6 +17,8 @@ logger = logging.getLogger(__name__) @bp.route('/') @login_required +@supervisor_required +@feature_required('scheduled_reports') def list_facilities(): if current_user.role == 'customer': cids = get_customer_scope(current_user) or [] @@ -54,6 +58,7 @@ def list_facilities(): @bp.route('/new', methods=['GET', 'POST']) @login_required @supervisor_required +@quota_soft_check('facilities') def create_facility(): form = FacilityForm() projects = Project.query.filter_by(active=True).order_by(Project.name).all() diff --git a/app/routes/inspections.py b/app/routes/inspections.py index 6dc4eba..f87a8f1 100644 --- a/app/routes/inspections.py +++ b/app/routes/inspections.py @@ -23,6 +23,7 @@ from app.models.notification import ( EVENT_CUSTOMER_INSPECTION_DONE, EVENT_CUSTOMER_ISSUE_UPDATED, ) from app.utils.audit import log_action, ACTION_CREATE, ACTION_UPDATE, ACTION_DELETE, ACTION_EXPORT +from app.tenancy.gates import quota_soft_check from app.utils.scope import get_customer_scope, get_inspector_scope from sqlalchemy.orm import joinedload @@ -345,6 +346,7 @@ def index(): @bp.route('/start', methods=['GET', 'POST']) @login_required +@quota_soft_check('inspections') def start(): form = StartInspectionForm() diff --git a/app/routes/issues.py b/app/routes/issues.py index 0790e5a..3e2f500 100644 --- a/app/routes/issues.py +++ b/app/routes/issues.py @@ -18,6 +18,7 @@ from app.utils.forms import IssueForm, IssueUpdateForm from app.utils.decorators import supervisor_required from app.utils.notifications import notify, notify_customers_for_facility, notify_by_matrix from app.utils.audit import log_action, ACTION_CREATE, ACTION_UPDATE, ACTION_DELETE, ACTION_EXPORT +from app.tenancy.gates import quota_soft_check from app.utils.pdf_export import generate_issues_list_pdf from app.utils.scope import get_customer_scope, get_inspector_scope from app.utils.sla import sla_status @@ -665,6 +666,7 @@ def unfollow(issue_id): @bp.route('/new', methods=['GET', 'POST']) @login_required +@quota_soft_check('issues') def create(): if current_user.role not in ('admin', 'director', 'customer'): abort(403) diff --git a/app/routes/scheduled_reports.py b/app/routes/scheduled_reports.py index 486c94e..d6ff222 100644 --- a/app/routes/scheduled_reports.py +++ b/app/routes/scheduled_reports.py @@ -42,6 +42,8 @@ from app.utils.decorators import supervisor_required, admin_required from app.utils.audit import log_action, ACTION_CREATE, ACTION_UPDATE, ACTION_DELETE from app.utils.time_utils import now_eastern from app.utils.sla import sla_status +from app.tenancy.gates import feature_required + logger = logging.getLogger(__name__) @@ -297,6 +299,7 @@ def _send_report(report: ScheduledReport): @bp.route('/') @login_required @admin_required +@feature_required('scheduled_reports') def index(): reports = ScheduledReport.query.order_by(ScheduledReport.name).all() return render_template('scheduled_reports/index.html', reports=reports) @@ -305,6 +308,7 @@ def index(): @bp.route('/new', methods=['GET', 'POST']) @login_required @admin_required +@feature_required('scheduled_reports') def create(): facilities = Facility.query.filter_by(active=True).order_by(Facility.name).all()