Files
ihrm/horilla/decorators.py
Horilla 2fee7c18bb [IMP] Remove inter module dependency (#274)
This commit introduces significant changes to the architecture of the Horilla HRMS system by decoupling interdependent modules. The following modifications were made:

1. **Module Independence**: Each module has been refactored to eliminate reliance on other modules, promoting a more modular and maintainable codebase.
2. **Refactored Imports and Dependencies**: Adjusted import statements and dependency injections to support independent module operation.
3. **Compatibility and Functionality**: Ensured that all modules are compatible with existing systems and maintain their intended functionality both independently and when integrated with other modules.

These changes enhance the modularity, maintainability, and scalability of the Horilla HRMS, allowing developers to work on individual modules without affecting the entire system. Future development and deployment will be more efficient and less prone to issues arising from tightly coupled code.

**NOTE**
For existing Horilla users, if you face any issues during the migrations, please run the following command and try again the migrations.

- `python3 manage.py makemigrations`
- `python3 manage.py migrate base`
- `python3 manage.py migrate`





* [IMP] ASSET: Asset module dependency removal from other Horilla apps

* [IMP] ATTENDANCE: Attendance module dependency removal from other Horilla apps

* [IMP] BASE: Base module dependency removal from other Horilla apps

* [IMP] EMPLOYEE: Employee module dependency removal from other Horilla apps

* [IMP] HELPDESK: Helpdesk module dependency removal from other Horilla apps

* [IMP] HORILLA AUDIT: Horilla Audit module dependency removal from other Horilla apps

* [IMP] HORILLA CRUMBS: Horilla Crumbs module dependency removal from other Horilla apps

* [IMP] HORILLA AUTOMATIONS: Horilla Automations module dependency removal from other Horilla apps

* [IMP] HORILLA VIEWS: Horilla Views module dependency removal from other Horilla apps

* [IMP] LEAVE: Leave module dependency removal from other Horilla apps

* [IMP] OFFBOARDING: Offboarding module dependency removal from other Horilla apps

* [IMP] ONBOARDING: Onboarding module dependency removal from other Horilla apps

* [IMP] PMS: PMS module dependency removal from other Horilla apps

* [IMP] PAYROLL: Payroll module dependency removal from other Horilla apps

* [IMP] RECRUITMENT: Recruitment module dependency removal from other Horilla apps

* [IMP] HORILLA: Dependency removal updates

* [IMP] TEMPLATES: Dependency removal updates

* [IMP] STATIC: Dependency removal updates

* [IMP] HORILLA DOCUMENTS: Horilla Documents module dependency removal from other Horilla apps

* [ADD] HORILLA: methods.py

* [UPDT] HORILLA: Settings.py

* [FIX] EMPLOYEE: About tab issue

* Update horilla_settings.py

* Remove dummy db init password
2024-08-05 14:22:44 +05:30

431 lines
15 KiB
Python
Executable File

import logging
import os
from functools import wraps
from urllib.parse import urlencode
from django.contrib import messages
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import redirect, render
from django.urls import reverse
from django.utils.translation import gettext as _
from horilla import settings
from horilla.settings import BASE_DIR, TEMPLATES
logger = logging.getLogger(__name__)
TEMPLATES[0]["DIRS"] = [os.path.join(BASE_DIR, "templates")]
decorator_with_arguments = (
lambda decorator: lambda *args, **kwargs: lambda func: decorator(
func, *args, **kwargs
)
)
def check_manager(employee, instance):
from employee.models import Employee
try:
if isinstance(instance, Employee):
return instance.employee_work_info.reporting_manager_id == employee
return employee == instance.employee_id.employee_work_info.reporting_manager_id
except:
return False
@decorator_with_arguments
def permission_required(function, perm):
def _function(request, *args, **kwargs):
if request.user.has_perm(perm):
return function(request, *args, **kwargs)
else:
messages.info(request, "You dont have permission.")
previous_url = request.META.get("HTTP_REFERER", "/")
key = "HTTP_HX_REQUEST"
if key in request.META.keys():
return render(request, "decorator_404.html")
script = f'<script>window.location.href = "{previous_url}"</script>'
return HttpResponse(script)
return _function
decorator_with_arguments = (
lambda decorator: lambda *args, **kwargs: lambda func: decorator(
func, *args, **kwargs
)
)
@decorator_with_arguments
def delete_permission(function):
from employee.models import EmployeeWorkInformation
def _function(request, *args, **kwargs):
user = request.user
employee = user.employee_get
is_manager = EmployeeWorkInformation.objects.filter(
reporting_manager_id=employee
).exists()
if (
request.user.has_perm(
kwargs["model"]._meta.app_label
+ ".delete_"
+ kwargs["model"]._meta.model_name
)
or is_manager
):
return function(request, *args, **kwargs)
else:
messages.info(request, "You dont have permission for delete.")
previous_url = request.META.get("HTTP_REFERER", "/")
key = "HTTP_HX_REQUEST"
if key in request.META.keys():
return render(request, "decorator_404.html")
script = f'<script>window.location.href = "{previous_url}"</script>'
return HttpResponse(script)
return _function
decorator_with_arguments = (
lambda decorator: lambda *args, **kwargs: lambda func: decorator(
func, *args, **kwargs
)
)
@decorator_with_arguments
def duplicate_permission(function):
from employee.models import EmployeeWorkInformation
def _function(request, *args, **kwargs):
user = request.user
employee = user.employee_get
is_manager = EmployeeWorkInformation.objects.filter(
reporting_manager_id=employee
).exists()
app_label = kwargs["model"]._meta.app_label
model_name = kwargs["model"]._meta.model_name
try:
obj_id = kwargs["obj_id"]
object_instance = kwargs["model"].objects.filter(pk=obj_id).first()
if object_instance.employee_id == employee:
return function(request, *args, **kwargs)
except:
pass
permission = f"{app_label}.add_{model_name}"
if request.user.has_perm(permission) or is_manager:
return function(request, *args, **kwargs)
else:
messages.info(request, "You dont have permission for duplicate action.")
previous_url = request.META.get("HTTP_REFERER", "/")
key = "HTTP_HX_REQUEST"
if key in request.META.keys():
return render(request, "decorator_404.html")
script = f'<script>window.location.href = "{previous_url}"</script>'
return HttpResponse(script)
return _function
decorator_with_arguments = (
lambda decorator: lambda *args, **kwargs: lambda func: decorator(
func, *args, **kwargs
)
)
@decorator_with_arguments
def manager_can_enter(function, perm):
from base.models import MultipleApprovalManagers
from employee.models import EmployeeWorkInformation
"""
This method is used to check permission to employee for enter to the function if the employee
do not have permission also checks, has reporting manager.
"""
def _function(request, *args, **kwargs):
leave_perm = [
"leave.view_leaverequest",
"leave.change_leaverequest",
"leave.delete_leaverequest",
]
user = request.user
employee = user.employee_get
if perm in leave_perm:
is_approval_manager = MultipleApprovalManagers.objects.filter(
employee_id=employee.id
).exists()
if is_approval_manager:
return function(request, *args, **kwargs)
is_manager = EmployeeWorkInformation.objects.filter(
reporting_manager_id=employee
).exists()
if user.has_perm(perm) or is_manager:
return function(request, *args, **kwargs)
else:
messages.info(request, "You dont have permission.")
previous_url = request.META.get("HTTP_REFERER", "/")
script = f'<script>window.location.href = "{previous_url}"</script>'
key = "HTTP_HX_REQUEST"
if key in request.META.keys():
return render(request, "decorator_404.html")
return HttpResponse(script)
return _function
@decorator_with_arguments
def is_recruitment_manager(function, perm):
from recruitment.models import Recruitment
"""
This method is used to check permission to employee for enter to the function if the employee
do not have permission also checks, has manager of any recruitment.
"""
def _function(request, *args, **kwargs):
user = request.user
perm = "recruitment.view_recruitmentsurvey"
is_manager = False
recs = Recruitment.objects.all()
for i in recs:
for manager in i.recruitment_managers.all():
if request.user.employee_get == manager:
is_manager = True
if user.has_perm(perm) or is_manager:
return function(request, *args, **kwargs)
else:
messages.info(request, "You dont have permission.")
previous_url = request.META.get("HTTP_REFERER", "/")
script = f'<script>window.location.href = "{previous_url}"</script>'
key = "HTTP_HX_REQUEST"
if key in request.META.keys():
return render(request, "decorator_404.html")
return HttpResponse(script)
return _function
def login_required(view_func):
def wrapped_view(request, *args, **kwargs):
path = request.path
res = path.split("/", 2)[1].capitalize().replace("-", " ").upper()
if res == "PMS":
res = "Performance"
request.session["title"] = res
if path == "" or path == "/":
request.session["title"] = "Dashboard".upper()
if not request.user.is_authenticated:
login_url = reverse("login")
params = urlencode(request.GET)
url = f"{login_url}?next={request.path}"
if params:
url += f"&{params}"
return redirect(url)
try:
func = view_func(request, *args, **kwargs)
except Exception as e:
logger.error(e)
if (
"notifications_notification" in str(e)
and request.headers.get("X-Requested-With") != "XMLHttpRequest"
):
referer = request.META.get("HTTP_REFERER", "/")
messages.warning(request, str(e))
return HttpResponse(
f"<script>window.location.href ='{str(referer)}'</script>"
)
if not settings.DEBUG:
return render(request, "went_wrong.html")
return view_func(request, *args, **kwargs)
return func
return wrapped_view
def hx_request_required(view_func):
def wrapped_view(request, *args, **kwargs):
key = "HTTP_HX_REQUEST"
if key not in request.META.keys():
return render(request, "405.html")
return view_func(request, *args, **kwargs)
return wrapped_view
@decorator_with_arguments
def owner_can_enter(function, perm: str, model: object, manager_access=False):
from employee.models import Employee, EmployeeWorkInformation
"""
Only the users with permission, or the owner, or employees manager can enter,
If manager_access:True then all the managers can enter
"""
def _function(request, *args, **kwargs):
instance_id = kwargs[list(kwargs.keys())[0]]
if model == Employee:
employee = Employee.objects.get(id=instance_id)
else:
try:
employee = model.objects.get(id=instance_id).employee_id
except:
messages.error(request, ("Sorry, something went wrong!"))
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
can_enter = (
request.user.employee_get == employee
or request.user.has_perm(perm)
or check_manager(request.user.employee_get, employee)
or (
EmployeeWorkInformation.objects.filter(
reporting_manager_id__employee_user_id=request.user
).exists()
if manager_access
else False
)
)
if can_enter:
return function(request, *args, **kwargs)
return render(request, "no_perm.html")
return _function
def install_required(function):
from base.models import BiometricAttendance, TrackLateComeEarlyOut
def _function(request, *args, **kwargs):
if request.path_info.endswith("late-come-early-out-view/"):
object = TrackLateComeEarlyOut.objects.first()
if object.is_enable:
return function(request, *args, **kwargs)
else:
messages.info(
request,
_("Please enable the Track Late Come & Early Out from settings"),
)
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
object = BiometricAttendance.objects.all().first()
if object.is_installed:
return function(request, *args, **kwargs)
else:
messages.info(
request,
_(
"Please activate the biometric attendance feature in the settings menu."
),
)
return HttpResponseRedirect(request.META.get("HTTP_REFERER", "/"))
return _function
@decorator_with_arguments
def meeting_manager_can_enter(function, perm, answerable=False):
from employee.models import Employee
def _function(request, *args, **kwargs):
user = request.user
employee = user.employee_get
is_answer_employee = False
is_manager = (
Employee.objects.filter(
meeting_manager__isnull=False,
)
.filter(id=employee.id)
.exists()
)
if answerable:
is_answer_employee = (
Employee.objects.filter(
meeting_answer_employees__isnull=False,
)
.filter(id=employee.id)
.exists()
)
if user.has_perm(perm) or is_manager or is_answer_employee:
return function(request, *args, **kwargs)
else:
messages.info(request, "You dont have permission.")
previous_url = request.META.get("HTTP_REFERER", "/")
script = f'<script>window.location.href = "{previous_url}"</script>'
key = "HTTP_HX_REQUEST"
if key in request.META.keys():
return render(request, "decorator_404.html")
return HttpResponse(script)
return _function
DECORATOR_MAP = {
"login_required": login_required,
"permission_required": permission_required,
"delete_permission": delete_permission,
"duplicate_permission": duplicate_permission,
"manager_can_enter": manager_can_enter,
"is_recruitment_manager": is_recruitment_manager,
"hx_request_required": hx_request_required,
"owner_can_enter": owner_can_enter,
"install_required": install_required,
"meeting_manager_can_enter": meeting_manager_can_enter,
}
def get_decorator(decorator_string, args=None):
decorator = DECORATOR_MAP.get(decorator_string)
if decorator:
if args is not None:
if isinstance(args, (list, tuple)):
return decorator(*args)
else:
return decorator(args)
else:
return decorator
return None
def apply_decorators(decorators):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
decorated_func = func
for decorator_item in decorators:
if isinstance(decorator_item, str):
decorator = get_decorator(decorator_item)
elif (
isinstance(decorator_item, (list, tuple))
and len(decorator_item) == 2
):
decorator_string, decorator_args = decorator_item
decorator = get_decorator(decorator_string, decorator_args)
else:
print(f"Warning: Invalid decorator format: {decorator_item}")
continue
if decorator:
if callable(decorator):
decorated_func = decorator(decorated_func)
else:
# For decorators returned by decorator_with_arguments
decorated_func = decorator(decorated_func)
else:
print(f"Warning: Decorator '{decorator_item}' not found or invalid")
return decorated_func(*args, **kwargs)
return wrapper
return decorator