auth service up running

This commit is contained in:
2025-01-10 14:17:22 +03:00
parent 03accfed1b
commit 79aa3a1bc5
41 changed files with 480 additions and 340 deletions

View File

@@ -13,10 +13,21 @@ from api_configs import Auth, ApiStatic
from api_events.events.abstract_class import MethodToEvent, ActionsSchema
from databases import (
Companies, Staff, Duties, Departments, Employees,
BuildLivingSpace, BuildParts, Build, Duty, Event2Occupant,
Event2Employee, Users, UsersTokens, OccupantTypes,
RelationshipEmployee2Build
Companies,
Staff,
Duties,
Departments,
Employees,
BuildLivingSpace,
BuildParts,
Build,
Duty,
Event2Occupant,
Event2Employee,
Users,
UsersTokens,
OccupantTypes,
RelationshipEmployee2Build,
)
from api_services import (
@@ -28,17 +39,23 @@ from api_services import (
)
from api_validations.validations_request import (
Login, Logout, ChangePassword, Remember,
Forgot, CreatePassword, OccupantSelection,
Login,
Logout,
ChangePassword,
Remember,
Forgot,
CreatePassword,
OccupantSelection,
EmployeeSelection,
)
from api_validations.validations_response import (
AuthenticationLoginResponse,
AuthenticationRefreshResponse,
AuthenticationUserInfoResponse
AuthenticationUserInfoResponse,
)
class AuthenticationLoginEventMethods(MethodToEvent):
event_type = "LOGIN"
event_description = "Login via domain and access key : [email] | [phone]"
@@ -56,19 +73,22 @@ class AuthenticationLoginEventMethods(MethodToEvent):
try:
access_dict = Users.login_user_with_credentials(data=data, request=request)
found_user = access_dict.get("user")
if not found_user:
user_logger.log_login_attempt(
request, None, data.domain, data.access_key,
success=False, error="Invalid credentials"
request,
None,
data.domain,
data.access_key,
success=False,
error="Invalid credentials",
)
return ResponseHandler.unauthorized("Invalid credentials")
user_logger.log_login_attempt(
request, found_user.id, data.domain, data.access_key,
success=True
request, found_user.id, data.domain, data.access_key, success=True
)
response_data = {
"access_token": access_dict.get("access_token"),
"refresh_token": access_dict.get("refresher_token"),
@@ -78,17 +98,13 @@ class AuthenticationLoginEventMethods(MethodToEvent):
return ResponseHandler.success(
message="User logged in successfully",
data=response_data,
response_model=AuthenticationLoginResponse
response_model=AuthenticationLoginResponse,
)
except Exception as e:
user_logger.log_login_attempt(
request, None, data.domain, data.access_key,
success=False, error=str(e)
)
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=str(e)
request, None, data.domain, data.access_key, success=False, error=str(e)
)
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=str(e))
class AuthenticationSelectEventMethods(MethodToEvent):
@@ -105,14 +121,13 @@ class AuthenticationSelectEventMethods(MethodToEvent):
@classmethod
def _handle_employee_selection(
cls,
data: EmployeeSelection,
token_dict: EmployeeTokenObject,
request: Request
cls, data: EmployeeSelection, token_dict: EmployeeTokenObject, request: Request
):
"""Handle employee company selection"""
if data.company_uu_id not in token_dict.companies_uu_id_list:
return ResponseHandler.unauthorized("Company not found in user's company list")
return ResponseHandler.unauthorized(
"Company not found in user's company list"
)
selected_company = Companies.filter_one(
Companies.uu_id == data.company_uu_id
@@ -122,29 +137,27 @@ class AuthenticationSelectEventMethods(MethodToEvent):
# Get department IDs for the company
department_ids = [
dept.id for dept in Departments.filter_all(
dept.id
for dept in Departments.filter_all(
Departments.company_id == selected_company.id
).data
]
# Get duties IDs for the company
duties_ids = [
duty.id for duty in Duties.filter_all(
Duties.company_id == selected_company.id
).data
duty.id
for duty in Duties.filter_all(Duties.company_id == selected_company.id).data
]
# Get staff IDs
staff_ids = [
staff.id for staff in Staff.filter_all(
Staff.duties_id.in_(duties_ids)
).data
staff.id for staff in Staff.filter_all(Staff.duties_id.in_(duties_ids)).data
]
# Get employee
employee = Employees.filter_one(
Employees.people_id == token_dict.person_id,
Employees.staff_id.in_(staff_ids)
Employees.staff_id.in_(staff_ids),
).data
if not employee:
@@ -158,16 +171,14 @@ class AuthenticationSelectEventMethods(MethodToEvent):
# Get staff and duties
staff = Staff.filter_one(Staff.id == employee.staff_id).data
duties = Duties.filter_one(Duties.id == staff.duties_id).data
department = Departments.filter_one(
Departments.id == duties.department_id
).data
department = Departments.filter_one(Departments.id == duties.department_id).data
# Get bulk duty
bulk_id = Duty.filter_by_one(system=True, duty_code="BULK").data
bulk_duty_id = Duties.filter_by_one(
company_id=selected_company.id,
duties_id=bulk_id.id,
**Duties.valid_record_dict
**Duties.valid_record_dict,
).data
# Create company token
@@ -183,7 +194,7 @@ class AuthenticationSelectEventMethods(MethodToEvent):
staff_uu_id=staff.uu_id.__str__(),
employee_id=employee.id,
employee_uu_id=employee.uu_id.__str__(),
reachable_event_list_id=reachable_event_list_id
reachable_event_list_id=reachable_event_list_id,
)
# Update Redis
@@ -192,24 +203,19 @@ class AuthenticationSelectEventMethods(MethodToEvent):
@classmethod
def _handle_occupant_selection(
cls,
data: OccupantSelection,
token_dict: OccupantTokenObject,
request: Request
cls, data: OccupantSelection, token_dict: OccupantTokenObject, request: Request
):
"""Handle occupant type selection"""
# Get occupant type
occupant_type = OccupantTypes.filter_by_one(
system=True,
uu_id=data.occupant_uu_id
system=True, uu_id=data.occupant_uu_id
).data
if not occupant_type:
return ResponseHandler.not_found("Occupant Type not found")
# Get build part
build_part = BuildParts.filter_by_one(
system=True,
uu_id=data.build_part_uu_id
system=True, uu_id=data.build_part_uu_id
).data
if not build_part:
return ResponseHandler.not_found("Build Part not found")
@@ -230,7 +236,7 @@ class AuthenticationSelectEventMethods(MethodToEvent):
selected_occupant_type = BuildLivingSpace.filter_one(
BuildLivingSpace.occupant_type == occupant_type.id,
BuildLivingSpace.person_id == token_dict.person_id,
BuildLivingSpace.build_parts_id == build_part.id
BuildLivingSpace.build_parts_id == build_part.id,
).data
if not selected_occupant_type:
return ResponseHandler.not_found("Selected occupant type not found")
@@ -255,7 +261,7 @@ class AuthenticationSelectEventMethods(MethodToEvent):
responsible_employee_uuid=responsible_employee.uu_id.__str__(),
responsible_company_id=company_related.id,
responsible_company_uuid=company_related.uu_id.__str__(),
reachable_event_list_id=reachable_event_list_id
reachable_event_list_id=reachable_event_list_id,
)
# Update Redis
@@ -276,13 +282,11 @@ class AuthenticationSelectEventMethods(MethodToEvent):
elif isinstance(token_dict, OccupantTokenObject):
return cls._handle_occupant_selection(data, token_dict, request)
return ResponseHandler.error(
"Invalid token type",
status_code=status.HTTP_400_BAD_REQUEST
"Invalid token type", status_code=status.HTTP_400_BAD_REQUEST
)
except Exception as e:
return ResponseHandler.error(
str(e),
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
str(e), status_code=status.HTTP_500_INTERNAL_SERVER_ERROR
)
@@ -331,9 +335,7 @@ class AuthenticationRefreshEventMethods(MethodToEvent):
return ResponseHandler.unauthorized()
# Get user and token info
found_user = Users.filter_one(
Users.uu_id == token_dict.user_uu_id
).data
found_user = Users.filter_one(Users.uu_id == token_dict.user_uu_id).data
if not found_user:
return ResponseHandler.not_found("User not found")
@@ -349,12 +351,12 @@ class AuthenticationRefreshEventMethods(MethodToEvent):
response_data = {
"access_token": access_token,
"refresh_token": getattr(user_token, "token", None),
"user": found_user.get_dict()
"user": found_user.get_dict(),
}
return ResponseHandler.success(
"User info refreshed successfully",
data=response_data,
response_model=AuthenticationRefreshResponse
response_model=AuthenticationRefreshResponse,
)
except Exception as e:
return ResponseHandler.error(str(e))
@@ -381,7 +383,9 @@ class AuthenticationChangePasswordEventMethods(MethodToEvent):
):
try:
if not isinstance(token_dict, EmployeeTokenObject):
return ResponseHandler.unauthorized("Only employees can change password")
return ResponseHandler.unauthorized(
"Only employees can change password"
)
found_user = Users.filter_one(Users.uu_id == token_dict.user_uu_id).data
if not found_user:
@@ -389,22 +393,27 @@ class AuthenticationChangePasswordEventMethods(MethodToEvent):
if not found_user.check_password(data.old_password):
user_logger.log_password_change(
request, found_user.id, "change",
success=False, error="Invalid old password"
request,
found_user.id,
"change",
success=False,
error="Invalid old password",
)
return ResponseHandler.unauthorized("Old password is incorrect")
found_user.set_password(data.new_password)
user_logger.log_password_change(
request, found_user.id, "change",
success=True
request, found_user.id, "change", success=True
)
return ResponseHandler.success("Password changed successfully")
except Exception as e:
user_logger.log_password_change(
request, found_user.id if found_user else None,
"change", success=False, error=str(e)
request,
found_user.id if found_user else None,
"change",
success=False,
error=str(e),
)
return ResponseHandler.error(str(e))
@@ -471,7 +480,9 @@ class AuthenticationDisconnectUserEventMethods(MethodToEvent):
found_user = Users.filter_one(Users.uu_id == token_dict.user_uu_id).data
if not found_user:
return ResponseHandler.not_found("User not found")
if already_tokens := RedisActions.get_object_via_user_uu_id(user_id=str(found_user.uu_id)):
if already_tokens := RedisActions.get_object_via_user_uu_id(
user_id=str(found_user.uu_id)
):
for key, token_user in already_tokens.items():
RedisActions.delete_key(key)
selected_user = Users.filter_one(
@@ -566,7 +577,7 @@ class AuthenticationRefreshTokenEventMethods(MethodToEvent):
return ResponseHandler.success(
"User is logged in successfully via refresher token",
data=response_data,
response_model=AuthenticationRefreshResponse
response_model=AuthenticationRefreshResponse,
)
return ResponseHandler.not_found("Invalid data")
@@ -697,7 +708,7 @@ class AuthenticationDownloadAvatarEventMethods(MethodToEvent):
return ResponseHandler.success(
"Avatar and profile is shared via user credentials",
data=user_info,
response_model=AuthenticationUserInfoResponse
response_model=AuthenticationUserInfoResponse,
)
return ResponseHandler.not_found("Invalid data")