From 9fb517fa15fe4ac0f812c0aa4c27e220d2979c4b Mon Sep 17 00:00:00 2001 From: Berkay Date: Sun, 15 Jun 2025 19:05:48 +0300 Subject: [PATCH] user selection compoleted tested --- .../Account/events/account_records/cluster.py | 2 + .../account_records/flat_representative.py | 60 +++++ .../Builds/Auth/endpoints/auth/router.py | 5 +- ServicesApi/Builds/Auth/events/auth/events.py | 205 +++++++++++------- .../validations/request/auth/validations.py | 6 +- .../Identity/events/people/flat_tenant.py | 58 +++++ .../Extensions/Middlewares/token_provider.py | 4 +- .../Extensions/OnMemory/redis_handlers.py | 29 ++- ServicesApi/Schemas/building/build.py | 18 +- ServicesApi/Schemas/event/event.py | 10 +- ServicesApi/Validations/token/validations.py | 4 +- ServicesWeb/customer/README.md | 64 ++++-- .../app/api/context/dash/selection/route.ts | 5 +- .../customer/src/app/api/login/email/route.ts | 3 +- .../src/app/api/login/logout/route.ts | 26 +++ .../components/custom/header/component.tsx | 28 +-- .../custom/menu/clientSelectionSection.tsx | 89 +++++--- .../src/components/custom/menu/component.tsx | 14 +- .../custom/menu/renderOneClientSelection.tsx | 58 +++-- .../custom/menu/userProfileSection.tsx | 23 +- .../custom/context/dash/selection/fetch.tsx | 18 +- .../src/fetchers/custom/login/login.tsx | 147 ++++++------- .../src/fetchers/types/login/validations.ts | 6 +- ServicesWeb/customer/src/pages/multi/index.ts | 5 +- 24 files changed, 574 insertions(+), 313 deletions(-) create mode 100644 ServicesApi/Builds/Account/events/account_records/flat_representative.py create mode 100644 ServicesApi/Builds/Identity/events/people/flat_tenant.py create mode 100644 ServicesWeb/customer/src/app/api/login/logout/route.ts diff --git a/ServicesApi/Builds/Account/events/account_records/cluster.py b/ServicesApi/Builds/Account/events/account_records/cluster.py index 2c41b8b..e1678f2 100644 --- a/ServicesApi/Builds/Account/events/account_records/cluster.py +++ b/ServicesApi/Builds/Account/events/account_records/cluster.py @@ -6,11 +6,13 @@ from .supers_events import ( SuperAccountRecordsUpdateEvent, SuperAccountRecordsDeleteEvent, ) +from .flat_representative import FlatRepresentativeAccountRecordsListEvent AccountRecordsRouterCluster = RouterCluster(name="AccountRecordsRouterCluster") AccountRecordsListEventCluster = EventCluster(name="AccountRecordsListEventCluster", endpoint_uu_id=endpoints_index["AccountRecordsList"]) AccountRecordsListEventCluster.add_event(SuperAccountRecordsListEvent) +AccountRecordsListEventCluster.add_event(FlatRepresentativeAccountRecordsListEvent) AccountRecordsCreateEventCluster = EventCluster(name="AccountRecordsCreateEventCluster", endpoint_uu_id=endpoints_index["AccountRecordsCreate"]) AccountRecordsCreateEventCluster.add_event(SuperAccountRecordsCreateEvent) diff --git a/ServicesApi/Builds/Account/events/account_records/flat_representative.py b/ServicesApi/Builds/Account/events/account_records/flat_representative.py new file mode 100644 index 0000000..e50da1f --- /dev/null +++ b/ServicesApi/Builds/Account/events/account_records/flat_representative.py @@ -0,0 +1,60 @@ +from typing import Any + +from Initializer.event_clusters import Event +from Validations.response import ( + PaginateOnly, + Pagination, + PaginationResult, + PostgresResponseSingle, + PostgresResponse, + EndpointResponse +) +from Validations.defaults.validations import CommonHeaders +from Schemas import AccountRecords +from Extensions.Middlewares.token_provider import TokenProvider + + +# List all account records endpoint Flat Representative +FlatRepresentativeAccountRecordsListEvent = Event( + name="flat_representative_account_records_list", + key="7cb248d3-d75a-4d28-8be5-f147089ce654", + request_validator=None, # TODO: Add request validator + response_validator=None, # TODO: Add response validator + description="Flat Representative Account Records List all flat representative users endpoint", +) + +class FlatRepresentativeAccountRecordsListPydantic: + uu_id: str + bank_date: datetime.datetime + currency_value: float + process_name: str + + +def flat_representative_account_records_list_callable(list_options: PaginateOnly, header: CommonHeaders): + list_options = PaginateOnly(**list_options.model_dump()) + token_object = TokenProvider.get_dict_from_redis(token=header.token) + if not token_object.is_occupant: + raise Exception("Forbidden for employees") + + pagination_query = {} + if list_options.query: + pagination_query = FlatRepresentativeAccountRecordsListPydantic(**list_options.query) + + with AccountRecords.new_session() as db_session: + AccountRecords.set_session(db_session) + if pagination_query: + account_records_list = AccountRecords.query.filter( + *AccountRecords.convert(pagination_query), + AccountRecords.build_parts_id == token_object.selected_occupant.build_id + ) + else: + account_records_list = AccountRecords.query.filter( + AccountRecords.build_parts_id == token_object.selected_occupant.build_id + ) + pagination = Pagination(data=account_records_list) + pagination.change(**list_options.model_dump()) + pagination_result = PaginationResult(data=account_records_list, pagination=pagination, response_model=FlatRepresentativeAccountRecordsListPydantic) + return EndpointResponse(message="MSG0003-LIST", pagination_result=pagination_result).response + + +FlatRepresentativeAccountRecordsListEvent.event_callable = flat_representative_account_records_list_callable diff --git a/ServicesApi/Builds/Auth/endpoints/auth/router.py b/ServicesApi/Builds/Auth/endpoints/auth/router.py index fcbe57c..b95fa71 100644 --- a/ServicesApi/Builds/Auth/endpoints/auth/router.py +++ b/ServicesApi/Builds/Auth/endpoints/auth/router.py @@ -7,8 +7,7 @@ from config import api_config from validations.request.auth.validations import ( RequestLogin, RequestResetPassword, - RequestSelectLiving, - RequestSelectEmployee, + RequestSelect, RequestCreatePassword, RequestChangePassword, RequestForgotPasswordPhone, @@ -44,7 +43,7 @@ auth_route_select_living = "AuthSelectLiving" description="Selection of users company or occupant type", operation_id=endpoints_index[auth_route_select_living] ) -def select_living(data: Union[RequestSelectLiving, RequestSelectEmployee], headers: CommonHeaders = Depends(CommonHeaders.as_dependency)): +def select_living(data: Union[RequestSelect], headers: CommonHeaders = Depends(CommonHeaders.as_dependency)): """Select token object company or occupant type""" token_object = TokenProvider.get_dict_from_redis(token=headers.token) return AuthHandlers.LoginHandler.authentication_select_company_or_occupant_type(request=headers.request, data=data) diff --git a/ServicesApi/Builds/Auth/events/auth/events.py b/ServicesApi/Builds/Auth/events/auth/events.py index fc270b9..b30f36d 100644 --- a/ServicesApi/Builds/Auth/events/auth/events.py +++ b/ServicesApi/Builds/Auth/events/auth/events.py @@ -5,8 +5,9 @@ from config import api_config from Schemas import ( Users, People, - BuildLivingSpace, + Build, BuildParts, + BuildLivingSpace, OccupantTypes, Employees, Addresses, @@ -78,6 +79,8 @@ class LoginHandler: user_handler, other_domains_list, main_domain = UserHandlers(), [], "" found_user = user_handler.check_user_exists(access_key=data.access_key, db_session=db_session) + redis_handler = RedisHandlers() + with mongo_handler.collection(f"{str(found_user.related_company)}*Domain") as collection: result = collection.find_one({"user_uu_id": str(found_user.uu_id)}) if not result: @@ -133,15 +136,13 @@ class LoginHandler: person_uu_id=str(list_employees[0]["People.uu_id"]), request=dict(headers.request.headers), domain_list=other_domains_list, companies_uu_id_list=companies_uu_id_list, companies_id_list=companies_id_list, duty_uu_id_list=duty_uu_id_list, duty_id_list=duty_id_list, ).model_dump() - employee_uuid = str(companies_list[0]["uu_id"]) - print('employee_uuid', employee_uuid) set_to_redis_dict = dict( - user=found_user, token=model_value, add_uuid=employee_uuid, + user=found_user, token=model_value, header_info=dict(language=headers.language, domain=headers.domain, timezone=headers.timezone), ) user_dict = found_user.get_dict() person_dict = found_user.person.get_dict() - if access_token := RedisHandlers().set_object_to_redis(**set_to_redis_dict): + if access_token := redis_handler.set_object_to_redis(**set_to_redis_dict): return { "access_token": access_token, "user_type": UserType.employee.name, @@ -166,12 +167,15 @@ class LoginHandler: language = headers.request.headers.get("language", "tr") domain = headers.request.headers.get("domain", None) timezone = headers.request.headers.get("tz", None) or "GMT+3" + BuildLivingSpace.set_session(db_session) BuildParts.set_session(db_session) OccupantTypes.set_session(db_session) user_handler = UserHandlers() found_user = user_handler.check_user_exists(access_key=data.access_key, db_session=db_session) other_domains_list, main_domain = [], "" + redis_handler = RedisHandlers() + with mongo_handler.collection(f"{str(found_user.related_company)}*Domain") as collection: result = collection.find_one({"user_uu_id": str(found_user.uu_id)}) if not result: @@ -189,6 +193,10 @@ class LoginHandler: if not living_spaces: raise ValueError("EYS_0006") + + user_dict = found_user.get_dict() + person_dict = found_user.person.get_dict() + for living_space in living_spaces: build_part = BuildParts.query.filter(BuildParts.id == living_space.build_parts_id).first() if not build_part: @@ -197,28 +205,40 @@ class LoginHandler: build = build_part.buildings occupant_type = OccupantTypes.query.filter(OccupantTypes.id == living_space.occupant_type_id).first() occupant_data = { - "build_living_space_uu_id": str(living_space.uu_id), "part_uu_id": str(build_part.uu_id), "part_name": build_part.part_name(), "part_level": build_part.part_level, - "occupant_uu_id": str(occupant_type.uu_id), "description": occupant_type.occupant_description, "code": occupant_type.occupant_code, + "build_living_space_uu_id": str(living_space.uu_id), "part_uu_id": str(build_part.uu_id), "part_name": build_part.part_name(db=db_session), + "part_level": build_part.part_level, "occupant_uu_id": str(occupant_type.uu_id), "description": occupant_type.occupant_description, + "code": occupant_type.occupant_code, } build_key = str(build.uu_id) if build_key not in occupants_selection_dict: - occupants_selection_dict[build_key] = {"build_uu_id": build_key, "build_name": build.build_name, "build_no": build.build_no, "occupants": [occupant_data],} + occupants_selection_dict[build_key] = {"build_uu_id": build_key, "build_name": build.build_name, "build_no": build.build_no, "occupants": [occupant_data]} else: occupants_selection_dict[build_key]["occupants"].append(occupant_data) person = found_user.person model_value = OccupantTokenObject( user_type=UserType.occupant.value, user_uu_id=str(found_user.uu_id), user_id=found_user.id, person_id=person.id, - person_uu_id=str(person.uu_id), domain_list=other_domains_list, request=dict(request.headers), available_occupants=occupants_selection_dict, + person_uu_id=str(person.uu_id), domain_list=other_domains_list, request=dict(headers.request.headers), available_occupants=occupants_selection_dict, ).model_dump() - redis_handler = RedisHandlers() - if access_token := redis_handler.set_object_to_redis( - user=found_user, token=model_value, add_uuid=living_space.uu_id, - header_info=dict(language=language, domain=domain, timezone=timezone) - ): - return {"access_token": access_token, "user_type": UserType.occupant.name, "selection_list": occupants_selection_dict} - raise ValueError("Something went wrong") + + set_redis_dict = dict(user=found_user, token=model_value, header_info=dict(language=language, domain=domain, timezone=timezone)) + if access_token := redis_handler.set_object_to_redis(**set_redis_dict): + return { + "access_token": access_token, + "user_type": UserType.occupant.name, + "user": { + "uuid": user_dict["uu_id"], "avatar": user_dict["avatar"], "email": user_dict["email"], "phone_number": user_dict["phone_number"], "user_tag": user_dict["user_tag"], + "password_expiry_begins": str(arrow.get(user_dict["password_expiry_begins"]).shift(days=int(user_dict["password_expires_day"]))), + "person": { + "uuid": person_dict["uu_id"], "firstname": person_dict["firstname"], "surname": person_dict["surname"], + "middle_name": person_dict["middle_name"], "sex_code": person_dict["sex_code"], "person_tag": person_dict["person_tag"], + "country_code": person_dict["country_code"], "birth_date": person_dict["birth_date"], + }, + }, + "selection_list": occupants_selection_dict, + } + raise ValueError("Something went wrong") @classmethod def authentication_login_with_domain_and_creds(cls, headers: CommonHeaders, data: Any): @@ -264,10 +284,12 @@ class LoginHandler: with Users.new_session() as db_session: if data.uuid not in token_dict.companies_uu_id_list: ValueError("EYS_0011") + list_of_returns = ( - Employees.id, Employees.uu_id, People.id, People.uu_id, Users.id, Users.uu_id, Companies.id, Companies.uu_id, - Departments.id, Departments.uu_id, Duty.id, Duty.uu_id, Addresses.id, Addresses.letter_address, Staff.id, Staff.uu_id, - Duties.id, Duties.uu_id, + Employees.id, Employees.uu_id, People.id, People.uu_id, Users.id, Users.uu_id, Companies.id, Companies.uu_id, Companies.public_name, Companies.company_type, + Departments.id, Departments.uu_id, Duty.id, Duty.uu_id, Addresses.id, Addresses.letter_address, Staff.id, Staff.uu_id, Duty.duty_name, + Duties.id, Duties.uu_id, BuildParts.id, BuildParts.uu_id, BuildParts.part_name, BuildParts.part_level, BuildParts.part_code, + OccupantTypes.id, OccupantTypes.uu_id, OccupantTypes.occupant_type, OccupantTypes.occupant_description, Addresses.letter_address ) selected_company_query = db_session.query(*list_of_returns @@ -298,82 +320,76 @@ class LoginHandler: filter_endpoints_and_events = db_session.query(EndpointRestriction.operation_uu_id, Events.function_code ).join(EndpointRestriction, EndpointRestriction.id == Events.endpoint_id).filter().all() reachable_event_codes = {endpoint_name: function_code for endpoint_name, function_code in filter_endpoints_and_events} + # Get reachable applications reachable_app_codes = Application2Employee.get_application_codes(employee_id=int(result_with_keys_dict['Employees.id']), db=db_session) - company_token = CompanyToken( - company_uu_id=str(result_with_keys_dict['Companies.uu_id']), - company_id=int(result_with_keys_dict['Companies.id']), - department_id=int(result_with_keys_dict['Departments.id']), - department_uu_id=str(result_with_keys_dict['Departments.uu_id']), - duty_id=int(result_with_keys_dict['Duty.id']), - duty_uu_id=str(result_with_keys_dict['Duty.uu_id']), - bulk_duties_id=int(result_with_keys_dict['Duties.id']), - staff_id=int(result_with_keys_dict['Staff.id']), - staff_uu_id=str(result_with_keys_dict['Staff.uu_id']), - employee_id=int(result_with_keys_dict['Employees.id']), - employee_uu_id=str(result_with_keys_dict['Employees.uu_id']), - reachable_event_codes=reachable_event_codes, - reachable_app_codes=reachable_app_codes, - ) + add_company = { + "uu_id": str(result_with_keys_dict["Employees.uu_id"]), + "public_name": result_with_keys_dict["Companies.public_name"], + "company_type": result_with_keys_dict["Companies.company_type"], + "company_address": result_with_keys_dict["Addresses.letter_address"], + "duty": result_with_keys_dict["Duty.duty_name"], + "company_uuid": str(result_with_keys_dict["Companies.uu_id"]) + } redis_handler = RedisHandlers() - redis_result = redis_handler.update_token_at_redis( - token=access_token, add_payload=company_token, add_uuid=str(result_with_keys_dict['Employees.uu_id']) - ) + user_uu_id = Users.query.filter(Users.person_id == result_with_keys_dict['People.id']).first().uu_id + redis_result = redis_handler.update_token_at_redis(token=access_token, add_payload=add_company, user_uuid=user_uu_id) return {"selected_uu_id": data.uuid} @classmethod def handle_occupant_selection(cls, access_token: str, data: Any, token_dict: TokenDictType): """Handle occupant type selection""" with BuildLivingSpace.new_session() as db: - # Get selected occupant type - selected_build_living_space: BuildLivingSpace = BuildLivingSpace.filter_one(BuildLivingSpace.uu_id == data.build_living_space_uu_id, db=db).data - if not selected_build_living_space: + BuildLivingSpace.set_session(db) + BuildParts.set_session(db) + Users.set_session(db) + + list_of_returns = ( + BuildLivingSpace.id, BuildLivingSpace.uu_id, OccupantTypes.id, OccupantTypes.uu_id, OccupantTypes.occupant_type, BuildParts.id, BuildParts.uu_id, Build.id, Build.uu_id, + BuildParts.id, BuildParts.part_level, OccupantTypes.occupant_description, OccupantTypes.occupant_code, People.id, People.uu_id + ) + + selected_build_living_space_query = db.query(*list_of_returns + ).join(OccupantTypes, OccupantTypes.id == BuildLivingSpace.occupant_type_id + ).join(BuildParts, BuildParts.id == BuildLivingSpace.build_parts_id + ).join(Build, Build.id == BuildParts.build_id + ).join(People, People.id == BuildLivingSpace.person_id + ).filter(BuildLivingSpace.uu_id == data.uuid) + + selected_build_living_space_first = selected_build_living_space_query.first() + if not selected_build_living_space_first: raise ValueError("EYS_0012") + + result_with_keys_dict = {} + for ix, selected_build_living_space_item in enumerate(selected_build_living_space_first): + result_with_keys_dict[str(list_of_returns[ix])] = selected_build_living_space_item - # Get reachable events - reachable_event_codes = Event2Occupant.get_event_codes(build_living_space_id=selected_build_living_space.id, db=db) - occupant_type = OccupantTypes.filter_one_system(OccupantTypes.id == selected_build_living_space.occupant_type_id, db=db).data - build_part = BuildParts.filter_one(BuildParts.id == selected_build_living_space.build_parts_id, db=db) - build = build_part.buildings - reachable_app_codes = Application2Occupant.get_application_codes(build_living_space_id=selected_build_living_space.id, db=db) - # responsible_employee = Employees.filter_one( - # Employees.id == build_part.responsible_employee_id, - # db=db, - # ).data - # related_company = RelationshipEmployee2Build.filter_one( - # RelationshipEmployee2Build.member_id == build.id, - # db=db, - # ).data - # Get company - # company_related = Companies.filter_one( - # Companies.id == related_company.company_id, - # db=db, - # ).data + filter_endpoints_and_events = db.query(EndpointRestriction.operation_uu_id, Events.function_code + ).join(EndpointRestriction, EndpointRestriction.id == Events.endpoint_id).filter().all() + reachable_event_codes = {endpoint_name: function_code for endpoint_name, function_code in filter_endpoints_and_events} - # Create occupant token - occupant_token = OccupantToken( - living_space_id=selected_build_living_space.id, - living_space_uu_id=selected_build_living_space.uu_id.__str__(), - occupant_type_id=occupant_type.id, - occupant_type_uu_id=occupant_type.uu_id.__str__(), - occupant_type=occupant_type.occupant_type, - build_id=build.id, - build_uuid=build.uu_id.__str__(), - build_part_id=build_part.id, - build_part_uuid=build_part.uu_id.__str__(), - # responsible_employee_id=responsible_employee.id, - # responsible_employee_uuid=responsible_employee.uu_id.__str__(), - # responsible_company_id=company_related.id, - # responsible_company_uuid=company_related.uu_id.__str__(), - reachable_event_codes=reachable_event_codes, - reachable_app_codes=reachable_app_codes, - ) + # Get reachable applications + reachable_app_codes = Application2Occupant.get_application_codes(build_living_space_id=selected_build_living_space_first.id, db=db) + + build_part = BuildParts.query.filter(BuildParts.id == result_with_keys_dict['BuildParts.id']).first() + if not build_part: + raise ValueError("EYS_0013") + + add_build_living_space = { + "build_living_space_uu_id": str(data.uuid), + "part_uu_id": str(result_with_keys_dict['BuildParts.uu_id']), + "part_name": build_part.part_name(db=db), + "part_level": result_with_keys_dict['BuildParts.part_level'], + "occupant_uu_id": str(result_with_keys_dict['OccupantTypes.uu_id']), + "description": result_with_keys_dict['OccupantTypes.occupant_description'], + "code": result_with_keys_dict['OccupantTypes.occupant_code'] + } redis_handler = RedisHandlers() - redis_handler.update_token_at_redis( - token=access_token, add_payload=occupant_token, add_uuid=occupant_token.living_space_uu_id - ) - return {"selected_uu_id": occupant_token.living_space_uu_id} + + user_uu_id = Users.query.filter(Users.person_id == result_with_keys_dict['People.id']).first().uu_id + redis_handler.update_token_at_redis(token=access_token, add_payload=add_build_living_space, user_uuid=user_uu_id) + return {"selected_uu_id": data.uuid} @classmethod def authentication_select_company_or_occupant_type(cls, request: Any, data: Any): @@ -469,3 +485,30 @@ class AuthHandlers: LoginHandler: LoginHandler = LoginHandler() PasswordHandler: PasswordHandler = PasswordHandler() + + +# Get selected occupant type +# selected_build_living_space: BuildLivingSpace = BuildLivingSpace.filter_one(BuildLivingSpace.uu_id == data.build_living_space_uu_id, db=db).data +# if not selected_build_living_space: +# raise ValueError("EYS_0012") + +# occupant_type = OccupantTypes.filter_one_system(OccupantTypes.id == selected_build_living_space.occupant_type_id, db=db).data +# build_part = BuildParts.filter_one(BuildParts.id == selected_build_living_space.build_parts_id, db=db) +# build = build_part.buildings +# reachable_app_codes = Application2Occupant.get_application_codes(build_living_space_id=selected_build_living_space.id, db=db) +# responsible_employee = Employees.filter_one( +# Employees.id == build_part.responsible_employee_id, +# db=db, +# ).data +# related_company = RelationshipEmployee2Build.filter_one( +# RelationshipEmployee2Build.member_id == build.id, +# db=db, +# ).data +# Get company +# company_related = Companies.filter_one( +# Companies.id == related_company.company_id, +# db=db, +# ).data + +# Get reachable events +# reachable_event_codes = Event2Occupant.get_event_codes(build_living_space_id=selected_build_living_space.id, db=db) \ No newline at end of file diff --git a/ServicesApi/Builds/Auth/validations/request/auth/validations.py b/ServicesApi/Builds/Auth/validations/request/auth/validations.py index 0d22e37..17378f1 100644 --- a/ServicesApi/Builds/Auth/validations/request/auth/validations.py +++ b/ServicesApi/Builds/Auth/validations/request/auth/validations.py @@ -14,7 +14,7 @@ class RequestVerifyOTP(BaseModel): otp: str -class RequestSelectEmployee(BaseModel): +class RequestSelect(BaseModel): uuid: str @@ -23,10 +23,6 @@ class RequestResetPassword(BaseModel): password: str re_password: str - -class RequestSelectLiving(BaseModel): - uuid: str - class RequestCreatePassword(BaseModel): password_token: str password: str diff --git a/ServicesApi/Builds/Identity/events/people/flat_tenant.py b/ServicesApi/Builds/Identity/events/people/flat_tenant.py new file mode 100644 index 0000000..5784c89 --- /dev/null +++ b/ServicesApi/Builds/Identity/events/people/flat_tenant.py @@ -0,0 +1,58 @@ +from typing import Any + +from Initializer.event_clusters import Event +from Validations.response import ( + PaginateOnly, + Pagination, + PaginationResult, + PostgresResponseSingle, + PostgresResponse, + EndpointResponse +) +from Validations.defaults.validations import CommonHeaders +from Schemas import People +from Extensions.Middlewares.token_provider import TokenProvider + + +# List all people endpoint Flat Tenant +FlatTenantPeopleListEvent = Event( + name="flat_tenant_people_list", + key="7cb248d3-d75a-4d28-8be5-f147089ce654", + request_validator=None, # TODO: Add request validator + response_validator=None, # TODO: Add response validator + description="Flat Tenant People List all flat tenant users endpoint", +) + +class FlatTenantPeopleListPydantic: + ... + + + +def flat_tenant_people_list_callable(list_options: PaginateOnly, header: CommonHeaders): + list_options = PaginateOnly(**list_options.model_dump()) + token_object = TokenProvider.get_dict_from_redis(token=header.token) + if not token_object.is_occupant: + raise Exception("Forbidden for employees") + + pagination_query = {} + if list_options.query: + pagination_query = FlatTenantPeopleListPydantic(**list_options.query) + + with People.new_session() as db_session: + People.set_session(db_session) + if pagination_query: + people_list = People.query.filter( + *People.convert(pagination_query), + People.build_parts_id == token_object.selected_occupant.build_id + ) + else: + people_list = People.query.filter( + People.build_parts_id == token_object.selected_occupant.build_id + ) + pagination = Pagination(data=people_list) + pagination.change(**list_options.model_dump()) + pagination_result = PaginationResult(data=people_list, pagination=pagination, response_model=FlatTenantPeopleListPydantic) + return EndpointResponse(message="MSG0003-LIST", pagination_result=pagination_result).response + + +FlatTenantPeopleListEvent.event_callable = flat_tenant_people_list_callable diff --git a/ServicesApi/Extensions/Middlewares/token_provider.py b/ServicesApi/Extensions/Middlewares/token_provider.py index e35fed1..85c1dc7 100644 --- a/ServicesApi/Extensions/Middlewares/token_provider.py +++ b/ServicesApi/Extensions/Middlewares/token_provider.py @@ -36,6 +36,7 @@ class TokenProvider: """ token_to_use, user_uu_id_to_use = token or "*", user_uu_id or "*" list_of_token_dict, auth_key_list = [], [cls.AUTH_TOKEN, token_to_use, user_uu_id_to_use] + print("auth_key_list", auth_key_list) if token: result = RedisActions.get_json(list_keys=auth_key_list, limit=1) if first_record := result.first: @@ -56,7 +57,8 @@ class TokenProvider: Retrieve token object from Redis using token and user_uu_id """ token_to_use, user_uu_id_to_use = token or "*", user_uu_id or "*" - list_of_token_dict, auth_key_list = [], [cls.AUTH_TOKEN, token_to_use, user_uu_id_to_use, "*"] + list_of_token_dict, auth_key_list = [], [cls.AUTH_TOKEN, token_to_use, user_uu_id_to_use] + print("auth_key_list", auth_key_list) if token: result = RedisActions.get_json(list_keys=auth_key_list, limit=1) if first_record := result.first: diff --git a/ServicesApi/Extensions/OnMemory/redis_handlers.py b/ServicesApi/Extensions/OnMemory/redis_handlers.py index e2a7156..36ebaf7 100644 --- a/ServicesApi/Extensions/OnMemory/redis_handlers.py +++ b/ServicesApi/Extensions/OnMemory/redis_handlers.py @@ -33,7 +33,7 @@ class RedisHandlers: @classmethod def get_object_from_redis(cls, access_token: str) -> TokenDictType: - redis_response = RedisActions.get_json(list_keys=[cls.AUTH_TOKEN, access_token, "*", "*"]) + redis_response = RedisActions.get_json(list_keys=[cls.AUTH_TOKEN, access_token, "*"]) if not redis_response.status: raise ValueError("EYS_0001") if redis_object := redis_response.first: @@ -41,30 +41,27 @@ class RedisHandlers: raise ValueError("EYS_0002") @classmethod - def set_object_to_redis(cls, user: Users, token, header_info, add_uuid: str): - result_delete = RedisActions.delete(list_keys=[cls.AUTH_TOKEN, "*", str(user.uu_id), add_uuid]) + def set_object_to_redis(cls, user: Users, token, header_info): + result_delete = RedisActions.delete(list_keys=[cls.AUTH_TOKEN, "*", str(user.uu_id)]) generated_access_token = PasswordModule.generate_access_token() keys = [cls.AUTH_TOKEN, generated_access_token, str(user.uu_id)] - if add_uuid: - keys.append(add_uuid) - RedisActions.set_json(list_keys=keys, value={**token, **header_info}, expires={"hours": 1, "minutes": 30}) - return generated_access_token RedisActions.set_json(list_keys=keys, value={**token, **header_info}, expires={"hours": 1, "minutes": 30}) return generated_access_token @classmethod - def update_token_at_redis(cls, token: str, add_payload: Union[CompanyToken, OccupantToken], add_uuid: str): - if already_token_data := RedisActions.get_json(list_keys=[cls.AUTH_TOKEN, token, '*', add_uuid]).first: + def update_token_at_redis(cls, token: str, add_payload: Union[dict], user_uuid: str): + list_keys = [cls.AUTH_TOKEN, token, "*"] + print("user_uuid", user_uuid, "add_payload", add_payload) + if not user_uuid: + raise ValueError("User UUID not found") + if already_token_data := RedisActions.get_json(list_keys=list_keys).first: already_token = cls.process_redis_object(already_token_data) - if already_token.is_employee and isinstance(add_payload, CompanyToken): + if already_token.is_employee: already_token.selected_company = add_payload - list_keys = [cls.AUTH_TOKEN, token, str(already_token.user_uu_id), str(add_uuid)] - print('is_employee: ', list_keys) - elif already_token.is_occupant and isinstance(add_payload, OccupantToken): + elif already_token.is_occupant: already_token.selected_occupant = add_payload - list_keys = [cls.AUTH_TOKEN, token, str(already_token.user_uu_id), str(add_uuid)] - print('is_occupant: ', list_keys) + list_keys = [cls.AUTH_TOKEN, token, str(user_uuid)] + print("already_token", already_token) result = RedisActions.set_json(list_keys=list_keys, value=already_token.model_dump(), expires={"hours": 1, "minutes": 30}) - RedisActions.delete(list_keys=[cls.AUTH_TOKEN, token, str(already_token.user_uu_id)]) return result.first raise ValueError("Something went wrong") diff --git a/ServicesApi/Schemas/building/build.py b/ServicesApi/Schemas/building/build.py index 9fd3eb0..5ae81c2 100644 --- a/ServicesApi/Schemas/building/build.py +++ b/ServicesApi/Schemas/building/build.py @@ -238,9 +238,14 @@ class Build(CrudCollection): building_types = None for part in self.parts: building_types = {} - build_type = BuildTypes.filter_by_one( - system=True, id=part.build_part_type_id, db=db_session - ).data + build_type = BuildTypes.query.filter( + BuildTypes.id == part.build_part_type_id + ).first() + if not build_type: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail="There is no building type in this building.", + ) if build_type.type_code in building_types: building_types[build_type.type_code]["list"].append(part.part_no) else: @@ -327,9 +332,10 @@ class BuildParts(CrudCollection): ) def part_name(self, db): - if build_type := BuildTypes.filter_by_one( - system=True, id=self.part_type_id, db=db - ).data: + BuildTypes.set_session(db) + if build_type := BuildTypes.query.filter( + BuildTypes.id == self.part_type_id + ).first(): return f"{str(build_type.type_name).upper()} : {str(self.part_no).upper()}" return f"Undefined:{str(build_type.type_name).upper()}" diff --git a/ServicesApi/Schemas/event/event.py b/ServicesApi/Schemas/event/event.py index ec3f63e..a41e676 100644 --- a/ServicesApi/Schemas/event/event.py +++ b/ServicesApi/Schemas/event/event.py @@ -415,7 +415,8 @@ class Application2Employee(CrudCollection): applications = Applications.query.filter(Applications.id.in_([application.application_id for application in active_applications])).all() if extra_applications := Application2EmployeeExtra.query.filter(Application2EmployeeExtra.employee_id == employee_id).all(): applications_extra = Applications.query.filter(Applications.id.in_([application.application_id for application in extra_applications])).all() - applications.extend(applications_extra) + if applications_extra: + applications.extend(applications_extra) applications_dict = {} for application in applications: if not application.site_url in applications_dict: @@ -466,13 +467,6 @@ class Application2Occupant(CrudCollection): applications_extra = Applications.query.filter(Applications.id.in_([application.application_id for application in extra_applications])).all() applications.extend(applications_extra) applications_dict = {} - for application in applications: - if not application.site_url in applications_dict: - applications_dict[str(application.site_url)] = str(application.application_code) - else: - ValueError("Duplicate application code found for single endpoint") - applications.extend(applications_extra) - applications_dict = {} for application in applications: if not application.site_url in applications_dict: applications_dict[str(application.site_url)] = str(application.application_code) diff --git a/ServicesApi/Validations/token/validations.py b/ServicesApi/Validations/token/validations.py index 26ff579..bcab34a 100644 --- a/ServicesApi/Validations/token/validations.py +++ b/ServicesApi/Validations/token/validations.py @@ -89,7 +89,7 @@ class OccupantTokenObject(ApplicationToken): # Occupant Token Object -> Requires selection of the occupant type for a specific build part available_occupants: dict = None - selected_occupant: Optional[OccupantToken] = None # Selected Occupant Type + selected_occupant: Optional[dict] = None # Selected Occupant Type @property def is_employee(self) -> bool: @@ -109,7 +109,7 @@ class EmployeeTokenObject(ApplicationToken): duty_id_list: list[int] # List of duty objects duty_uu_id_list: list[str] # List of duty objects - selected_company: Optional[CompanyToken] = None # Selected Company Object + selected_company: Optional[dict] = None # Selected Company Object @property def is_employee(self) -> bool: diff --git a/ServicesWeb/customer/README.md b/ServicesWeb/customer/README.md index e215bc4..7b78ee1 100644 --- a/ServicesWeb/customer/README.md +++ b/ServicesWeb/customer/README.md @@ -1,36 +1,52 @@ -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +# Occupant Types -## Getting Started +Toplantı Başkanı Toplantı Başkanı MT-PRS Toplantı MT +Toplantı Katip Toplantıda tutanak tutan kişi MT-WRT Toplantı MT +Toplantı Katılımcısı Toplantıda sadece katılan kişi MT-ATT Toplantı MT +Toplantı Danışman Toplantıda danışmanlık yapan kişi MT-ADV Toplantı MT +Toplantı Seçilmiş Başkanı Toplantı Seçilmiş Başkanı MT-VPR Toplantı MT -First, run the development server: +Daire Sahibi Daire Sahibi FL-OWN Daire FL +Daire Kiracısı Daire Kiracısı FL-TEN Daire FL +Daire Sakini Daire Sakini FL-RES Daire FL +Daire Sakini Vekili Daire Sakini Vekili FL-REP Daire FL -```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev -``` +Bina Avukatı Bina Avukatı BU-ATT Bina BU +Bina Avukatı Yardımcısı Bina Avukatı Yardımcısı BU-ATA Bina BU +Bina Denetmen Yardımcısı Bina Denetmen Yardımcısı BU-SPA Bina BU +Bina Denetmeni Bina Denetmeni BU-SPV Bina BU +Bina Yönetici Yardımcısı Bina Yönetici Yardımcısı BU-MNA Bina BU +Bina Yöneticisi Bina Yöneticisi BU-MNG Bina BU +Bina Muhasabecisi Bina Muhasabecisi BU-ACC Bina BU -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +Proje Lideri Proje Lideri PRJ-LDR Proje PRJ +Proje Sorumlusu Proje Sorumlusu PRJ-RES Proje PRJ +Proje Ekibi Proje Ekibi PRJ-EMP Proje PRJ +Proje Finans Sorumlusu Proje Finans Sorumlusu PRJ-FIN Proje PRJ +Proje Teknik Sorumlusu Proje Teknik Sorumlusu PRJ-TEC Proje PRJ -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. +Bina Teknik Sorumlusu Bina Teknik Sorumlusu BU-TEC Bina BU +Bina Teknik Elemanı Bina Teknik Elemanı BU-EMP Bina BU +Bina Teknik Freelancer Bina Teknik Freelancer BU-FLC Bina BU -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. +Daire Mülkiyet Vekili Daire Mülkiyet Vekili FL-DEP Daire FL -## Learn More +# Employee Types -To learn more about Next.js, take a look at the following resources: +General Manager GM0001 General Manager +Business Manager BM0001 Business Manager +IT Manager IT0001 IT Manager +BULK BULK BULK RECORDS OF THE COMPANY +OCCUPANT OCCUPANT OCCUPANT RECORDS OF THE COMPANY +Database Manager DM Database Manager +Network Manager NM Network Manager +Application Manager AM Application Manager +Super User SUE Super User -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! +Daire Sakini Vekili Daire Sakini Vekili FL-REP Daire FL +URL Type Tested +/building/accounts/managment/accounts : flat_representative No -## Deploy on Vercel +/definitions/identifications/people : flat_tenant No -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. - -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/ServicesWeb/customer/src/app/api/context/dash/selection/route.ts b/ServicesWeb/customer/src/app/api/context/dash/selection/route.ts index 898c27e..2afe97a 100644 --- a/ServicesWeb/customer/src/app/api/context/dash/selection/route.ts +++ b/ServicesWeb/customer/src/app/api/context/dash/selection/route.ts @@ -1,6 +1,6 @@ import { getSelectionFromRedis, - setSelectionToRedis, + setActiveSelectionToRedis, } from "@/fetchers/custom/context/dash/selection/fetch"; import { AuthError } from "@/fetchers/types/context"; import { NextResponse } from "next/server"; @@ -43,7 +43,8 @@ export async function GET() { export async function POST(request: Request) { try { const selection = await request.json(); - await setSelectionToRedis(selection); + await setActiveSelectionToRedis(selection); + return NextResponse.json({ status: 200, data: selection || null, diff --git a/ServicesWeb/customer/src/app/api/login/email/route.ts b/ServicesWeb/customer/src/app/api/login/email/route.ts index ad9d6d9..ec2c013 100644 --- a/ServicesWeb/customer/src/app/api/login/email/route.ts +++ b/ServicesWeb/customer/src/app/api/login/email/route.ts @@ -1,5 +1,5 @@ import { NextResponse } from "next/server"; -import { loginViaAccessKeys } from "@/fetchers/custom/login/login"; +import { loginViaAccessKeys, initFirstSelection } from "@/fetchers/custom/login/login"; import { loginSchemaEmail } from "@/pages/single/auth/login/schemas"; export async function POST(req: Request): Promise { @@ -20,6 +20,7 @@ export async function POST(req: Request): Promise { } const userLogin = await loginViaAccessKeys(dataValidated); + await initFirstSelection(userLogin.data?.firstSelection, userLogin.data?.userType); if (userLogin.status === 200 || userLogin.status === 202) { return NextResponse.json({ status: 200, diff --git a/ServicesWeb/customer/src/app/api/login/logout/route.ts b/ServicesWeb/customer/src/app/api/login/logout/route.ts new file mode 100644 index 0000000..38217f5 --- /dev/null +++ b/ServicesWeb/customer/src/app/api/login/logout/route.ts @@ -0,0 +1,26 @@ +import { NextResponse } from "next/server"; +import { logoutActiveSession } from "@/fetchers/custom/login/login"; + +export async function GET(req: Request): Promise { + try { + const headers = req.headers; + const userLogin = await logoutActiveSession(); + if (userLogin.status === 200 || userLogin.status === 202) { + return NextResponse.json({ + status: 200, + message: "Logout successfully completed", + data: userLogin.data, + }); + } else { + return NextResponse.json({ + status: userLogin.status, + message: "Logout NOT successfully completed", + }); + } + } catch (error) { + return NextResponse.json({ + status: 401, + message: "Logout NOT successfully completed", + }); + } +} diff --git a/ServicesWeb/customer/src/components/custom/header/component.tsx b/ServicesWeb/customer/src/components/custom/header/component.tsx index 0a55458..da1e9c8 100644 --- a/ServicesWeb/customer/src/components/custom/header/component.tsx +++ b/ServicesWeb/customer/src/components/custom/header/component.tsx @@ -1,9 +1,11 @@ 'use client'; +import { useRouter } from "next/navigation"; import { FC, useState, useEffect } from "react"; import { HeaderProps } from "@/validations/mutual/dashboard/props"; import { langGetKey } from "@/lib/langGet"; import { LanguageTypes } from "@/validations/mutual/language/validations"; import LanguageSelectionComponent from "@/components/mutual/languageSelection/component"; +import { apiGetFetcher } from "@/lib/fetcher"; const translations = { en: { @@ -34,30 +36,25 @@ const HeaderComponent: FC = ({ userData, userLoading, userError, refreshUser, updateUser }) => { const lang = onlineData?.lang as LanguageTypes || 'en'; + const router = useRouter(); + const [activeTab, setActiveTab] = useState('notifications'); const [isFullscreen, setIsFullscreen] = useState(false); useEffect(() => { - const handleFullscreenChange = () => { - setIsFullscreen(!!document.fullscreenElement); - }; - + const handleFullscreenChange = () => { setIsFullscreen(!!document.fullscreenElement) }; document.addEventListener('fullscreenchange', handleFullscreenChange); - return () => { - document.removeEventListener('fullscreenchange', handleFullscreenChange); - }; + return () => { document.removeEventListener('fullscreenchange', handleFullscreenChange) }; }, []); const toggleFullscreen = () => { - if (document.fullscreenElement) { - document.exitFullscreen(); - } else { - document.documentElement.requestFullscreen().catch(err => { - console.error(`Error attempting to enable fullscreen: ${err.message}`); - }); + if (document.fullscreenElement) { document.exitFullscreen() } else { + document.documentElement.requestFullscreen().catch(err => { console.error(`Error attempting to enable fullscreen: ${err.message}`) }); } }; + const logoutSession = () => { apiGetFetcher({ url: '/api/login/logout', isNoCache: true }).then((logoutSession) => { router.push('/auth/login') }) } + return (
}> diff --git a/ServicesWeb/customer/src/components/custom/menu/renderOneClientSelection.tsx b/ServicesWeb/customer/src/components/custom/menu/renderOneClientSelection.tsx index 413638d..458e700 100644 --- a/ServicesWeb/customer/src/components/custom/menu/renderOneClientSelection.tsx +++ b/ServicesWeb/customer/src/components/custom/menu/renderOneClientSelection.tsx @@ -2,32 +2,44 @@ import { FC } from "react"; import { Briefcase } from "lucide-react"; - interface Props { item: any; - isSelected: boolean; - onClickHandler: (item: any) => void; + selectedItem: any; + refreshSelection: () => Promise; + updateSelection: (newSelection: any) => Promise; } -const RenderOneClientSelection: FC = ({ item, isSelected, onClickHandler }) => { - if (isSelected) { +const selectFromSelectionList = (item: any, selectedItem: any, updateSelection: (newSelection: any) => Promise, refreshSelection: () => Promise) => { + const selectedUUID = selectedItem?.uu_id || selectedItem?.build_living_space_uu_id; + const itemUUID = item?.uu_id || item?.build_living_space_uu_id; + if (selectedUUID !== itemUUID) { updateSelection(item); refreshSelection() } +} + +const RenderOneClientSelection: FC = ({ item, selectedItem, updateSelection, refreshSelection }) => { + const selectedUUID = selectedItem?.uu_id || selectedItem?.build_living_space_uu_id; + const itemUUID = item?.uu_id || item?.build_living_space_uu_id; + const getDisplayName = () => { if (item.public_name) return item.public_name; if (item.part_name) return item.part_name; return "No Name" }; + const getDescription = () => { if (item.duty) return item.duty; if (item.description) return item.description; if (item.code) return item.code; return "" }; + const getInitials = () => { const name = getDisplayName(); return name.slice(0, 2) }; + + if (selectedUUID !== itemUUID) { return ( -
{ onClickHandler(item) }} +
{ selectFromSelectionList(item, selectedItem, updateSelection, refreshSelection) }} className="w-full text-xs bg-white shadow rounded-lg overflow-hidden transition-all hover:shadow-md mb-2 cursor-pointer"> -
+
-
- {item.avatar ? (Company) : - (
{(item.public_name || "No Name").slice(0, 2)}
)} +
+ {item.avatar ? (Occupant) : + (
{getInitials()}
)}
-
- +
+
-

{item.public_name} {item.company_type}

-

{item.duty}

+

{getDisplayName()} {item.company_type || ''}

+

{getDescription()}

@@ -35,21 +47,21 @@ const RenderOneClientSelection: FC = ({ item, isSelected, onClickHandler ) } return ( -
-
+
+
-
- {item.avatar ? (Company) : - (
{(item.duty || "No Duty").slice(0, 2)}
)} +
+ {item.avatar ? (Occupant) : + (
{getInitials()}
)}
-
- +
+
-

{item.public_name} {item.company_type}

-

{item.duty}

+

{getDisplayName()} {item.company_type || ''}

+

{getDescription()}

diff --git a/ServicesWeb/customer/src/components/custom/menu/userProfileSection.tsx b/ServicesWeb/customer/src/components/custom/menu/userProfileSection.tsx index a833251..95a5e98 100644 --- a/ServicesWeb/customer/src/components/custom/menu/userProfileSection.tsx +++ b/ServicesWeb/customer/src/components/custom/menu/userProfileSection.tsx @@ -1,15 +1,29 @@ 'use client'; import { FC } from "react"; -import { ClientUser } from "@/types/mutual/context/validations"; -import { ClientOnline } from "@/types/mutual/context/validations"; +import { ClientUser } from "@/types/mutual/context"; +import { ClientOnline } from "@/types/mutual/context"; +import { ClientSelection } from "@/types/mutual/context"; interface UserProfileSectionProps { userData: ClientUser | null; onlineData: ClientOnline | null; + selectionData: ClientSelection; } -const UserProfileSection: FC = ({ userData, onlineData }) => { +const UserProfileSection: FC = ({ userData, onlineData, selectionData }) => { + console.log("selectionData", selectionData) + if (!selectionData?.activeSelection) return null; + let selectionDefinitionFirst = ""; + let selectionDefinitionSecond = ""; + if (selectionData.activeSelection?.description && selectionData.activeSelection?.part_name) { + selectionDefinitionFirst = selectionData?.activeSelection?.description || "No selection"; + selectionDefinitionSecond = selectionData?.activeSelection?.part_name || "No selection"; + } else { + selectionDefinitionFirst = selectionData?.activeSelection?.public_name || "No selection"; + selectionDefinitionSecond = selectionData?.activeSelection?.duty || "No selection"; + } + if (!userData) return null; return (
@@ -26,7 +40,8 @@ const UserProfileSection: FC = ({ userData, onlineData

{userData?.person ? `${userData.person.firstname} ${userData.person.surname}` : 'User'}

{userData?.email || 'No email'}

-

{onlineData?.userType || 'guest'}

+

{selectionDefinitionFirst}

+

{selectionDefinitionSecond || ''}

diff --git a/ServicesWeb/customer/src/fetchers/custom/context/dash/selection/fetch.tsx b/ServicesWeb/customer/src/fetchers/custom/context/dash/selection/fetch.tsx index 558473e..ab5fd21 100644 --- a/ServicesWeb/customer/src/fetchers/custom/context/dash/selection/fetch.tsx +++ b/ServicesWeb/customer/src/fetchers/custom/context/dash/selection/fetch.tsx @@ -3,6 +3,7 @@ import { redis } from "@/lib/redis"; import { functionRetrieveUserSelection } from "@/fetchers/fecther"; import { ClientSelection, AuthError } from "@/fetchers/types/context"; import { getCompleteFromRedis, setCompleteToRedis } from "@/fetchers/custom/context/complete/fetch"; +import { loginSelectEmployee, loginSelectOccupant } from "@/fetchers/custom/login/login"; const getSelectionFromRedis = async (): Promise => { try { @@ -17,7 +18,7 @@ const getSelectionFromRedis = async (): Promise => { } catch (error) { return { selectionList: [], activeSelection: {} } } } -const setSelectionToRedis = async (selectionObject: ClientSelection) => { +const setActiveSelectionToRedis = async (selectionObject: any) => { try { const decrpytUserSelection = await functionRetrieveUserSelection() if (!decrpytUserSelection) throw new AuthError("No user selection found"); @@ -30,10 +31,19 @@ const setSelectionToRedis = async (selectionObject: ClientSelection) => { const oldData = await getCompleteFromRedis(); if (!oldData) throw new AuthError("No old data found in redis"); - await setCompleteToRedis({ ...oldData, selection: selectionObject }) + await setCompleteToRedis({ + ...oldData, selection: { + selectionList: oldData.selection.selectionList, + activeSelection: selectionObject + } + }) + if (oldData.online.userType.toUpperCase() === "EMPLOYEE") { + await loginSelectEmployee({ uuid: selectionObject.uuid }); + } else if (oldData.online.userType.toUpperCase() === "OCCUPANT") { + await loginSelectOccupant({ uuid: selectionObject.build_living_space_uu_id }); + } return true; } catch (error) { - // Re-throw AuthError instances, wrap other errors as AuthError if (error instanceof AuthError) { throw error; } else { @@ -42,4 +52,4 @@ const setSelectionToRedis = async (selectionObject: ClientSelection) => { } } -export { getSelectionFromRedis, setSelectionToRedis }; +export { getSelectionFromRedis, setActiveSelectionToRedis }; diff --git a/ServicesWeb/customer/src/fetchers/custom/login/login.tsx b/ServicesWeb/customer/src/fetchers/custom/login/login.tsx index 96d7212..ee22545 100644 --- a/ServicesWeb/customer/src/fetchers/custom/login/login.tsx +++ b/ServicesWeb/customer/src/fetchers/custom/login/login.tsx @@ -15,7 +15,7 @@ import { import { retrievePageList } from "@/fetchers/mutual/cookies/token"; import { deleteAllCookies } from "@/fetchers/mutual/cookies/cookie-actions"; import { setMenuToRedis } from "@/fetchers/custom/context/page/menu/fetch"; -import { LoginViaAccessKeys, LoginSelect, LoginSelectOccupant } from "@/fetchers/types/login/validations"; +import { LoginViaAccessKeys, LoginSelect } from "@/fetchers/types/login/validations"; async function logoutActiveSession() { const response = await fetchDataWithToken(urlLogoutEndpoint, {}, "GET", false); @@ -25,29 +25,50 @@ async function logoutActiveSession() { async function initRedis(loginRespone: any, firstSelection: any, accessToken: string, redisKey: string) { let alreadyAtRedis = null - try { - const redisData = await getCompleteFromRedis(); - alreadyAtRedis = redisData; - } catch (error) { } + console.log("loginRespone", loginRespone) + console.log("firstSelection", firstSelection) + console.log("accessToken", accessToken) + console.log("redisKey", redisKey) if (!alreadyAtRedis) { - const loginObjectToRedis = { - online: { - ...defaultValuesOnline, - lastLogin: new Date(), - userType: `${loginRespone.user_type}`.toUpperCase(), - lang: loginRespone.user.person.country_code.toLowerCase(), - }, - pageConfig: defaultValuesPageConfig, - menu: defaultValuesMenu, - header: defaultValuesHeader, - selection: { selectionList: loginRespone.selection_list, activeSelection: firstSelection }, - user: loginRespone.user, - settings: { lastOnline: new Date(), token: accessToken }, - chatRoom: [], - notifications: [], - messages: [], + if (loginRespone.user_type.toUpperCase() === "EMPLOYEE") { + const loginObjectToRedis = { + online: { ...defaultValuesOnline, lastLogin: new Date(), userType: `${loginRespone.user_type}`.toUpperCase(), lang: loginRespone.user.person.country_code.toLowerCase() }, + pageConfig: defaultValuesPageConfig, + menu: defaultValuesMenu, + header: defaultValuesHeader, + selection: { selectionList: loginRespone.selection_list, activeSelection: firstSelection }, + user: loginRespone.user, + settings: { lastOnline: new Date(), token: accessToken }, + chatRoom: [], + notifications: [], + messages: [], + } + await setNewCompleteToRedis(loginObjectToRedis, redisKey); + } else if (loginRespone.user_type.toUpperCase() === "OCCUPANT") { + const loginObjectToRedis = { + online: { ...defaultValuesOnline, lastLogin: new Date(), userType: `${loginRespone.user_type}`.toUpperCase(), lang: "tr" }, + pageConfig: defaultValuesPageConfig, + menu: defaultValuesMenu, + header: defaultValuesHeader, + selection: { selectionList: loginRespone.selection_list, activeSelection: firstSelection }, + user: loginRespone.user, + settings: { lastOnline: new Date(), token: accessToken }, + chatRoom: [], + notifications: [], + messages: [], + } + await setNewCompleteToRedis(loginObjectToRedis, redisKey); } - await setNewCompleteToRedis(loginObjectToRedis, redisKey); + } +} + +async function initFirstSelection(firstSelection: any, userType: string) { + if (userType === "EMPLOYEE") { + const uuid = firstSelection.uuid; + await loginSelectEmployee({ uuid }); + } else if (userType === "OCCUPANT") { + const uuid = firstSelection.build_living_space_uu_id; + await loginSelectOccupant({ uuid }); } } @@ -68,22 +89,24 @@ async function loginViaAccessKeys(payload: LoginViaAccessKeys) { if (response.status === 200 || response.status === 202) { const loginRespone: any = response?.data; - const firstSelection = loginRespone.selection_list.find((item: any) => item.uu_id === loginRespone.selection_list[0].uu_id); + let firstSelection = null + + if (loginRespone.user_type.toUpperCase() === "EMPLOYEE") { + firstSelection = loginRespone.selection_list.find((item: any) => item.uu_id === loginRespone.selection_list[0].uu_id); + } else if (loginRespone.user_type.toUpperCase() === "OCCUPANT") { + const firstKeyOfSelectionList = Object.keys(loginRespone.selection_list)[0]; + firstSelection = loginRespone.selection_list[firstKeyOfSelectionList].occupants[0]; + } const nextCrypto = new NextCrypto(tokenSecret); const accessToken = await nextCrypto.encrypt(loginRespone.access_token); - - const redisKey = `CLIENT:${loginRespone.user_type.toUpperCase()}:${firstSelection.uu_id}`; + const userType = loginRespone.user_type.toUpperCase() + const redisKey = `CLIENT:${userType}:${loginRespone.user.uuid}`; const redisKeyAccess = await nextCrypto.encrypt(redisKey); - const usersSelection = await nextCrypto.encrypt( - JSON.stringify({ - selected: firstSelection.uu_id, - userType: loginRespone.user_type.toUpperCase(), - redisKey, - }) - ); + const usersSelection = await nextCrypto.encrypt(JSON.stringify({ selected: firstSelection, userType, redisKey })); await initRedis(loginRespone, firstSelection, accessToken, redisKey); + cookieStore.set({ name: "eys-zzz", value: accessToken, @@ -99,12 +122,16 @@ async function loginViaAccessKeys(payload: LoginViaAccessKeys) { value: usersSelection, ...cookieObject, }); + try { return { completed: true, message: "Login successful", status: 200, - data: loginRespone, + data: { + userType, + firstSelection, + }, }; } catch (error) { console.error("JSON parse error:", error); @@ -112,7 +139,10 @@ async function loginViaAccessKeys(payload: LoginViaAccessKeys) { completed: false, message: "Login NOT successful", status: 401, - data: "{}", + data: { + userType, + firstSelection, + }, }; } } @@ -135,65 +165,32 @@ async function loginViaAccessKeys(payload: LoginViaAccessKeys) { } async function loginSelectEmployee(payload: LoginSelect) { - const cookieStore = await cookies(); - const nextCrypto = new NextCrypto(tokenSecret); const employeeUUID = payload.uuid; - const redisKey = `CLIENT:EMPLOYEE:${employeeUUID}`; const selectResponse: any = await fetchDataWithToken(urlLoginSelectEndpoint, { uuid: employeeUUID }, "POST", false); - cookieStore.delete({ name: "eys-sel", ...cookieObject }); - + console.log("selectResponse", selectResponse) if (selectResponse.status === 200 || selectResponse.status === 202) { - const usersSelection = await nextCrypto.encrypt( - JSON.stringify({ - selected: employeeUUID, - userType: "employee", - redisKey, - }) - ); - cookieStore.set({ - name: "eys-sel", - value: usersSelection, - ...cookieObject, - }); try { - const pageList = await retrievePageList() - await setMenuToRedis({ - selectionList: pageList, - activeSelection: "/dashboard" - }) + console.log("selectResponse", selectResponse) } catch (error) { } } return selectResponse; } -async function loginSelectOccupant(payload: LoginSelectOccupant) { +async function loginSelectOccupant(payload: LoginSelect) { const livingSpaceUUID = payload.uuid; - const cookieStore = await cookies(); - const nextCrypto = new NextCrypto(tokenSecret); - const selectResponse: any = await fetchDataWithToken(urlLoginSelectEndpoint, { uuid: livingSpaceUUID }, "POST", false); - const redisKey = `CLIENT:OCCUPANT:${livingSpaceUUID}`; - cookieStore.delete("eys-sel"); - + console.log("selectResponse", selectResponse) if (selectResponse.status === 200 || selectResponse.status === 202) { - const usersSelection = await nextCrypto.encrypt( - JSON.stringify({ - selected: livingSpaceUUID, - userType: "OCCUPANT", - redisKey, - }) - ); - cookieStore.set({ - name: "eys-sel", - value: usersSelection, - ...cookieObject, - }); + try { + console.log("selectResponse", selectResponse) + } catch (error) { } } return selectResponse; } export { loginViaAccessKeys, + initFirstSelection, loginSelectEmployee, loginSelectOccupant, logoutActiveSession, diff --git a/ServicesWeb/customer/src/fetchers/types/login/validations.ts b/ServicesWeb/customer/src/fetchers/types/login/validations.ts index d634ee9..b0deddc 100644 --- a/ServicesWeb/customer/src/fetchers/types/login/validations.ts +++ b/ServicesWeb/customer/src/fetchers/types/login/validations.ts @@ -8,8 +8,4 @@ interface LoginSelect { uuid: string; } -interface LoginSelectOccupant { - uuid: any; -} - -export type { LoginViaAccessKeys, LoginSelect, LoginSelectOccupant }; +export type { LoginViaAccessKeys, LoginSelect }; diff --git a/ServicesWeb/customer/src/pages/multi/index.ts b/ServicesWeb/customer/src/pages/multi/index.ts index f9c65c5..c29f415 100644 --- a/ServicesWeb/customer/src/pages/multi/index.ts +++ b/ServicesWeb/customer/src/pages/multi/index.ts @@ -1,10 +1,7 @@ import { DashboardPage } from "@/components/custom/content/DashboardPage"; const pageIndexMulti: Record>> = { - "/dashboard": { - DashboardPage: DashboardPage, - }, - // Add more pages as needed + "/dashboard": { DashboardPage: DashboardPage }, }; export { pageIndexMulti };