Pylint updates

This commit is contained in:
Horilla
2025-03-06 12:10:47 +05:30
parent 4232301540
commit 39784bbc73
12 changed files with 165 additions and 76 deletions

View File

@@ -1,7 +1,7 @@
import datetime import datetime
import sys import sys
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.schedulers.background import BackgroundScheduler
today = datetime.datetime.today() today = datetime.datetime.today()
@@ -22,7 +22,11 @@ def create_work_record(date=today):
WorkRecords.objects.get_or_create( WorkRecords.objects.get_or_create(
employee_id=employee, employee_id=employee,
date=date, date=date,
defaults={"work_record_type": "DFT", "shift_id": shift, "message": ""}, defaults={
"work_record_type": "DFT",
"shift_id": shift,
"message": "",
},
) )
except: except:
pass pass

View File

@@ -1,22 +1,18 @@
# attendance/signals.py # attendance/signals.py
from datetime import datetime, timedelta from datetime import datetime, timedelta
from django.apps import apps from django.apps import apps
from django.db.models.signals import post_migrate, post_save, pre_delete from django.db.models.signals import post_migrate, post_save, pre_delete
from django.utils.translation import gettext_lazy as _
from django.dispatch import receiver from django.dispatch import receiver
from django.utils.translation import gettext_lazy as _
from attendance.methods.utils import strtime_seconds from attendance.methods.utils import strtime_seconds
from attendance.models import ( from attendance.models import Attendance, AttendanceGeneralSetting, WorkRecords
Attendance,
AttendanceGeneralSetting,
WorkRecords,
)
from base.models import Company, PenaltyAccounts from base.models import Company, PenaltyAccounts
from employee.models import Employee from employee.models import Employee
from horilla.methods import get_horilla_model_class from horilla.methods import get_horilla_model_class
if apps.is_installed("payroll"): if apps.is_installed("payroll"):
@receiver(post_save, sender=PenaltyAccounts) @receiver(post_save, sender=PenaltyAccounts)
@@ -148,7 +144,7 @@ def add_missing_attendance_to_workrecord(sender, **kwargs):
if sender.label not in ["attendance", "leave"]: if sender.label not in ["attendance", "leave"]:
return return
from attendance.models import WorkRecords, Attendance from attendance.models import Attendance, WorkRecords
try: try:
work_records = WorkRecords.objects.filter( work_records = WorkRecords.objects.filter(
@@ -230,6 +226,7 @@ def create_attendance_setting(sender, instance, created, raw, **kwargs):
if created: if created:
AttendanceGeneralSetting.objects.get_or_create(company_id=instance) AttendanceGeneralSetting.objects.get_or_create(company_id=instance)
@receiver(post_migrate) @receiver(post_migrate)
def create_missing_work_records(sender, **kwargs): def create_missing_work_records(sender, **kwargs):
if sender.label not in ["attendance"]: if sender.label not in ["attendance"]:
@@ -247,10 +244,15 @@ def create_missing_work_records(sender, **kwargs):
end_date = datetime.today().date() end_date = datetime.today().date()
existing_dates = set( existing_dates = set(
WorkRecords.objects.filter(employee_id=employee.id).values_list("date", flat=True) WorkRecords.objects.filter(employee_id=employee.id).values_list(
"date", flat=True
)
) )
all_dates = {start_date + timedelta(days=i) for i in range((end_date - start_date).days)} all_dates = {
start_date + timedelta(days=i)
for i in range((end_date - start_date).days)
}
missing_dates = all_dates - existing_dates missing_dates = all_dates - existing_dates
work_records_to_create = [ work_records_to_create = [
@@ -264,8 +266,11 @@ def create_missing_work_records(sender, **kwargs):
] ]
if work_records_to_create: if work_records_to_create:
WorkRecords.objects.bulk_create(work_records_to_create, batch_size=500, ignore_conflicts=True) WorkRecords.objects.bulk_create(
work_records_to_create, batch_size=500, ignore_conflicts=True
)
except Exception as e: except Exception as e:
print(f"Error creating missing work records for employee {employee}: {e}") print(
f"Error creating missing work records for employee {employee}: {e}"
)

View File

@@ -1,16 +1,18 @@
from django.apps import AppConfig from django.apps import AppConfig
from django.conf import settings from django.conf import settings
import horilla.horilla_settings import horilla.horilla_settings
class HorillaLdapConfig(AppConfig): class HorillaLdapConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField' default_auto_field = "django.db.models.BigAutoField"
name = 'horilla_ldap' name = "horilla_ldap"
def ready(self): def ready(self):
from django.urls import include, path from django.urls import include, path
from horilla.urls import urlpatterns
from horilla.horilla_settings import APPS from horilla.horilla_settings import APPS
from horilla.urls import urlpatterns
APPS.append("horilla_ldap") APPS.append("horilla_ldap")
urlpatterns.append( urlpatterns.append(

View File

@@ -1,14 +1,19 @@
from django import forms from django import forms
from .models import LDAPSettings
from django.template.loader import render_to_string from django.template.loader import render_to_string
from base.forms import ModelForm from base.forms import ModelForm
from .models import LDAPSettings
class LDAPSettingsForm(ModelForm): class LDAPSettingsForm(ModelForm):
bind_password = forms.CharField(widget=forms.PasswordInput(attrs={"class":"oh-input w-100"}), required=True) bind_password = forms.CharField(
widget=forms.PasswordInput(attrs={"class": "oh-input w-100"}), required=True
)
class Meta: class Meta:
model = LDAPSettings model = LDAPSettings
fields = ['ldap_server', 'bind_dn', 'bind_password', 'base_dn'] fields = ["ldap_server", "bind_dn", "bind_password", "base_dn"]
def as_p(self): def as_p(self):
""" """

View File

@@ -1,16 +1,18 @@
import platform
import re import re
import sys import sys
import platform
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.db.models import Q from django.db.models import Q
from django.contrib.auth.models import User
from horilla_ldap.models import LDAPSettings
from employee.models import Employee from employee.models import Employee
from horilla_ldap.models import LDAPSettings
if platform.system() == "Linux": if platform.system() == "Linux":
import ldap # Use python-ldap for Linux import ldap # Use python-ldap for Linux
else: else:
from ldap3 import Server, Connection, ALL # Use ldap3 for Windows from ldap3 import ALL, Connection, Server # Use ldap3 for Windows
class Command(BaseCommand): class Command(BaseCommand):
@@ -33,7 +35,11 @@ class Command(BaseCommand):
base_dn = settings.base_dn base_dn = settings.base_dn
if not all([ldap_server, bind_dn, bind_password, base_dn]): if not all([ldap_server, bind_dn, bind_password, base_dn]):
self.stdout.write(self.style.ERROR("LDAP settings are incomplete. Please check your configuration.")) self.stdout.write(
self.style.ERROR(
"LDAP settings are incomplete. Please check your configuration."
)
)
return return
try: try:
@@ -42,7 +48,9 @@ class Command(BaseCommand):
connection = ldap.initialize(ldap_server) connection = ldap.initialize(ldap_server)
connection.simple_bind_s(bind_dn, bind_password) connection.simple_bind_s(bind_dn, bind_password)
search_filter = "(objectClass=inetOrgPerson)" search_filter = "(objectClass=inetOrgPerson)"
results = connection.search_s(base_dn, ldap.SCOPE_SUBTREE, search_filter) results = connection.search_s(
base_dn, ldap.SCOPE_SUBTREE, search_filter
)
for dn, entry in results: for dn, entry in results:
user_id = entry.get("uid", [b""])[0].decode("utf-8") user_id = entry.get("uid", [b""])[0].decode("utf-8")
@@ -53,13 +61,17 @@ class Command(BaseCommand):
phone = entry.get("telephoneNumber", [b""])[0].decode("utf-8") phone = entry.get("telephoneNumber", [b""])[0].decode("utf-8")
# Get the password from LDAP # Get the password from LDAP
ldap_password = entry.get("telephoneNumber", [b""])[0].decode("utf-8") ldap_password = entry.get("telephoneNumber", [b""])[0].decode(
"utf-8"
)
# Remove non-numeric characters but keep numbers # Remove non-numeric characters but keep numbers
clean_phone = re.sub(r"[^\d]", "", phone) clean_phone = re.sub(r"[^\d]", "", phone)
ldap_password = clean_phone ldap_password = clean_phone
self.create_or_update_employee(user_id, email, first_name, last_name, phone, ldap_password) self.create_or_update_employee(
user_id, email, first_name, last_name, phone, ldap_password
)
connection.unbind_s() connection.unbind_s()
@@ -68,11 +80,27 @@ class Command(BaseCommand):
server = Server(ldap_server, get_info=ALL) server = Server(ldap_server, get_info=ALL)
connection = Connection(server, user=bind_dn, password=bind_password) connection = Connection(server, user=bind_dn, password=bind_password)
if not connection.bind(): if not connection.bind():
self.stdout.write(self.style.ERROR(f"Failed to bind to LDAP server: {connection.last_error}")) self.stdout.write(
self.style.ERROR(
f"Failed to bind to LDAP server: {connection.last_error}"
)
)
return return
search_filter = "(objectClass=inetOrgPerson)" search_filter = "(objectClass=inetOrgPerson)"
connection.search(base_dn, search_filter, attributes=['uid', 'mail', 'givenName', 'sn', 'cn', 'telephoneNumber', 'userPassword']) connection.search(
base_dn,
search_filter,
attributes=[
"uid",
"mail",
"givenName",
"sn",
"cn",
"telephoneNumber",
"userPassword",
],
)
for entry in connection.entries: for entry in connection.entries:
user_id = entry.uid.value if entry.uid else "" user_id = entry.uid.value if entry.uid else ""
@@ -86,32 +114,44 @@ class Command(BaseCommand):
clean_phone = re.sub(r"[^\d]", "", phone) clean_phone = re.sub(r"[^\d]", "", phone)
ldap_password = clean_phone ldap_password = clean_phone
self.create_or_update_employee(user_id, email, first_name, last_name, phone, ldap_password) self.create_or_update_employee(
user_id, email, first_name, last_name, phone, ldap_password
)
connection.unbind() connection.unbind()
except Exception as e: except Exception as e:
self.stderr.write(self.style.ERROR(f"Error: {e}")) self.stderr.write(self.style.ERROR(f"Error: {e}"))
def create_or_update_employee(self, user_id, email, first_name, last_name, phone, ldap_password): def create_or_update_employee(
self, user_id, email, first_name, last_name, phone, ldap_password
):
employee, created = Employee.objects.update_or_create( employee, created = Employee.objects.update_or_create(
email=email, email=email,
defaults={ defaults={
"employee_first_name": first_name or "", "employee_first_name": first_name or "",
"employee_last_name": last_name or "", "employee_last_name": last_name or "",
"phone": phone or "", "phone": phone or "",
} },
) )
try: try:
user = User.objects.get(Q(username=email) | Q(username=user_id) | Q(email=email)) user = User.objects.get(
Q(username=email) | Q(username=user_id) | Q(email=email)
)
user.username = user_id user.username = user_id
user.set_password(ldap_password) # Hash and store password securely user.set_password(ldap_password) # Hash and store password securely
user.save() user.save()
action = "Updated" action = "Updated"
except User.DoesNotExist: except User.DoesNotExist:
self.stdout.write(self.style.WARNING(f"User for employee {first_name} {last_name} does not exist.")) self.stdout.write(
self.style.WARNING(
f"User for employee {first_name} {last_name} does not exist."
)
)
return return
action = "Created" if created else "Updated" action = "Created" if created else "Updated"
self.stdout.write(self.style.SUCCESS(f"{action} employee {first_name} {last_name}.")) self.stdout.write(
self.style.SUCCESS(f"{action} employee {first_name} {last_name}.")
)

View File

@@ -1,13 +1,15 @@
import hashlib
import base64 import base64
import hashlib
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from ldap3 import Server, Connection, ALL, ALL_ATTRIBUTES from ldap3 import ALL, ALL_ATTRIBUTES, Connection, Server
from horilla_ldap.models import LDAPSettings
from employee.models import Employee from employee.models import Employee
from horilla_ldap.models import LDAPSettings
class Command(BaseCommand): class Command(BaseCommand):
help = 'Import users from Django to LDAP using LDAP settings from the database' help = "Import users from Django to LDAP using LDAP settings from the database"
def handle(self, *args, **kwargs): def handle(self, *args, **kwargs):
# Get LDAP settings from the database # Get LDAP settings from the database
@@ -23,7 +25,11 @@ class Command(BaseCommand):
base_dn = settings.base_dn base_dn = settings.base_dn
if not all([ldap_server, bind_dn, bind_password, base_dn]): if not all([ldap_server, bind_dn, bind_password, base_dn]):
self.stdout.write(self.style.ERROR("LDAP settings are incomplete. Please check your configuration.")) self.stdout.write(
self.style.ERROR(
"LDAP settings are incomplete. Please check your configuration."
)
)
return return
# Connect to the LDAP server # Connect to the LDAP server
@@ -37,40 +43,65 @@ class Command(BaseCommand):
for user in users: for user in users:
if not user.employee_user_id: if not user.employee_user_id:
self.stdout.write(self.style.WARNING(f"Skipping user {user} due to missing employee_user_id")) self.stdout.write(
self.style.WARNING(
f"Skipping user {user} due to missing employee_user_id"
)
)
continue continue
dn = f"uid={user.employee_user_id.username},{base_dn}" dn = f"uid={user.employee_user_id.username},{base_dn}"
# Securely hash the password using SHA # Securely hash the password using SHA
hashed_password = "{SHA}" + base64.b64encode(hashlib.sha1(user.phone.encode()).digest()).decode() hashed_password = (
"{SHA}"
+ base64.b64encode(
hashlib.sha1(user.phone.encode()).digest()
).decode()
)
if user.employee_last_name is None: if user.employee_last_name is None:
user.employee_last_name = " " user.employee_last_name = " "
attributes = { attributes = {
'objectClass': ['inetOrgPerson'], "objectClass": ["inetOrgPerson"],
'givenName': user.employee_first_name or "", "givenName": user.employee_first_name or "",
'sn': user.employee_last_name or "", "sn": user.employee_last_name or "",
'cn': f"{user.employee_first_name} {user.employee_last_name}", "cn": f"{user.employee_first_name} {user.employee_last_name}",
'uid': user.email or "", "uid": user.email or "",
'mail': user.email or "", "mail": user.email or "",
"telephoneNumber": user.phone or "", "telephoneNumber": user.phone or "",
'userPassword': hashed_password, # Securely store password "userPassword": hashed_password, # Securely store password
} }
# Check if the user already exists in LDAP # Check if the user already exists in LDAP
conn.search(base_dn, f'(uid={user.employee_user_id.username})', attributes=ALL_ATTRIBUTES) conn.search(
base_dn,
f"(uid={user.employee_user_id.username})",
attributes=ALL_ATTRIBUTES,
)
if conn.entries: if conn.entries:
self.stdout.write(self.style.WARNING(f'{user.employee_first_name} {user.employee_last_name} already exists in LDAP. Skipping...')) self.stdout.write(
self.style.WARNING(
f"{user.employee_first_name} {user.employee_last_name} already exists in LDAP. Skipping..."
)
)
else: else:
# Add user to LDAP # Add user to LDAP
if not conn.add(dn, attributes=attributes): if not conn.add(dn, attributes=attributes):
self.stdout.write(self.style.ERROR(f'Failed to add {user.employee_first_name} {user.employee_last_name}: {conn.result}')) self.stdout.write(
self.style.ERROR(
f"Failed to add {user.employee_first_name} {user.employee_last_name}: {conn.result}"
)
)
else: else:
self.stdout.write(self.style.SUCCESS(f'Successfully added {user.employee_first_name} {user.employee_last_name} to LDAP.')) self.stdout.write(
self.style.SUCCESS(
f"Successfully added {user.employee_first_name} {user.employee_last_name} to LDAP."
)
)
conn.unbind() conn.unbind()
except Exception as e: except Exception as e:
self.stdout.write(self.style.ERROR(f'An error occurred: {e}')) self.stdout.write(self.style.ERROR(f"An error occurred: {e}"))

View File

@@ -3,8 +3,6 @@ from django.db import models
# Create your models here. # Create your models here.
from django.db import models
class LDAPSettings(models.Model): class LDAPSettings(models.Model):
ldap_server = models.CharField(max_length=255, default="ldap://127.0.0.1:389") ldap_server = models.CharField(max_length=255, default="ldap://127.0.0.1:389")
bind_dn = models.CharField(max_length=255, default="cn=admin,dc=horilla,dc=com") bind_dn = models.CharField(max_length=255, default="cn=admin,dc=horilla,dc=com")
@@ -13,4 +11,3 @@ class LDAPSettings(models.Model):
def __str__(self): def __str__(self):
return f"LDAP Settings ({self.ldap_server})" return f"LDAP Settings ({self.ldap_server})"

View File

@@ -5,4 +5,4 @@
{% csrf_token %} {% csrf_token %}
{{ form.as_p }} {{ form.as_p }}
</form> </form>
{% endblock settings %} {% endblock settings %}

View File

@@ -5,8 +5,9 @@ This module is used to map url path with view methods.
""" """
from django.urls import path from django.urls import path
from horilla_ldap import views from horilla_ldap import views
urlpatterns = [ urlpatterns = [
path('settings/ldap-settings/', views.ldap_settings_view, name='ldap-settings'), path("settings/ldap-settings/", views.ldap_settings_view, name="ldap-settings"),
] ]

View File

@@ -1,13 +1,14 @@
from django.contrib import messages
from django.shortcuts import render from django.shortcuts import render
# Create your views here.
from horilla.decorators import login_required
from .models import LDAPSettings
from .forms import LDAPSettingsForm
from django.utils.translation import gettext as __ from django.utils.translation import gettext as __
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.contrib import messages
from horilla.decorators import login_required
from .forms import LDAPSettingsForm
from .models import LDAPSettings
# Create your views here.
@login_required @login_required

View File

@@ -3,14 +3,13 @@
import threading import threading
from django.apps import apps from django.apps import apps
from django.db.models.signals import post_migrate, pre_save, post_save, pre_delete from django.db.models.signals import post_migrate, post_save, pre_delete, pre_save
from django.dispatch import receiver from django.dispatch import receiver
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from horilla.methods import get_horilla_model_class from horilla.methods import get_horilla_model_class
from leave.models import LeaveRequest from leave.models import LeaveRequest
if apps.is_installed("attendance"): if apps.is_installed("attendance"):
@receiver(pre_save, sender=LeaveRequest) @receiver(pre_save, sender=LeaveRequest)

View File

@@ -1,7 +1,12 @@
from django.db.models.signals import m2m_changed, post_save
from django.dispatch import receiver from django.dispatch import receiver
from django.db.models.signals import post_save, m2m_changed
from recruitment.models import CandidateDocument, CandidateDocumentRequest, Recruitment, Stage from recruitment.models import (
CandidateDocument,
CandidateDocumentRequest,
Recruitment,
Stage,
)
@receiver(post_save, sender=Recruitment) @receiver(post_save, sender=Recruitment)
@@ -44,4 +49,3 @@ def candidate_document_create(instance):
) )
document.title = f"Upload {instance.title}" document.title = f"Upload {instance.title}"
document.save() document.save()