coati-payroll 0.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of coati-payroll might be problematic. Click here for more details.
- coati_payroll/__init__.py +415 -0
- coati_payroll/app.py +95 -0
- coati_payroll/audit_helpers.py +904 -0
- coati_payroll/auth.py +123 -0
- coati_payroll/cli.py +1318 -0
- coati_payroll/config.py +219 -0
- coati_payroll/demo_data.py +813 -0
- coati_payroll/enums.py +278 -0
- coati_payroll/forms.py +1769 -0
- coati_payroll/formula_engine/__init__.py +81 -0
- coati_payroll/formula_engine/ast/__init__.py +110 -0
- coati_payroll/formula_engine/ast/ast_visitor.py +259 -0
- coati_payroll/formula_engine/ast/expression_evaluator.py +228 -0
- coati_payroll/formula_engine/ast/safe_operators.py +131 -0
- coati_payroll/formula_engine/ast/type_converter.py +172 -0
- coati_payroll/formula_engine/data_sources.py +752 -0
- coati_payroll/formula_engine/engine.py +247 -0
- coati_payroll/formula_engine/exceptions.py +52 -0
- coati_payroll/formula_engine/execution/__init__.py +24 -0
- coati_payroll/formula_engine/execution/execution_context.py +52 -0
- coati_payroll/formula_engine/execution/step_executor.py +62 -0
- coati_payroll/formula_engine/execution/variable_store.py +59 -0
- coati_payroll/formula_engine/novelty_codes.py +206 -0
- coati_payroll/formula_engine/results/__init__.py +20 -0
- coati_payroll/formula_engine/results/execution_result.py +59 -0
- coati_payroll/formula_engine/steps/__init__.py +30 -0
- coati_payroll/formula_engine/steps/assignment_step.py +71 -0
- coati_payroll/formula_engine/steps/base_step.py +48 -0
- coati_payroll/formula_engine/steps/calculation_step.py +42 -0
- coati_payroll/formula_engine/steps/conditional_step.py +122 -0
- coati_payroll/formula_engine/steps/step_factory.py +58 -0
- coati_payroll/formula_engine/steps/tax_lookup_step.py +45 -0
- coati_payroll/formula_engine/tables/__init__.py +24 -0
- coati_payroll/formula_engine/tables/bracket_calculator.py +51 -0
- coati_payroll/formula_engine/tables/table_lookup.py +161 -0
- coati_payroll/formula_engine/tables/tax_table.py +32 -0
- coati_payroll/formula_engine/validation/__init__.py +24 -0
- coati_payroll/formula_engine/validation/schema_validator.py +37 -0
- coati_payroll/formula_engine/validation/security_validator.py +52 -0
- coati_payroll/formula_engine/validation/tax_table_validator.py +205 -0
- coati_payroll/formula_engine_examples.py +153 -0
- coati_payroll/i18n.py +54 -0
- coati_payroll/initial_data.py +613 -0
- coati_payroll/interes_engine.py +450 -0
- coati_payroll/liquidacion_engine/__init__.py +25 -0
- coati_payroll/liquidacion_engine/engine.py +267 -0
- coati_payroll/locale_config.py +165 -0
- coati_payroll/log.py +138 -0
- coati_payroll/model.py +2410 -0
- coati_payroll/nomina_engine/__init__.py +87 -0
- coati_payroll/nomina_engine/calculators/__init__.py +30 -0
- coati_payroll/nomina_engine/calculators/benefit_calculator.py +79 -0
- coati_payroll/nomina_engine/calculators/concept_calculator.py +254 -0
- coati_payroll/nomina_engine/calculators/deduction_calculator.py +105 -0
- coati_payroll/nomina_engine/calculators/exchange_rate_calculator.py +51 -0
- coati_payroll/nomina_engine/calculators/perception_calculator.py +75 -0
- coati_payroll/nomina_engine/calculators/salary_calculator.py +86 -0
- coati_payroll/nomina_engine/domain/__init__.py +27 -0
- coati_payroll/nomina_engine/domain/calculation_items.py +52 -0
- coati_payroll/nomina_engine/domain/employee_calculation.py +53 -0
- coati_payroll/nomina_engine/domain/payroll_context.py +44 -0
- coati_payroll/nomina_engine/engine.py +188 -0
- coati_payroll/nomina_engine/processors/__init__.py +28 -0
- coati_payroll/nomina_engine/processors/accounting_processor.py +171 -0
- coati_payroll/nomina_engine/processors/accumulation_processor.py +90 -0
- coati_payroll/nomina_engine/processors/loan_processor.py +227 -0
- coati_payroll/nomina_engine/processors/novelty_processor.py +42 -0
- coati_payroll/nomina_engine/processors/vacation_processor.py +67 -0
- coati_payroll/nomina_engine/repositories/__init__.py +32 -0
- coati_payroll/nomina_engine/repositories/acumulado_repository.py +83 -0
- coati_payroll/nomina_engine/repositories/base_repository.py +40 -0
- coati_payroll/nomina_engine/repositories/config_repository.py +102 -0
- coati_payroll/nomina_engine/repositories/employee_repository.py +34 -0
- coati_payroll/nomina_engine/repositories/exchange_rate_repository.py +58 -0
- coati_payroll/nomina_engine/repositories/novelty_repository.py +54 -0
- coati_payroll/nomina_engine/repositories/planilla_repository.py +52 -0
- coati_payroll/nomina_engine/results/__init__.py +24 -0
- coati_payroll/nomina_engine/results/error_result.py +28 -0
- coati_payroll/nomina_engine/results/payroll_result.py +53 -0
- coati_payroll/nomina_engine/results/validation_result.py +39 -0
- coati_payroll/nomina_engine/services/__init__.py +22 -0
- coati_payroll/nomina_engine/services/accounting_voucher_service.py +708 -0
- coati_payroll/nomina_engine/services/employee_processing_service.py +173 -0
- coati_payroll/nomina_engine/services/payroll_execution_service.py +374 -0
- coati_payroll/nomina_engine/services/snapshot_service.py +295 -0
- coati_payroll/nomina_engine/validators/__init__.py +31 -0
- coati_payroll/nomina_engine/validators/base_validator.py +48 -0
- coati_payroll/nomina_engine/validators/currency_validator.py +50 -0
- coati_payroll/nomina_engine/validators/employee_validator.py +87 -0
- coati_payroll/nomina_engine/validators/period_validator.py +44 -0
- coati_payroll/nomina_engine/validators/planilla_validator.py +136 -0
- coati_payroll/plugin_manager.py +176 -0
- coati_payroll/queue/__init__.py +33 -0
- coati_payroll/queue/driver.py +127 -0
- coati_payroll/queue/drivers/__init__.py +22 -0
- coati_payroll/queue/drivers/dramatiq_driver.py +268 -0
- coati_payroll/queue/drivers/huey_driver.py +390 -0
- coati_payroll/queue/drivers/noop_driver.py +54 -0
- coati_payroll/queue/selector.py +121 -0
- coati_payroll/queue/tasks.py +764 -0
- coati_payroll/rate_limiting.py +83 -0
- coati_payroll/rbac.py +183 -0
- coati_payroll/report_engine.py +512 -0
- coati_payroll/report_export.py +208 -0
- coati_payroll/schema_validator.py +167 -0
- coati_payroll/security.py +77 -0
- coati_payroll/static/styles.css +1044 -0
- coati_payroll/system_reports.py +573 -0
- coati_payroll/templates/auth/login.html +189 -0
- coati_payroll/templates/base.html +283 -0
- coati_payroll/templates/index.html +227 -0
- coati_payroll/templates/macros.html +146 -0
- coati_payroll/templates/modules/calculation_rule/form.html +78 -0
- coati_payroll/templates/modules/calculation_rule/index.html +102 -0
- coati_payroll/templates/modules/calculation_rule/schema_editor.html +1159 -0
- coati_payroll/templates/modules/carga_inicial_prestacion/form.html +170 -0
- coati_payroll/templates/modules/carga_inicial_prestacion/index.html +170 -0
- coati_payroll/templates/modules/carga_inicial_prestacion/reporte.html +193 -0
- coati_payroll/templates/modules/config_calculos/index.html +44 -0
- coati_payroll/templates/modules/configuracion/index.html +90 -0
- coati_payroll/templates/modules/currency/form.html +47 -0
- coati_payroll/templates/modules/currency/index.html +64 -0
- coati_payroll/templates/modules/custom_field/form.html +62 -0
- coati_payroll/templates/modules/custom_field/index.html +78 -0
- coati_payroll/templates/modules/deduccion/form.html +1 -0
- coati_payroll/templates/modules/deduccion/index.html +1 -0
- coati_payroll/templates/modules/employee/form.html +254 -0
- coati_payroll/templates/modules/employee/index.html +76 -0
- coati_payroll/templates/modules/empresa/form.html +74 -0
- coati_payroll/templates/modules/empresa/index.html +71 -0
- coati_payroll/templates/modules/exchange_rate/form.html +47 -0
- coati_payroll/templates/modules/exchange_rate/import.html +93 -0
- coati_payroll/templates/modules/exchange_rate/index.html +114 -0
- coati_payroll/templates/modules/liquidacion/index.html +58 -0
- coati_payroll/templates/modules/liquidacion/nueva.html +51 -0
- coati_payroll/templates/modules/liquidacion/ver.html +91 -0
- coati_payroll/templates/modules/payroll_concepts/audit_log.html +146 -0
- coati_payroll/templates/modules/percepcion/form.html +1 -0
- coati_payroll/templates/modules/percepcion/index.html +1 -0
- coati_payroll/templates/modules/planilla/config.html +190 -0
- coati_payroll/templates/modules/planilla/config_deducciones.html +129 -0
- coati_payroll/templates/modules/planilla/config_empleados.html +116 -0
- coati_payroll/templates/modules/planilla/config_percepciones.html +113 -0
- coati_payroll/templates/modules/planilla/config_prestaciones.html +118 -0
- coati_payroll/templates/modules/planilla/config_reglas.html +120 -0
- coati_payroll/templates/modules/planilla/ejecutar_nomina.html +106 -0
- coati_payroll/templates/modules/planilla/form.html +197 -0
- coati_payroll/templates/modules/planilla/index.html +144 -0
- coati_payroll/templates/modules/planilla/listar_nominas.html +91 -0
- coati_payroll/templates/modules/planilla/log_nomina.html +135 -0
- coati_payroll/templates/modules/planilla/novedades/form.html +177 -0
- coati_payroll/templates/modules/planilla/novedades/index.html +170 -0
- coati_payroll/templates/modules/planilla/ver_nomina.html +477 -0
- coati_payroll/templates/modules/planilla/ver_nomina_empleado.html +231 -0
- coati_payroll/templates/modules/plugins/index.html +71 -0
- coati_payroll/templates/modules/prestacion/form.html +1 -0
- coati_payroll/templates/modules/prestacion/index.html +1 -0
- coati_payroll/templates/modules/prestacion_management/dashboard.html +150 -0
- coati_payroll/templates/modules/prestacion_management/initial_balance_bulk.html +195 -0
- coati_payroll/templates/modules/prestamo/approve.html +156 -0
- coati_payroll/templates/modules/prestamo/condonacion.html +249 -0
- coati_payroll/templates/modules/prestamo/detail.html +443 -0
- coati_payroll/templates/modules/prestamo/form.html +203 -0
- coati_payroll/templates/modules/prestamo/index.html +150 -0
- coati_payroll/templates/modules/prestamo/pago_extraordinario.html +211 -0
- coati_payroll/templates/modules/prestamo/tabla_pago_pdf.html +181 -0
- coati_payroll/templates/modules/report/admin_index.html +125 -0
- coati_payroll/templates/modules/report/detail.html +129 -0
- coati_payroll/templates/modules/report/execute.html +266 -0
- coati_payroll/templates/modules/report/index.html +95 -0
- coati_payroll/templates/modules/report/permissions.html +64 -0
- coati_payroll/templates/modules/settings/index.html +274 -0
- coati_payroll/templates/modules/shared/concept_form.html +201 -0
- coati_payroll/templates/modules/shared/concept_index.html +145 -0
- coati_payroll/templates/modules/tipo_planilla/form.html +70 -0
- coati_payroll/templates/modules/tipo_planilla/index.html +68 -0
- coati_payroll/templates/modules/user/form.html +65 -0
- coati_payroll/templates/modules/user/index.html +76 -0
- coati_payroll/templates/modules/user/profile.html +81 -0
- coati_payroll/templates/modules/vacation/account_detail.html +149 -0
- coati_payroll/templates/modules/vacation/account_form.html +52 -0
- coati_payroll/templates/modules/vacation/account_index.html +68 -0
- coati_payroll/templates/modules/vacation/dashboard.html +156 -0
- coati_payroll/templates/modules/vacation/initial_balance_bulk.html +149 -0
- coati_payroll/templates/modules/vacation/initial_balance_form.html +93 -0
- coati_payroll/templates/modules/vacation/leave_request_detail.html +158 -0
- coati_payroll/templates/modules/vacation/leave_request_form.html +61 -0
- coati_payroll/templates/modules/vacation/leave_request_index.html +98 -0
- coati_payroll/templates/modules/vacation/policy_detail.html +176 -0
- coati_payroll/templates/modules/vacation/policy_form.html +152 -0
- coati_payroll/templates/modules/vacation/policy_index.html +79 -0
- coati_payroll/templates/modules/vacation/register_taken_form.html +178 -0
- coati_payroll/translations/en/LC_MESSAGES/messages.mo +0 -0
- coati_payroll/translations/en/LC_MESSAGES/messages.po +7283 -0
- coati_payroll/translations/es/LC_MESSAGES/messages.mo +0 -0
- coati_payroll/translations/es/LC_MESSAGES/messages.po +7374 -0
- coati_payroll/vacation_service.py +451 -0
- coati_payroll/version.py +18 -0
- coati_payroll/vistas/__init__.py +64 -0
- coati_payroll/vistas/calculation_rule.py +307 -0
- coati_payroll/vistas/carga_inicial_prestacion.py +423 -0
- coati_payroll/vistas/config_calculos.py +72 -0
- coati_payroll/vistas/configuracion.py +87 -0
- coati_payroll/vistas/constants.py +17 -0
- coati_payroll/vistas/currency.py +112 -0
- coati_payroll/vistas/custom_field.py +120 -0
- coati_payroll/vistas/employee.py +305 -0
- coati_payroll/vistas/empresa.py +153 -0
- coati_payroll/vistas/exchange_rate.py +341 -0
- coati_payroll/vistas/liquidacion.py +205 -0
- coati_payroll/vistas/payroll_concepts.py +580 -0
- coati_payroll/vistas/planilla/__init__.py +38 -0
- coati_payroll/vistas/planilla/association_routes.py +238 -0
- coati_payroll/vistas/planilla/config_routes.py +158 -0
- coati_payroll/vistas/planilla/export_routes.py +175 -0
- coati_payroll/vistas/planilla/helpers/__init__.py +34 -0
- coati_payroll/vistas/planilla/helpers/association_helpers.py +161 -0
- coati_payroll/vistas/planilla/helpers/excel_helpers.py +29 -0
- coati_payroll/vistas/planilla/helpers/form_helpers.py +97 -0
- coati_payroll/vistas/planilla/nomina_routes.py +488 -0
- coati_payroll/vistas/planilla/novedad_routes.py +227 -0
- coati_payroll/vistas/planilla/routes.py +145 -0
- coati_payroll/vistas/planilla/services/__init__.py +26 -0
- coati_payroll/vistas/planilla/services/export_service.py +687 -0
- coati_payroll/vistas/planilla/services/nomina_service.py +233 -0
- coati_payroll/vistas/planilla/services/novedad_service.py +126 -0
- coati_payroll/vistas/planilla/services/planilla_service.py +34 -0
- coati_payroll/vistas/planilla/validators/__init__.py +18 -0
- coati_payroll/vistas/planilla/validators/planilla_validators.py +40 -0
- coati_payroll/vistas/plugins.py +45 -0
- coati_payroll/vistas/prestacion.py +272 -0
- coati_payroll/vistas/prestamo.py +808 -0
- coati_payroll/vistas/report.py +432 -0
- coati_payroll/vistas/settings.py +29 -0
- coati_payroll/vistas/tipo_planilla.py +134 -0
- coati_payroll/vistas/user.py +172 -0
- coati_payroll/vistas/vacation.py +1045 -0
- coati_payroll-0.0.2.dist-info/LICENSE +201 -0
- coati_payroll-0.0.2.dist-info/METADATA +581 -0
- coati_payroll-0.0.2.dist-info/RECORD +243 -0
- coati_payroll-0.0.2.dist-info/WHEEL +5 -0
- coati_payroll-0.0.2.dist-info/entry_points.txt +2 -0
- coati_payroll-0.0.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Copyright 2025 BMO Soluciones, S.A.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
"""Rate limiting configuration for the application.
|
|
15
|
+
|
|
16
|
+
This module configures rate limiting to protect against brute force attacks
|
|
17
|
+
and abuse, particularly for authentication endpoints.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
from os import environ
|
|
23
|
+
from flask_limiter import Limiter
|
|
24
|
+
from flask_limiter.util import get_remote_address
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_rate_limiter_storage():
|
|
28
|
+
"""Get storage backend for rate limiter based on available configuration.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
str: Storage URI for rate limiter
|
|
32
|
+
- Uses Redis if REDIS_URL or SESSION_REDIS_URL is available (production)
|
|
33
|
+
- Falls back to memory storage for development/testing
|
|
34
|
+
"""
|
|
35
|
+
# Try to get Redis URL from environment
|
|
36
|
+
redis_url = environ.get("REDIS_URL") or environ.get("SESSION_REDIS_URL")
|
|
37
|
+
|
|
38
|
+
if redis_url:
|
|
39
|
+
# Use Redis for distributed rate limiting (production)
|
|
40
|
+
return redis_url
|
|
41
|
+
else:
|
|
42
|
+
# Use memory storage for development/testing
|
|
43
|
+
# Note: This won't work across multiple processes
|
|
44
|
+
return "memory://"
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def configure_rate_limiting(app):
|
|
48
|
+
"""Configure rate limiting for the Flask application.
|
|
49
|
+
|
|
50
|
+
Sets up Flask-Limiter with appropriate storage backend:
|
|
51
|
+
- Redis for production (distributed, persistent)
|
|
52
|
+
- Memory for development (simple, non-persistent)
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
app: Flask application instance
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
Limiter: Configured Flask-Limiter instance
|
|
59
|
+
"""
|
|
60
|
+
from coati_payroll.log import log
|
|
61
|
+
|
|
62
|
+
storage_uri = get_rate_limiter_storage()
|
|
63
|
+
|
|
64
|
+
# Log which storage backend we're using
|
|
65
|
+
if storage_uri.startswith("redis"):
|
|
66
|
+
log.info("Rate limiting configured with Redis storage (production mode)")
|
|
67
|
+
else:
|
|
68
|
+
log.info("Rate limiting configured with memory storage (development mode)")
|
|
69
|
+
|
|
70
|
+
limiter = Limiter(
|
|
71
|
+
app=app,
|
|
72
|
+
key_func=get_remote_address,
|
|
73
|
+
storage_uri=storage_uri,
|
|
74
|
+
default_limits=["200 per day", "50 per hour"], # Global limits
|
|
75
|
+
storage_options={"socket_connect_timeout": 30},
|
|
76
|
+
strategy="fixed-window", # Count resets at fixed intervals
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Note: Specific endpoint rate limits can be applied using decorators in the blueprints.
|
|
80
|
+
# For the login endpoint, we apply a stricter limit (5 per minute) to prevent brute force.
|
|
81
|
+
# This is documented in the security audit report.
|
|
82
|
+
|
|
83
|
+
return limiter
|
coati_payroll/rbac.py
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
# Copyright 2025 BMO Soluciones, S.A.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
"""Role-Based Access Control (RBAC) utilities.
|
|
15
|
+
|
|
16
|
+
This module provides decorators and utilities for implementing role-based
|
|
17
|
+
access control throughout the application.
|
|
18
|
+
|
|
19
|
+
User Types:
|
|
20
|
+
- admin: Full access to all functionalities
|
|
21
|
+
- hhrr: HR personnel with access to employee and payroll management
|
|
22
|
+
- audit: Read-only access for auditing purposes
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from __future__ import annotations
|
|
26
|
+
|
|
27
|
+
# <-------------------------------------------------------------------------> #
|
|
28
|
+
# Standard library
|
|
29
|
+
# <-------------------------------------------------------------------------> #
|
|
30
|
+
from functools import wraps
|
|
31
|
+
|
|
32
|
+
# <-------------------------------------------------------------------------> #
|
|
33
|
+
# Third party libraries
|
|
34
|
+
# <-------------------------------------------------------------------------> #
|
|
35
|
+
from flask import abort, flash, redirect, url_for
|
|
36
|
+
from flask_login import current_user
|
|
37
|
+
|
|
38
|
+
# <-------------------------------------------------------------------------> #
|
|
39
|
+
# Third party libraries
|
|
40
|
+
# <-------------------------------------------------------------------------> #
|
|
41
|
+
from coati_payroll.enums import TipoUsuario
|
|
42
|
+
from coati_payroll.i18n import _
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def require_role(*allowed_roles: str):
|
|
46
|
+
"""Decorator to restrict access to specific user roles.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
*allowed_roles: Variable number of allowed role strings (admin, hhrr, audit)
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
Decorated function that checks user role before execution
|
|
53
|
+
|
|
54
|
+
Example:
|
|
55
|
+
@require_role(TipoUsuario.ADMIN)
|
|
56
|
+
def admin_only_view():
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
@require_role(TipoUsuario.ADMIN, TipoUsuario.HHRR)
|
|
60
|
+
def admin_or_hr_view():
|
|
61
|
+
pass
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
def decorator(f):
|
|
65
|
+
@wraps(f)
|
|
66
|
+
def decorated_function(*args, **kwargs):
|
|
67
|
+
if not current_user.is_authenticated:
|
|
68
|
+
flash(_("Favor iniciar sesión para acceder al sistema."), "warning")
|
|
69
|
+
return redirect(url_for("auth.login"))
|
|
70
|
+
|
|
71
|
+
# Check if user has required role
|
|
72
|
+
if current_user.tipo not in allowed_roles:
|
|
73
|
+
flash(_("No tiene permisos para acceder a esta funcionalidad."), "danger")
|
|
74
|
+
abort(403)
|
|
75
|
+
|
|
76
|
+
return f(*args, **kwargs)
|
|
77
|
+
|
|
78
|
+
return decorated_function
|
|
79
|
+
|
|
80
|
+
return decorator
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def require_read_access():
|
|
84
|
+
"""Decorator to allow read access to admin, hhrr, and audit users.
|
|
85
|
+
|
|
86
|
+
This is used for listing and viewing data where all user types should
|
|
87
|
+
have access but audit users are read-only.
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
Decorated function that allows read access to all authenticated users
|
|
91
|
+
|
|
92
|
+
Example:
|
|
93
|
+
@require_read_access()
|
|
94
|
+
def list_employees():
|
|
95
|
+
pass
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
def decorator(f):
|
|
99
|
+
@wraps(f)
|
|
100
|
+
def decorated_function(*args, **kwargs):
|
|
101
|
+
if not current_user.is_authenticated:
|
|
102
|
+
flash(_("Favor iniciar sesión para acceder al sistema."), "warning")
|
|
103
|
+
return redirect(url_for("auth.login"))
|
|
104
|
+
|
|
105
|
+
# All authenticated users can read
|
|
106
|
+
return f(*args, **kwargs)
|
|
107
|
+
|
|
108
|
+
return decorated_function
|
|
109
|
+
|
|
110
|
+
return decorator
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def require_write_access():
|
|
114
|
+
"""Decorator to restrict write operations to admin and hhrr users only.
|
|
115
|
+
|
|
116
|
+
Audit users are denied access to create, update, or delete operations.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
Decorated function that checks write permissions
|
|
120
|
+
|
|
121
|
+
Example:
|
|
122
|
+
@require_write_access()
|
|
123
|
+
def create_employee():
|
|
124
|
+
pass
|
|
125
|
+
|
|
126
|
+
@require_write_access()
|
|
127
|
+
def update_employee():
|
|
128
|
+
pass
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
def decorator(f):
|
|
132
|
+
@wraps(f)
|
|
133
|
+
def decorated_function(*args, **kwargs):
|
|
134
|
+
if not current_user.is_authenticated:
|
|
135
|
+
flash(_("Favor iniciar sesión para acceder al sistema."), "warning")
|
|
136
|
+
return redirect(url_for("auth.login"))
|
|
137
|
+
|
|
138
|
+
# Only admin and hhrr can write
|
|
139
|
+
if current_user.tipo not in [TipoUsuario.ADMIN, TipoUsuario.HHRR]:
|
|
140
|
+
flash(_("No tiene permisos para modificar datos. Su rol es de solo lectura."), "danger")
|
|
141
|
+
abort(403)
|
|
142
|
+
|
|
143
|
+
return f(*args, **kwargs)
|
|
144
|
+
|
|
145
|
+
return decorated_function
|
|
146
|
+
|
|
147
|
+
return decorator
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def is_admin() -> bool:
|
|
151
|
+
"""Check if current user is an administrator.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
True if current user has admin role, False otherwise
|
|
155
|
+
"""
|
|
156
|
+
return current_user.is_authenticated and current_user.tipo == TipoUsuario.ADMIN
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def is_hhrr() -> bool:
|
|
160
|
+
"""Check if current user is HR personnel.
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
True if current user has hhrr role, False otherwise
|
|
164
|
+
"""
|
|
165
|
+
return current_user.is_authenticated and current_user.tipo == TipoUsuario.HHRR
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def is_audit() -> bool:
|
|
169
|
+
"""Check if current user is an auditor.
|
|
170
|
+
|
|
171
|
+
Returns:
|
|
172
|
+
True if current user has audit role, False otherwise
|
|
173
|
+
"""
|
|
174
|
+
return current_user.is_authenticated and current_user.tipo == TipoUsuario.AUDIT
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def can_write() -> bool:
|
|
178
|
+
"""Check if current user has write permissions.
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
True if current user is admin or hhrr, False otherwise
|
|
182
|
+
"""
|
|
183
|
+
return current_user.is_authenticated and current_user.tipo in [TipoUsuario.ADMIN, TipoUsuario.HHRR]
|