@platform-modules/foreign-ministry 1.3.336 → 1.3.337
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env +5 -11
- package/dist/auth/authenticate-jwt-session.d.ts +19 -0
- package/dist/auth/authenticate-jwt-session.js +35 -0
- package/dist/auth/jwt-token.helper.d.ts +18 -0
- package/dist/auth/jwt-token.helper.js +58 -0
- package/dist/auth/user-session-validation.d.ts +42 -0
- package/dist/auth/user-session-validation.js +95 -0
- package/dist/i18n/workflow-chat-i18n.json +41 -41
- package/dist/i18n/workflow-chat-message.builder.d.ts +9 -0
- package/dist/i18n/workflow-chat-message.builder.js +60 -27
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/models/AppointmentChatModel.d.ts +0 -2
- package/dist/models/AppointmentChatModel.js +0 -8
- package/dist/models/AppointmentWorkflowModel.d.ts +0 -2
- package/dist/models/AppointmentWorkflowModel.js +0 -8
- package/dist/models/AssistanceCitizensAbroadChatModel.d.ts +0 -2
- package/dist/models/AssistanceCitizensAbroadChatModel.js +0 -8
- package/dist/models/AssistanceCitizensAbroadWorkflowModel.d.ts +0 -1
- package/dist/models/AssistanceCitizensAbroadWorkflowModel.js +0 -4
- package/dist/models/ChildrensEducationChatModel.d.ts +0 -2
- package/dist/models/ChildrensEducationChatModel.js +0 -8
- package/dist/models/ChildrensEducationWorkflowModel.d.ts +0 -1
- package/dist/models/ChildrensEducationWorkflowModel.js +0 -4
- package/dist/models/DiplomaticAcademyChatModel.d.ts +0 -2
- package/dist/models/DiplomaticAcademyChatModel.js +0 -8
- package/dist/models/DiplomaticAcademyWorkflowModel.d.ts +0 -2
- package/dist/models/DiplomaticAcademyWorkflowModel.js +0 -8
- package/dist/models/DiplomaticChatsModel.d.ts +0 -2
- package/dist/models/DiplomaticChatsModel.js +0 -8
- package/dist/models/DiplomaticWorkFlowModel.d.ts +0 -2
- package/dist/models/DiplomaticWorkFlowModel.js +0 -8
- package/dist/models/DocumentTranslationChatModel.d.ts +0 -2
- package/dist/models/DocumentTranslationChatModel.js +0 -8
- package/dist/models/DocumentTranslationWorkflowModel.d.ts +0 -2
- package/dist/models/DocumentTranslationWorkflowModel.js +0 -8
- package/dist/models/EarlyCheckoutChatModel.d.ts +0 -2
- package/dist/models/EarlyCheckoutChatModel.js +0 -8
- package/dist/models/EarlyCheckoutWorkflowModel.d.ts +0 -2
- package/dist/models/EarlyCheckoutWorkflowModel.js +0 -8
- package/dist/models/EmbassyEvaluationChatModel.d.ts +0 -1
- package/dist/models/EmbassyEvaluationChatModel.js +0 -4
- package/dist/models/EmbassyEvaluationWorkflowModel.d.ts +0 -1
- package/dist/models/EmbassyEvaluationWorkflowModel.js +0 -4
- package/dist/models/EmployeeCardChatsModel.d.ts +0 -2
- package/dist/models/EmployeeCardChatsModel.js +0 -8
- package/dist/models/EmployeeCardWorkFlowModel.d.ts +0 -2
- package/dist/models/EmployeeCardWorkFlowModel.js +0 -8
- package/dist/models/EmployeeEvaluationChatModel.d.ts +0 -1
- package/dist/models/EmployeeEvaluationChatModel.js +0 -4
- package/dist/models/EmployeeEvaluationWorkflowModel.d.ts +0 -1
- package/dist/models/EmployeeEvaluationWorkflowModel.js +0 -4
- package/dist/models/EmployeeOfMonthNominationChatModel.d.ts +0 -1
- package/dist/models/EmployeeOfMonthNominationChatModel.js +0 -4
- package/dist/models/EmployeeOfMonthNominationWorkflowModel.d.ts +0 -1
- package/dist/models/EmployeeOfMonthNominationWorkflowModel.js +0 -4
- package/dist/models/EmployeeOfMonthSupportNominationChatModel.d.ts +0 -1
- package/dist/models/EmployeeOfMonthSupportNominationChatModel.js +0 -4
- package/dist/models/EmployeeOfMonthSupportNominationWorkflowModel.d.ts +0 -1
- package/dist/models/EmployeeOfMonthSupportNominationWorkflowModel.js +0 -4
- package/dist/models/FinancialChatsModel.d.ts +0 -2
- package/dist/models/FinancialChatsModel.js +0 -8
- package/dist/models/FinancialWorkFlowModel.d.ts +0 -2
- package/dist/models/FinancialWorkFlowModel.js +0 -8
- package/dist/models/FoodChatModel.d.ts +0 -1
- package/dist/models/FoodChatModel.js +0 -4
- package/dist/models/FoodWorkflowModel.d.ts +0 -2
- package/dist/models/FoodWorkflowModel.js +0 -8
- package/dist/models/GatePassChatsModel.d.ts +0 -2
- package/dist/models/GatePassChatsModel.js +0 -8
- package/dist/models/GatePassWorkFlowModel.d.ts +0 -2
- package/dist/models/GatePassWorkFlowModel.js +0 -8
- package/dist/models/GeneralServiceChatsModel.d.ts +0 -2
- package/dist/models/GeneralServiceChatsModel.js +0 -8
- package/dist/models/GeneralServiceWorkFlowModel.d.ts +0 -2
- package/dist/models/GeneralServiceWorkFlowModel.js +0 -8
- package/dist/models/HallChatModel.d.ts +0 -1
- package/dist/models/HallChatModel.js +0 -4
- package/dist/models/HallWorkflowModel.d.ts +0 -2
- package/dist/models/HallWorkflowModel.js +0 -8
- package/dist/models/HousingRentalAccommodationChatModel.d.ts +0 -2
- package/dist/models/HousingRentalAccommodationChatModel.js +0 -8
- package/dist/models/HousingRentalAccommodationWorkflowModel.d.ts +0 -1
- package/dist/models/HousingRentalAccommodationWorkflowModel.js +0 -4
- package/dist/models/HousingRentalVehicleChatModel.d.ts +0 -2
- package/dist/models/HousingRentalVehicleChatModel.js +0 -8
- package/dist/models/HousingRentalVehicleWorkflowModel.d.ts +0 -1
- package/dist/models/HousingRentalVehicleWorkflowModel.js +0 -4
- package/dist/models/InitiatorEmployeeNominationChatModel.d.ts +0 -1
- package/dist/models/InitiatorEmployeeNominationChatModel.js +0 -4
- package/dist/models/InitiatorEmployeeNominationWorkflowModel.d.ts +0 -1
- package/dist/models/InitiatorEmployeeNominationWorkflowModel.js +0 -4
- package/dist/models/InnovativeEmployeeNominationChatModel.d.ts +0 -1
- package/dist/models/InnovativeEmployeeNominationChatModel.js +0 -4
- package/dist/models/InnovativeEmployeeNominationWorkflowModel.d.ts +0 -1
- package/dist/models/InnovativeEmployeeNominationWorkflowModel.js +0 -4
- package/dist/models/IpeGrievanceChatModel.d.ts +0 -1
- package/dist/models/IpeGrievanceChatModel.js +0 -4
- package/dist/models/IpeGrievanceWorkflowModel.d.ts +0 -1
- package/dist/models/IpeGrievanceWorkflowModel.js +0 -4
- package/dist/models/LMSCourseExternalLecturerChatModel.d.ts +0 -2
- package/dist/models/LMSCourseExternalLecturerChatModel.js +0 -8
- package/dist/models/LMSCourseExternalLecturerWorkflowModel.d.ts +0 -2
- package/dist/models/LMSCourseExternalLecturerWorkflowModel.js +0 -8
- package/dist/models/LMSExternalCourseParticipationChatModel.d.ts +0 -2
- package/dist/models/LMSExternalCourseParticipationChatModel.js +0 -8
- package/dist/models/LMSExternalCourseParticipationWorkflowModel.d.ts +0 -2
- package/dist/models/LMSExternalCourseParticipationWorkflowModel.js +0 -8
- package/dist/models/LMSExternalEntityTrainedChatModel.d.ts +0 -2
- package/dist/models/LMSExternalEntityTrainedChatModel.js +0 -8
- package/dist/models/LMSExternalEntityTrainedWorkflowModel.d.ts +0 -2
- package/dist/models/LMSExternalEntityTrainedWorkflowModel.js +0 -8
- package/dist/models/LanguageCourseChatModel.d.ts +0 -2
- package/dist/models/LanguageCourseChatModel.js +0 -8
- package/dist/models/LanguageCourseWorkflowModel.d.ts +0 -2
- package/dist/models/LanguageCourseWorkflowModel.js +0 -8
- package/dist/models/LeaveChatModel.d.ts +0 -2
- package/dist/models/LeaveChatModel.js +0 -8
- package/dist/models/LeaveWorkFlowModel.d.ts +0 -2
- package/dist/models/LeaveWorkFlowModel.js +0 -8
- package/dist/models/MediaChatModel.d.ts +0 -2
- package/dist/models/MediaChatModel.js +0 -8
- package/dist/models/MediaWorkflowModel.d.ts +0 -2
- package/dist/models/MediaWorkflowModel.js +0 -8
- package/dist/models/MedicalExpensesChatModel.d.ts +0 -2
- package/dist/models/MedicalExpensesChatModel.js +0 -8
- package/dist/models/MedicalExpensesWorkflowModel.d.ts +0 -1
- package/dist/models/MedicalExpensesWorkflowModel.js +0 -4
- package/dist/models/MeetingChatModel.d.ts +0 -2
- package/dist/models/MeetingChatModel.js +0 -8
- package/dist/models/MeetingWorkflowModel.d.ts +0 -2
- package/dist/models/MeetingWorkflowModel.js +0 -8
- package/dist/models/MissionBankAccountChatModel.d.ts +0 -2
- package/dist/models/MissionBankAccountChatModel.js +0 -8
- package/dist/models/MissionBankAccountWorkflowModel.d.ts +0 -2
- package/dist/models/MissionBankAccountWorkflowModel.js +0 -8
- package/dist/models/MissionContractsChatModel.d.ts +0 -2
- package/dist/models/MissionContractsChatModel.js +0 -8
- package/dist/models/MissionContractsWorkflowModel.d.ts +0 -1
- package/dist/models/MissionContractsWorkflowModel.js +0 -4
- package/dist/models/MissionTravelChatModel.d.ts +0 -1
- package/dist/models/MissionTravelChatModel.js +0 -4
- package/dist/models/MissionTravelWorkflowModel.d.ts +0 -2
- package/dist/models/MissionTravelWorkflowModel.js +0 -8
- package/dist/models/NationalDayCelebrationsChatModel.d.ts +0 -2
- package/dist/models/NationalDayCelebrationsChatModel.js +0 -8
- package/dist/models/NationalDayCelebrationsWorkflowModel.d.ts +0 -1
- package/dist/models/NationalDayCelebrationsWorkflowModel.js +0 -4
- package/dist/models/RecruitmentDomesticWorkersChatModel.d.ts +0 -2
- package/dist/models/RecruitmentDomesticWorkersChatModel.js +0 -8
- package/dist/models/RecruitmentDomesticWorkersWorkflowModel.d.ts +0 -1
- package/dist/models/RecruitmentDomesticWorkersWorkflowModel.js +0 -4
- package/dist/models/RegisterCandidateChatModel.d.ts +0 -2
- package/dist/models/RegisterCandidateChatModel.js +0 -8
- package/dist/models/RegisterCandidateWorkflowModel.d.ts +0 -2
- package/dist/models/RegisterCandidateWorkflowModel.js +0 -8
- package/dist/models/RegisterVacancyChatModel.d.ts +0 -2
- package/dist/models/RegisterVacancyChatModel.js +0 -8
- package/dist/models/RegisterVacancyWorkflowModel.d.ts +0 -2
- package/dist/models/RegisterVacancyWorkflowModel.js +0 -8
- package/dist/models/RepatriationCitizensChatModel.d.ts +0 -2
- package/dist/models/RepatriationCitizensChatModel.js +0 -8
- package/dist/models/RepatriationCitizensWorkflowModel.d.ts +0 -1
- package/dist/models/RepatriationCitizensWorkflowModel.js +0 -4
- package/dist/models/RequestParcelChatModel.d.ts +0 -2
- package/dist/models/RequestParcelChatModel.js +0 -8
- package/dist/models/RequestParcelWorkflowModel.d.ts +0 -2
- package/dist/models/RequestParcelWorkflowModel.js +0 -8
- package/dist/models/RequestPassportChatModel.d.ts +0 -2
- package/dist/models/RequestPassportChatModel.js +0 -8
- package/dist/models/RequestPassportWorkflowModel.d.ts +0 -2
- package/dist/models/RequestPassportWorkflowModel.js +0 -8
- package/dist/models/ResignationTerminationChatModel.d.ts +0 -2
- package/dist/models/ResignationTerminationChatModel.js +0 -8
- package/dist/models/ResignationTerminationWorkflowModel.d.ts +0 -2
- package/dist/models/ResignationTerminationWorkflowModel.js +0 -8
- package/dist/models/RetiredCardChatsModel.d.ts +0 -2
- package/dist/models/RetiredCardChatsModel.js +0 -8
- package/dist/models/RetiredCardWorkFlowModel.d.ts +0 -2
- package/dist/models/RetiredCardWorkFlowModel.js +0 -8
- package/dist/models/SecurityChatsModel.d.ts +0 -2
- package/dist/models/SecurityChatsModel.js +0 -8
- package/dist/models/StayAfterHoursChatModel.d.ts +0 -2
- package/dist/models/StayAfterHoursChatModel.js +0 -8
- package/dist/models/StayAfterHoursWorkflowModel.d.ts +0 -2
- package/dist/models/StayAfterHoursWorkflowModel.js +0 -8
- package/dist/models/TransferAllowanceChatModel.d.ts +0 -2
- package/dist/models/TransferAllowanceChatModel.js +0 -8
- package/dist/models/TransferAllowanceWorkflowModel.d.ts +0 -1
- package/dist/models/TransferAllowanceWorkflowModel.js +0 -4
- package/dist/models/TransferMissionChatModel.d.ts +0 -2
- package/dist/models/TransferMissionChatModel.js +0 -8
- package/dist/models/TransferMissionWorkflowModel.d.ts +0 -2
- package/dist/models/TransferMissionWorkflowModel.js +0 -8
- package/dist/models/TransferSalaryBankAccountChatModel.d.ts +0 -2
- package/dist/models/TransferSalaryBankAccountChatModel.js +0 -8
- package/dist/models/TransferSalaryBankAccountWorkflowModel.d.ts +0 -1
- package/dist/models/TransferSalaryBankAccountWorkflowModel.js +0 -4
- package/dist/models/UpdateAttendanceChatModel.d.ts +0 -1
- package/dist/models/UpdateAttendanceChatModel.js +0 -4
- package/dist/models/UpdateAttendanceWorkflowModel.d.ts +0 -2
- package/dist/models/UpdateAttendanceWorkflowModel.js +0 -8
- package/dist/models/user.d.ts +1 -0
- package/dist/models/user.js +4 -0
- package/package.json +1 -1
- package/sql/add_users_is_selected_lang.sql +11 -0
- package/src/index.ts +1 -3
- package/src/models/AppointmentChatModel.ts +0 -6
- package/src/models/AppointmentWorkflowModel.ts +0 -6
- package/src/models/AssistanceCitizensAbroadChatModel.ts +0 -6
- package/src/models/AssistanceCitizensAbroadWorkflowModel.ts +0 -3
- package/src/models/ChildrensEducationChatModel.ts +0 -6
- package/src/models/ChildrensEducationWorkflowModel.ts +0 -3
- package/src/models/DiplomaticAcademyChatModel.ts +0 -6
- package/src/models/DiplomaticAcademyWorkflowModel.ts +0 -6
- package/src/models/DiplomaticChatsModel.ts +0 -6
- package/src/models/DiplomaticWorkFlowModel.ts +0 -6
- package/src/models/DocumentTranslationChatModel.ts +0 -6
- package/src/models/DocumentTranslationWorkflowModel.ts +0 -6
- package/src/models/EarlyCheckoutChatModel.ts +0 -6
- package/src/models/EarlyCheckoutWorkflowModel.ts +0 -6
- package/src/models/EmbassyEvaluationChatModel.ts +0 -3
- package/src/models/EmbassyEvaluationWorkflowModel.ts +0 -3
- package/src/models/EmployeeCardChatsModel.ts +0 -6
- package/src/models/EmployeeCardWorkFlowModel.ts +2 -8
- package/src/models/EmployeeEvaluationChatModel.ts +0 -3
- package/src/models/EmployeeEvaluationWorkflowModel.ts +0 -3
- package/src/models/EmployeeOfMonthNominationChatModel.ts +0 -3
- package/src/models/EmployeeOfMonthNominationWorkflowModel.ts +0 -3
- package/src/models/EmployeeOfMonthSupportNominationChatModel.ts +0 -3
- package/src/models/EmployeeOfMonthSupportNominationWorkflowModel.ts +0 -3
- package/src/models/FinancialChatsModel.ts +0 -6
- package/src/models/FinancialWorkFlowModel.ts +0 -6
- package/src/models/FoodChatModel.ts +0 -3
- package/src/models/FoodWorkflowModel.ts +0 -6
- package/src/models/GatePassChatsModel.ts +0 -6
- package/src/models/GatePassWorkFlowModel.ts +2 -8
- package/src/models/GeneralServiceChatsModel.ts +0 -6
- package/src/models/GeneralServiceWorkFlowModel.ts +0 -6
- package/src/models/HallChatModel.ts +0 -3
- package/src/models/HallWorkflowModel.ts +0 -6
- package/src/models/HousingRentalAccommodationChatModel.ts +0 -6
- package/src/models/HousingRentalAccommodationWorkflowModel.ts +0 -3
- package/src/models/HousingRentalVehicleChatModel.ts +0 -6
- package/src/models/HousingRentalVehicleWorkflowModel.ts +0 -3
- package/src/models/InitiatorEmployeeNominationChatModel.ts +0 -3
- package/src/models/InitiatorEmployeeNominationWorkflowModel.ts +0 -3
- package/src/models/InnovativeEmployeeNominationChatModel.ts +0 -3
- package/src/models/InnovativeEmployeeNominationWorkflowModel.ts +0 -3
- package/src/models/IpeGrievanceChatModel.ts +0 -3
- package/src/models/IpeGrievanceWorkflowModel.ts +0 -3
- package/src/models/LMSCourseExternalLecturerChatModel.ts +0 -6
- package/src/models/LMSCourseExternalLecturerWorkflowModel.ts +0 -6
- package/src/models/LMSExternalCourseParticipationChatModel.ts +0 -6
- package/src/models/LMSExternalCourseParticipationWorkflowModel.ts +0 -6
- package/src/models/LMSExternalEntityTrainedChatModel.ts +0 -6
- package/src/models/LMSExternalEntityTrainedWorkflowModel.ts +0 -6
- package/src/models/LanguageCourseChatModel.ts +0 -6
- package/src/models/LanguageCourseWorkflowModel.ts +0 -6
- package/src/models/LeaveChatModel.ts +1 -7
- package/src/models/LeaveWorkFlowModel.ts +0 -6
- package/src/models/MediaChatModel.ts +0 -6
- package/src/models/MediaWorkflowModel.ts +0 -6
- package/src/models/MedicalExpensesChatModel.ts +0 -6
- package/src/models/MedicalExpensesWorkflowModel.ts +0 -3
- package/src/models/MeetingChatModel.ts +0 -6
- package/src/models/MeetingWorkflowModel.ts +0 -6
- package/src/models/MissionBankAccountChatModel.ts +0 -6
- package/src/models/MissionBankAccountWorkflowModel.ts +0 -6
- package/src/models/MissionContractsChatModel.ts +0 -6
- package/src/models/MissionContractsWorkflowModel.ts +0 -3
- package/src/models/MissionTravelChatModel.ts +0 -3
- package/src/models/MissionTravelWorkflowModel.ts +0 -6
- package/src/models/NationalDayCelebrationsChatModel.ts +0 -6
- package/src/models/NationalDayCelebrationsWorkflowModel.ts +0 -3
- package/src/models/RecruitmentDomesticWorkersChatModel.ts +0 -6
- package/src/models/RecruitmentDomesticWorkersWorkflowModel.ts +0 -3
- package/src/models/RegisterCandidateChatModel.ts +0 -6
- package/src/models/RegisterCandidateWorkflowModel.ts +0 -6
- package/src/models/RegisterVacancyChatModel.ts +0 -6
- package/src/models/RegisterVacancyWorkflowModel.ts +0 -6
- package/src/models/RepatriationCitizensChatModel.ts +0 -6
- package/src/models/RepatriationCitizensWorkflowModel.ts +0 -3
- package/src/models/RequestParcelChatModel.ts +0 -6
- package/src/models/RequestParcelWorkflowModel.ts +0 -6
- package/src/models/RequestPassportChatModel.ts +0 -6
- package/src/models/RequestPassportWorkflowModel.ts +0 -6
- package/src/models/ResignationTerminationChatModel.ts +0 -6
- package/src/models/ResignationTerminationWorkflowModel.ts +0 -6
- package/src/models/RetiredCardChatsModel.ts +0 -6
- package/src/models/RetiredCardWorkFlowModel.ts +2 -8
- package/src/models/SecurityChatsModel.ts +0 -6
- package/src/models/StayAfterHoursChatModel.ts +0 -6
- package/src/models/StayAfterHoursWorkflowModel.ts +0 -6
- package/src/models/TransferAllowanceChatModel.ts +0 -6
- package/src/models/TransferAllowanceWorkflowModel.ts +0 -3
- package/src/models/TransferMissionChatModel.ts +0 -6
- package/src/models/TransferMissionWorkflowModel.ts +0 -6
- package/src/models/TransferSalaryBankAccountChatModel.ts +0 -6
- package/src/models/TransferSalaryBankAccountWorkflowModel.ts +0 -3
- package/src/models/UpdateAttendanceChatModel.ts +0 -3
- package/src/models/UpdateAttendanceWorkflowModel.ts +0 -6
- package/src/models/user.ts +3 -0
- package/tsconfig.json +0 -1
- package/sql/add_fm_workflow_chat_arabic_columns.sql +0 -153
- package/src/i18n/workflow-chat-i18n.json +0 -320
- package/src/i18n/workflow-chat-i18n.ts +0 -5
- package/src/i18n/workflow-chat-message.builder.ts +0 -1405
package/.env
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
DB_HOST=164.52.222.169
|
|
8
|
-
DB_PORT=5432
|
|
9
|
-
DB_USER=postgres_admin_user
|
|
10
|
-
DB_PASS=pg_admin_user_pwd_caa_fa_$%^&OIukhjgcvbn
|
|
11
|
-
DB_NAME=FM
|
|
1
|
+
DB_HOST=localhost
|
|
2
|
+
DB_PORT=5432
|
|
3
|
+
DB_USER=postgres
|
|
4
|
+
DB_PASS=Fa@123
|
|
5
|
+
DB_NAME=FM
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { UserSessionReader } from './user-session-validation';
|
|
2
|
+
export type JwtAuthFailure = {
|
|
3
|
+
ok: false;
|
|
4
|
+
statusCode: 401;
|
|
5
|
+
message: string;
|
|
6
|
+
};
|
|
7
|
+
export type JwtAuthSuccess = {
|
|
8
|
+
ok: true;
|
|
9
|
+
claims: Record<string, unknown>;
|
|
10
|
+
userId: number;
|
|
11
|
+
sessionId: number | null;
|
|
12
|
+
};
|
|
13
|
+
export type JwtAuthResult = JwtAuthSuccess | JwtAuthFailure;
|
|
14
|
+
/**
|
|
15
|
+
* After jwt.verify(), enforce server-side session binding (logout revocation).
|
|
16
|
+
*/
|
|
17
|
+
export declare function authorizeVerifiedJwtSession(verified: Record<string, unknown>, sessionReader: UserSessionReader, options?: {
|
|
18
|
+
requireActiveSession?: boolean;
|
|
19
|
+
}): Promise<JwtAuthResult>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.authorizeVerifiedJwtSession = authorizeVerifiedJwtSession;
|
|
4
|
+
const jwt_token_helper_1 = require("./jwt-token.helper");
|
|
5
|
+
const user_session_validation_1 = require("./user-session-validation");
|
|
6
|
+
/**
|
|
7
|
+
* After jwt.verify(), enforce server-side session binding (logout revocation).
|
|
8
|
+
*/
|
|
9
|
+
async function authorizeVerifiedJwtSession(verified, sessionReader, options) {
|
|
10
|
+
const parsed = (0, jwt_token_helper_1.parseVerifiedJwtClaims)(verified);
|
|
11
|
+
if (!parsed) {
|
|
12
|
+
return { ok: false, statusCode: 401, message: 'Invalid Token' };
|
|
13
|
+
}
|
|
14
|
+
const requireActiveSession = options?.requireActiveSession !== false;
|
|
15
|
+
if (requireActiveSession) {
|
|
16
|
+
const sessionValid = await (0, user_session_validation_1.validateUserSessionBinding)(parsed.userId, parsed.sessionId, sessionReader);
|
|
17
|
+
if (!sessionValid) {
|
|
18
|
+
return { ok: false, statusCode: 401, message: 'Session Expired please login again' };
|
|
19
|
+
}
|
|
20
|
+
if (parsed.sessionId != null) {
|
|
21
|
+
const isCurrent = await (0, user_session_validation_1.validateJwtSessionIsCurrent)(parsed.userId, parsed.sessionId, sessionReader);
|
|
22
|
+
if (!isCurrent) {
|
|
23
|
+
return { ok: false, statusCode: 401, message: 'Session Expired please login again' };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const sessionId = await (0, user_session_validation_1.resolveAuthorizedSessionId)(parsed.userId, parsed.sessionId, sessionReader);
|
|
28
|
+
const { sessionId: _jwtSessionId, ...claimsWithoutSession } = parsed.raw;
|
|
29
|
+
return {
|
|
30
|
+
ok: true,
|
|
31
|
+
claims: claimsWithoutSession,
|
|
32
|
+
userId: parsed.userId,
|
|
33
|
+
sessionId,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extract portal API JWT from standard request headers.
|
|
3
|
+
* Supports `jwt` header (legacy) and `Authorization: Bearer <token>`.
|
|
4
|
+
*/
|
|
5
|
+
export declare function extractJwtToken(headers: Record<string, string | string[] | undefined> | undefined): string | null;
|
|
6
|
+
export type JwtTokenRequest = {
|
|
7
|
+
headers: Record<string, string | string[] | undefined>;
|
|
8
|
+
body?: unknown;
|
|
9
|
+
};
|
|
10
|
+
/** JWT from headers (`jwt`, `Authorization: Bearer`) or JSON body (`token`, `jwt`, `access_token`). */
|
|
11
|
+
export declare function extractJwtTokenFromRequest(request: JwtTokenRequest): string | null;
|
|
12
|
+
export type VerifiedJwtClaims = {
|
|
13
|
+
userId: number;
|
|
14
|
+
sessionId: number | null;
|
|
15
|
+
raw: Record<string, unknown>;
|
|
16
|
+
};
|
|
17
|
+
/** Parse verified JWT payload into userId + sessionId. */
|
|
18
|
+
export declare function parseVerifiedJwtClaims(verified: Record<string, unknown>): VerifiedJwtClaims | null;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractJwtToken = extractJwtToken;
|
|
4
|
+
exports.extractJwtTokenFromRequest = extractJwtTokenFromRequest;
|
|
5
|
+
exports.parseVerifiedJwtClaims = parseVerifiedJwtClaims;
|
|
6
|
+
/**
|
|
7
|
+
* Extract portal API JWT from standard request headers.
|
|
8
|
+
* Supports `jwt` header (legacy) and `Authorization: Bearer <token>`.
|
|
9
|
+
*/
|
|
10
|
+
function extractJwtToken(headers) {
|
|
11
|
+
if (!headers)
|
|
12
|
+
return null;
|
|
13
|
+
const pick = (value) => {
|
|
14
|
+
const raw = Array.isArray(value) ? value[0] : value;
|
|
15
|
+
const trimmed = raw?.trim();
|
|
16
|
+
return trimmed ? trimmed : null;
|
|
17
|
+
};
|
|
18
|
+
const fromJwtHeader = pick(headers.jwt ?? headers.JWT);
|
|
19
|
+
if (fromJwtHeader)
|
|
20
|
+
return fromJwtHeader;
|
|
21
|
+
const authorization = pick(headers.authorization ?? headers.Authorization);
|
|
22
|
+
if (!authorization)
|
|
23
|
+
return null;
|
|
24
|
+
const bearerMatch = /^Bearer\s+(.+)$/i.exec(authorization);
|
|
25
|
+
if (bearerMatch?.[1]?.trim())
|
|
26
|
+
return bearerMatch[1].trim();
|
|
27
|
+
return authorization;
|
|
28
|
+
}
|
|
29
|
+
/** JWT from headers (`jwt`, `Authorization: Bearer`) or JSON body (`token`, `jwt`, `access_token`). */
|
|
30
|
+
function extractJwtTokenFromRequest(request) {
|
|
31
|
+
const fromHeaders = extractJwtToken(request.headers);
|
|
32
|
+
if (fromHeaders)
|
|
33
|
+
return fromHeaders;
|
|
34
|
+
const body = request.body;
|
|
35
|
+
if (!body || typeof body !== 'object')
|
|
36
|
+
return null;
|
|
37
|
+
for (const key of ['token', 'jwt', 'access_token']) {
|
|
38
|
+
const value = body[key];
|
|
39
|
+
if (typeof value === 'string' && value.trim())
|
|
40
|
+
return value.trim();
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
/** Parse verified JWT payload into userId + sessionId. */
|
|
45
|
+
function parseVerifiedJwtClaims(verified) {
|
|
46
|
+
const userId = Number(verified.userId);
|
|
47
|
+
if (!Number.isFinite(userId) || userId <= 0)
|
|
48
|
+
return null;
|
|
49
|
+
const sessionIdRaw = verified.sessionId;
|
|
50
|
+
const parsedSessionId = sessionIdRaw == null || sessionIdRaw === '' ? null : Number(sessionIdRaw);
|
|
51
|
+
return {
|
|
52
|
+
userId,
|
|
53
|
+
sessionId: parsedSessionId != null && Number.isFinite(parsedSessionId) && parsedSessionId > 0
|
|
54
|
+
? parsedSessionId
|
|
55
|
+
: null,
|
|
56
|
+
raw: verified,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side JWT session binding (VAPT M003/M004).
|
|
3
|
+
* JWT remains valid cryptographically until exp; access is allowed only while
|
|
4
|
+
* the bound user_sessions row is active and not expired.
|
|
5
|
+
*/
|
|
6
|
+
export type UserSessionRow = {
|
|
7
|
+
id?: number;
|
|
8
|
+
};
|
|
9
|
+
export type UserSessionReader = {
|
|
10
|
+
isSessionActiveById(sessionId: number, userId: number): Promise<boolean>;
|
|
11
|
+
/** Legacy fallback when REQUIRE_JWT_SESSION_ID=false and token has no sessionId. */
|
|
12
|
+
isSessionActive?(userId: number): Promise<UserSessionRow | null | undefined>;
|
|
13
|
+
/** Latest active session row id for user (highest id). */
|
|
14
|
+
getLatestActiveSessionId?(userId: number): Promise<number | null>;
|
|
15
|
+
};
|
|
16
|
+
/** Default true — only the newest active session may use the API when JWT carries sessionId. */
|
|
17
|
+
export declare function isSingleSessionOnLogin(): boolean;
|
|
18
|
+
/** When true (default), JWT must include sessionId and that session must be active. */
|
|
19
|
+
export declare function isRequireJwtSessionId(): boolean;
|
|
20
|
+
export declare function resolveJwtSessionId(sessionId: unknown): number | null;
|
|
21
|
+
/**
|
|
22
|
+
* Validate that a verified JWT is still authorized (not logged out / expired server-side).
|
|
23
|
+
*/
|
|
24
|
+
export declare function validateUserSessionBinding(userId: number, sessionId: number | null | undefined, reader: UserSessionReader): Promise<boolean>;
|
|
25
|
+
/** After row-level active check, enforce single-session policy (reject superseded JWTs). */
|
|
26
|
+
export declare function validateJwtSessionIsCurrent(userId: number, sessionId: number, reader: UserSessionReader): Promise<boolean>;
|
|
27
|
+
/** Resolve session id for request meta: JWT claim first, else latest active DB row. */
|
|
28
|
+
export declare function resolveAuthorizedSessionId(userId: number, jwtSessionId: number | null, reader: UserSessionReader): Promise<number | null>;
|
|
29
|
+
/** Shared TypeORM filters: active, not deleted, not past expires_at. */
|
|
30
|
+
export declare function applyActiveUserSessionFilters(qb: {
|
|
31
|
+
andWhere: (clause: string, params?: Record<string, unknown>) => unknown;
|
|
32
|
+
orderBy?: (sort: string, order?: 'ASC' | 'DESC') => unknown;
|
|
33
|
+
}, alias?: string): void;
|
|
34
|
+
/** Prefer newest active session when multiple rows match (legacy path). */
|
|
35
|
+
export declare function applyLatestActiveUserSessionOrdering(qb: {
|
|
36
|
+
orderBy: (sort: string, order?: 'ASC' | 'DESC') => unknown;
|
|
37
|
+
}, alias?: string): void;
|
|
38
|
+
/** @deprecated Use applyActiveUserSessionFilters — kept for backward compatibility. */
|
|
39
|
+
export declare function activeUserSessionSql(alias?: string): {
|
|
40
|
+
clause: string;
|
|
41
|
+
params: Record<string, unknown>;
|
|
42
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Server-side JWT session binding (VAPT M003/M004).
|
|
4
|
+
* JWT remains valid cryptographically until exp; access is allowed only while
|
|
5
|
+
* the bound user_sessions row is active and not expired.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.isSingleSessionOnLogin = isSingleSessionOnLogin;
|
|
9
|
+
exports.isRequireJwtSessionId = isRequireJwtSessionId;
|
|
10
|
+
exports.resolveJwtSessionId = resolveJwtSessionId;
|
|
11
|
+
exports.validateUserSessionBinding = validateUserSessionBinding;
|
|
12
|
+
exports.validateJwtSessionIsCurrent = validateJwtSessionIsCurrent;
|
|
13
|
+
exports.resolveAuthorizedSessionId = resolveAuthorizedSessionId;
|
|
14
|
+
exports.applyActiveUserSessionFilters = applyActiveUserSessionFilters;
|
|
15
|
+
exports.applyLatestActiveUserSessionOrdering = applyLatestActiveUserSessionOrdering;
|
|
16
|
+
exports.activeUserSessionSql = activeUserSessionSql;
|
|
17
|
+
/** Default true — only the newest active session may use the API when JWT carries sessionId. */
|
|
18
|
+
function isSingleSessionOnLogin() {
|
|
19
|
+
const raw = (process.env.SINGLE_SESSION_ON_LOGIN ?? 'true').trim().toLowerCase();
|
|
20
|
+
return raw !== 'false' && raw !== '0' && raw !== 'no';
|
|
21
|
+
}
|
|
22
|
+
/** When true (default), JWT must include sessionId and that session must be active. */
|
|
23
|
+
function isRequireJwtSessionId() {
|
|
24
|
+
const raw = (process.env.REQUIRE_JWT_SESSION_ID ?? 'true').trim().toLowerCase();
|
|
25
|
+
return raw !== 'false' && raw !== '0' && raw !== 'no';
|
|
26
|
+
}
|
|
27
|
+
function resolveJwtSessionId(sessionId) {
|
|
28
|
+
if (sessionId == null || sessionId === '')
|
|
29
|
+
return null;
|
|
30
|
+
const sid = Number(sessionId);
|
|
31
|
+
if (!Number.isFinite(sid) || sid <= 0)
|
|
32
|
+
return null;
|
|
33
|
+
return sid;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Validate that a verified JWT is still authorized (not logged out / expired server-side).
|
|
37
|
+
*/
|
|
38
|
+
async function validateUserSessionBinding(userId, sessionId, reader) {
|
|
39
|
+
if (!Number.isFinite(userId) || userId <= 0)
|
|
40
|
+
return false;
|
|
41
|
+
const sid = resolveJwtSessionId(sessionId);
|
|
42
|
+
if (sid != null) {
|
|
43
|
+
return reader.isSessionActiveById(sid, userId);
|
|
44
|
+
}
|
|
45
|
+
if (isRequireJwtSessionId()) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
if (!reader.isSessionActive)
|
|
49
|
+
return false;
|
|
50
|
+
const legacy = await reader.isSessionActive(userId);
|
|
51
|
+
return !!legacy;
|
|
52
|
+
}
|
|
53
|
+
/** After row-level active check, enforce single-session policy (reject superseded JWTs). */
|
|
54
|
+
async function validateJwtSessionIsCurrent(userId, sessionId, reader) {
|
|
55
|
+
if (!isSingleSessionOnLogin() || !reader.getLatestActiveSessionId)
|
|
56
|
+
return true;
|
|
57
|
+
const latest = await reader.getLatestActiveSessionId(userId);
|
|
58
|
+
if (latest == null)
|
|
59
|
+
return true;
|
|
60
|
+
return latest === sessionId;
|
|
61
|
+
}
|
|
62
|
+
/** Resolve session id for request meta: JWT claim first, else latest active DB row. */
|
|
63
|
+
async function resolveAuthorizedSessionId(userId, jwtSessionId, reader) {
|
|
64
|
+
if (jwtSessionId != null)
|
|
65
|
+
return jwtSessionId;
|
|
66
|
+
if (reader.getLatestActiveSessionId) {
|
|
67
|
+
return reader.getLatestActiveSessionId(userId);
|
|
68
|
+
}
|
|
69
|
+
if (!reader.isSessionActive)
|
|
70
|
+
return null;
|
|
71
|
+
const legacy = await reader.isSessionActive(userId);
|
|
72
|
+
const legacyId = Number(legacy?.id);
|
|
73
|
+
return Number.isFinite(legacyId) && legacyId > 0 ? legacyId : null;
|
|
74
|
+
}
|
|
75
|
+
/** Shared TypeORM filters: active, not deleted, not past expires_at. */
|
|
76
|
+
function applyActiveUserSessionFilters(qb, alias = 'user_sessions') {
|
|
77
|
+
qb.andWhere(`${alias}.is_active = :is_active`, { is_active: true });
|
|
78
|
+
qb.andWhere(`(${alias}.is_deleted IS NULL OR ${alias}.is_deleted = :is_deleted)`, { is_deleted: false });
|
|
79
|
+
qb.andWhere(`(${alias}.expires_at IS NULL OR ${alias}.expires_at > :session_now)`, { session_now: new Date() });
|
|
80
|
+
}
|
|
81
|
+
/** Prefer newest active session when multiple rows match (legacy path). */
|
|
82
|
+
function applyLatestActiveUserSessionOrdering(qb, alias = 'user_sessions') {
|
|
83
|
+
qb.orderBy(`${alias}.id`, 'DESC');
|
|
84
|
+
}
|
|
85
|
+
/** @deprecated Use applyActiveUserSessionFilters — kept for backward compatibility. */
|
|
86
|
+
function activeUserSessionSql(alias = 'user_sessions') {
|
|
87
|
+
return {
|
|
88
|
+
clause: `${alias}.is_active = :is_active AND (${alias}.is_deleted IS NULL OR ${alias}.is_deleted = :is_deleted) AND (${alias}.expires_at IS NULL OR ${alias}.expires_at > :session_now)`,
|
|
89
|
+
params: {
|
|
90
|
+
is_active: true,
|
|
91
|
+
is_deleted: false,
|
|
92
|
+
session_now: new Date(),
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
"request_approval_pending": {
|
|
20
20
|
"en": "Request Approval Pending",
|
|
21
|
-
"ar": "
|
|
21
|
+
"ar": "الموافقة على الطلب قيد الانتظار"
|
|
22
22
|
},
|
|
23
23
|
"request_approval_in_progress_from": {
|
|
24
24
|
"en": "Request Approval In Progress from {{name}}",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"request_approval_pending_from": {
|
|
28
28
|
"en": "Request Approval Pending from {{name}}",
|
|
29
|
-
"ar": "
|
|
29
|
+
"ar": "الموافقة على الطلب قيد الانتظار من {{name}}"
|
|
30
30
|
},
|
|
31
31
|
"request_approved_by": {
|
|
32
32
|
"en": "Request Approved by {{name}}{{comment}}",
|
|
@@ -46,11 +46,11 @@
|
|
|
46
46
|
},
|
|
47
47
|
"request_returned_for_modification_by": {
|
|
48
48
|
"en": "Request Returned for Modification by {{name}}{{comment}}",
|
|
49
|
-
"ar": "
|
|
49
|
+
"ar": "تمت إعادة الطلب للتعديل من قبل {{name}}{{comment}}"
|
|
50
50
|
},
|
|
51
51
|
"request_returned_for_modification": {
|
|
52
52
|
"en": "Request Returned for Modification{{comment}}",
|
|
53
|
-
"ar": "
|
|
53
|
+
"ar": "تمت إعادة الطلب للتعديل{{comment}}"
|
|
54
54
|
},
|
|
55
55
|
"request_closed_by": {
|
|
56
56
|
"en": "Request Closed by: {{name}}{{comment}}",
|
|
@@ -62,47 +62,47 @@
|
|
|
62
62
|
},
|
|
63
63
|
"it_helpdesk_wf_hos_assigned": {
|
|
64
64
|
"en": "{{approverRoleName}} assigned the request to {{assignedRoleName}}{{comment}}",
|
|
65
|
-
"ar": "
|
|
65
|
+
"ar": "تم تعيين الطلب إلى {{assignedRoleName}} من قبل {{approverRoleName}}{{comment}}"
|
|
66
66
|
},
|
|
67
67
|
"it_helpdesk_wf_technician_assigned": {
|
|
68
68
|
"en": "IT technician {{level}} assigned by {{approverRoleName}}{{comment}}",
|
|
69
|
-
"ar": "تم تعيين فني
|
|
69
|
+
"ar": "تم تعيين فني تقنية المعلومات {{level}} من قبل {{approverRoleName}}{{comment}}"
|
|
70
70
|
},
|
|
71
71
|
"it_helpdesk_wf_reassigned_technician": {
|
|
72
72
|
"en": "{{approverRoleName}} reassigned request to Technician{{comment}}{{modifiers}}",
|
|
73
|
-
"ar": "
|
|
73
|
+
"ar": "{{approverRoleName}} تمت إعادة تعيين الطلب إلى الفني{{comment}}{{modifiers}}"
|
|
74
74
|
},
|
|
75
75
|
"it_helpdesk_wf_reassigned_l3": {
|
|
76
76
|
"en": "{{approverRoleName}} reassigned request to L3{{comment}}{{modifiers}}",
|
|
77
|
-
"ar": "
|
|
77
|
+
"ar": "{{approverRoleName}} تمت إعادة تعيين الطلب إلى المستوى الثالث (L3){{comment}}{{modifiers}}"
|
|
78
78
|
},
|
|
79
79
|
"it_helpdesk_wf_reassigned_generic": {
|
|
80
80
|
"en": "{{approverRoleName}} {{level}} reassigned{{comment}}{{modifiers}}",
|
|
81
|
-
"ar": "
|
|
81
|
+
"ar": "{{approverRoleName}} {{level}} إعادة التعيين{{comment}}{{modifiers}}"
|
|
82
82
|
},
|
|
83
83
|
"it_helpdesk_wf_closed_request": {
|
|
84
84
|
"en": "{{approverRoleName}} closed request{{comment}}",
|
|
85
|
-
"ar": "
|
|
85
|
+
"ar": "تم إغلاق الطلب من قبل {{approverRoleName}}{{comment}}"
|
|
86
86
|
},
|
|
87
87
|
"it_helpdesk_wf_closed_request_cap": {
|
|
88
88
|
"en": "{{approverRoleName}} Closed request{{comment}}",
|
|
89
|
-
"ar": "
|
|
89
|
+
"ar": "تم إغلاق الطلب من قبل {{approverRoleName}}{{comment}}"
|
|
90
90
|
},
|
|
91
91
|
"it_helpdesk_wf_l3_approved_by": {
|
|
92
92
|
"en": "{{roleName}} approved the request by {{userName}}{{comment}}",
|
|
93
|
-
"ar": "
|
|
93
|
+
"ar": "{{roleName}} تمت الموافقة على الطلب من قبل {{userName}}{{comment}}"
|
|
94
94
|
},
|
|
95
95
|
"it_helpdesk_wf_l3_rejected_by": {
|
|
96
96
|
"en": "{{roleName}} rejected the request by {{userName}}{{comment}}",
|
|
97
|
-
"ar": "
|
|
97
|
+
"ar": "{{roleName}} تم رفض الطلب من قبل {{userName}}{{comment}}"
|
|
98
98
|
},
|
|
99
99
|
"it_helpdesk_wf_level_approved": {
|
|
100
100
|
"en": "Level {{level}} approved by {{approverRoleName}}{{comment}}",
|
|
101
|
-
"ar": "تمت الموافقة
|
|
101
|
+
"ar": "تمت الموافقة من قبل {{approverRoleName}} للمستوى {{level}}{{comment}}"
|
|
102
102
|
},
|
|
103
103
|
"it_helpdesk_wf_rejected": {
|
|
104
104
|
"en": "{{approverRoleName}} rejected the request{{comment}}",
|
|
105
|
-
"ar": "
|
|
105
|
+
"ar": "{{approverRoleName}} تم رفض الطلب{{comment}}"
|
|
106
106
|
},
|
|
107
107
|
"it_helpdesk_wf_status_by_role": {
|
|
108
108
|
"en": "Request {{status}} by {{approverRoleName}}{{comment}}",
|
|
@@ -110,29 +110,29 @@
|
|
|
110
110
|
},
|
|
111
111
|
"it_helpdesk_wf_l3_step_rejected": {
|
|
112
112
|
"en": "{{roleName}} rejected the request{{comment}}",
|
|
113
|
-
"ar": "
|
|
113
|
+
"ar": "{{roleName}} تم رفض الطلب{{comment}}"
|
|
114
114
|
},
|
|
115
115
|
"it_helpdesk_wf_technician_completed": {
|
|
116
116
|
"en": "Technician action completed - request closed by {{roleName}}{{comment}}",
|
|
117
|
-
"ar": "
|
|
117
|
+
"ar": "تم استكمال إجراء الفني - تم إغلاق الطلب من قبل {{roleName}}{{comment}}"
|
|
118
118
|
},
|
|
119
119
|
"it_helpdesk_wf_routing_rejected": {
|
|
120
120
|
"en": "Workflow routing completed - request rejected at L3{{comment}}",
|
|
121
|
-
"ar": "
|
|
121
|
+
"ar": "تم استكمال مسار سير العمل - تم رفض الطلب في المستوى الثالث (L3){{comment}}"
|
|
122
122
|
},
|
|
123
123
|
"it_helpdesk_wf_routing_resolved": {
|
|
124
124
|
"en": "Workflow routing completed - request resolved at L3",
|
|
125
|
-
"ar": "
|
|
125
|
+
"ar": "تم استكمال مسار سير العمل - تم حل الطلب في المستوى الثالث (L3)"
|
|
126
126
|
}
|
|
127
127
|
},
|
|
128
128
|
"chatTemplates": {
|
|
129
129
|
"request_submitted_by": {
|
|
130
130
|
"en": "Request Submitted by {{userName}} ({{employeeId}})",
|
|
131
|
-
"ar": "تم تقديم الطلب
|
|
131
|
+
"ar": "تم تقديم الطلب من قبل {{userName}} ({{employeeId}})"
|
|
132
132
|
},
|
|
133
133
|
"cancellation_submitted_by": {
|
|
134
134
|
"en": "Cancellation request submitted by {{userName}} ({{employeeId}})",
|
|
135
|
-
"ar": "تم تقديم طلب الإلغاء
|
|
135
|
+
"ar": "تم تقديم طلب الإلغاء من قبل {{userName}} ({{employeeId}})"
|
|
136
136
|
},
|
|
137
137
|
"cancellation_submitted": {
|
|
138
138
|
"en": "Cancellation request submitted",
|
|
@@ -152,7 +152,7 @@
|
|
|
152
152
|
},
|
|
153
153
|
"request_returned_for_modification_by_role": {
|
|
154
154
|
"en": "Request Returned for Modification by: {{roleName}}{{comment}}",
|
|
155
|
-
"ar": "
|
|
155
|
+
"ar": "تمت إعادة الطلب للتعديل من قبل: {{roleName}}{{comment}}"
|
|
156
156
|
},
|
|
157
157
|
"request_approved": {
|
|
158
158
|
"en": "Request Approved{{comment}}",
|
|
@@ -164,7 +164,7 @@
|
|
|
164
164
|
},
|
|
165
165
|
"request_returned_for_modification": {
|
|
166
166
|
"en": "Request Returned for Modification{{comment}}",
|
|
167
|
-
"ar": "
|
|
167
|
+
"ar": "تمت إعادة الطلب للتعديل{{comment}}"
|
|
168
168
|
},
|
|
169
169
|
"request_closed_by_role": {
|
|
170
170
|
"en": "Request Closed by: {{roleName}}{{comment}}",
|
|
@@ -172,11 +172,11 @@
|
|
|
172
172
|
},
|
|
173
173
|
"request_for_change_by_role": {
|
|
174
174
|
"en": "Request For Change by: {{roleName}}{{comment}}",
|
|
175
|
-
"ar": "طلب
|
|
175
|
+
"ar": "طلب تغيير من قبل: {{roleName}}{{comment}}"
|
|
176
176
|
},
|
|
177
177
|
"request_for_change_requested_by_role": {
|
|
178
178
|
"en": "Request For Change requested by: {{roleName}}{{comment}}",
|
|
179
|
-
"ar": "تم طلب
|
|
179
|
+
"ar": "تم طلب التغيير من قبل: {{roleName}}{{comment}}"
|
|
180
180
|
},
|
|
181
181
|
"attachment_uploaded": {
|
|
182
182
|
"en": "Attachment uploaded: {{fileName}}",
|
|
@@ -188,11 +188,11 @@
|
|
|
188
188
|
},
|
|
189
189
|
"task_status_in_progress_by_role": {
|
|
190
190
|
"en": "Task status updated to \"In Progress\" by: {{roleName}}",
|
|
191
|
-
"ar": "تم تحديث حالة المهمة إلى \"قيد التنفيذ\"
|
|
191
|
+
"ar": "تم تحديث حالة المهمة إلى \"قيد التنفيذ\" من قبل: {{roleName}}"
|
|
192
192
|
},
|
|
193
193
|
"task_completed_by_role": {
|
|
194
194
|
"en": "Task Completed by: {{roleName}}{{comment}}",
|
|
195
|
-
"ar": "
|
|
195
|
+
"ar": "اكتملت المهمة من قبل: {{roleName}}{{comment}}"
|
|
196
196
|
},
|
|
197
197
|
"task_status_updated": {
|
|
198
198
|
"en": "Task status updated to {{status}}",
|
|
@@ -204,23 +204,23 @@
|
|
|
204
204
|
},
|
|
205
205
|
"it_helpdesk_technician_assigned": {
|
|
206
206
|
"en": "IT technician {{level}} assigned to {{assignedRoleName}}: {{assignedUserName}}{{comment}}",
|
|
207
|
-
"ar": "تم تعيين فني
|
|
207
|
+
"ar": "تم تعيين فني تقنية المعلومات {{level}} إلى {{assignedRoleName}}: {{assignedUserName}}{{comment}}"
|
|
208
208
|
},
|
|
209
209
|
"it_helpdesk_reassigned_to_role": {
|
|
210
210
|
"en": "{{approverRoleName}} reassigned request to {{reassignedRoleName}}{{comment}}",
|
|
211
|
-
"ar": "
|
|
211
|
+
"ar": "{{approverRoleName}} تمت إعادة تعيين الطلب إلى {{reassignedRoleName}}{{comment}}"
|
|
212
212
|
},
|
|
213
213
|
"it_helpdesk_reassigned_to_l3": {
|
|
214
214
|
"en": "{{approverRoleName}} reassigned request to L3{{comment}}",
|
|
215
|
-
"ar": "
|
|
215
|
+
"ar": "{{approverRoleName}} تمت إعادة تعيين الطلب إلى المستوى الثالث (L3){{comment}}"
|
|
216
216
|
},
|
|
217
217
|
"it_helpdesk_reassigned_generic": {
|
|
218
218
|
"en": "{{approverRoleName}} {{level}} reassigned the request{{comment}}",
|
|
219
|
-
"ar": "
|
|
219
|
+
"ar": "{{approverRoleName}} {{level}} تمت إعادة تعيين الطلب{{comment}}"
|
|
220
220
|
},
|
|
221
221
|
"request_submitted_with_ref": {
|
|
222
222
|
"en": "{{requestLabel}} #{{requestId}} has been submitted by {{userName}} ({{employeeId}})",
|
|
223
|
-
"ar": "تم تقديم {{requestLabel}} رقم {{requestId}}
|
|
223
|
+
"ar": "تم تقديم {{requestLabel}} رقم {{requestId}} من قبل {{userName}} ({{employeeId}})"
|
|
224
224
|
},
|
|
225
225
|
"security_access_approval_step": {
|
|
226
226
|
"en": "{{productLabel}} request #{{requestId}} was {{statusWord}} (approval step {{approvalLevel}}).{{comment}}",
|
|
@@ -228,7 +228,7 @@
|
|
|
228
228
|
},
|
|
229
229
|
"logistics_actual_return_updated": {
|
|
230
230
|
"en": "{{roleName}} updated the Vehicle Actual Return Date, Time, and Reason. Actual Return Date: {{date}}, Actual Return Time: {{time}}, Reason: {{reason}}",
|
|
231
|
-
"ar": "قام {{roleName}} بتحديث تاريخ
|
|
231
|
+
"ar": "قام {{roleName}} بتحديث تاريخ الإرجاع الفعلي للمركبة والوقت والسبب. تاريخ الإرجاع الفعلي: {{date}}، وقت الإرجاع الفعلي: {{time}}، السبب: {{reason}}"
|
|
232
232
|
}
|
|
233
233
|
},
|
|
234
234
|
"notificationTemplates": {
|
|
@@ -238,11 +238,11 @@
|
|
|
238
238
|
},
|
|
239
239
|
"it_helpdesk_notif_request_closed": {
|
|
240
240
|
"en": "IT request #{{requestId}} has been closed",
|
|
241
|
-
"ar": "تم إغلاق طلب
|
|
241
|
+
"ar": "تم إغلاق طلب تقنية المعلومات رقم {{requestId}}"
|
|
242
242
|
},
|
|
243
243
|
"it_helpdesk_notif_request_rejected": {
|
|
244
244
|
"en": "IT request #{{requestId}} has been rejected",
|
|
245
|
-
"ar": "تم رفض طلب
|
|
245
|
+
"ar": "تم رفض طلب تقنية المعلومات رقم {{requestId}}"
|
|
246
246
|
},
|
|
247
247
|
"fm_request_submitted_title": {
|
|
248
248
|
"en": "Request Submitted",
|
|
@@ -305,15 +305,15 @@
|
|
|
305
305
|
"chatStatusLabels": {
|
|
306
306
|
"Submitted": "تم التقديم",
|
|
307
307
|
"Received": "تم الاستلام",
|
|
308
|
-
"Approved": "
|
|
309
|
-
"Rejected": "
|
|
308
|
+
"Approved": "تم الموافقة",
|
|
309
|
+
"Rejected": "تم الرفض",
|
|
310
310
|
"Pending": "قيد الانتظار",
|
|
311
|
-
"Returned for Modification": "
|
|
312
|
-
"Request For Change": "طلب
|
|
311
|
+
"Returned for Modification": "تمت إعادته للتعديل",
|
|
312
|
+
"Request For Change": "طلب تغيير",
|
|
313
313
|
"Closed": "مغلق",
|
|
314
314
|
"Completed": "مكتمل",
|
|
315
|
-
"Assigned": "
|
|
316
|
-
"Reassigned": "
|
|
315
|
+
"Assigned": "تم التعيين",
|
|
316
|
+
"Reassigned": "تمت إعادة التعيين",
|
|
317
317
|
"In Progress": "قيد التنفيذ",
|
|
318
318
|
"Attachment uploaded": "تم رفع المرفق"
|
|
319
319
|
}
|
|
@@ -96,6 +96,13 @@ export declare function toChatPersistFields(bilingual: BilingualText, status: st
|
|
|
96
96
|
status: string;
|
|
97
97
|
status_ar: string | null;
|
|
98
98
|
};
|
|
99
|
+
/** User-typed chat — never auto-translate; message_ar stays null. */
|
|
100
|
+
export declare function buildUserEnteredChatPersistFields(message: string, status: string): {
|
|
101
|
+
message: string;
|
|
102
|
+
message_ar: null;
|
|
103
|
+
status: string;
|
|
104
|
+
status_ar: string | null;
|
|
105
|
+
};
|
|
99
106
|
/** Bilingual chat insert fields for models using `content` column (Leave, Financial, etc.). */
|
|
100
107
|
export declare function toContentChatPersistFields(bilingual: BilingualText, status: string): {
|
|
101
108
|
content: string;
|
|
@@ -306,6 +313,8 @@ export declare function resolveChatStatusAr(status: string | null | undefined):
|
|
|
306
313
|
export declare function extractBilingualActorsFromRecord(record: Record<string, unknown>): BilingualActorNames;
|
|
307
314
|
export declare function resolveWorkflowContentAr(content: string | null | undefined, actors?: BilingualActorNames): string | null;
|
|
308
315
|
export declare function resolveChatMessageAr(message: string | null | undefined, actors?: BilingualActorNames): string | null;
|
|
316
|
+
/** True when message matches a known system chat template (safe to resolve message_ar). */
|
|
317
|
+
export declare function isSystemGeneratedChatMessage(message: string | null | undefined, actors?: BilingualActorNames): boolean;
|
|
309
318
|
/** Generic workflow log enricher — use in all module repositories. */
|
|
310
319
|
export declare function enrichWorkflowLog(log: Record<string, unknown>): Record<string, unknown>;
|
|
311
320
|
/** Generic chat enricher — use in all module repositories. Handles `message` or `content` column. */
|