├── tests ├── jest.d.ts ├── integration │ └── setup.ts ├── interfaces │ └── utils.ts ├── mocks │ ├── services │ │ └── userProfile.ts │ ├── randomData.ts │ └── grpc │ │ └── clients.ts ├── unit │ ├── actions │ │ ├── v1 │ │ │ ├── diiaId │ │ │ │ ├── getSigningHistory.spec.ts │ │ │ │ ├── getIdentifiers.spec.ts │ │ │ │ └── hasIdentifier.spec.ts │ │ │ ├── userInfo │ │ │ │ ├── hasUserProfile.spec.ts │ │ │ │ └── loadUserProfileFeaturesAsync.spec.ts │ │ │ ├── userDocument │ │ │ │ ├── getDocumentsTypeOrder.spec.ts │ │ │ │ └── hasOneOfDocuments.spec.ts │ │ │ ├── userVerification │ │ │ │ └── areFeaturePointsExist.spec.ts │ │ │ └── subscription │ │ │ │ └── getSubscribedSegments.spec.ts │ │ └── v2 │ │ │ ├── diiaId │ │ │ ├── checkIdentifierAvailability.spec.ts │ │ │ └── getIdentifiers.spec.ts │ │ │ └── userDocument │ │ │ ├── getDocumentsTypeOrder.spec.ts │ │ │ └── hasDocuments.spec.ts │ ├── providers │ │ └── creditHistory │ │ │ └── mock.spec.ts │ ├── scheduledTasks │ │ ├── checkDriverLicensesExpirations.ts.spec.ts │ │ ├── checkVehicleLicensesExpirations.spec.ts │ │ └── checkCovidCertificatesExpirations.spec.ts │ └── services │ │ └── address.spec.ts ├── tsconfig.json └── utils │ ├── getApp.ts │ └── deps.ts ├── src ├── interfaces │ ├── types │ │ └── index.ts │ ├── services │ │ ├── superGen.ts │ │ ├── userActionAccess.ts │ │ ├── fileGeneration.ts │ │ ├── eResidentDiiaIdConfirmation.ts │ │ ├── userSharingHistory.ts │ │ ├── userSigningHistory.ts │ │ ├── onboarding.ts │ │ ├── documentFeaturePoints.ts │ │ ├── auth.ts │ │ ├── userDocumentSettings.ts │ │ ├── userDocumentStorage.ts │ │ └── index.ts │ ├── config.ts │ ├── tasks │ │ ├── index.ts │ │ └── createNotificationsBatches.ts │ ├── eventListeners │ │ ├── authUserLogOut.ts │ │ ├── removeDocumentPhoto.ts │ │ ├── addDocumentPhoto.ts │ │ ├── authCreateOrUpdateUserProfile.ts │ │ ├── authCreateOrUpdateEResidentProfile.ts │ │ ├── publicServicePenaltyCreated.ts │ │ ├── documentsAdultRegistrationAddressCommunity.ts │ │ ├── addDocumentInProfile.ts │ │ ├── acquirersSharingStatus.ts │ │ ├── addDocumentsInProfile.ts │ │ ├── publicServiceSigningStatus.ts │ │ └── acquirersSigningStatus.ts │ ├── externalEventListeners │ │ ├── diiaIdCertificateInfo.ts │ │ ├── ubkiCreditInfo.ts │ │ ├── diiaIdCertificateRevoke.ts │ │ ├── faceRecoUserPhotoExtractFeaturePoints.ts │ │ ├── diiaIdCertificateCreate.ts │ │ ├── index.ts │ │ ├── diiaIdHashFile.ts │ │ ├── getUserInfoForFilters.ts │ │ ├── diiaIdSignDpsPackagePrepare.ts │ │ ├── notificationTopicSubscribeTarget.ts │ │ ├── diiaIdHashFilesIntegrity.ts │ │ ├── notificationSendTarget.ts │ │ ├── diiaIdHashFiles.ts │ │ └── diiaIdSignHashesInit.ts │ ├── actions │ │ ├── v2 │ │ │ ├── diiaId │ │ │ │ ├── getIdentifiers.ts │ │ │ │ ├── checkIdentifierAvailability.ts │ │ │ │ ├── initDiiaIdHashesSigning.ts │ │ │ │ ├── hashFilesToSign.ts │ │ │ │ ├── hasIdentifier.ts │ │ │ │ ├── getIdentifier.ts │ │ │ │ ├── createDiiaIdIdentifier.ts │ │ │ │ └── getSigningHistory.ts │ │ │ ├── userDocument │ │ │ │ ├── getDocumentsTypeOrder.ts │ │ │ │ ├── hasDocuments.ts │ │ │ │ ├── getUserDocuments.ts │ │ │ │ ├── saveDocumentTypesOrder.ts │ │ │ │ └── saveDocumentsOrderByDocumentType.ts │ │ │ ├── userHistory │ │ │ │ ├── getHistoryScreen.ts │ │ │ │ ├── getHistoryItemById.ts │ │ │ │ └── getHistoryByAction.ts │ │ │ └── subscription │ │ │ │ └── getSubscribedSegments.ts │ │ ├── v1 │ │ │ ├── diiaId │ │ │ │ ├── getIdentifiers.ts │ │ │ │ ├── deleteIdentifier.ts │ │ │ │ ├── hasIdentifier.ts │ │ │ │ ├── validateSignedFileHashes.ts │ │ │ │ ├── hashFileToSign.ts │ │ │ │ ├── checkIdentifierAvailability.ts │ │ │ │ ├── validateHashSignatures.ts │ │ │ │ ├── getIdentifier.ts │ │ │ │ ├── areSignedFileHashesValid.ts │ │ │ │ ├── getSigningHistory.ts │ │ │ │ ├── getDpsPreparedPackage.ts │ │ │ │ ├── getDpsHashFilesToSign.ts │ │ │ │ ├── createIdentifiers.ts │ │ │ │ ├── initHashesSigning.ts │ │ │ │ ├── hashFilesToSign.ts │ │ │ │ └── verifyHash.ts │ │ │ ├── userDocument │ │ │ │ ├── getDocumentsTypeOrder.ts │ │ │ │ ├── hasOneOfDocuments.ts │ │ │ │ ├── processUserDocuments.ts │ │ │ │ ├── updateDocumentVisibility.ts │ │ │ │ ├── removeBirthCertificate.ts │ │ │ │ ├── addDocumentInStorage.ts │ │ │ │ ├── hasStorageDocument.ts │ │ │ │ ├── removeUserDocumentById.ts │ │ │ │ ├── getUserDocumentSettings.ts │ │ │ │ ├── removeFromStorageByHashData.ts │ │ │ │ ├── getDocumentsOrder.ts │ │ │ │ ├── saveDocumentTypesOrder.ts │ │ │ │ ├── createDocumentFeaturePoints.ts │ │ │ │ ├── getUserDocuments.ts │ │ │ │ ├── getDecryptedDataFromStorage.ts │ │ │ │ ├── getDocumentsByFilters.ts │ │ │ │ ├── getEncryptedDataFromStorage.ts │ │ │ │ ├── checkUserDocumentsByTypes.ts │ │ │ │ ├── saveDocumentsOrderByDocumentType.ts │ │ │ │ ├── removeCovidCertificateFromStorage.ts │ │ │ │ └── getSubscribedDocuments.ts │ │ │ ├── userInfo │ │ │ │ ├── getCabinetUserInfo.ts │ │ │ │ ├── hasUserProfile.ts │ │ │ │ ├── loadUserProfileFeaturesAsync.ts │ │ │ │ ├── getUserInfo.ts │ │ │ │ ├── getUserProfiles.ts │ │ │ │ ├── getUserInfoForFilters.ts │ │ │ │ ├── getServiceUserByLogin.ts │ │ │ │ ├── getUsersFilterCoverage.ts │ │ │ │ ├── getUserProfileFeatures.ts │ │ │ │ └── saveUserCitizenship.ts │ │ │ ├── isUkrainianCitizen.ts │ │ │ ├── userVerification │ │ │ │ ├── getFeatures.ts │ │ │ │ ├── areFeaturePointsExist.ts │ │ │ │ ├── getFeaturePoints.ts │ │ │ │ └── checkDocumentsFeaturePoints.ts │ │ │ ├── createInternationalBankCard.ts │ │ │ ├── subscription │ │ │ │ ├── getSubscriptions.ts │ │ │ │ ├── getSubscribedSegments.ts │ │ │ │ ├── removeSubscription.ts │ │ │ │ ├── isSubscribed.ts │ │ │ │ ├── subscribe.ts │ │ │ │ ├── unsubscribe.ts │ │ │ │ ├── getSubscribedUserIdentifier.ts │ │ │ │ └── addSubscription.ts │ │ │ ├── userHistory │ │ │ │ ├── getHistoryScreen.ts │ │ │ │ ├── getSessionHistoryScreen.ts │ │ │ │ ├── getUserSharingStatuses.ts │ │ │ │ ├── getUserSigningStatuses.ts │ │ │ │ ├── countHistoryByAction.ts │ │ │ │ ├── getHistoryItemById.ts │ │ │ │ ├── getHistoryByAction.ts │ │ │ │ ├── getSessionHistoryItemById.ts │ │ │ │ └── getEResidentHistoryByAction.ts │ │ │ ├── createOrUpdateProfile.ts │ │ │ ├── startSendingSilentPushes.ts │ │ │ ├── generateInternationalItn.ts │ │ │ ├── decryptDocumentFromStorage.ts │ │ │ ├── actionAccess │ │ │ │ ├── hasActionAccess.ts │ │ │ │ ├── increaseCounterActionAccess.ts │ │ │ │ └── nullifyCounterActionAccess.ts │ │ │ ├── startSendingMessageNotifications.ts │ │ │ └── encryptDocumentInStorage.ts │ │ ├── v5 │ │ │ └── userDocument │ │ │ │ └── hasDocuments.ts │ │ ├── v3 │ │ │ ├── userDocument │ │ │ │ └── hasDocuments.ts │ │ │ ├── userHistory │ │ │ │ └── getHistoryByAction.ts │ │ │ └── diiaId │ │ │ │ └── areSignedFileHashesValid.ts │ │ └── v4 │ │ │ └── userDocument │ │ │ └── hasDocuments.ts │ ├── locales.ts │ ├── models │ │ ├── unregisteredOfficeProfile.ts │ │ ├── userOnboarding.ts │ │ ├── serviceUser.ts │ │ ├── userNewFeatures.ts │ │ ├── distribution.ts │ │ ├── userDevice.ts │ │ ├── documentFeaturePoints.ts │ │ ├── eResidentDevice.ts │ │ ├── userActionAccessSetting.ts │ │ ├── userDocumentStorage.ts │ │ ├── eResidentProfile.ts │ │ ├── newFeatures.ts │ │ ├── userDocumentSettings.ts │ │ ├── diiaId.ts │ │ ├── userSharingHistoryItem.ts │ │ ├── onboarding.ts │ │ ├── userDocument.ts │ │ ├── userProfile.ts │ │ └── subscription.ts │ └── providers │ │ └── creditHistory │ │ ├── index.ts │ │ └── ubch.ts ├── index.ts ├── externalEventListeners │ ├── diiaIdCertificateInfo.ts │ ├── diiaIdHashFile.ts │ ├── diiaIdSignDpsPackageInit.ts │ ├── diiaIdHashFilesIntegrity.ts │ ├── diiaIdSignDpsPackagePrepare.ts │ ├── diiaIdHashFiles.ts │ └── getUserInfoForFilters.ts ├── models │ ├── userOnboarding.ts │ ├── serviceUser.ts │ ├── userNewFeatures.ts │ ├── unregisteredOfficeProfile.ts │ ├── distribution.ts │ ├── userDevice.ts │ ├── eResidentDevice.ts │ ├── userActionAccessSetting.ts │ ├── userDocumentStorage.ts │ ├── documentFeaturePoints.ts │ ├── userDocumentSettings.ts │ └── diiaId.ts ├── bootstrap.ts ├── services │ ├── address.ts │ ├── serviceUser.ts │ ├── unregisteredOfficeProfile.ts │ ├── subscription │ │ └── strategies │ │ │ └── publicService.ts │ └── userActionAccessSetting.ts ├── providers │ └── creditHistory │ │ └── mock.ts ├── locales │ ├── en.json │ └── uk.json ├── dataMappers │ ├── documentFeaturePointsDataMapper.ts │ └── userProfileDataMapper.ts ├── scheduledTasks │ ├── checkDriverLicensesExpirations.ts │ ├── checkVehicleLicensesExpirations.ts │ └── checkCovidCertificatesExpirations.ts ├── actions │ ├── v1 │ │ ├── userInfo │ │ │ ├── getUserInfo.ts │ │ │ ├── getCabinetUserInfo.ts │ │ │ ├── hasUserProfile.ts │ │ │ ├── loadUserProfileFeaturesAsync.ts │ │ │ ├── getUserInfoForFilters.ts │ │ │ ├── getServiceUserByLogin.ts │ │ │ ├── getUserProfileFeatures.ts │ │ │ ├── getUserProfiles.ts │ │ │ └── saveUserCitizenship.ts │ │ ├── diiaId │ │ │ ├── getIdentifiers.ts │ │ │ ├── getSigningHistory.ts │ │ │ ├── hasIdentifier.ts │ │ │ ├── deleteIdentifier.ts │ │ │ ├── getIdentifier.ts │ │ │ └── getDpsPreparedPackage.ts │ │ ├── userHistory │ │ │ ├── getHistoryScreen.ts │ │ │ ├── getUserSharingStatuses.ts │ │ │ ├── getUserSigningStatuses.ts │ │ │ └── getSessionHistoryScreen.ts │ │ ├── subscription │ │ │ ├── getSubscriptions.ts │ │ │ ├── getSubscribedSegments.ts │ │ │ └── isSubscribed.ts │ │ ├── userDocument │ │ │ ├── getDocumentsTypeOrder.ts │ │ │ ├── getDocumentsOrder.ts │ │ │ ├── getUserDocumentSettings.ts │ │ │ ├── removeFromStorageByHashData.ts │ │ │ ├── processUserDocuments.ts │ │ │ └── hasOneOfDocuments.ts │ │ ├── userVerification │ │ │ ├── getFeaturePoints.ts │ │ │ ├── areFeaturePointsExist.ts │ │ │ ├── getFeatures.ts │ │ │ ├── checkDocumentsFeaturePoints.ts │ │ │ └── getEResidentFeatures.ts │ │ └── actionAccess │ │ │ ├── hasActionAccess.ts │ │ │ ├── nullifyCounterActionAccess.ts │ │ │ └── increaseCounterActionAccess.ts │ └── v2 │ │ ├── diiaId │ │ ├── getIdentifiers.ts │ │ ├── checkIdentifierAvailability.ts │ │ └── getIdentifier.ts │ │ ├── userHistory │ │ └── getHistoryScreen.ts │ │ ├── userDocument │ │ └── getDocumentsTypeOrder.ts │ │ └── subscription │ │ └── getSubscribedSegments.ts ├── eventListeners │ ├── removeDocumentPhoto.ts │ └── addDocumentPhoto.ts └── validation │ └── index.ts ├── .eslintignore ├── scripts └── generateEnv.sh ├── .dockerignore ├── migrate-mongo-config.ts ├── migrations ├── sample-migration.ts ├── tsconfig.json └── 20201228162642-add-user-action-access-setting.ts ├── .github └── workflows │ └── accept-contribution.yml ├── .env.test ├── tsconfig.json └── proto └── user-profile.proto /tests/jest.d.ts: -------------------------------------------------------------------------------- 1 | import '@diia-inhouse/configs/jest/types' 2 | -------------------------------------------------------------------------------- /src/interfaces/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from '@interfaces/config' 2 | -------------------------------------------------------------------------------- /src/interfaces/services/superGen.ts: -------------------------------------------------------------------------------- 1 | export interface GenerationResult { 2 | file: string 3 | } 4 | -------------------------------------------------------------------------------- /tests/integration/setup.ts: -------------------------------------------------------------------------------- 1 | import nock from 'nock' 2 | 3 | nock.disableNetConnect() 4 | 5 | jest.setTimeout(3000000) 6 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | coverage 4 | *.js 5 | jest.config.* 6 | migrate-mongo-config.ts 7 | src/generated 8 | -------------------------------------------------------------------------------- /src/interfaces/config.ts: -------------------------------------------------------------------------------- 1 | import config from '@src/config' 2 | 3 | export type AppConfig = Awaited> 4 | -------------------------------------------------------------------------------- /src/interfaces/services/userActionAccess.ts: -------------------------------------------------------------------------------- 1 | export enum ActionAccessType { 2 | AddBirthCertificate = 'addBirthCertificate', 3 | } 4 | -------------------------------------------------------------------------------- /src/interfaces/tasks/index.ts: -------------------------------------------------------------------------------- 1 | export enum ServiceTask { 2 | CREATE_NOTIFICATIONS_BATCHES = 'createNotificationsBatches', 3 | } 4 | -------------------------------------------------------------------------------- /tests/interfaces/utils.ts: -------------------------------------------------------------------------------- 1 | import TestKit from '@diia-inhouse/test' 2 | 3 | export interface TestDeps { 4 | testKit: TestKit 5 | } 6 | -------------------------------------------------------------------------------- /src/interfaces/services/fileGeneration.ts: -------------------------------------------------------------------------------- 1 | export interface GeneratePdfResult { 2 | fileName: string 3 | fileContent: Buffer 4 | } 5 | -------------------------------------------------------------------------------- /src/interfaces/eventListeners/authUserLogOut.ts: -------------------------------------------------------------------------------- 1 | export interface EventPayload { 2 | mobileUid: string 3 | userIdentifier: string 4 | } 5 | -------------------------------------------------------------------------------- /scripts/generateEnv.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Use "$@" to represent all the arguments 4 | for envVar in "$@" 5 | do 6 | echo $envVar >> .env 7 | done -------------------------------------------------------------------------------- /src/interfaces/externalEventListeners/diiaIdCertificateInfo.ts: -------------------------------------------------------------------------------- 1 | export interface DiiaIdCertificateInfoResponse { 2 | subjDRFOCode: string 3 | } 4 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | tsconfig-test.json 3 | coverage 4 | .vscode 5 | README.md 6 | Dockerfile 7 | jest.config.js 8 | .gitlab-ci.yml 9 | .git 10 | .gitignore -------------------------------------------------------------------------------- /src/interfaces/actions/v2/diiaId/getIdentifiers.ts: -------------------------------------------------------------------------------- 1 | import { DiiaIdIdentifiersResponse } from '@interfaces/services/diiaId' 2 | 3 | export type ActionResult = DiiaIdIdentifiersResponse 4 | -------------------------------------------------------------------------------- /migrate-mongo-config.ts: -------------------------------------------------------------------------------- 1 | require('dotenv-flow').config({ silent: true }) 2 | 3 | import { MongoHelper } from '@diia-inhouse/db' 4 | 5 | module.exports = MongoHelper.getMigrateMongoConfig() 6 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/diiaId/getIdentifiers.ts: -------------------------------------------------------------------------------- 1 | import { DiiaIdIdentifiersResponseV1 } from '@interfaces/services/diiaId' 2 | 3 | export type ActionResult = DiiaIdIdentifiersResponseV1 4 | -------------------------------------------------------------------------------- /src/interfaces/eventListeners/removeDocumentPhoto.ts: -------------------------------------------------------------------------------- 1 | export interface EventPayload { 2 | userIdentifier: string 3 | documentType: string 4 | documentIdentifier: string 5 | } 6 | -------------------------------------------------------------------------------- /src/interfaces/locales.ts: -------------------------------------------------------------------------------- 1 | import localesEn from '@src/locales/en.json' 2 | import localesUk from '@src/locales/uk.json' 3 | 4 | export type Locales = typeof localesEn & typeof localesUk 5 | -------------------------------------------------------------------------------- /src/interfaces/services/eResidentDiiaIdConfirmation.ts: -------------------------------------------------------------------------------- 1 | export interface EResidentDiiaIdInfoRequest { 2 | certificateSerialNumber: string 3 | registryUserIdentifier: string 4 | } 5 | -------------------------------------------------------------------------------- /src/interfaces/eventListeners/addDocumentPhoto.ts: -------------------------------------------------------------------------------- 1 | export interface EventPayload { 2 | userIdentifier: string 3 | documentType: string 4 | documentIdentifier: string 5 | photo: string 6 | } 7 | -------------------------------------------------------------------------------- /src/interfaces/services/userSharingHistory.ts: -------------------------------------------------------------------------------- 1 | import { UserSharingHistoryItem } from '@interfaces/models/userSharingHistoryItem' 2 | 3 | export type UpsertItemParams = Omit 4 | -------------------------------------------------------------------------------- /src/interfaces/services/userSigningHistory.ts: -------------------------------------------------------------------------------- 1 | import { UserSigningHistoryItem } from '@interfaces/models/userSigningHistoryItem' 2 | 3 | export type UpsertItemParams = Omit 4 | -------------------------------------------------------------------------------- /src/interfaces/models/unregisteredOfficeProfile.ts: -------------------------------------------------------------------------------- 1 | import { DiiaOfficeProfile } from '@interfaces/models/userProfile' 2 | 3 | export interface UnregisteredOfficeProfile { 4 | identifier: string 5 | profile: DiiaOfficeProfile 6 | } 7 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { initTracing } from '@diia-inhouse/diia-app' 2 | 3 | const serviceName = 'User' 4 | 5 | initTracing(serviceName) 6 | 7 | import 'module-alias/register' 8 | import { bootstrap } from './bootstrap' 9 | 10 | bootstrap(serviceName) 11 | -------------------------------------------------------------------------------- /src/interfaces/eventListeners/authCreateOrUpdateUserProfile.ts: -------------------------------------------------------------------------------- 1 | import { ActHeaders, Gender } from '@diia-inhouse/types' 2 | 3 | export interface EventPayload { 4 | itn: string 5 | gender: Gender 6 | birthDay: string 7 | headers: ActHeaders 8 | } 9 | -------------------------------------------------------------------------------- /src/interfaces/providers/creditHistory/index.ts: -------------------------------------------------------------------------------- 1 | export interface CreditHistoryProvider { 2 | subscribe(itn: string): Promise 3 | publishSubscription(itn: string): Promise 4 | unsubscribe(subId: string, itn: string): Promise 5 | } 6 | -------------------------------------------------------------------------------- /src/interfaces/externalEventListeners/ubkiCreditInfo.ts: -------------------------------------------------------------------------------- 1 | import { ExternalResponseBaseEventPayload } from '.' 2 | 3 | export interface EventPayload extends Pick { 4 | response: { 5 | data: string 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/getDocumentsTypeOrder.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | export type CustomActionArguments = UserActionArguments 4 | 5 | export interface ActionResult { 6 | documentsTypeOrder: string[] 7 | } 8 | -------------------------------------------------------------------------------- /src/interfaces/actions/v2/userDocument/getDocumentsTypeOrder.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | export type CustomActionArguments = UserActionArguments 4 | 5 | export interface ActionResult { 6 | documentsTypeOrder: string[] 7 | } 8 | -------------------------------------------------------------------------------- /src/interfaces/services/onboarding.ts: -------------------------------------------------------------------------------- 1 | import { NewFeaturesData } from '@interfaces/models/newFeatures' 2 | import { OnboardingData } from '@interfaces/models/onboarding' 3 | 4 | export interface OnboardingInfo { 5 | features?: NewFeaturesData | OnboardingData 6 | } 7 | -------------------------------------------------------------------------------- /src/interfaces/eventListeners/authCreateOrUpdateEResidentProfile.ts: -------------------------------------------------------------------------------- 1 | import { ActHeaders, Gender } from '@diia-inhouse/types' 2 | 3 | export interface EventPayload { 4 | userIdentifier: string 5 | gender: Gender 6 | birthDay: string 7 | headers: ActHeaders 8 | } 9 | -------------------------------------------------------------------------------- /src/interfaces/models/userOnboarding.ts: -------------------------------------------------------------------------------- 1 | import { Document } from '@diia-inhouse/db' 2 | 3 | export interface UserOnboarding { 4 | mobileUid: string 5 | onboardingAppVersion: string 6 | } 7 | 8 | export interface UserOnboardingModel extends UserOnboarding, Document {} 9 | -------------------------------------------------------------------------------- /src/interfaces/externalEventListeners/diiaIdCertificateRevoke.ts: -------------------------------------------------------------------------------- 1 | import { ExternalResponseBaseEventPayload } from '.' 2 | 3 | export interface EventPayload extends ExternalResponseBaseEventPayload { 4 | response?: { 5 | success: boolean 6 | error?: string 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/interfaces/models/serviceUser.ts: -------------------------------------------------------------------------------- 1 | import { Document } from '@diia-inhouse/db' 2 | 3 | export interface ServiceUser { 4 | login: string 5 | hashedPassword?: string 6 | twoFactorSecret?: string 7 | } 8 | 9 | export interface ServiceUserModel extends ServiceUser, Document {} 10 | -------------------------------------------------------------------------------- /src/interfaces/tasks/createNotificationsBatches.ts: -------------------------------------------------------------------------------- 1 | import { mongo } from '@diia-inhouse/db' 2 | import { PlatformType } from '@diia-inhouse/types' 3 | 4 | export interface EventPayload { 5 | messageId: mongo.ObjectId 6 | platformTypes: PlatformType[] 7 | useExpirations: boolean 8 | } 9 | -------------------------------------------------------------------------------- /src/interfaces/externalEventListeners/faceRecoUserPhotoExtractFeaturePoints.ts: -------------------------------------------------------------------------------- 1 | import { ExternalResponseBaseEventPayload } from '.' 2 | 3 | export interface EventPayload extends Pick { 4 | response: { 5 | feature_points: number[] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userInfo/getCabinetUserInfo.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { CabinetUserInfo } from '@interfaces/services/userProfile' 4 | 5 | export type CustomActionArguments = UserActionArguments 6 | 7 | export type ActionResult = CabinetUserInfo 8 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/isUkrainianCitizen.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends ServiceActionArguments { 4 | params: { 5 | userIdentifier: string 6 | } 7 | } 8 | 9 | export type ActionResult = boolean 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userVerification/getFeatures.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { OnboardingInfo } from '@interfaces/services/onboarding' 4 | 5 | export type CustomActionArguments = ServiceActionArguments 6 | 7 | export type ActionResult = OnboardingInfo 8 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userInfo/hasUserProfile.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends ServiceActionArguments { 4 | params: { 5 | userIdentifier: string 6 | } 7 | } 8 | 9 | export type ActionResult = boolean 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userInfo/loadUserProfileFeaturesAsync.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends ServiceActionArguments { 4 | params: { 5 | itn: string 6 | } 7 | } 8 | 9 | export type ActionResult = void 10 | -------------------------------------------------------------------------------- /src/interfaces/models/userNewFeatures.ts: -------------------------------------------------------------------------------- 1 | import { Document } from '@diia-inhouse/db' 2 | 3 | export interface UserNewFeatures { 4 | mobileUid: string 5 | featuresAppVersion: string 6 | viewsCounter: number 7 | } 8 | 9 | export interface UserNewFeaturesModel extends UserNewFeatures, Document {} 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/createInternationalBankCard.ts: -------------------------------------------------------------------------------- 1 | import { PartnerActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends PartnerActionArguments { 4 | params: { 5 | itn: string 6 | cardMask: string 7 | iban: string 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/subscription/getSubscriptions.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { SubscriptionsResponse } from '@interfaces/services/subscription' 4 | 5 | export type CustomActionArguments = UserActionArguments 6 | 7 | export type ActionResult = SubscriptionsResponse 8 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userHistory/getHistoryScreen.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { HistoryScreenResponseV1 } from '@interfaces/services/userHistory' 4 | 5 | export type CustomActionArguments = UserActionArguments 6 | 7 | export type ActionResult = HistoryScreenResponseV1 8 | -------------------------------------------------------------------------------- /src/interfaces/actions/v2/userHistory/getHistoryScreen.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { HistoryScreenResponse } from '@interfaces/services/userHistory' 4 | 5 | export type CustomActionArguments = UserActionArguments 6 | 7 | export type ActionResult = HistoryScreenResponse 8 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/subscription/getSubscribedSegments.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends ServiceActionArguments { 4 | params: { 5 | userIdentifier: string 6 | } 7 | } 8 | 9 | export type ActionResult = string[] 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userInfo/getUserInfo.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { UserInfoWithAttentionMessage } from '@interfaces/services/userProfile' 4 | 5 | export type CustomActionArguments = UserActionArguments 6 | 7 | export type ActionResult = UserInfoWithAttentionMessage 8 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/createOrUpdateProfile.ts: -------------------------------------------------------------------------------- 1 | import { Gender, ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends ServiceActionArguments { 4 | params: { 5 | identifier: string 6 | gender: Gender 7 | birthDay: string 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userVerification/areFeaturePointsExist.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends ServiceActionArguments { 4 | params: { 5 | userIdentifier: string 6 | } 7 | } 8 | 9 | export type ActionResult = boolean 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/startSendingSilentPushes.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends ServiceActionArguments { 4 | params: { 5 | actionType: string 6 | } 7 | } 8 | 9 | export interface ActionResult { 10 | success: boolean 11 | } 12 | -------------------------------------------------------------------------------- /src/interfaces/eventListeners/publicServicePenaltyCreated.ts: -------------------------------------------------------------------------------- 1 | export interface EventPayload { 2 | penaltyId: string 3 | vehicleLicenseIdentifier?: string 4 | fixingDate: Date 5 | } 6 | 7 | export interface IdentifiedPenalty { 8 | penaltyId: string 9 | penaltyFixingDate: Date 10 | userIdentifier: string 11 | } 12 | -------------------------------------------------------------------------------- /src/interfaces/externalEventListeners/diiaIdCertificateCreate.ts: -------------------------------------------------------------------------------- 1 | import { ExternalResponseBaseEventPayload } from '.' 2 | 3 | import { DiiaIdCreateCertificateResponse } from '@interfaces/services/diiaId' 4 | 5 | export interface EventPayload extends ExternalResponseBaseEventPayload { 6 | response?: DiiaIdCreateCertificateResponse 7 | } 8 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/diiaId/deleteIdentifier.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { ProcessCode } from '@interfaces/services' 4 | 5 | export type CustomActionArguments = UserActionArguments 6 | 7 | export interface ActionResult { 8 | success: boolean 9 | processCode: ProcessCode 10 | } 11 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/diiaId/hasIdentifier.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends ServiceActionArguments { 4 | params: { 5 | userIdentifier: string 6 | mobileUidToFilter: string 7 | } 8 | } 9 | 10 | export type ActionResult = boolean 11 | -------------------------------------------------------------------------------- /src/interfaces/models/distribution.ts: -------------------------------------------------------------------------------- 1 | import { Document, mongo } from '@diia-inhouse/db' 2 | import { PlatformType } from '@diia-inhouse/types' 3 | 4 | export interface Distribution { 5 | messageId: mongo.ObjectId 6 | platformTypes: PlatformType[] 7 | } 8 | 9 | export interface DistributionModel extends Distribution, Document {} 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v2/diiaId/checkIdentifierAvailability.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { DiiaIdIdentifier } from '@interfaces/services/diiaId' 4 | 5 | export type CustomActionArguments = UserActionArguments 6 | 7 | export interface ActionResult { 8 | identifiers: DiiaIdIdentifier[] 9 | } 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v2/userDocument/hasDocuments.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends ServiceActionArguments { 4 | params: { 5 | userIdentifier: string 6 | documentTypes: string[][] 7 | } 8 | } 9 | 10 | export type ActionResult = boolean 11 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/hasOneOfDocuments.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends ServiceActionArguments { 4 | params: { 5 | userIdentifier: string 6 | documentTypes: string[] 7 | } 8 | } 9 | 10 | export type ActionResult = boolean 11 | -------------------------------------------------------------------------------- /src/interfaces/externalEventListeners/index.ts: -------------------------------------------------------------------------------- 1 | import { HttpStatusCode } from '@diia-inhouse/types' 2 | 3 | export interface ExternalResponseEventError { 4 | message: string 5 | http_code: HttpStatusCode 6 | } 7 | 8 | export interface ExternalResponseBaseEventPayload { 9 | uuid: string 10 | error?: ExternalResponseEventError 11 | } 12 | -------------------------------------------------------------------------------- /src/interfaces/actions/v2/diiaId/initDiiaIdHashesSigning.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { InitDiiaIdHashesSigningRequest } from '@src/generated' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: InitDiiaIdHashesSigningRequest 7 | } 8 | 9 | export type ActionResult = void 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/diiaId/validateSignedFileHashes.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { ValidateSignedFileHashesRequest } from '@src/generated' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: ValidateSignedFileHashesRequest 7 | } 8 | 9 | export type ActionResult = void 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/processUserDocuments.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends ServiceActionArguments { 4 | params: { 5 | userIdentifier: string 6 | documentTypes: string[] 7 | } 8 | } 9 | 10 | export type ActionResult = [string, string][] 11 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/updateDocumentVisibility.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { UpdateDocumentVisibilityReq } from '@src/generated' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: UpdateDocumentVisibilityReq 7 | } 8 | 9 | export type ActionResult = void 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/removeBirthCertificate.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends UserActionArguments { 4 | params: { 5 | documentType: string 6 | documentId: string 7 | } 8 | } 9 | 10 | export interface ActionResult { 11 | success: boolean 12 | } 13 | -------------------------------------------------------------------------------- /src/interfaces/actions/v5/userDocument/hasDocuments.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { HasDocumentsRequest, HasDocumentsResponse } from '@src/generated' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: HasDocumentsRequest 7 | } 8 | 9 | export type ActionResult = HasDocumentsResponse 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/diiaId/hashFileToSign.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { HashFileToSignRequest, HashFileToSignResponse } from '@src/generated' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: HashFileToSignRequest 7 | } 8 | 9 | export type ActionResult = HashFileToSignResponse 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v2/diiaId/hashFilesToSign.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { HashFilesToSignRequest, HashFilesToSignResponse } from '@src/generated' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: HashFilesToSignRequest 7 | } 8 | 9 | export type ActionResult = HashFilesToSignResponse 10 | -------------------------------------------------------------------------------- /src/interfaces/eventListeners/documentsAdultRegistrationAddressCommunity.ts: -------------------------------------------------------------------------------- 1 | import { Gender } from '@diia-inhouse/types' 2 | 3 | export interface EventPayload { 4 | userIdentifier: string 5 | fName: string 6 | lName: string 7 | mName: string 8 | birthDay: string 9 | gender: Gender 10 | koatuu?: string 11 | communityKodificatorCode?: string 12 | } 13 | -------------------------------------------------------------------------------- /src/interfaces/models/userDevice.ts: -------------------------------------------------------------------------------- 1 | import { Document } from '@diia-inhouse/db' 2 | import { PlatformType } from '@diia-inhouse/types' 3 | 4 | export interface UserDevice { 5 | mobileUid: string 6 | userIdentifier?: string 7 | platformType: PlatformType 8 | platformVersion: string 9 | } 10 | 11 | export interface UserDeviceModel extends UserDevice, Document {} 12 | -------------------------------------------------------------------------------- /src/interfaces/services/documentFeaturePoints.ts: -------------------------------------------------------------------------------- 1 | export interface CheckPointsResult { 2 | documentType: string 3 | documentIdentifier: string 4 | } 5 | 6 | export interface GetPointsResult { 7 | documentType: string 8 | documentIdentifier: string 9 | points: number[] 10 | } 11 | 12 | export interface FeaturePointResponse { 13 | feature_points: number[] 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userInfo/getUserProfiles.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { GetUserProfilesRequest, GetUserProfilesResponse } from '@src/generated' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: GetUserProfilesRequest 7 | } 8 | 9 | export type ActionResult = GetUserProfilesResponse 10 | -------------------------------------------------------------------------------- /src/interfaces/models/documentFeaturePoints.ts: -------------------------------------------------------------------------------- 1 | import { Document } from '@diia-inhouse/db' 2 | 3 | export interface DocumentFeaturePoints { 4 | userIdentifier: string 5 | documentType: string 6 | documentIdentifier: string 7 | requestId: string 8 | points?: number[] 9 | } 10 | 11 | export interface DocumentFeaturePointsModel extends DocumentFeaturePoints, Document {} 12 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/generateInternationalItn.ts: -------------------------------------------------------------------------------- 1 | import { Gender, ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends ServiceActionArguments { 4 | params: { 5 | phoneNumber: string 6 | gender: Gender 7 | birthDay: string 8 | } 9 | } 10 | 11 | export interface ActionResult { 12 | itn: string 13 | } 14 | -------------------------------------------------------------------------------- /src/interfaces/actions/v2/userDocument/getUserDocuments.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { GetUserDocumentsRequest, GetUserDocumentsResponse } from '@src/generated' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: GetUserDocumentsRequest 7 | } 8 | 9 | export type ActionResult = GetUserDocumentsResponse 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/addDocumentInStorage.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends ServiceActionArguments { 4 | params: { 5 | userIdentifier: string 6 | mobileUid?: string 7 | hashData: string 8 | documentType: string 9 | encryptedData: string 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/hasStorageDocument.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends ServiceActionArguments { 4 | params: { 5 | userIdentifier: string 6 | mobileUid: string 7 | documentType: string 8 | id: string 9 | } 10 | } 11 | 12 | export type ActionResult = boolean 13 | -------------------------------------------------------------------------------- /src/interfaces/actions/v2/diiaId/hasIdentifier.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { HasDiiaIdIdentifierRequest, HasDiiaIdIdentifierResponse } from '@src/generated' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: HasDiiaIdIdentifierRequest 7 | } 8 | 9 | export type ActionResult = HasDiiaIdIdentifierResponse 10 | -------------------------------------------------------------------------------- /src/interfaces/models/eResidentDevice.ts: -------------------------------------------------------------------------------- 1 | import { Document } from '@diia-inhouse/db' 2 | import { PlatformType } from '@diia-inhouse/types' 3 | 4 | export interface EResidentDevice { 5 | mobileUid: string 6 | userIdentifier?: string 7 | platformType: PlatformType 8 | platformVersion: string 9 | } 10 | 11 | export interface EResidentDeviceModel extends EResidentDevice, Document {} 12 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/diiaId/checkIdentifierAvailability.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { SignAlgo } from '@interfaces/models/diiaId' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | signAlgo: SignAlgo 8 | } 9 | } 10 | 11 | export interface ActionResult { 12 | identifier?: string 13 | } 14 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userHistory/getSessionHistoryScreen.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { HistoryScreenResponse } from '@interfaces/services/userHistory' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | sessionId: string 8 | } 9 | } 10 | 11 | export type ActionResult = HistoryScreenResponse 12 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userInfo/getUserInfoForFilters.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { UserInfoForFilters } from '@interfaces/services/userProfile' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | userIdentifier: string 8 | } 9 | } 10 | 11 | export type ActionResult = UserInfoForFilters 12 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/removeUserDocumentById.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends ServiceActionArguments { 4 | params: { 5 | userIdentifier: string 6 | documentType: string 7 | documentId: string 8 | mobileUid: string 9 | } 10 | } 11 | 12 | export type ActionResult = void 13 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userInfo/getServiceUserByLogin.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { ServiceUser } from '@interfaces/models/serviceUser' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | login: string 8 | hashedPassword: string 9 | } 10 | } 11 | 12 | export type ActionResult = ServiceUser 13 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/diiaId/validateHashSignatures.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { ValidateHashSignaturesRequest, ValidateHashSignaturesResponse } from '@src/generated' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: ValidateHashSignaturesRequest 7 | } 8 | 9 | export type ActionResult = ValidateHashSignaturesResponse 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/subscription/removeSubscription.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { SubscriptionCode } from '@interfaces/services/subscription' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | code: SubscriptionCode 8 | } 9 | } 10 | 11 | export interface ActionResult { 12 | success: boolean 13 | } 14 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/getUserDocumentSettings.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { GetUserDocumentSettingsReq, GetUserDocumentSettingsRes } from '@src/generated' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: GetUserDocumentSettingsReq 7 | } 8 | 9 | export type ActionResult = GetUserDocumentSettingsRes 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/removeFromStorageByHashData.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends ServiceActionArguments { 4 | params: { 5 | userIdentifier: string 6 | mobileUid?: string 7 | documentType: string 8 | hashData: string 9 | } 10 | } 11 | 12 | export type ActionResult = void 13 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userInfo/getUsersFilterCoverage.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { UserFilter, UserFilterCoverage } from '@interfaces/services/userProfile' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | filter: UserFilter 8 | } 9 | } 10 | 11 | export type ActionResult = UserFilterCoverage 12 | -------------------------------------------------------------------------------- /src/interfaces/actions/v2/subscription/getSubscribedSegments.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { GetSubscribedSegmentsRequest, GetSubscribedSegmentsResponse } from '@src/generated' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: GetSubscribedSegmentsRequest 7 | } 8 | 9 | export type ActionResult = GetSubscribedSegmentsResponse 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userHistory/getUserSharingStatuses.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { UserHistoryItemStatusRecord } from '@interfaces/services/userHistory' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | sharingIds: string[] 8 | } 9 | } 10 | 11 | export type ActionResult = UserHistoryItemStatusRecord[] 12 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userHistory/getUserSigningStatuses.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { UserHistoryItemStatusRecord } from '@interfaces/services/userHistory' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | resourceIds: string[] 8 | } 9 | } 10 | 11 | export type ActionResult = UserHistoryItemStatusRecord[] 12 | -------------------------------------------------------------------------------- /src/interfaces/actions/v3/userDocument/hasDocuments.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { DocumentFilter } from '@interfaces/services/userDocument' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | userIdentifier: string 8 | filters: DocumentFilter[][] 9 | } 10 | } 11 | 12 | export type ActionResult = boolean 13 | -------------------------------------------------------------------------------- /src/interfaces/models/userActionAccessSetting.ts: -------------------------------------------------------------------------------- 1 | import { Document } from '@diia-inhouse/db' 2 | 3 | import { ActionAccessType } from '@interfaces/services/userActionAccess' 4 | 5 | export interface UserActionAccessSetting { 6 | actionAccessType: ActionAccessType 7 | expirationTime: number 8 | maxValue: number 9 | } 10 | 11 | export interface UserActionAccessSettingModel extends UserActionAccessSetting, Document {} 12 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/decryptDocumentFromStorage.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { DecryptedDocument } from '@interfaces/services/userDocumentStorage' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | userIdentifier: string 8 | documentType: string 9 | } 10 | } 11 | 12 | export type ActionResult = DecryptedDocument 13 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/getDocumentsOrder.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { UserDocumentsOrderParams, UserDocumentsOrderResponse } from '@interfaces/services/userDocumentSettings' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: UserDocumentsOrderParams 7 | } 8 | 9 | export type ActionResult = UserDocumentsOrderResponse[] 10 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/actionAccess/hasActionAccess.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { ActionAccessType } from '@interfaces/services/userActionAccess' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | userIdentifier: string 8 | actionAccessType: ActionAccessType 9 | } 10 | } 11 | 12 | export type ActionResult = boolean 13 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userHistory/countHistoryByAction.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { HistoryAction } from '@interfaces/services/userHistory' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | action: HistoryAction 8 | sessionId?: string 9 | } 10 | } 11 | 12 | export interface ActionResult { 13 | count: number 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userVerification/getFeaturePoints.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { GetPointsResult } from '@interfaces/services/documentFeaturePoints' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | userIdentifier: string 8 | } 9 | } 10 | 11 | export interface ActionResult { 12 | points: GetPointsResult[] 13 | } 14 | -------------------------------------------------------------------------------- /migrations/sample-migration.ts: -------------------------------------------------------------------------------- 1 | import 'module-alias/register' 2 | import { config } from 'dotenv-flow' 3 | import { Db } from 'mongodb' 4 | 5 | config({ silent: true }) 6 | 7 | const collectionName = '' 8 | 9 | export async function up(db: Db): Promise { 10 | // await db.createCollection(collectionName) 11 | } 12 | 13 | export async function down(db: Db): Promise { 14 | // await db.dropCollection(collectionName) 15 | } 16 | -------------------------------------------------------------------------------- /src/interfaces/models/userDocumentStorage.ts: -------------------------------------------------------------------------------- 1 | import { Document } from '@diia-inhouse/db' 2 | 3 | export interface UserDocumentStorage { 4 | userIdentifier: string 5 | mobileUid?: string 6 | hashData: string 7 | documentType: string 8 | encryptedData: string 9 | encryptedPhoto?: string 10 | encryptedDocPhoto?: string 11 | } 12 | 13 | export interface UserDocumentStorageModel extends UserDocumentStorage, Document {} 14 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/actionAccess/increaseCounterActionAccess.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { ActionAccessType } from '@interfaces/services/userActionAccess' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | userIdentifier: string 8 | actionAccessType: ActionAccessType 9 | } 10 | } 11 | 12 | export type ActionResult = void 13 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/actionAccess/nullifyCounterActionAccess.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { ActionAccessType } from '@interfaces/services/userActionAccess' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | userIdentifier: string 8 | actionAccessType: ActionAccessType 9 | } 10 | } 11 | 12 | export type ActionResult = void 13 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/saveDocumentTypesOrder.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { DocumentTypeWithOrder } from '@interfaces/services/userDocumentSettings' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | documentsOrder: DocumentTypeWithOrder[] 8 | } 9 | } 10 | 11 | export interface ActionResult { 12 | success: boolean 13 | } 14 | -------------------------------------------------------------------------------- /src/interfaces/actions/v2/diiaId/getIdentifier.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { SignAlgo } from '@interfaces/models/diiaId' 4 | import { DiiaIdIdentifierResponse } from '@interfaces/services/diiaId' 5 | 6 | export interface CustomActionArguments extends UserActionArguments { 7 | params: { 8 | signAlgo: SignAlgo 9 | } 10 | } 11 | 12 | export type ActionResult = DiiaIdIdentifierResponse 13 | -------------------------------------------------------------------------------- /src/interfaces/actions/v2/userDocument/saveDocumentTypesOrder.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { DocumentTypeWithOrder } from '@interfaces/services/userDocumentSettings' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | documentsOrder: DocumentTypeWithOrder[] 8 | } 9 | } 10 | 11 | export interface ActionResult { 12 | success: boolean 13 | } 14 | -------------------------------------------------------------------------------- /src/interfaces/actions/v2/userHistory/getHistoryItemById.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { HistoryItemResponse, UserHistoryCode } from '@interfaces/services/userHistory' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | itemId: string 8 | actionCode: UserHistoryCode 9 | } 10 | } 11 | 12 | export type ActionResult = HistoryItemResponse 13 | -------------------------------------------------------------------------------- /src/interfaces/externalEventListeners/diiaIdHashFile.ts: -------------------------------------------------------------------------------- 1 | import { FileToHash, HashedFile } from '@interfaces/externalEventListeners/diiaIdHashFiles' 2 | import { SignAlgo } from '@interfaces/models/diiaId' 3 | 4 | export interface DiiaIdHashFileRequest { 5 | processId: string 6 | file: FileToHash 7 | signAlgo: SignAlgo 8 | } 9 | 10 | export interface DiiaIdHashFileResponse { 11 | processId: string 12 | hash: HashedFile 13 | } 14 | -------------------------------------------------------------------------------- /.github/workflows/accept-contribution.yml: -------------------------------------------------------------------------------- 1 | on: 2 | workflow_dispatch: 3 | inputs: 4 | pr_number: 5 | description: Number of accepted PR 6 | required: true 7 | 8 | jobs: 9 | accept-contribution: 10 | with: 11 | pr_number: ${{ inputs.pr_number }} 12 | uses: diia-open-source/reusable-workflows/.github/workflows/accept-contribution-be.yml@main 13 | secrets: inherit 14 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/createDocumentFeaturePoints.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | export interface CustomActionArguments extends ServiceActionArguments { 4 | params: { 5 | userIdentifier?: string 6 | documentType: string 7 | documentIdentifier: string 8 | photo: string 9 | } 10 | } 11 | 12 | export interface ActionResult { 13 | points: number[] 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/diiaId/getIdentifier.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { SignAlgo } from '@interfaces/models/diiaId' 4 | import { DiiaIdResponse } from '@interfaces/services/diiaId' 5 | 6 | export interface CustomActionArguments extends UserActionArguments { 7 | params: { 8 | signAlgo: SignAlgo 9 | } 10 | } 11 | 12 | export interface ActionResult { 13 | diiaId?: DiiaIdResponse 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userInfo/getUserProfileFeatures.ts: -------------------------------------------------------------------------------- 1 | import { ProfileFeature, ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { UserProfileFeatures } from '@interfaces/models/userProfile' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | userIdentifier: string 8 | features: ProfileFeature[] 9 | } 10 | } 11 | 12 | export type ActionResult = UserProfileFeatures 13 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userVerification/checkDocumentsFeaturePoints.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { CheckPointsResult } from '@interfaces/services/documentFeaturePoints' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | userIdentifier: string 8 | } 9 | } 10 | 11 | export interface ActionResult { 12 | documents: CheckPointsResult[] 13 | } 14 | -------------------------------------------------------------------------------- /src/interfaces/externalEventListeners/getUserInfoForFilters.ts: -------------------------------------------------------------------------------- 1 | import { Gender } from '@diia-inhouse/types' 2 | 3 | import { UserDocumentTypesCounts } from '@interfaces/services/userDocument' 4 | 5 | export interface EventPayload { 6 | uuid: string 7 | request: { 8 | userIdentifier: string 9 | } 10 | } 11 | 12 | export interface ActionResult { 13 | age: number 14 | gender: Gender 15 | documents: UserDocumentTypesCounts 16 | } 17 | -------------------------------------------------------------------------------- /tests/mocks/services/userProfile.ts: -------------------------------------------------------------------------------- 1 | import { randomUUID } from 'node:crypto' 2 | 3 | import { Gender } from '@diia-inhouse/types' 4 | 5 | import { UserProfile } from '@interfaces/models/userProfile' 6 | 7 | export function getUserProfile(data: Partial = {}): UserProfile { 8 | return { 9 | identifier: randomUUID(), 10 | gender: Gender.female, 11 | birthDay: new Date('2000-01-01'), 12 | ...data, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/diiaId/areSignedFileHashesValid.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { SignAlgo } from '@interfaces/models/diiaId' 4 | import { SignedFileHash } from '@interfaces/services/diiaId' 5 | 6 | export interface CustomActionArguments extends UserActionArguments { 7 | params: { 8 | files: SignedFileHash[] 9 | signAlgo: SignAlgo 10 | } 11 | } 12 | 13 | export type ActionResult = boolean 14 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/diiaId/getSigningHistory.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | // import { SigningRequest } from '@interfaces/models/diiaIdSigningRequest'; 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | skip?: number 8 | limit?: number 9 | } 10 | } 11 | 12 | export interface ActionResult { 13 | signingRequests: unknown[] 14 | total: number 15 | } 16 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/subscription/isSubscribed.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { PublicServiceCode } from '@interfaces/models/subscription' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | userIdentifier: string 8 | publicService: PublicServiceCode 9 | subscriptionKey?: string 10 | } 11 | } 12 | 13 | export type ActionResult = boolean 14 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userHistory/getHistoryItemById.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { SigningHistoryItemResponseV1, UserHistoryCode } from '@interfaces/services/userHistory' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | itemId: string 8 | actionCode: UserHistoryCode 9 | } 10 | } 11 | 12 | export type ActionResult = SigningHistoryItemResponseV1 13 | -------------------------------------------------------------------------------- /src/interfaces/externalEventListeners/diiaIdSignDpsPackagePrepare.ts: -------------------------------------------------------------------------------- 1 | export interface DiiaIdSignDpsPackagePrepareRequest { 2 | identifier: string 3 | registryUserIdentifier: string 4 | certificateSerialNumber: string 5 | } 6 | 7 | export interface TaxReportDao { 8 | fname: string 9 | contentBase64: string 10 | } 11 | 12 | export interface DiiaIdSignDpsPackagePrepareResponse { 13 | identifier: string 14 | inReportDaoArray: TaxReportDao[] 15 | } 16 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/getUserDocuments.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { UserDocument } from '@interfaces/models/userDocument' 4 | import { GetUserDocumentsParams } from '@interfaces/services/userDocument' 5 | 6 | export interface CustomActionArguments extends ServiceActionArguments { 7 | params: GetUserDocumentsParams 8 | } 9 | 10 | export interface ActionResult { 11 | documents: UserDocument[] 12 | } 13 | -------------------------------------------------------------------------------- /src/interfaces/actions/v2/userHistory/getHistoryByAction.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { HistoryResponseByCodeV1, UserHistoryCode } from '@interfaces/services/userHistory' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | action: UserHistoryCode 8 | skip?: number 9 | limit?: number 10 | } 11 | } 12 | 13 | export type ActionResult = HistoryResponseByCodeV1 14 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userInfo/saveUserCitizenship.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { CitizenshipSource } from '@interfaces/models/userProfile' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | userIdentifier: string 8 | source: CitizenshipSource 9 | sourceId: string 10 | } 11 | } 12 | 13 | export interface ActionResult { 14 | success: boolean 15 | } 16 | -------------------------------------------------------------------------------- /src/interfaces/eventListeners/addDocumentInProfile.ts: -------------------------------------------------------------------------------- 1 | import { PlatformType } from '@diia-inhouse/types' 2 | 3 | import { UserProfileDocument } from '@interfaces/services/documents' 4 | 5 | export interface EventPayload extends UserProfileDocument { 6 | userIdentifier: string 7 | documentType: string 8 | headers: { 9 | mobileUid: string 10 | platformType: PlatformType 11 | platformVersion: string 12 | appVersion: string 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/getDecryptedDataFromStorage.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { DecryptedDocuments } from '@interfaces/services/userDocumentStorage' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | userIdentifier: string 8 | mobileUid?: string 9 | documentTypes?: string[] 10 | } 11 | } 12 | 13 | export type ActionResult = DecryptedDocuments 14 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userHistory/getHistoryByAction.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { HistoryAction, HistoryResponse } from '@interfaces/services/userHistory' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | action: HistoryAction 8 | session?: string 9 | skip?: number 10 | limit?: number 11 | } 12 | } 13 | 14 | export type ActionResult = HistoryResponse 15 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userHistory/getSessionHistoryItemById.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { HistoryItemResponse, UserHistoryCode } from '@interfaces/services/userHistory' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | sessionId: string 8 | actionCode: UserHistoryCode 9 | itemId: string 10 | } 11 | } 12 | 13 | export type ActionResult = HistoryItemResponse 14 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/startSendingMessageNotifications.ts: -------------------------------------------------------------------------------- 1 | import { mongo } from '@diia-inhouse/db' 2 | import { PlatformType, ServiceActionArguments } from '@diia-inhouse/types' 3 | 4 | export interface CustomActionArguments extends ServiceActionArguments { 5 | params: { 6 | messageId: string 7 | platformTypes?: PlatformType[] 8 | useExpirations?: boolean 9 | } 10 | } 11 | 12 | export interface ActionResult { 13 | distributionId: mongo.ObjectId 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/subscription/subscribe.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { SubscriptionType } from '@interfaces/models/subscription' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | subscriptionType: SubscriptionType 8 | documentType: string 9 | documentSubscriptionId: string 10 | } 11 | } 12 | 13 | export interface ActionResult { 14 | success: boolean 15 | } 16 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userHistory/getEResidentHistoryByAction.ts: -------------------------------------------------------------------------------- 1 | import { AppUserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { HistoryAction, HistoryResponse } from '@interfaces/services/userHistory' 4 | 5 | export type CustomActionArguments = AppUserActionArguments & { 6 | params: { 7 | action: HistoryAction 8 | session?: string 9 | skip?: number 10 | limit?: number 11 | } 12 | } 13 | 14 | export type ActionResult = HistoryResponse 15 | -------------------------------------------------------------------------------- /src/interfaces/actions/v4/userDocument/hasDocuments.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { DocumentFilter } from '@interfaces/services/userDocument' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | userIdentifier: string 8 | filters: DocumentFilter[][] 9 | } 10 | } 11 | 12 | export type ActionResult = { 13 | hasDocuments: boolean 14 | missingDocumnets: string[] 15 | } 16 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/subscription/unsubscribe.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { SubscriptionType } from '@interfaces/models/subscription' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | subscriptionType: SubscriptionType 8 | documentType: string 9 | documentSubscriptionId: string 10 | } 11 | } 12 | 13 | export interface ActionResult { 14 | success: boolean 15 | } 16 | -------------------------------------------------------------------------------- /src/interfaces/services/auth.ts: -------------------------------------------------------------------------------- 1 | export enum AuthProviderName { 2 | Monobank = 'monobank', 3 | PrivatBank = 'privatbank', 4 | PhotoId = 'photoid', 5 | BankId = 'bankid', 6 | Nfc = 'nfc', 7 | } 8 | 9 | export enum AuthSchemaCode { 10 | DiiaIdCreation = 'diia-id-creation', 11 | EResidentDiiaIdCreation = 'e-resident-diia-id-creation', 12 | } 13 | 14 | export interface RevokeSubmitAfterUserAuthStepsResult { 15 | success: boolean 16 | revokedActions: number 17 | } 18 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/diiaId/getDpsPreparedPackage.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { TaxReportDao } from '@interfaces/externalEventListeners/diiaIdSignDpsPackagePrepare' 4 | import { SignAlgo } from '@interfaces/models/diiaId' 5 | 6 | export interface CustomActionArguments extends UserActionArguments { 7 | params: { 8 | signAlgo: SignAlgo 9 | } 10 | } 11 | 12 | export interface ActionResult { 13 | taxPackage: TaxReportDao[] 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/getDocumentsByFilters.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { UserDocument } from '@interfaces/models/userDocument' 4 | import { DocumentFilter } from '@interfaces/services/userDocument' 5 | 6 | export interface CustomActionArguments extends ServiceActionArguments { 7 | params: { 8 | filters: DocumentFilter[] 9 | } 10 | } 11 | 12 | export interface ActionResult { 13 | documents: UserDocument[] 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/actions/v3/userHistory/getHistoryByAction.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { HistoryResponseByCode, UserHistoryCode } from '@interfaces/services/userHistory' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | action: UserHistoryCode 8 | session?: string 9 | skip?: number 10 | limit?: number 11 | } 12 | } 13 | 14 | export type ActionResult = HistoryResponseByCode 15 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/getEncryptedDataFromStorage.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { EncryptedDataByDocumentType } from '@interfaces/services/userDocumentStorage' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | userIdentifier: string 8 | mobileUid?: string 9 | documentTypes?: string[] 10 | } 11 | } 12 | 13 | export type ActionResult = EncryptedDataByDocumentType 14 | -------------------------------------------------------------------------------- /src/interfaces/eventListeners/acquirersSharingStatus.ts: -------------------------------------------------------------------------------- 1 | import { SharingHistoryAcquirer, SharingHistoryOffer } from '@interfaces/models/userSharingHistoryItem' 2 | import { UserHistoryItemStatus } from '@interfaces/services/userHistory' 3 | 4 | export interface EventPayload { 5 | userIdentifier: string 6 | mobileUid: string 7 | sharingId: string 8 | status: UserHistoryItemStatus 9 | documents: string[] 10 | acquirer: SharingHistoryAcquirer 11 | offer?: SharingHistoryOffer 12 | } 13 | -------------------------------------------------------------------------------- /src/interfaces/actions/v2/diiaId/createDiiaIdIdentifier.ts: -------------------------------------------------------------------------------- 1 | import { AppUserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { SignAlgo } from '@interfaces/models/diiaId' 4 | import { ProcessCode } from '@interfaces/services' 5 | 6 | export type CustomActionArguments = AppUserActionArguments & { 7 | params: { 8 | processId: string 9 | signAlgo: SignAlgo 10 | } 11 | } 12 | 13 | export interface ActionResult { 14 | identifier: string 15 | processCode: ProcessCode 16 | } 17 | -------------------------------------------------------------------------------- /src/interfaces/externalEventListeners/notificationTopicSubscribeTarget.ts: -------------------------------------------------------------------------------- 1 | import { NotificationAppVersionsByPlatformType } from '@interfaces/services/notification' 2 | import { UserFilter } from '@interfaces/services/userProfile' 3 | 4 | export interface EventPayload { 5 | uuid: string 6 | request: { 7 | filter: UserFilter 8 | channel: string 9 | topicsBatch?: number 10 | campaignId?: string 11 | appVersions?: NotificationAppVersionsByPlatformType 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/checkUserDocumentsByTypes.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { DocumentToVerify, VerifiedDocument } from '@interfaces/services/userDocument' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | userIdentifier: string 8 | documentsToVerify: DocumentToVerify[] 9 | } 10 | } 11 | 12 | export interface ActionResult { 13 | verifiedDocuments: VerifiedDocument[] 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/externalEventListeners/diiaIdHashFilesIntegrity.ts: -------------------------------------------------------------------------------- 1 | import { FileIntegrityResult, SignedFileHash } from '@interfaces/services/diiaId' 2 | 3 | export interface DiiaIdHashFilesIntegrityRequest { 4 | identifier: string 5 | registryUserIdentifier: string 6 | certificateSerialNumber: string 7 | files: SignedFileHash[] 8 | returnOriginals?: boolean 9 | } 10 | 11 | export interface DiiaIdHashFilesIntegrityResponse { 12 | identifier: string 13 | checkResults: FileIntegrityResult[] 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/encryptDocumentInStorage.ts: -------------------------------------------------------------------------------- 1 | import { DocumentDecryptedData } from '@diia-inhouse/crypto' 2 | import { ServiceActionArguments } from '@diia-inhouse/types' 3 | 4 | export interface CustomActionArguments extends ServiceActionArguments { 5 | params: { 6 | userIdentifier: string 7 | documentType: string 8 | dataToEncrypt: DocumentDecryptedData 9 | photoToEncrypt?: string 10 | docPhotoToEncrypt?: string 11 | } 12 | } 13 | 14 | export type ActionResult = void 15 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/saveDocumentsOrderByDocumentType.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { SaveDocumentsOrderByDocumentTypeRequest } from '@interfaces/services/userDocumentSettings' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | documentType: string 8 | documentsOrder: SaveDocumentsOrderByDocumentTypeRequest[] 9 | } 10 | } 11 | 12 | export interface ActionResult { 13 | success: boolean 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/actions/v2/userDocument/saveDocumentsOrderByDocumentType.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { SaveDocumentsOrderByDocumentTypeRequest } from '@interfaces/services/userDocumentSettings' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | documentType: string 8 | documentsOrder: SaveDocumentsOrderByDocumentTypeRequest[] 9 | } 10 | } 11 | 12 | export interface ActionResult { 13 | success: boolean 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/diiaId/getDpsHashFilesToSign.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { FileToHash, HashedFile } from '@interfaces/externalEventListeners/diiaIdHashFiles' 4 | import { SignAlgo } from '@interfaces/models/diiaId' 5 | 6 | export interface CustomActionArguments extends UserActionArguments { 7 | params: { 8 | files: FileToHash[] 9 | signAlgo: SignAlgo 10 | } 11 | } 12 | 13 | export interface ActionResult { 14 | hashedFiles: HashedFile[] 15 | } 16 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/subscription/getSubscribedUserIdentifier.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { PublicServiceCode, SubscriptionType } from '@interfaces/models/subscription' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | subscriptionType: SubscriptionType 8 | publicServiceCode: PublicServiceCode 9 | subscribedIdentifier: string 10 | } 11 | } 12 | 13 | export type ActionResult = string | undefined 14 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/subscription/addSubscription.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { ProcessCode } from '@interfaces/services' 4 | import { SubscriptionCode } from '@interfaces/services/subscription' 5 | 6 | export interface CustomActionArguments extends UserActionArguments { 7 | params: { 8 | code: SubscriptionCode 9 | segmentId?: string 10 | } 11 | } 12 | 13 | export interface ActionResult { 14 | success?: boolean 15 | processCode?: ProcessCode 16 | } 17 | -------------------------------------------------------------------------------- /src/interfaces/eventListeners/addDocumentsInProfile.ts: -------------------------------------------------------------------------------- 1 | import { PlatformType } from '@diia-inhouse/types' 2 | 3 | import { UserProfileDocument } from '@interfaces/services/documents' 4 | 5 | export interface EventPayload { 6 | userIdentifier: string 7 | documentType: string 8 | documents: UserProfileDocument[] 9 | headers: { 10 | mobileUid?: string 11 | platformType?: PlatformType 12 | platformVersion?: string 13 | appVersion?: string 14 | } 15 | removeMissingDocuments?: boolean 16 | } 17 | -------------------------------------------------------------------------------- /src/interfaces/actions/v2/diiaId/getSigningHistory.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { AttentionMessage } from '@interfaces/services/index' 4 | 5 | export interface CustomActionArguments extends UserActionArguments { 6 | params: { 7 | skip?: number 8 | limit?: number 9 | } 10 | } 11 | 12 | export interface ActionResult { 13 | isAvailable: boolean 14 | text?: string 15 | attentionMessage?: AttentionMessage 16 | signingRequests: unknown[] 17 | total: number 18 | } 19 | -------------------------------------------------------------------------------- /src/interfaces/actions/v3/diiaId/areSignedFileHashesValid.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { SignAlgo } from '@interfaces/models/diiaId' 4 | import { AreSignedFileHashesValidResult, SignedFileHash } from '@interfaces/services/diiaId' 5 | 6 | export interface CustomActionArguments extends UserActionArguments { 7 | params: { 8 | files: SignedFileHash[] 9 | returnOriginals?: boolean 10 | signAlgo: SignAlgo 11 | } 12 | } 13 | 14 | export type ActionResult = AreSignedFileHashesValidResult 15 | -------------------------------------------------------------------------------- /tests/unit/actions/v1/diiaId/getSigningHistory.spec.ts: -------------------------------------------------------------------------------- 1 | import GetDiiaIdSigningHistoryAction from '@actions/v1/diiaId/getSigningHistory' 2 | 3 | describe(`Action ${GetDiiaIdSigningHistoryAction.name}`, () => { 4 | const getDiiaIdSigningHistoryAction = new GetDiiaIdSigningHistoryAction() 5 | 6 | describe('Method `handler`', () => { 7 | it('should return result of signing history', async () => { 8 | expect(await getDiiaIdSigningHistoryAction.handler()).toMatchObject({ signingRequests: [], total: 0 }) 9 | }) 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /src/interfaces/externalEventListeners/notificationSendTarget.ts: -------------------------------------------------------------------------------- 1 | import { MessageTemplateCode, NotificationAppVersionsByPlatformType, TemplateParams } from '@interfaces/services/notification' 2 | import { UserFilter } from '@interfaces/services/userProfile' 3 | 4 | export interface EventPayload { 5 | uuid: string 6 | request: { 7 | filter: UserFilter 8 | templateCode: MessageTemplateCode 9 | resourceId?: string 10 | templateParams?: TemplateParams 11 | appVersions?: NotificationAppVersionsByPlatformType 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/externalEventListeners/diiaIdCertificateInfo.ts: -------------------------------------------------------------------------------- 1 | import { EventBusListener } from '@diia-inhouse/diia-queue' 2 | import { ValidationSchema } from '@diia-inhouse/validators' 3 | 4 | import { ExternalEvent } from '@interfaces/queue' 5 | 6 | export default class DiiaIdCertificateInfoEventListener implements EventBusListener { 7 | readonly event: ExternalEvent = ExternalEvent.DiiaIdCertificateInfo 8 | 9 | readonly isSync: boolean = true 10 | 11 | readonly validationRules: ValidationSchema = { 12 | subjDRFOCode: { type: 'string' }, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/removeCovidCertificateFromStorage.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { VaccinationCertificateType } from '@interfaces/services/userDocumentStorage' 4 | 5 | export interface CustomActionArguments extends ServiceActionArguments { 6 | params: { 7 | userIdentifier: string 8 | mobileUid: string 9 | documentType: string 10 | types: VaccinationCertificateType[] 11 | birthCertificateId?: string 12 | } 13 | } 14 | 15 | export type ActionResult = void 16 | -------------------------------------------------------------------------------- /src/models/userOnboarding.ts: -------------------------------------------------------------------------------- 1 | import { Model, Schema, model, models } from '@diia-inhouse/db' 2 | 3 | import { UserOnboarding } from '@interfaces/models/userOnboarding' 4 | 5 | const userOnboardingSchema = new Schema( 6 | { 7 | mobileUid: { type: String, unique: true, required: true }, 8 | onboardingAppVersion: { type: String, required: true }, 9 | }, 10 | { 11 | timestamps: true, 12 | }, 13 | ) 14 | 15 | export default >models.UserOnboarding || model('UserOnboarding', userOnboardingSchema) 16 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/userDocument/getSubscribedDocuments.ts: -------------------------------------------------------------------------------- 1 | import { ServiceActionArguments } from '@diia-inhouse/types' 2 | 3 | import { SubscriptionType } from '@interfaces/models/subscription' 4 | import { UserDocument } from '@interfaces/models/userDocument' 5 | 6 | export interface CustomActionArguments extends ServiceActionArguments { 7 | params: { 8 | userIdentifier: string 9 | subscriptionType: SubscriptionType 10 | documentType: string 11 | } 12 | } 13 | 14 | export interface ActionResult { 15 | documents: UserDocument[] 16 | } 17 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/diiaId/createIdentifiers.ts: -------------------------------------------------------------------------------- 1 | import { AppUserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { SignAlgo } from '@interfaces/models/diiaId' 4 | import { ProcessCode } from '@interfaces/services' 5 | import { DiiaIdIdentifier } from '@interfaces/services/diiaId' 6 | 7 | export type CustomActionArguments = AppUserActionArguments & { 8 | params: { 9 | processId: string 10 | signAlgo: SignAlgo[] 11 | } 12 | } 13 | 14 | export interface ActionResult { 15 | identifiers: DiiaIdIdentifier[] 16 | processCode: ProcessCode 17 | } 18 | -------------------------------------------------------------------------------- /src/models/serviceUser.ts: -------------------------------------------------------------------------------- 1 | import { Model, Schema, model, models } from '@diia-inhouse/db' 2 | 3 | import { ServiceUser } from '@interfaces/models/serviceUser' 4 | 5 | const ServiceUserSchema = new Schema( 6 | { 7 | login: { type: String, required: true, unique: true }, 8 | hashedPassword: { type: String }, 9 | twoFactorSecret: { type: String, unique: true, sparse: true }, 10 | }, 11 | { 12 | timestamps: true, 13 | }, 14 | ) 15 | 16 | export default >models.ServiceUser || model('ServiceUser', ServiceUserSchema) 17 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/diiaId/initHashesSigning.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { DiiaIdSignType } from '@interfaces/externalEventListeners/diiaIdSignHashesInit' 4 | import { SignAlgo } from '@interfaces/models/diiaId' 5 | 6 | export interface CustomActionArguments extends UserActionArguments { 7 | params: { 8 | signAlgo: SignAlgo 9 | signType: DiiaIdSignType 10 | noSigningTime?: boolean 11 | noContentTimestamp?: boolean 12 | } 13 | } 14 | 15 | export interface ActionResult { 16 | success: boolean 17 | } 18 | -------------------------------------------------------------------------------- /src/bootstrap.ts: -------------------------------------------------------------------------------- 1 | import { Application, ServiceContext } from '@diia-inhouse/diia-app' 2 | 3 | import configFactory from '@src/config' 4 | import deps from '@src/deps' 5 | 6 | import { AppDeps } from '@interfaces/application' 7 | import { AppConfig } from '@interfaces/config' 8 | 9 | export async function bootstrap(serviceName: string): Promise { 10 | const app = new Application>(serviceName) 11 | 12 | await app.setConfig(configFactory) 13 | 14 | await app.setDeps(deps) 15 | 16 | const { start } = await app.initialize() 17 | 18 | await start() 19 | } 20 | -------------------------------------------------------------------------------- /src/models/userNewFeatures.ts: -------------------------------------------------------------------------------- 1 | import { Model, Schema, model, models } from '@diia-inhouse/db' 2 | 3 | import { UserNewFeatures } from '@interfaces/models/userNewFeatures' 4 | 5 | const userFeaturesSchema = new Schema( 6 | { 7 | mobileUid: { type: String, required: true, unique: true }, 8 | featuresAppVersion: { type: String, required: true }, 9 | viewsCounter: { type: Number, required: true }, 10 | }, 11 | { 12 | timestamps: true, 13 | }, 14 | ) 15 | 16 | export default >models.UserFeatures || model('UserFeatures', userFeaturesSchema) 17 | -------------------------------------------------------------------------------- /src/services/address.ts: -------------------------------------------------------------------------------- 1 | import { MoleculerService } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion } from '@diia-inhouse/types' 4 | 5 | export default class AddressService { 6 | private readonly serviceName = 'Address' 7 | 8 | constructor(private readonly moleculer: MoleculerService) {} 9 | 10 | async findCommunityCodeByKoatuu(koatuu?: string): Promise { 11 | return await this.moleculer.act( 12 | this.serviceName, 13 | { name: 'findCommunityCodeByKoatuu', actionVersion: ActionVersion.V1 }, 14 | { params: { koatuu } }, 15 | ) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig", 3 | "compilerOptions": { 4 | "baseUrl": "../", 5 | "paths": { 6 | "@services/*": ["src/services/*"], 7 | "@providers/*": ["src/providers/*"], 8 | "@interfaces/*": ["src/interfaces/*"], 9 | "@models/*": ["src/models/*"], 10 | "@dataMappers/*": ["src/dataMappers/*"], 11 | "@actions/*": ["src/actions/*"], 12 | "@src/*": ["src/*"], 13 | "@tests/*": ["tests/*"], 14 | "@mocks/*": ["tests/mocks/*"] 15 | } 16 | }, 17 | "include": ["./**/*"] 18 | } 19 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/diiaId/hashFilesToSign.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { FileToHash, HashedFile } from '@interfaces/externalEventListeners/diiaIdHashFiles' 4 | import { SignAlgo } from '@interfaces/models/diiaId' 5 | import { HashFilesToSignOptions } from '@interfaces/services/diiaId' 6 | 7 | export interface CustomActionArguments extends UserActionArguments { 8 | params: { 9 | files: FileToHash[] 10 | signAlgo: SignAlgo 11 | options?: HashFilesToSignOptions 12 | } 13 | } 14 | 15 | export interface ActionResult { 16 | hashedFiles: HashedFile[] 17 | } 18 | -------------------------------------------------------------------------------- /src/models/unregisteredOfficeProfile.ts: -------------------------------------------------------------------------------- 1 | import { Model, Schema, model, models } from '@diia-inhouse/db' 2 | 3 | import { diiaOfficeProfileSchema } from '@models/userProfile' 4 | 5 | import { UnregisteredOfficeProfile } from '@interfaces/models/unregisteredOfficeProfile' 6 | 7 | const unregisteredOfficeProfile = new Schema({ 8 | identifier: { type: String, unique: true, required: true }, 9 | profile: { type: diiaOfficeProfileSchema }, 10 | }) 11 | 12 | export default >models.UnregisteredOfficeProfile || 13 | model('UnregisteredOfficeProfile', unregisteredOfficeProfile) 14 | -------------------------------------------------------------------------------- /src/interfaces/models/eResidentProfile.ts: -------------------------------------------------------------------------------- 1 | import { Document } from '@diia-inhouse/db' 2 | import { Gender } from '@diia-inhouse/types' 3 | 4 | export enum CitizenshipSource { 5 | EResidentRegistry = 'eResidentRegistry', 6 | } 7 | 8 | export interface EResidentProfileCitizenship { 9 | country: string 10 | date: Date 11 | sourceId?: string 12 | } 13 | 14 | export interface EResidentProfile { 15 | identifier: string 16 | gender: Gender 17 | birthDay: Date 18 | citizenship?: Record 19 | } 20 | 21 | export interface EResidentProfileModel extends EResidentProfile, Document {} 22 | -------------------------------------------------------------------------------- /src/interfaces/externalEventListeners/diiaIdHashFiles.ts: -------------------------------------------------------------------------------- 1 | import { SignAlgo } from '@interfaces/models/diiaId' 2 | 3 | export interface FileToHash { 4 | name: string 5 | file: string 6 | isRequireInternalSign?: boolean 7 | } 8 | 9 | export interface DiiaIdHashFilesRequest { 10 | identifier: string 11 | registryUserIdentifier: string 12 | certificateSerialNumber: string 13 | files: FileToHash[] 14 | signAlgo: SignAlgo 15 | } 16 | 17 | export interface HashedFile { 18 | name: string 19 | hash: string 20 | } 21 | 22 | export interface DiiaIdHashFilesResponse { 23 | identifier: string 24 | hashes: HashedFile[] 25 | } 26 | -------------------------------------------------------------------------------- /src/providers/creditHistory/mock.ts: -------------------------------------------------------------------------------- 1 | import { v4 as uuid } from 'uuid' 2 | 3 | import { Logger } from '@diia-inhouse/types' 4 | 5 | import { CreditHistoryProvider } from '@interfaces/providers/creditHistory' 6 | 7 | export default class UbchMockProvider implements CreditHistoryProvider { 8 | constructor(private readonly logger: Logger) { 9 | this.logger.info('Enabled ubch mock provider') 10 | } 11 | 12 | async subscribe(): Promise { 13 | return uuid() 14 | } 15 | 16 | async publishSubscription(): Promise { 17 | return 18 | } 19 | 20 | async unsubscribe(): Promise { 21 | return 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/interfaces/actions/v1/diiaId/verifyHash.ts: -------------------------------------------------------------------------------- 1 | import { UserActionArguments } from '@diia-inhouse/types' 2 | 3 | import { PublicServiceCode } from '@interfaces/models/subscription' 4 | import { SigningHistoryRecipient } from '@interfaces/models/userSigningHistoryItem' 5 | import { SignedFileHash } from '@interfaces/services/diiaId' 6 | 7 | export interface CustomActionArguments extends UserActionArguments { 8 | params: { 9 | files: SignedFileHash[] 10 | publicService: PublicServiceCode | string 11 | applicationId: string 12 | documents: string[] 13 | recipient: SigningHistoryRecipient 14 | } 15 | } 16 | 17 | export type ActionResult = void 18 | -------------------------------------------------------------------------------- /.env.test: -------------------------------------------------------------------------------- 1 | LOG_LEVEL=error 2 | 3 | UBCH_IS_ENABLED=true 4 | 5 | METRICS_PROMETHEUS_IS_ENABLED=false 6 | 7 | RABBIT_HOST=127.0.0.1 8 | RABBIT_PORT=5672 9 | RABBIT_USERNAME=guest 10 | RABBIT_PASSWORD=guest 11 | RABBIT_HEARTBEAT=60 12 | RABBIT_QUEUE_PREFETCH_COUNT=1 13 | 14 | EXTERNAL_RABBIT_HOST=127.0.0.1 15 | EXTERNAL_RABBIT_PORT=5672 16 | EXTERNAL_RABBIT_USERNAME=guest 17 | EXTERNAL_RABBIT_PASSWORD=guest 18 | EXTERNAL_RABBIT_HEARTBEAT=60 19 | EXTERNAL_RABBIT_QUEUE_PREFETCH_COUNT=1 20 | EXTERNAL_RABBIT_ASSERT_EXCHANGES=true 21 | 22 | TRANSPORT_TYPE='nats' 23 | TRANSPORT_OPTIONS='{"host":"localhost","port":"4222"}' 24 | 25 | GRPC_SERVER_ENABLED=false 26 | 27 | PROFILE_FEATURES_ENABLED=true 28 | -------------------------------------------------------------------------------- /src/interfaces/models/newFeatures.ts: -------------------------------------------------------------------------------- 1 | import { Document } from '@diia-inhouse/db' 2 | import { PlatformType, SessionType } from '@diia-inhouse/types' 3 | 4 | import { OnboardingBoard } from './onboarding' 5 | 6 | export interface NewFeaturesData { 7 | header: { 8 | logo: string 9 | title?: string 10 | subTitle?: string 11 | } 12 | boards: OnboardingBoard[] 13 | } 14 | 15 | export interface NewFeatures { 16 | appVersion: string 17 | platformType: PlatformType 18 | isVisible: boolean 19 | data: NewFeaturesData 20 | viewsCount: number 21 | sessionType: SessionType 22 | } 23 | 24 | export interface NewFeaturesModel extends NewFeatures, Document {} 25 | -------------------------------------------------------------------------------- /src/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "diiaId": { 3 | "getIdentifier": { 4 | "v2": { 5 | "activated": { 6 | "noDocumentWasSigned": "You have not signed any document in the application yet." 7 | }, 8 | "notActivated": { 9 | "description": "Verify your identity and create a PIN for your e-Signature to activate it.", 10 | "text": "Before activating, please read the {link1}", 11 | "link1Name": "Application for Accession to the Agreement on the Provision of Qualified Electronic Trust Signatures." 12 | } 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/services/serviceUser.ts: -------------------------------------------------------------------------------- 1 | import { FilterQuery } from '@diia-inhouse/db' 2 | import { AccessDeniedError } from '@diia-inhouse/errors' 3 | 4 | import serviceUserModel from '@models/serviceUser' 5 | 6 | import { ServiceUserModel } from '@interfaces/models/serviceUser' 7 | 8 | export default class ServiceUserService { 9 | async getServiceUserByLogin(login: string): Promise { 10 | const query: FilterQuery = { login } 11 | const serviceUser = await serviceUserModel.findOne(query) 12 | if (!serviceUser) { 13 | throw new AccessDeniedError('ServiceUser not found') 14 | } 15 | 16 | return serviceUser 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/models/distribution.ts: -------------------------------------------------------------------------------- 1 | import { Model, Schema, model, models } from '@diia-inhouse/db' 2 | import { PlatformType } from '@diia-inhouse/types' 3 | 4 | import { Distribution } from '@interfaces/models/distribution' 5 | 6 | const distributionSchema = new Schema( 7 | { 8 | messageId: { type: Schema.Types.ObjectId, unique: true, required: true }, 9 | platformTypes: { type: [String], enum: Object.values(PlatformType), default: [], required: true }, 10 | }, 11 | { 12 | timestamps: true, 13 | }, 14 | ) 15 | 16 | export const skipSyncIndexes = true 17 | 18 | export default >models.Distribution || model('Distribution', distributionSchema) 19 | -------------------------------------------------------------------------------- /src/interfaces/models/userDocumentSettings.ts: -------------------------------------------------------------------------------- 1 | import { Document } from '@diia-inhouse/db' 2 | 3 | export interface DocumentTypeSetting { 4 | documentTypeOrder: number 5 | documentIdentifiers?: { 6 | [key: string]: number 7 | } 8 | hiddenDocuments?: string[] 9 | /** Overrides defaultHidden field in documentSettings of document service */ 10 | hiddenDocumentType?: boolean 11 | } 12 | 13 | export type DocumentTypeSettings = { [key in string]?: DocumentTypeSetting | unknown } 14 | 15 | export interface UserDocumentSettings extends DocumentTypeSettings { 16 | userIdentifier: string 17 | } 18 | 19 | export interface UserDocumentSettingsModel extends UserDocumentSettings, Document {} 20 | -------------------------------------------------------------------------------- /src/models/userDevice.ts: -------------------------------------------------------------------------------- 1 | import { Model, Schema, model, models } from '@diia-inhouse/db' 2 | import { PlatformType } from '@diia-inhouse/types' 3 | 4 | import { UserDevice } from '@interfaces/models/userDevice' 5 | 6 | const userDeviceSchema = new Schema( 7 | { 8 | mobileUid: { type: String, unique: true, required: true }, 9 | userIdentifier: { type: String, index: true }, 10 | platformType: { type: String, enum: Object.values(PlatformType), required: true }, 11 | platformVersion: { type: String, required: true }, 12 | }, 13 | { 14 | timestamps: true, 15 | }, 16 | ) 17 | 18 | export default >models.UserDevice || model('UserDevice', userDeviceSchema) 19 | -------------------------------------------------------------------------------- /migrations/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig", 3 | "ts-node": { 4 | "files": true 5 | }, 6 | "compilerOptions": { 7 | "baseUrl": "..", 8 | "paths": { 9 | "@services/*": ["dist/types/services/*"], 10 | "@interfaces/*": ["dist/types/interfaces/*"], 11 | "@models/*": ["dist/types/models/*"], 12 | "@dataMappers/*": ["dist/types/dataMappers/*"], 13 | "@utils/*": ["dist/types/utils/*"], 14 | "@xmlMappings/*": ["dist/types/xmlMappings/*"], 15 | "@actions/*": ["dist/types/actions/*"], 16 | "@pages/*": ["dist/types/pages/*"], 17 | "@src/*": ["dist/types/*"] 18 | } 19 | }, 20 | "include": ["./**/*"] 21 | } 22 | -------------------------------------------------------------------------------- /src/dataMappers/documentFeaturePointsDataMapper.ts: -------------------------------------------------------------------------------- 1 | import { DocumentFeaturePointsModel } from '@interfaces/models/documentFeaturePoints' 2 | import { CheckPointsResult, GetPointsResult } from '@interfaces/services/documentFeaturePoints' 3 | 4 | export default class DocumentFeaturePointsDataMapper { 5 | toCheckResult(model: Omit): CheckPointsResult { 6 | const { documentType, documentIdentifier } = model 7 | 8 | return { documentType, documentIdentifier } 9 | } 10 | 11 | toGetResult(model: DocumentFeaturePointsModel): GetPointsResult { 12 | const { documentType, documentIdentifier, points = [] } = model 13 | 14 | return { documentType, documentIdentifier, points } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/interfaces/eventListeners/publicServiceSigningStatus.ts: -------------------------------------------------------------------------------- 1 | import { PublicServiceCode } from '@interfaces/models/subscription' 2 | import { SigningHistoryRecipient } from '@interfaces/models/userSigningHistoryItem' 3 | import { UserHistoryItemStatus } from '@interfaces/services/userHistory' 4 | 5 | // TODO(BACK-1845): make required when public-service-service is deployed 6 | export interface SigningStatusEventPayload { 7 | userIdentifier: string 8 | mobileUid: string 9 | platformType?: string 10 | platformVersion?: string 11 | resourceId?: string 12 | status: UserHistoryItemStatus 13 | documents: string[] 14 | recipient: SigningHistoryRecipient 15 | publicService?: PublicServiceCode | string 16 | applicationId?: string 17 | } 18 | -------------------------------------------------------------------------------- /tests/utils/getApp.ts: -------------------------------------------------------------------------------- 1 | import { Application, ServiceContext, ServiceOperator } from '@diia-inhouse/diia-app' 2 | 3 | import configFactory from '@src/config' 4 | 5 | import { TestDeps } from '@tests/interfaces/utils' 6 | import deps from '@tests/utils/deps' 7 | 8 | import { AppDeps } from '@interfaces/application' 9 | import { AppConfig } from '@interfaces/config' 10 | 11 | export async function getApp(): Promise> { 12 | const app = new Application>('User') 13 | 14 | await app.setConfig(configFactory) 15 | await app.setDeps(deps) 16 | const appOperator = await app.initialize() 17 | 18 | await appOperator.start() 19 | 20 | return appOperator 21 | } 22 | -------------------------------------------------------------------------------- /src/interfaces/eventListeners/acquirersSigningStatus.ts: -------------------------------------------------------------------------------- 1 | import { SignAlgo } from '@interfaces/models/diiaId' 2 | import { Action, SigningHistoryAcquirer, SigningHistoryOffer } from '@interfaces/models/userSigningHistoryItem' 3 | import { UserHistoryItemStatus } from '@interfaces/services/userHistory' 4 | 5 | // TODO(BACK-1845): make required when document-acquirers-service is deployed 6 | export interface EventPayload { 7 | userIdentifier: string 8 | mobileUid: string 9 | platformType?: string 10 | platformVersion?: string 11 | action?: Action 12 | resourceId: string 13 | status: UserHistoryItemStatus 14 | documents: string[] 15 | acquirer: SigningHistoryAcquirer 16 | offer: SigningHistoryOffer 17 | signAlgo?: SignAlgo 18 | } 19 | -------------------------------------------------------------------------------- /src/models/eResidentDevice.ts: -------------------------------------------------------------------------------- 1 | import { Model, Schema, model, models } from '@diia-inhouse/db' 2 | import { PlatformType } from '@diia-inhouse/types' 3 | 4 | import { EResidentDevice } from '@interfaces/models/eResidentDevice' 5 | 6 | const eResidentDeviceSchema = new Schema( 7 | { 8 | mobileUid: { type: String, unique: true, required: true }, 9 | userIdentifier: { type: String, index: true }, 10 | platformType: { type: String, enum: Object.values(PlatformType), required: true }, 11 | platformVersion: { type: String, required: true }, 12 | }, 13 | { 14 | timestamps: true, 15 | }, 16 | ) 17 | 18 | export const skipSyncIndexes = true 19 | 20 | export default >models.EResidentDevice || model('EResidentDevice', eResidentDeviceSchema) 21 | -------------------------------------------------------------------------------- /src/externalEventListeners/diiaIdHashFile.ts: -------------------------------------------------------------------------------- 1 | import { EventBusListener } from '@diia-inhouse/diia-queue' 2 | import { ValidationSchema } from '@diia-inhouse/validators' 3 | 4 | import { DiiaIdHashFileResponse } from '@interfaces/externalEventListeners/diiaIdHashFile' 5 | import { ExternalEvent } from '@interfaces/queue' 6 | 7 | export default class DiiaIdHashFileEventListener implements EventBusListener { 8 | readonly event: ExternalEvent = ExternalEvent.DiiaIdHashFile 9 | 10 | readonly isSync: boolean = true 11 | 12 | readonly validationRules: ValidationSchema = { 13 | processId: { type: 'string' }, 14 | hash: { 15 | type: 'object', 16 | props: { 17 | name: { type: 'string' }, 18 | hash: { type: 'string' }, 19 | }, 20 | }, 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/interfaces/models/diiaId.ts: -------------------------------------------------------------------------------- 1 | import { Document } from '@diia-inhouse/db' 2 | 3 | import { IdentityDocumentType } from '@interfaces/services/documents' 4 | 5 | export enum SignAlgo { 6 | DSTU = 'DSTU', 7 | ECDSA = 'ECDSA', 8 | } 9 | 10 | export interface DiiaIdRevoking { 11 | eventUuid: string 12 | error?: string 13 | } 14 | 15 | export interface DiiaId { 16 | userIdentifier: string 17 | mobileUid: string 18 | identifier: string 19 | creationDate?: Date 20 | expirationDate?: Date 21 | isDeleted: boolean 22 | deletedAt?: Date 23 | identityDocumentType?: IdentityDocumentType 24 | revoking?: DiiaIdRevoking 25 | signAlgo: SignAlgo 26 | registryUserIdentifier?: string 27 | certificateSerialNumber?: string 28 | } 29 | 30 | export interface DiiaIdModel extends DiiaId, Document { 31 | createdAt?: Date 32 | } 33 | -------------------------------------------------------------------------------- /src/models/userActionAccessSetting.ts: -------------------------------------------------------------------------------- 1 | import { Model, Schema, model, models } from '@diia-inhouse/db' 2 | 3 | import { UserActionAccessSetting } from '@interfaces/models/userActionAccessSetting' 4 | import { ActionAccessType } from '@interfaces/services/userActionAccess' 5 | 6 | const userActionAccessSettingSchema = new Schema( 7 | { 8 | actionAccessType: { type: String, enum: Object.values(ActionAccessType), unique: true, required: true }, 9 | maxValue: { type: Number, required: true }, 10 | expirationTime: { type: Number, required: true }, 11 | }, 12 | { 13 | timestamps: true, 14 | }, 15 | ) 16 | 17 | export const skipSyncIndexes = true 18 | 19 | export default >models.UserActionAccessSetting || 20 | model('UserActionAccessSetting', userActionAccessSettingSchema) 21 | -------------------------------------------------------------------------------- /src/scheduledTasks/checkDriverLicensesExpirations.ts: -------------------------------------------------------------------------------- 1 | import { EventBusListener } from '@diia-inhouse/diia-queue' 2 | import { Logger } from '@diia-inhouse/types' 3 | 4 | import UserDocumentService from '@services/userDocument' 5 | 6 | import { ScheduledTaskEvent } from '@interfaces/queue' 7 | 8 | export default class CheckDriverLicensesExpirationsTask implements EventBusListener { 9 | constructor( 10 | private readonly userDocumentService: UserDocumentService, 11 | private readonly logger: Logger, 12 | ) {} 13 | 14 | readonly event: ScheduledTaskEvent = ScheduledTaskEvent.UserCheckDriverLicensesExpirations 15 | 16 | async handler(): Promise { 17 | this.logger.info('Start checking driver licenses expirations for notifications') 18 | 19 | await this.userDocumentService.checkDriverLicensesExpirations() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/actions/v1/userInfo/getUserInfo.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | 5 | import UserProfileService from '@services/userProfile' 6 | 7 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userInfo/getUserInfo' 8 | 9 | export default class GetUserInfoAction implements AppAction { 10 | constructor(private readonly userProfileService: UserProfileService) {} 11 | 12 | readonly sessionType: SessionType = SessionType.User 13 | 14 | readonly actionVersion: ActionVersion = ActionVersion.V1 15 | 16 | readonly name: string = 'getUserInfo' 17 | 18 | async handler(args: CustomActionArguments): Promise { 19 | const { user } = args.session 20 | 21 | return this.userProfileService.getUserInfo(user) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/scheduledTasks/checkVehicleLicensesExpirations.ts: -------------------------------------------------------------------------------- 1 | import { EventBusListener } from '@diia-inhouse/diia-queue' 2 | import { Logger } from '@diia-inhouse/types' 3 | 4 | import UserDocumentService from '@services/userDocument' 5 | 6 | import { ScheduledTaskEvent } from '@interfaces/queue' 7 | 8 | export default class CheckVehicleLicensesExpirationsTask implements EventBusListener { 9 | constructor( 10 | private readonly userDocumentService: UserDocumentService, 11 | private readonly logger: Logger, 12 | ) {} 13 | 14 | readonly event: ScheduledTaskEvent = ScheduledTaskEvent.UserCheckVehicleLicensesExpirations 15 | 16 | async handler(): Promise { 17 | this.logger.info('Start checking vehicle licenses expirations for notifications') 18 | 19 | await this.userDocumentService.checkVehicleLicensesExpirations() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /migrations/20201228162642-add-user-action-access-setting.ts: -------------------------------------------------------------------------------- 1 | import 'module-alias/register' 2 | 3 | import { mongo } from '@diia-inhouse/db' 4 | 5 | import { UserActionAccessSetting } from '@interfaces/models/userActionAccessSetting' 6 | import { ActionAccessType } from '@interfaces/services/userActionAccess' 7 | 8 | const collectionName = 'useractionaccesssettings' 9 | 10 | export async function up(db: mongo.Db): Promise { 11 | const oneDayInSec: number = 24 * 60 * 60 12 | 13 | const setting: UserActionAccessSetting = { 14 | actionAccessType: ActionAccessType.AddBirthCertificate, 15 | maxValue: 10, 16 | expirationTime: oneDayInSec, 17 | } 18 | 19 | await db.collection(collectionName).insertOne(setting) 20 | } 21 | 22 | export async function down(db: mongo.Db): Promise { 23 | await db.dropCollection(collectionName) 24 | } 25 | -------------------------------------------------------------------------------- /src/externalEventListeners/diiaIdSignDpsPackageInit.ts: -------------------------------------------------------------------------------- 1 | import { EventBusListener } from '@diia-inhouse/diia-queue' 2 | import { ValidationSchema } from '@diia-inhouse/validators' 3 | 4 | import { ExternalEvent } from '@interfaces/queue' 5 | 6 | export default class DiiaIdSignDpsPackagePrepareEventListener implements EventBusListener { 7 | readonly event: ExternalEvent = ExternalEvent.DiiaIdSignDpsPackageInit 8 | 9 | readonly isSync: boolean = true 10 | 11 | readonly validationRules: ValidationSchema = { 12 | identifier: { type: 'string' }, 13 | hashes: { 14 | type: 'array', 15 | items: { 16 | type: 'object', 17 | props: { 18 | name: { type: 'string' }, 19 | hash: { type: 'string' }, 20 | }, 21 | }, 22 | }, 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/externalEventListeners/diiaIdHashFilesIntegrity.ts: -------------------------------------------------------------------------------- 1 | import { EventBusListener } from '@diia-inhouse/diia-queue' 2 | import { ValidationSchema } from '@diia-inhouse/validators' 3 | 4 | import { ExternalEvent } from '@interfaces/queue' 5 | 6 | export default class DiiaIdHashFilesIntegrityEventListener implements EventBusListener { 7 | readonly event: ExternalEvent = ExternalEvent.DiiaIdHashFilesIntegrity 8 | 9 | readonly isSync: boolean = true 10 | 11 | readonly validationRules: ValidationSchema = { 12 | identifier: { type: 'string' }, 13 | checkResults: { 14 | type: 'array', 15 | items: { 16 | type: 'object', 17 | props: { 18 | name: { type: 'string' }, 19 | checked: { type: 'boolean' }, 20 | }, 21 | }, 22 | }, 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/interfaces/services/userDocumentSettings.ts: -------------------------------------------------------------------------------- 1 | import { DiiaOfficeProfileData, ProfileFeature, SessionType } from '@diia-inhouse/types' 2 | 3 | export interface DocumentTypeWithOrder { 4 | order: number 5 | documentType: string 6 | } 7 | 8 | export interface SaveDocumentsOrderByDocumentTypeRequest { 9 | order: number 10 | docNumber: string 11 | } 12 | 13 | export interface UserDocumentsOrderResponse { 14 | documentType: string 15 | documentIdentifiers?: string[] 16 | } 17 | 18 | export interface UserDocumentsOrderParams { 19 | userIdentifier: string 20 | features?: { 21 | [ProfileFeature.office]?: DiiaOfficeProfileData 22 | } 23 | } 24 | 25 | export interface DocumentVisibilitySettings { 26 | hiddenDocuments: string[] 27 | hiddenDocumentType: boolean 28 | } 29 | 30 | export type DocumentsDefaultOrder = Partial> 31 | -------------------------------------------------------------------------------- /src/scheduledTasks/checkCovidCertificatesExpirations.ts: -------------------------------------------------------------------------------- 1 | import { EventBusListener } from '@diia-inhouse/diia-queue' 2 | import { Logger } from '@diia-inhouse/types' 3 | 4 | import UserDocumentService from '@services/userDocument' 5 | 6 | import { ScheduledTaskEvent } from '@interfaces/queue' 7 | 8 | export default class CheckCovidCertificatesExpirationsTask implements EventBusListener { 9 | constructor( 10 | private readonly userDocumentService: UserDocumentService, 11 | private readonly logger: Logger, 12 | ) {} 13 | 14 | readonly event: ScheduledTaskEvent = ScheduledTaskEvent.UserCheckCovidCertificatesExpirations 15 | 16 | async handler(): Promise { 17 | this.logger.info('Start checking covid certificates expirations for notifications') 18 | 19 | await this.userDocumentService.checkInternationalVaccinationCertificatesExpirations() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/actions/v1/userInfo/getCabinetUserInfo.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | 5 | import UserProfileService from '@services/userProfile' 6 | 7 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userInfo/getCabinetUserInfo' 8 | 9 | export default class GetCabinetUserInfoAction implements AppAction { 10 | constructor(private readonly userProfileService: UserProfileService) {} 11 | 12 | readonly sessionType: SessionType = SessionType.CabinetUser 13 | 14 | readonly actionVersion: ActionVersion = ActionVersion.V1 15 | 16 | readonly name: string = 'getCabinetUserInfo' 17 | 18 | async handler(args: CustomActionArguments): Promise { 19 | const { user } = args.session 20 | 21 | return this.userProfileService.getCabinetUserInfo(user) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/externalEventListeners/diiaIdSignDpsPackagePrepare.ts: -------------------------------------------------------------------------------- 1 | import { EventBusListener } from '@diia-inhouse/diia-queue' 2 | import { ValidationSchema } from '@diia-inhouse/validators' 3 | 4 | import { ExternalEvent } from '@interfaces/queue' 5 | 6 | export default class DiiaIdSignDpsPackageInitEventListener implements EventBusListener { 7 | readonly event: ExternalEvent = ExternalEvent.DiiaIdSignDpsPackagePrepare 8 | 9 | readonly isSync: boolean = true 10 | 11 | readonly validationRules: ValidationSchema = { 12 | identifier: { type: 'string' }, 13 | inReportDaoArray: { 14 | type: 'array', 15 | empty: false, 16 | items: { 17 | type: 'object', 18 | props: { 19 | fname: { type: 'string' }, 20 | contentBase64: { type: 'string' }, 21 | }, 22 | }, 23 | }, 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@diia-inhouse/configs/tsconfig/tsconfig.esm.json", 3 | "compilerOptions": { 4 | "plugins": [{ "transform": "@diia-inhouse/diia-app/dist/plugins/openapi" }], 5 | "outDir": "dist", 6 | "declarationDir": "dist/types", 7 | "baseUrl": "./", 8 | "strict": true, 9 | "resolveJsonModule": true, 10 | "paths": { 11 | "@services/*": ["src/services/*"], 12 | "@providers/*": ["src/providers/*"], 13 | "@interfaces/*": ["src/interfaces/*"], 14 | "@models/*": ["src/models/*"], 15 | "@dataMappers/*": ["src/dataMappers/*"], 16 | "@actions/*": ["src/actions/*"], 17 | "@src/*": ["src/*"], 18 | "@tests/*": ["tests/*"], 19 | "@mocks/*": ["tests/mocks/*"] 20 | }, 21 | "lib": ["DOM"] 22 | }, 23 | "include": ["src/**/*", "tests/jest.d.ts"] 24 | } 25 | -------------------------------------------------------------------------------- /src/actions/v1/diiaId/getIdentifiers.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType, UserActionArguments } from '@diia-inhouse/types' 4 | 5 | import DiiaIdService from '@services/diiaId' 6 | 7 | import { ActionResult } from '@interfaces/actions/v1/diiaId/getIdentifiers' 8 | 9 | export default class GetDiiaIdIdentifiersAction implements AppAction { 10 | constructor(private readonly diiaIdService: DiiaIdService) {} 11 | 12 | readonly sessionType: SessionType = SessionType.User 13 | 14 | readonly actionVersion: ActionVersion = ActionVersion.V1 15 | 16 | readonly name: string = 'getDiiaIdIdentifiers' 17 | 18 | async handler(args: UserActionArguments): Promise { 19 | const { 20 | session: { user }, 21 | headers, 22 | } = args 23 | 24 | return await this.diiaIdService.getIdentifiersV1(user, headers) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/actions/v2/diiaId/getIdentifiers.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType, UserActionArguments } from '@diia-inhouse/types' 4 | 5 | import DiiaIdService from '@services/diiaId' 6 | 7 | import { ActionResult } from '@interfaces/actions/v2/diiaId/getIdentifiers' 8 | 9 | export default class GetDiiaIdIdentifiersAction implements AppAction { 10 | constructor(private readonly diiaIdService: DiiaIdService) {} 11 | 12 | readonly sessionType: SessionType = SessionType.User 13 | 14 | readonly actionVersion: ActionVersion = ActionVersion.V2 15 | 16 | readonly name: string = 'getDiiaIdIdentifiers' 17 | 18 | async handler(args: UserActionArguments): Promise { 19 | const { 20 | session: { user }, 21 | headers, 22 | } = args 23 | 24 | return await this.diiaIdService.getIdentifiers(user, headers) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/utils/deps.ts: -------------------------------------------------------------------------------- 1 | import { AwilixContainer, BaseDeps, DepsFactoryFn, MoleculerService, asClass, asValue } from '@diia-inhouse/diia-app' 2 | 3 | import TestKit, { mockClass } from '@diia-inhouse/test' 4 | 5 | import deps from '@src/deps' 6 | 7 | import { TestDeps } from '@tests/interfaces/utils' 8 | import { documentsDocServiceClient } from '@tests/mocks/grpc/clients' 9 | 10 | import { AppDeps } from '@interfaces/application' 11 | import { AppConfig } from '@interfaces/config' 12 | 13 | export default async ( 14 | config: AppConfig, 15 | baseContainer: AwilixContainer, 16 | ): ReturnType> => { 17 | return { 18 | ...(await deps(config, baseContainer)), 19 | 20 | testKit: asClass(TestKit).singleton(), 21 | moleculer: asClass(mockClass(MoleculerService)).singleton(), 22 | documentsServiceClient: asValue(documentsDocServiceClient), 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/interfaces/models/userSharingHistoryItem.ts: -------------------------------------------------------------------------------- 1 | import { Document, mongo } from '@diia-inhouse/db' 2 | 3 | import { UserHistoryItemStatus } from '@interfaces/services/userHistory' 4 | 5 | export interface StatusHistoryItem { 6 | status: UserHistoryItemStatus 7 | date: Date 8 | } 9 | 10 | export interface SharingHistoryAcquirer { 11 | id: mongo.ObjectId 12 | name: string 13 | address: string 14 | } 15 | 16 | export interface SharingHistoryOffer { 17 | hashId: string 18 | name: string 19 | } 20 | 21 | export interface UserSharingHistoryItem { 22 | userIdentifier: string 23 | sessionId: string 24 | sharingId: string 25 | status: UserHistoryItemStatus 26 | statusHistory: StatusHistoryItem[] 27 | documents: string[] 28 | date: Date 29 | acquirer: SharingHistoryAcquirer 30 | offer?: SharingHistoryOffer 31 | } 32 | 33 | export interface UserSharingHistoryItemModel extends UserSharingHistoryItem, Document {} 34 | -------------------------------------------------------------------------------- /tests/unit/providers/creditHistory/mock.spec.ts: -------------------------------------------------------------------------------- 1 | const uuidV4Stub = jest.fn() 2 | 3 | jest.mock('uuid', () => ({ v4: uuidV4Stub })) 4 | 5 | import DiiaLogger from '@diia-inhouse/diia-logger' 6 | import { mockInstance } from '@diia-inhouse/test' 7 | 8 | import MockProvider from '@providers/creditHistory/mock' 9 | 10 | const loggerMock = mockInstance(DiiaLogger) 11 | 12 | const provider = new MockProvider(loggerMock) 13 | 14 | describe('MockProvider', () => { 15 | it('should return uuid', async () => { 16 | uuidV4Stub.mockReturnValueOnce('uuid') 17 | 18 | expect(await provider.subscribe()).toBe('uuid') 19 | }) 20 | 21 | it('should return undefined after publish subscription', async () => { 22 | expect(await provider.publishSubscription()).toBeUndefined() 23 | }) 24 | 25 | it('should return undefined after unsubscription', async () => { 26 | expect(await provider.unsubscribe()).toBeUndefined() 27 | }) 28 | }) 29 | -------------------------------------------------------------------------------- /src/externalEventListeners/diiaIdHashFiles.ts: -------------------------------------------------------------------------------- 1 | import { EventBusListener } from '@diia-inhouse/diia-queue' 2 | import { ValidationSchema } from '@diia-inhouse/validators' 3 | 4 | import { DiiaIdHashFilesResponse } from '@interfaces/externalEventListeners/diiaIdHashFiles' 5 | import { ExternalEvent } from '@interfaces/queue' 6 | 7 | export default class DiiaIdHashFilesEventListener implements EventBusListener { 8 | readonly event: ExternalEvent = ExternalEvent.DiiaIdHashFiles 9 | 10 | readonly isSync: boolean = true 11 | 12 | readonly validationRules: ValidationSchema = { 13 | identifier: { type: 'string' }, 14 | hashes: { 15 | type: 'array', 16 | items: { 17 | type: 'object', 18 | props: { 19 | name: { type: 'string' }, 20 | hash: { type: 'string' }, 21 | }, 22 | }, 23 | }, 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/locales/uk.json: -------------------------------------------------------------------------------- 1 | { 2 | "diiaId": { 3 | "getIdentifier": { 4 | "v2": { 5 | "activated": { 6 | "noDocumentWasSigned": "Ви ще не підписали жодного документа в Дії." 7 | }, 8 | "notActivated": { 9 | "description": "Для активації необхідно буде підтвердити особу користувача та створити ПІН-код для вашого Дія.Підпис", 10 | "text": "Перед активацією ознайомтесь, будь ласка, зі змістом {link1}", 11 | "link1Name": "Заяви про приєднання до Договору про надання кваліфікованих електронних довірчих підписів." 12 | } 13 | } 14 | }, 15 | "getIdentifiers": { 16 | "v2": { 17 | "history": { 18 | "button": { 19 | "name": "Історія підписань та авторизації" 20 | } 21 | } 22 | } 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/dataMappers/userProfileDataMapper.ts: -------------------------------------------------------------------------------- 1 | import { UserTokenData } from '@diia-inhouse/types' 2 | 3 | import { AuthProviderName } from '@interfaces/services/auth' 4 | 5 | export default class UserProfileDataMapper { 6 | getUserInfoText(user: UserTokenData): string { 7 | const { 8 | phoneNumber, 9 | email, 10 | authEntryPoint: { isBankId, target }, 11 | } = user 12 | 13 | if (!phoneNumber && !email) { 14 | return 'Будь ласка, заповніть контактні дані.' 15 | } 16 | 17 | if (isBankId) { 18 | return 'Ми заповнили дані з вашого BankID. Будь ласка, перевірте їх та змініть за потреби.' 19 | } 20 | 21 | if ([AuthProviderName.PrivatBank, AuthProviderName.Monobank].includes(target)) { 22 | return 'Ми отримали дані від вашого банку. Будь ласка, перевірте їх та змініть за потреби.' 23 | } 24 | 25 | return 'Будь ласка, заповніть контактні дані.' 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/models/userDocumentStorage.ts: -------------------------------------------------------------------------------- 1 | import { Model, Schema, model, models } from '@diia-inhouse/db' 2 | 3 | import { UserDocumentStorage } from '@interfaces/models/userDocumentStorage' 4 | 5 | const userDocumentStorageSchema = new Schema( 6 | { 7 | userIdentifier: { type: String, required: true }, 8 | mobileUid: { type: String, index: true, optional: true }, 9 | hashData: { type: String, required: true }, 10 | documentType: { type: String, index: true, required: true }, 11 | encryptedData: { type: String, required: true }, 12 | encryptedPhoto: { type: String }, 13 | encryptedDocPhoto: { type: String }, 14 | }, 15 | { 16 | timestamps: true, 17 | }, 18 | ) 19 | 20 | userDocumentStorageSchema.index({ userIdentifier: 1, mobileUid: 1, hashData: 1, documentType: 1 }, { unique: true }) 21 | 22 | export default >models.UserDocumentStorage || model('UserDocumentStorage', userDocumentStorageSchema) 23 | -------------------------------------------------------------------------------- /src/actions/v1/diiaId/getSigningHistory.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import { ActionResult } from '@interfaces/actions/v1/diiaId/getSigningHistory' 7 | 8 | export default class GetDiiaIdSigningHistoryAction implements AppAction { 9 | readonly sessionType: SessionType = SessionType.User 10 | 11 | readonly actionVersion: ActionVersion = ActionVersion.V1 12 | 13 | readonly name: string = 'getDiiaIdSigningHistory' 14 | 15 | readonly validationRules: ValidationSchema = { 16 | skip: { type: 'number', convert: true, optional: true }, 17 | limit: { type: 'number', convert: true, optional: true }, 18 | } 19 | 20 | async handler(): Promise { 21 | const [signingRequests, total]: [unknown[], number] = await Promise.all([[], 0]) 22 | 23 | return { signingRequests, total } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/actions/v1/userHistory/getHistoryScreen.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | 5 | import UserHistoryService from '@services/userHistory' 6 | 7 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userHistory/getHistoryScreen' 8 | 9 | export default class GetHistoryScreenAction implements AppAction { 10 | constructor(private readonly userHistoryService: UserHistoryService) {} 11 | 12 | readonly sessionType: SessionType = SessionType.User 13 | 14 | readonly actionVersion: ActionVersion = ActionVersion.V1 15 | 16 | readonly name: string = 'getHistoryScreen' 17 | 18 | async handler(args: CustomActionArguments): Promise { 19 | const { 20 | session: { 21 | user: { identifier: userIdentifier }, 22 | }, 23 | } = args 24 | 25 | return await this.userHistoryService.getHistoryScreenV1(userIdentifier) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/actions/v2/userHistory/getHistoryScreen.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | 5 | import UserHistoryService from '@services/userHistory' 6 | 7 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v2/userHistory/getHistoryScreen' 8 | 9 | export default class GetHistoryScreenAction implements AppAction { 10 | constructor(private readonly userHistoryService: UserHistoryService) {} 11 | 12 | readonly sessionType: SessionType = SessionType.User 13 | 14 | readonly actionVersion: ActionVersion = ActionVersion.V2 15 | 16 | readonly name: string = 'getHistoryScreen' 17 | 18 | async handler(args: CustomActionArguments): Promise { 19 | const { 20 | session: { 21 | user: { identifier: userIdentifier }, 22 | }, 23 | } = args 24 | 25 | return await this.userHistoryService.getHistoryScreen(userIdentifier) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/interfaces/services/userDocumentStorage.ts: -------------------------------------------------------------------------------- 1 | export type EncryptedDataByDocumentType = { 2 | [key in string]?: string[] 3 | } 4 | 5 | export type DecryptedDocument = Record & { photo?: string; docPhoto?: string } 6 | 7 | export type DecryptedDocuments = Record 8 | 9 | export enum VaccinationCertificateType { 10 | Vaccination = 'vaccination', 11 | Test = 'test', 12 | Recovery = 'recovery', 13 | } 14 | 15 | export interface StoredMedicalData { 16 | id: string 17 | documentType: string 18 | documentIdentifier: string 19 | vaccinations: unknown[] 20 | tests: unknown[] 21 | recoveries: unknown[] 22 | } 23 | 24 | export interface StoredBirthCertificateData { 25 | id: string 26 | serie: string 27 | number: string 28 | } 29 | 30 | export interface AddDocumentOps { 31 | mobileUid?: string 32 | compareExistedHashData?: boolean 33 | } 34 | 35 | export interface GetDocumentsOps { 36 | mobileUid?: string 37 | documentTypes?: string[] 38 | } 39 | -------------------------------------------------------------------------------- /tests/mocks/randomData.ts: -------------------------------------------------------------------------------- 1 | import { v4 as uuid } from 'uuid' 2 | 3 | import { IdentifierService } from '@diia-inhouse/crypto' 4 | 5 | export class RandomData { 6 | constructor(private readonly identifier: IdentifierService) {} 7 | 8 | generateItn(): string { 9 | return Math.floor(Math.random() * 10000000000).toString() 10 | } 11 | 12 | generateUserIdentifier(): string { 13 | const itn: string = this.generateItn() 14 | 15 | return this.identifier.createIdentifier(itn) 16 | } 17 | 18 | generateDocumentIdentifier(): string { 19 | return this.identifier.createIdentifier(uuid()) 20 | } 21 | 22 | generateDocumentIdentifiers(amount: number): string[] { 23 | const documentIdentifiers: string[] = [] 24 | 25 | for (let i = 0; i < amount; i++) { 26 | documentIdentifiers.push(this.generateDocumentIdentifier()) 27 | } 28 | 29 | return documentIdentifiers 30 | } 31 | 32 | generateDocId(): string { 33 | return uuid() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/interfaces/externalEventListeners/diiaIdSignHashesInit.ts: -------------------------------------------------------------------------------- 1 | import { ExternalResponseBaseEventPayload } from '.' 2 | 3 | export enum DiiaIdSignType { 4 | EU_SIGN_TYPE_CADES_BES = 1, 5 | EU_SIGN_TYPE_CADES_T = 4, 6 | EU_SIGN_TYPE_CADES_C = 8, 7 | EU_SIGN_TYPE_CADES_X_LONG = 16, 8 | EU_SIGN_TYPE_CADES_X_LONG_TRUSTED = 128, 9 | EU_SIGN_TYPE_CADES_X_LONG_TRUSTED_DIIA_SIGN_DSTU_EDITION = 144, 10 | } 11 | 12 | export interface DiiaIdSignHashesInitRequest { 13 | uuid: string 14 | request: { 15 | identifier: string 16 | certificateSerialNumber: string 17 | registryUserIdentifier: string 18 | signType?: DiiaIdSignType 19 | noSigningTime?: boolean 20 | noContentTimestamp?: boolean 21 | processId?: string 22 | } 23 | } 24 | 25 | export interface DiiaIdSignHashesInitResponse { 26 | identifier: string 27 | success: boolean 28 | } 29 | 30 | export interface EventPayload extends ExternalResponseBaseEventPayload { 31 | response?: DiiaIdSignHashesInitResponse 32 | } 33 | -------------------------------------------------------------------------------- /src/models/documentFeaturePoints.ts: -------------------------------------------------------------------------------- 1 | import { Model, Schema, model, models } from '@diia-inhouse/db' 2 | 3 | import { DocumentFeaturePoints } from '@interfaces/models/documentFeaturePoints' 4 | 5 | const documentFeaturePointsSchema = new Schema( 6 | { 7 | userIdentifier: { type: String, required: true }, 8 | documentType: { type: String, required: true }, 9 | documentIdentifier: { type: String, required: true }, 10 | requestId: { type: String, unique: true, required: true }, 11 | points: { type: [Number] }, 12 | }, 13 | { 14 | timestamps: true, 15 | }, 16 | ) 17 | 18 | documentFeaturePointsSchema.index( 19 | { 20 | userIdentifier: 1, 21 | documentType: 1, 22 | documentIdentifier: 1, 23 | }, 24 | { 25 | unique: true, 26 | }, 27 | ) 28 | 29 | export const skipSyncIndexes = true 30 | 31 | export default >models.DocumentFeaturePoints || model('DocumentFeaturePoints', documentFeaturePointsSchema) 32 | -------------------------------------------------------------------------------- /src/interfaces/models/onboarding.ts: -------------------------------------------------------------------------------- 1 | import { Document } from '@diia-inhouse/db' 2 | import { PlatformType, SessionType } from '@diia-inhouse/types' 3 | 4 | export enum OnboardingButtonAction { 5 | Skip = 'skip', 6 | } 7 | 8 | export interface OnboardingBoard { 9 | title: string 10 | backgroundColor: string 11 | text?: string 12 | image?: string 13 | list?: { 14 | bullet: string 15 | items: { text: string }[] 16 | } 17 | footer: { 18 | backgroundColor: string 19 | button: { 20 | label: string 21 | action: OnboardingButtonAction 22 | } 23 | } 24 | } 25 | 26 | export interface OnboardingData { 27 | header: { 28 | logo: string 29 | } 30 | boards: OnboardingBoard[] 31 | } 32 | 33 | export interface Onboarding { 34 | appVersion: string 35 | platformType: PlatformType 36 | isVisible: boolean 37 | data: OnboardingData 38 | sessionType?: SessionType 39 | } 40 | 41 | export interface OnboardingModel extends Onboarding, Document {} 42 | -------------------------------------------------------------------------------- /src/actions/v1/subscription/getSubscriptions.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | 5 | import SubscriptionService from '@services/subscription' 6 | 7 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/subscription/getSubscriptions' 8 | 9 | export default class GetSubscriptionsAction implements AppAction { 10 | constructor(private readonly subscriptionService: SubscriptionService) {} 11 | 12 | readonly sessionType: SessionType = SessionType.User 13 | 14 | readonly actionVersion: ActionVersion = ActionVersion.V1 15 | 16 | readonly name: string = 'getSubscriptions' 17 | 18 | async handler(args: CustomActionArguments): Promise { 19 | const { 20 | headers, 21 | session: { 22 | user: { identifier: userIdentifier, itn }, 23 | }, 24 | } = args 25 | 26 | return await this.subscriptionService.getSubscriptions(userIdentifier, itn, headers) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/services/unregisteredOfficeProfile.ts: -------------------------------------------------------------------------------- 1 | import unregisteredOfficeProfile from '@models/unregisteredOfficeProfile' 2 | 3 | import { DiiaOfficeProfile } from '@interfaces/models/userProfile' 4 | 5 | export default class UnregisteredOfficeProfile { 6 | async addUnregisteredProfile(identifier: string, profile: DiiaOfficeProfile): Promise { 7 | await unregisteredOfficeProfile.deleteOne({ 8 | 'profile.profileId': profile.profileId, 9 | identifier: { $ne: identifier }, 10 | }) 11 | 12 | await unregisteredOfficeProfile.updateOne({ identifier }, { profile }, { upsert: true }) 13 | } 14 | 15 | async removeUnregisteredProfile(identifier: string): Promise { 16 | await unregisteredOfficeProfile.deleteOne({ identifier }) 17 | } 18 | 19 | async getUnregisteredProfile(identifier: string): Promise { 20 | const unregisteredOfficeProfileItem = await unregisteredOfficeProfile.findOne({ identifier }) 21 | 22 | return unregisteredOfficeProfileItem?.profile 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/interfaces/models/userDocument.ts: -------------------------------------------------------------------------------- 1 | import { Document } from '@diia-inhouse/db' 2 | import { DocStatus, OwnerType } from '@diia-inhouse/types' 3 | 4 | import { ComparedTo, UserCompoundDocument, UserDocumentData } from '@interfaces/services/documents' 5 | import { MessageTemplateCode } from '@interfaces/services/notification' 6 | 7 | export type UserDocumentsNotifications = Partial> 8 | 9 | export interface UserDocument { 10 | userIdentifier: string 11 | mobileUid?: string 12 | documentType: string 13 | documentSubType?: string 14 | documentIdentifier: string 15 | normalizedDocumentIdentifier?: string 16 | fullNameHash?: string 17 | ownerType: OwnerType 18 | docId?: string 19 | docStatus?: DocStatus 20 | documentData?: UserDocumentData 21 | compoundDocument?: UserCompoundDocument 22 | registrationDate?: Date 23 | issueDate?: Date 24 | expirationDate?: Date 25 | notifications: UserDocumentsNotifications 26 | comparedTo?: ComparedTo 27 | } 28 | 29 | export interface UserDocumentModel extends UserDocument, Document {} 30 | -------------------------------------------------------------------------------- /src/actions/v1/userDocument/getDocumentsTypeOrder.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | 5 | import UserDocumentSettingsService from '@services/userDocumentSettings' 6 | 7 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userDocument/getDocumentsTypeOrder' 8 | 9 | export default class GetDocumentsTypeOrderAction implements AppAction { 10 | constructor(private readonly userDocumentSettingsService: UserDocumentSettingsService) {} 11 | 12 | readonly sessionType: SessionType = SessionType.User 13 | 14 | readonly actionVersion: ActionVersion = ActionVersion.V1 15 | 16 | readonly name: string = 'getDocumentsTypeOrder' 17 | 18 | async handler(args: CustomActionArguments): Promise { 19 | const { 20 | user: { identifier: userIdentifier }, 21 | } = args.session 22 | 23 | const documentsTypeOrder = await this.userDocumentSettingsService.getDocumentsTypeOrder({ userIdentifier }) 24 | 25 | return { documentsTypeOrder } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/actions/v1/userInfo/hasUserProfile.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import UserProfileService from '@services/userProfile' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userInfo/hasUserProfile' 9 | 10 | export default class HasUserProfileAction implements AppAction { 11 | constructor(private readonly userProfileService: UserProfileService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'hasUserProfile' 18 | 19 | readonly validationRules: ValidationSchema = { 20 | userIdentifier: { type: 'string' }, 21 | } 22 | 23 | async handler(args: CustomActionArguments): Promise { 24 | const { 25 | params: { userIdentifier }, 26 | } = args 27 | 28 | return await this.userProfileService.hasUserProfile(userIdentifier) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/actions/v1/userInfo/loadUserProfileFeaturesAsync.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import UserProfileService from '@services/userProfile' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userInfo/loadUserProfileFeaturesAsync' 9 | 10 | export default class LoadUserProfilesFeaturesAsyncAction implements AppAction { 11 | constructor(private readonly userProfileService: UserProfileService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'loadUserProfileFeaturesAsync' 18 | 19 | readonly validationRules: ValidationSchema = { 20 | itn: { type: 'string' }, 21 | } 22 | 23 | async handler(args: CustomActionArguments): Promise { 24 | const { itn } = args.params 25 | 26 | return await this.userProfileService.checkForUserProfileFeatures(itn) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/interfaces/models/userProfile.ts: -------------------------------------------------------------------------------- 1 | import { Document } from '@diia-inhouse/db' 2 | import { DiiaOfficeStatus, Gender, ProfileFeature } from '@diia-inhouse/types' 3 | 4 | export enum CitizenshipSource { 5 | BankAccount = 'bankAccount', 6 | } 7 | 8 | export interface UserProfileCitizenship { 9 | country: 'Ukraine' 10 | date: Date 11 | sourceId?: string 12 | } 13 | 14 | export interface UserProfileFeatures { 15 | [ProfileFeature.office]?: DiiaOfficeProfile 16 | } 17 | 18 | export interface UserProfile { 19 | identifier: string 20 | gender: Gender 21 | birthDay: Date 22 | citizenship?: Record 23 | communityCode?: string 24 | features?: UserProfileFeatures 25 | } 26 | 27 | export interface DiiaOfficeProfile { 28 | profileId: string 29 | organizationId: string 30 | unitId: string 31 | scopes: string[] 32 | tokenError?: string 33 | tokenFailedAt?: Date 34 | isOrganizationAdmin: boolean 35 | status: DiiaOfficeStatus 36 | googleWorkspace?: string 37 | } 38 | 39 | export interface UserProfileModel extends UserProfile, Document {} 40 | -------------------------------------------------------------------------------- /src/interfaces/providers/creditHistory/ubch.ts: -------------------------------------------------------------------------------- 1 | import { HttpStatusCode } from '@diia-inhouse/types' 2 | 3 | export enum SubscribeRequestLng { 4 | Ua = 'UA', 5 | Ru = 'RU', 6 | En = 'EN', 7 | } 8 | 9 | export enum OperationState { 10 | Y = 'Y', 11 | N = 'N', 12 | } 13 | 14 | export interface UbchRequest { 15 | data: string 16 | } 17 | 18 | export interface SubscribeRequestData { 19 | method: 'Rega' 20 | sessid: string 21 | inn: string 22 | lng: SubscribeRequestLng 23 | } 24 | 25 | export interface UnsubscribeRequestData { 26 | method: 'Disc' 27 | sessid: string 28 | inn: string 29 | lng: SubscribeRequestLng 30 | refagr: string 31 | } 32 | 33 | export type UbchRequestData = SubscribeRequestData | UnsubscribeRequestData 34 | 35 | export interface UbchResponse { 36 | data: string 37 | } 38 | 39 | export interface UbchResponseData { 40 | name: string 41 | message: string 42 | code: number 43 | status: HttpStatusCode 44 | type: string 45 | data?: { 46 | inn: string 47 | refagr: string 48 | servicestate: OperationState 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/actions/v1/userDocument/getDocumentsOrder.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import UserDocumentSettingsService from '@services/userDocumentSettings' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userDocument/getDocumentsOrder' 9 | 10 | export default class GetDocumentsOrderAction implements AppAction { 11 | constructor(private readonly userDocumentSettingsService: UserDocumentSettingsService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'getDocumentsOrder' 18 | 19 | readonly validationRules: ValidationSchema = { 20 | userIdentifier: { type: 'string' }, 21 | features: { type: 'object', optional: true }, 22 | } 23 | 24 | async handler(args: CustomActionArguments): Promise { 25 | return await this.userDocumentSettingsService.getDocumentsOrder(args.params) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/externalEventListeners/getUserInfoForFilters.ts: -------------------------------------------------------------------------------- 1 | import { EventBusListener } from '@diia-inhouse/diia-queue' 2 | import { ValidationSchema } from '@diia-inhouse/validators' 3 | 4 | import UserProfileService from '@services/userProfile' 5 | 6 | import { ActionResult, EventPayload } from '@interfaces/externalEventListeners/getUserInfoForFilters' 7 | import { ExternalEvent } from '@interfaces/queue' 8 | 9 | export default class GetUserInfoForFiltersAction implements EventBusListener { 10 | constructor(private readonly userProfileService: UserProfileService) {} 11 | 12 | readonly event: ExternalEvent = ExternalEvent.UserGetInfoForFilters 13 | 14 | readonly validationRules: ValidationSchema = { 15 | uuid: { type: 'uuid' }, 16 | request: { 17 | type: 'object', 18 | props: { 19 | userIdentifier: { type: 'string' }, 20 | }, 21 | }, 22 | } 23 | 24 | async handler(payload: EventPayload): Promise { 25 | const { userIdentifier } = payload.request 26 | 27 | return await this.userProfileService.getUserFilterInfo(userIdentifier) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/actions/v1/userInfo/getUserInfoForFilters.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import UserProfileService from '@services/userProfile' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userInfo/getUserInfoForFilters' 9 | 10 | export default class GetUserInfoForFiltersAction implements AppAction { 11 | constructor(private readonly userProfileService: UserProfileService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'getUserInfoForFilters' 18 | 19 | readonly validationRules: ValidationSchema = { 20 | userIdentifier: { type: 'string' }, 21 | } 22 | 23 | async handler(args: CustomActionArguments): Promise { 24 | const { 25 | params: { userIdentifier }, 26 | } = args 27 | 28 | return await this.userProfileService.getUserFilterInfo(userIdentifier) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/unit/scheduledTasks/checkDriverLicensesExpirations.ts.spec.ts: -------------------------------------------------------------------------------- 1 | import Logger from '@diia-inhouse/diia-logger' 2 | import { mockInstance } from '@diia-inhouse/test' 3 | 4 | import CheckDriverLicensesExpirationsTask from '@src/scheduledTasks/checkDriverLicensesExpirations' 5 | 6 | import UserDocumentService from '@services/userDocument' 7 | 8 | import { ScheduledTaskEvent } from '@interfaces/queue' 9 | 10 | describe(`Scheduled Task ${CheckDriverLicensesExpirationsTask.name}`, () => { 11 | const logger = mockInstance(Logger) 12 | const userDocumentService = mockInstance(UserDocumentService) 13 | const scheduledTask = new CheckDriverLicensesExpirationsTask(userDocumentService, logger) 14 | 15 | it('should call userDocumentService.checkDriverLicensesExpirations', async () => { 16 | await scheduledTask.handler() 17 | 18 | expect(scheduledTask.event).toBe(ScheduledTaskEvent.UserCheckDriverLicensesExpirations) 19 | expect(logger.info).toHaveBeenCalledWith('Start checking driver licenses expirations for notifications') 20 | expect(userDocumentService.checkDriverLicensesExpirations).toHaveBeenCalled() 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /tests/unit/scheduledTasks/checkVehicleLicensesExpirations.spec.ts: -------------------------------------------------------------------------------- 1 | import Logger from '@diia-inhouse/diia-logger' 2 | import { mockInstance } from '@diia-inhouse/test' 3 | 4 | import CheckVehicleLicensesExpirationsTask from '@src/scheduledTasks/checkVehicleLicensesExpirations' 5 | 6 | import UserDocumentService from '@services/userDocument' 7 | 8 | import { ScheduledTaskEvent } from '@interfaces/queue' 9 | 10 | describe(`Scheduled Task ${CheckVehicleLicensesExpirationsTask.name}`, () => { 11 | const logger = mockInstance(Logger) 12 | const userDocumentService = mockInstance(UserDocumentService) 13 | const scheduledTask = new CheckVehicleLicensesExpirationsTask(userDocumentService, logger) 14 | 15 | it('should call userDocumentService.checkVehicleLicensesExpirations', async () => { 16 | await scheduledTask.handler() 17 | 18 | expect(scheduledTask.event).toBe(ScheduledTaskEvent.UserCheckVehicleLicensesExpirations) 19 | expect(logger.info).toHaveBeenCalledWith('Start checking vehicle licenses expirations for notifications') 20 | expect(userDocumentService.checkVehicleLicensesExpirations).toHaveBeenCalled() 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /src/actions/v1/subscription/getSubscribedSegments.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import SubscriptionService from '@services/subscription' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/subscription/getSubscribedSegments' 9 | 10 | export default class GetSubscribedSegmentsAction implements AppAction { 11 | constructor(private readonly subscriptionService: SubscriptionService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'getSubscribedSegments' 18 | 19 | readonly validationRules: ValidationSchema = { 20 | userIdentifier: { type: 'string' }, 21 | } 22 | 23 | async handler(args: CustomActionArguments): Promise { 24 | const { 25 | params: { userIdentifier }, 26 | } = args 27 | 28 | return await this.subscriptionService.getSubscribedSegments(userIdentifier) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/actions/v1/userHistory/getUserSharingStatuses.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import UserSharingHistoryService from '@services/userSharingHistory' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userHistory/getUserSharingStatuses' 9 | 10 | export default class GetUserSharingStatusAction implements AppAction { 11 | constructor(private readonly userSharingHistoryService: UserSharingHistoryService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'getUserSharingStatuses' 18 | 19 | readonly validationRules: ValidationSchema = { 20 | sharingIds: { type: 'array', items: { type: 'string' } }, 21 | } 22 | 23 | async handler(args: CustomActionArguments): Promise { 24 | const { sharingIds } = args.params 25 | 26 | return await this.userSharingHistoryService.getItemStatuses(sharingIds) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/actions/v1/userHistory/getUserSigningStatuses.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import UserSigningHistoryService from '@services/userSigningHistory' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userHistory/getUserSigningStatuses' 9 | 10 | export default class GetUserSigningStatusesAction implements AppAction { 11 | constructor(private readonly userSigningHistoryService: UserSigningHistoryService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'getUserSigningStatuses' 18 | 19 | readonly validationRules: ValidationSchema = { 20 | resourceIds: { type: 'array', items: { type: 'string' } }, 21 | } 22 | 23 | async handler(args: CustomActionArguments): Promise { 24 | const { resourceIds } = args.params 25 | 26 | return await this.userSigningHistoryService.getItemStatuses(resourceIds) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/actions/v1/diiaId/hasIdentifier.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import DiiaIdService from '@services/diiaId' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/diiaId/hasIdentifier' 9 | 10 | export default class HasDiiaIdIdentifierAction implements AppAction { 11 | constructor(private readonly diiaIdService: DiiaIdService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'hasDiiaIdIdentifier' 18 | 19 | readonly validationRules: ValidationSchema = { 20 | userIdentifier: { type: 'string' }, 21 | mobileUidToFilter: { type: 'string' }, 22 | } 23 | 24 | async handler(args: CustomActionArguments): Promise { 25 | const { 26 | params: { userIdentifier, mobileUidToFilter }, 27 | } = args 28 | 29 | return await this.diiaIdService.hasIdentifier(userIdentifier, mobileUidToFilter) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/actions/v2/userDocument/getDocumentsTypeOrder.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | 5 | import UserDocumentSettingsService from '@services/userDocumentSettings' 6 | 7 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v2/userDocument/getDocumentsTypeOrder' 8 | 9 | export default class GetDocumentsTypeOrderAction implements AppAction { 10 | constructor(private readonly userDocumentSettingsService: UserDocumentSettingsService) {} 11 | 12 | readonly sessionType: SessionType = SessionType.User 13 | 14 | readonly actionVersion: ActionVersion = ActionVersion.V2 15 | 16 | readonly name: string = 'getDocumentsTypeOrder' 17 | 18 | async handler(args: CustomActionArguments): Promise { 19 | const { 20 | user: { identifier: userIdentifier }, 21 | features, 22 | } = args.session 23 | 24 | const documentsTypeOrder = await this.userDocumentSettingsService.getDocumentsTypeOrder({ 25 | userIdentifier, 26 | features, 27 | }) 28 | 29 | return { documentsTypeOrder } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/unit/services/address.spec.ts: -------------------------------------------------------------------------------- 1 | import { MoleculerService } from '@diia-inhouse/diia-app' 2 | 3 | import { mockInstance } from '@diia-inhouse/test' 4 | import { ActionVersion } from '@diia-inhouse/types' 5 | 6 | import AddressService from '@services/address' 7 | 8 | describe(`Service ${AddressService.name}`, () => { 9 | const moleculerServiceMock = mockInstance(MoleculerService) 10 | 11 | const addressService = new AddressService(moleculerServiceMock) 12 | 13 | describe('method: `findCommunityCodeByKoatuu`', () => { 14 | it('should return code', async () => { 15 | const koatuu = 'koatuu' 16 | const code = 'code' 17 | 18 | jest.spyOn(moleculerServiceMock, 'act').mockResolvedValueOnce(code) 19 | 20 | expect(await addressService.findCommunityCodeByKoatuu(koatuu)).toBe(code) 21 | expect(moleculerServiceMock.act).toHaveBeenCalledWith( 22 | 'Address', 23 | { name: 'findCommunityCodeByKoatuu', actionVersion: ActionVersion.V1 }, 24 | { params: { koatuu } }, 25 | ) 26 | expect(moleculerServiceMock.act).toHaveBeenCalledTimes(1) 27 | }) 28 | }) 29 | }) 30 | -------------------------------------------------------------------------------- /src/actions/v1/userVerification/getFeaturePoints.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import DocumentFeaturePointsService from '@services/documentFeaturePoints' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userVerification/getFeaturePoints' 9 | 10 | export default class GetFeaturePointsAction implements AppAction { 11 | constructor(private readonly documentFeaturePointsService: DocumentFeaturePointsService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'getFeaturePoints' 18 | 19 | readonly validationRules: ValidationSchema = { 20 | userIdentifier: { type: 'string' }, 21 | } 22 | 23 | async handler(args: CustomActionArguments): Promise { 24 | const { 25 | params: { userIdentifier }, 26 | } = args 27 | 28 | return { points: await this.documentFeaturePointsService.getFeaturePoints(userIdentifier) } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/unit/scheduledTasks/checkCovidCertificatesExpirations.spec.ts: -------------------------------------------------------------------------------- 1 | import Logger from '@diia-inhouse/diia-logger' 2 | import { mockInstance } from '@diia-inhouse/test' 3 | 4 | import CheckCovidCertificatesExpirationsTask from '@src/scheduledTasks/checkCovidCertificatesExpirations' 5 | 6 | import UserDocumentService from '@services/userDocument' 7 | 8 | import { ScheduledTaskEvent } from '@interfaces/queue' 9 | 10 | describe(`Scheduled Task ${CheckCovidCertificatesExpirationsTask.name}`, () => { 11 | const logger = mockInstance(Logger) 12 | const userDocumentService = mockInstance(UserDocumentService) 13 | const scheduledTask = new CheckCovidCertificatesExpirationsTask(userDocumentService, logger) 14 | 15 | it('should call userDocumentService.checkInternationalVaccinationCertificatesExpirations', async () => { 16 | await scheduledTask.handler() 17 | 18 | expect(scheduledTask.event).toBe(ScheduledTaskEvent.UserCheckCovidCertificatesExpirations) 19 | expect(logger.info).toHaveBeenCalledWith('Start checking covid certificates expirations for notifications') 20 | expect(userDocumentService.checkInternationalVaccinationCertificatesExpirations).toHaveBeenCalled() 21 | }) 22 | }) 23 | -------------------------------------------------------------------------------- /src/actions/v2/subscription/getSubscribedSegments.ts: -------------------------------------------------------------------------------- 1 | import { GrpcAppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import SubscriptionService from '@services/subscription' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v2/subscription/getSubscribedSegments' 9 | 10 | export default class GetSubscribedSegmentsAction implements GrpcAppAction { 11 | constructor(private readonly subscriptionService: SubscriptionService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V2 16 | 17 | readonly name: string = 'getSubscribedSegments' 18 | 19 | readonly validationRules: ValidationSchema = { 20 | userIdentifier: { type: 'string' }, 21 | } 22 | 23 | async handler(args: CustomActionArguments): Promise { 24 | const { 25 | params: { userIdentifier }, 26 | } = args 27 | 28 | const segments = await this.subscriptionService.getSubscribedSegments(userIdentifier) 29 | 30 | return { segments } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /tests/unit/actions/v1/userInfo/hasUserProfile.spec.ts: -------------------------------------------------------------------------------- 1 | import TestKit, { mockInstance } from '@diia-inhouse/test' 2 | 3 | import HasUserProfileAction from '@actions/v1/userInfo/hasUserProfile' 4 | 5 | import UserProfileService from '@services/userProfile' 6 | 7 | describe(`Action ${HasUserProfileAction.name}`, () => { 8 | const testKit = new TestKit() 9 | const headers = testKit.session.getHeaders() 10 | const userProfileServiceMock = mockInstance(UserProfileService) 11 | 12 | const hasUserProfileAction = new HasUserProfileAction(userProfileServiceMock) 13 | 14 | describe('method `handler`', () => { 15 | it('should return true if has user profile', async () => { 16 | const args = { 17 | params: { userIdentifier: 'userIdentifier' }, 18 | session: testKit.session.getUserSession(), 19 | headers, 20 | } 21 | 22 | jest.spyOn(userProfileServiceMock, 'hasUserProfile').mockResolvedValueOnce(true) 23 | 24 | expect(await hasUserProfileAction.handler(args)).toBeTruthy() 25 | 26 | expect(userProfileServiceMock.hasUserProfile).toHaveBeenCalledWith(args.params.userIdentifier) 27 | }) 28 | }) 29 | }) 30 | -------------------------------------------------------------------------------- /src/actions/v1/userDocument/getUserDocumentSettings.ts: -------------------------------------------------------------------------------- 1 | import { GrpcAppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import UserDocumentSettingsService from '@services/userDocumentSettings' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userDocument/getUserDocumentSettings' 9 | 10 | export default class GetUserDocumentSettingsAction implements GrpcAppAction { 11 | constructor(private readonly userDocumentSettingsService: UserDocumentSettingsService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'getUserDocumentSettings' 18 | 19 | readonly validationRules: ValidationSchema = { 20 | userIdentifier: { type: 'string' }, 21 | features: { type: 'array', items: { type: 'string' } }, 22 | } 23 | 24 | async handler(args: CustomActionArguments): Promise { 25 | const { params } = args 26 | 27 | return await this.userDocumentSettingsService.getDocumentSettings(params) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/actions/v1/userVerification/areFeaturePointsExist.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import DocumentFeaturePointsService from '@services/documentFeaturePoints' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userVerification/areFeaturePointsExist' 9 | 10 | export default class AreFeaturePointsExistAction implements AppAction { 11 | constructor(private readonly documentFeaturePointsService: DocumentFeaturePointsService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'areFeaturePointsExist' 18 | 19 | readonly validationRules: ValidationSchema = { 20 | userIdentifier: { type: 'string' }, 21 | } 22 | 23 | async handler(args: CustomActionArguments): Promise { 24 | const { 25 | params: { userIdentifier }, 26 | } = args 27 | 28 | return await this.documentFeaturePointsService.areFeaturePointsExistByUserIdentifier(userIdentifier) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/actions/v2/diiaId/checkIdentifierAvailability.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | 5 | import DiiaIdService from '@services/diiaId' 6 | 7 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v2/diiaId/checkIdentifierAvailability' 8 | import { DiiaIdIdentifier } from '@interfaces/services/diiaId' 9 | 10 | export default class CheckDiiaIdIdentifierAvailabilityAction implements AppAction { 11 | constructor(private readonly diiaIdService: DiiaIdService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.User 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V2 16 | 17 | readonly name: string = 'checkDiiaIdIdentifierAvailability' 18 | 19 | async handler(args: CustomActionArguments): Promise { 20 | const { 21 | session: { 22 | user: { identifier: userIdentifier }, 23 | }, 24 | headers: { mobileUid }, 25 | } = args 26 | 27 | const identifiers: DiiaIdIdentifier[] = await this.diiaIdService.getIdentifierAvailability(userIdentifier, mobileUid) 28 | 29 | return { identifiers } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/services/subscription/strategies/publicService.ts: -------------------------------------------------------------------------------- 1 | import { UpdateQuery } from '@diia-inhouse/db' 2 | 3 | import { SubscriptionModel, SubscriptionSubType, SubscriptionType } from '@interfaces/models/subscription' 4 | import { SubscriptionCode, SubscriptionParams, SubscriptionStrategy } from '@interfaces/services/subscription' 5 | 6 | export default class PublicServiceStrategyService implements SubscriptionStrategy { 7 | readonly subscriptionCode: SubscriptionCode = SubscriptionCode.PublicService 8 | 9 | async subscribe(subscription: SubscriptionModel, params: SubscriptionParams): Promise> { 10 | const { segmentId } = params 11 | if (!segmentId) { 12 | throw new Error('segmentId is not provided') 13 | } 14 | 15 | const subscribedSegments = subscription[SubscriptionType.Segment]?.[SubscriptionSubType.PublicServices] 16 | if (subscribedSegments?.includes(segmentId)) { 17 | return 18 | } 19 | 20 | const modifier: UpdateQuery = { 21 | $addToSet: { [`${SubscriptionType.Segment}.${SubscriptionSubType.PublicServices}`]: segmentId }, 22 | } 23 | 24 | return modifier 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/unit/actions/v1/userDocument/getDocumentsTypeOrder.spec.ts: -------------------------------------------------------------------------------- 1 | import TestKit, { mockInstance } from '@diia-inhouse/test' 2 | 3 | import GetDocumentsTypeOrderAction from '@actions/v1/userDocument/getDocumentsTypeOrder' 4 | 5 | import UserDocumentSettingsService from '@services/userDocumentSettings' 6 | 7 | describe(`Action ${GetDocumentsTypeOrderAction.name}`, () => { 8 | const testKit = new TestKit() 9 | const userDocumentSettingsService = mockInstance(UserDocumentSettingsService) 10 | const action = new GetDocumentsTypeOrderAction(userDocumentSettingsService) 11 | 12 | it('should call getDocumentsTypeOrder', async () => { 13 | const { session, headers } = testKit.session.getUserActionArguments() 14 | const { identifier: userIdentifier } = session.user 15 | const documentsTypeOrder = ['uId', 'idCard', 'taxpayerCard'] 16 | 17 | jest.spyOn(userDocumentSettingsService, 'getDocumentsTypeOrder').mockResolvedValueOnce(documentsTypeOrder) 18 | 19 | const result = await action.handler({ session, headers }) 20 | 21 | expect(userDocumentSettingsService.getDocumentsTypeOrder).toHaveBeenCalledWith({ userIdentifier }) 22 | expect(result).toEqual({ documentsTypeOrder }) 23 | }) 24 | }) 25 | -------------------------------------------------------------------------------- /src/actions/v1/userVerification/getFeatures.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { BadRequestError } from '@diia-inhouse/errors' 4 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 5 | 6 | import OnboardingService from '@services/onboarding' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userVerification/getFeatures' 9 | 10 | export default class GetFeaturesAction implements AppAction { 11 | constructor(private readonly onboardingService: OnboardingService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'getFeatures' 18 | 19 | async handler(args: CustomActionArguments): Promise { 20 | const { 21 | headers: { mobileUid, appVersion, platformType }, 22 | } = args 23 | 24 | if (!mobileUid || !appVersion || !platformType) { 25 | throw new BadRequestError('Missing mobileUid, appVersion or platformType', { mobileUid, appVersion, platformType }) 26 | } 27 | 28 | return await this.onboardingService.getFeatures(mobileUid, appVersion, platformType) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/unit/actions/v2/diiaId/checkIdentifierAvailability.spec.ts: -------------------------------------------------------------------------------- 1 | import TestKit, { mockInstance } from '@diia-inhouse/test' 2 | 3 | import CheckDiiaIdIdentifierAvailabilityAction from '@actions/v2/diiaId/checkIdentifierAvailability' 4 | 5 | import DiiaIdService from '@services/diiaId' 6 | 7 | import { SignAlgo } from '@interfaces/models/diiaId' 8 | 9 | describe(`Action ${CheckDiiaIdIdentifierAvailabilityAction.name}`, () => { 10 | const testKit = new TestKit() 11 | const diiaIdService = mockInstance(DiiaIdService) 12 | const action = new CheckDiiaIdIdentifierAvailabilityAction(diiaIdService) 13 | 14 | it('should return identifiers', async () => { 15 | const headers = testKit.session.getHeaders() 16 | const session = testKit.session.getUserSession() 17 | 18 | const identifiers = [{ identifier: 'identifier', signAlgo: SignAlgo.DSTU }] 19 | 20 | jest.spyOn(diiaIdService, 'getIdentifierAvailability').mockResolvedValueOnce(identifiers) 21 | 22 | const result = await action.handler({ session, headers }) 23 | 24 | expect(diiaIdService.getIdentifierAvailability).toHaveBeenCalledWith(session.user.identifier, headers.mobileUid) 25 | expect(result).toEqual({ identifiers }) 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /src/actions/v1/userInfo/getServiceUserByLogin.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import ServiceUserService from '@services/serviceUser' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userInfo/getServiceUserByLogin' 9 | 10 | export default class GetServiceUserByLoginAction implements AppAction { 11 | constructor(private readonly serviceUserService: ServiceUserService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'getServiceUserByLogin' 18 | 19 | readonly validationRules: ValidationSchema = { 20 | login: { type: 'string' }, 21 | } 22 | 23 | async handler(args: CustomActionArguments): Promise { 24 | const { 25 | params: { login: loginParam }, 26 | } = args 27 | 28 | const { login, hashedPassword, twoFactorSecret } = await this.serviceUserService.getServiceUserByLogin(loginParam) 29 | 30 | return { login, hashedPassword, twoFactorSecret } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/actions/v1/userVerification/checkDocumentsFeaturePoints.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import DocumentFeaturePointsService from '@services/documentFeaturePoints' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userVerification/checkDocumentsFeaturePoints' 9 | 10 | export default class CheckDocumentsFeaturePointsAction implements AppAction { 11 | constructor(private readonly documentFeaturePointsService: DocumentFeaturePointsService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'checkDocumentsFeaturePoints' 18 | 19 | readonly validationRules: ValidationSchema = { 20 | userIdentifier: { type: 'string' }, 21 | } 22 | 23 | async handler(args: CustomActionArguments): Promise { 24 | const { userIdentifier } = args.params 25 | 26 | return { 27 | documents: await this.documentFeaturePointsService.checkDocumentsFeaturePoints(userIdentifier), 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/actions/v1/userInfo/getUserProfileFeatures.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, ProfileFeature, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import UserProfileService from '@services/userProfile' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userInfo/getUserProfileFeatures' 9 | 10 | export default class GetUserProfileFeaturesAction implements AppAction { 11 | constructor(private readonly userProfileService: UserProfileService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'getUserProfileFeatures' 18 | 19 | readonly validationRules: ValidationSchema = { 20 | userIdentifier: { type: 'string' }, 21 | features: { type: 'array', items: { type: 'string', enum: Object.values(ProfileFeature) } }, 22 | } 23 | 24 | async handler(args: CustomActionArguments): Promise { 25 | const { userIdentifier, features } = args.params 26 | 27 | return await this.userProfileService.getUserProfileFeatures(userIdentifier, features) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /proto/user-profile.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | import "google/protobuf/timestamp.proto"; 4 | 5 | import "token/gender.proto"; 6 | import "profileFeature.proto"; 7 | 8 | package ua.gov.diia.user.userprofile; 9 | option java_multiple_files = true; 10 | option java_package = "ua.gov.diia.user.userprofile"; 11 | 12 | message GetUserProfileFeaturesRequest { 13 | string userIdentifier = 1; 14 | repeated ua.gov.diia.types.profilefeatures.ProfileFeature features = 2; 15 | } 16 | 17 | message GetUserProfileFeaturesResponse { 18 | optional DiiaOfficeProfile office = 1; 19 | } 20 | 21 | message GetUserProfilesRequest { repeated string userIdentifiers = 1; } 22 | 23 | message GetUserProfilesResponse { repeated UserProfile userProfiles = 1; } 24 | 25 | message UserProfile { 26 | string identifier = 1; 27 | ua.gov.diia.types.token.Gender gender = 2; 28 | google.protobuf.Timestamp birthDay = 3; 29 | } 30 | 31 | message DiiaOfficeProfile { 32 | string profileId = 1; 33 | string organizationId = 2; 34 | string unitId = 3; 35 | repeated string scopes = 4; 36 | bool isOrganizationAdmin = 5; 37 | Status status = 6; 38 | optional string googleWorkspace = 7; 39 | 40 | enum Status { 41 | ACTIVE = 0; 42 | SUSPENDED = 1; 43 | DISMISSED = 2; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/actions/v2/diiaId/getIdentifier.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import DiiaIdService from '@services/diiaId' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v2/diiaId/getIdentifier' 9 | import { SignAlgo } from '@interfaces/models/diiaId' 10 | 11 | export default class GetDiiaIdIdentifierAction implements AppAction { 12 | constructor(private readonly diiaIdService: DiiaIdService) {} 13 | 14 | readonly sessionType: SessionType = SessionType.User 15 | 16 | readonly actionVersion: ActionVersion = ActionVersion.V2 17 | 18 | readonly name: string = 'getDiiaIdIdentifier' 19 | 20 | readonly validationRules: ValidationSchema = { 21 | signAlgo: { type: 'string', enum: Object.values(SignAlgo), default: SignAlgo.DSTU }, 22 | } 23 | 24 | async handler(args: CustomActionArguments): Promise { 25 | const { 26 | params: { signAlgo }, 27 | session: { user }, 28 | headers, 29 | } = args 30 | 31 | return await this.diiaIdService.getIdentifierV2(user, headers, signAlgo) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/models/userDocumentSettings.ts: -------------------------------------------------------------------------------- 1 | import { Model, Schema, SchemaDefinition, model, models } from '@diia-inhouse/db' 2 | 3 | import { DocumentTypeSetting, UserDocumentSettings, UserDocumentSettingsModel } from '@interfaces/models/userDocumentSettings' 4 | 5 | const documentTypeSettingsSchema = new Schema( 6 | { 7 | documentTypeOrder: { type: Number, required: true }, 8 | documentIdentifiers: { type: Object }, 9 | hiddenDocuments: { type: [String] }, 10 | hiddenDocumentType: { type: Boolean }, 11 | }, 12 | { 13 | _id: false, 14 | }, 15 | ) 16 | 17 | const userDocumentSettingsSchemaDefinition: SchemaDefinition = { 18 | type: Map, 19 | of: { type: [documentTypeSettingsSchema, { userIdentifier: { type: String, required: true } }] }, 20 | } 21 | 22 | const userDocumentSettingsSchema = new Schema(userDocumentSettingsSchemaDefinition, { 23 | timestamps: true, 24 | strict: false, 25 | }) 26 | 27 | userDocumentSettingsSchema.index({ userIdentifier: 1 }, { unique: true }) 28 | 29 | export const skipSyncIndexes = true 30 | 31 | export default >models.UserDocumentSettings || model('UserDocumentSettings', userDocumentSettingsSchema) 32 | -------------------------------------------------------------------------------- /src/services/userActionAccessSetting.ts: -------------------------------------------------------------------------------- 1 | import { InternalServerError } from '@diia-inhouse/errors' 2 | 3 | import userUserActionAccessSettingModel from '@models/userActionAccessSetting' 4 | 5 | import { UserActionAccessSettingModel } from '@interfaces/models/userActionAccessSetting' 6 | import { ActionAccessType } from '@interfaces/services/userActionAccess' 7 | 8 | export default class UserActionAccessSettingService { 9 | private userActionAccessSettingSettings: Map = new Map() 10 | 11 | async getSetting(actionAccessType: ActionAccessType): Promise { 12 | const cachedMaxValue = this.userActionAccessSettingSettings.get(actionAccessType) 13 | if (cachedMaxValue !== undefined) { 14 | return cachedMaxValue 15 | } 16 | 17 | const userActionAccessSetting = await userUserActionAccessSettingModel.findOne({ actionAccessType }) 18 | if (!userActionAccessSetting) { 19 | throw new InternalServerError(`There is no user action access setting for the ${actionAccessType}`) 20 | } 21 | 22 | this.userActionAccessSettingSettings.set(actionAccessType, userActionAccessSetting) 23 | 24 | return userActionAccessSetting 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/unit/actions/v1/diiaId/getIdentifiers.spec.ts: -------------------------------------------------------------------------------- 1 | import TestKit, { mockInstance } from '@diia-inhouse/test' 2 | 3 | import GetDiiaIdIdentifiersAction from '@actions/v1/diiaId/getIdentifiers' 4 | 5 | import DiiaIdService from '@services/diiaId' 6 | 7 | describe(`Action ${GetDiiaIdIdentifiersAction.name}`, () => { 8 | const testKit = new TestKit() 9 | const diiaIdServiceMock = mockInstance(DiiaIdService) 10 | 11 | const getDiiaIdIdentifiersAction = new GetDiiaIdIdentifiersAction(diiaIdServiceMock) 12 | 13 | describe('Method `handler`', () => { 14 | it('should return diiaId', async () => { 15 | const args = { 16 | session: testKit.session.getUserSession(), 17 | headers: testKit.session.getHeaders(), 18 | } 19 | 20 | const identifiers = { 21 | identifiers: [], 22 | hasSigningHistory: true, 23 | } 24 | 25 | jest.spyOn(diiaIdServiceMock, 'getIdentifiersV1').mockResolvedValueOnce(identifiers) 26 | 27 | expect(await getDiiaIdIdentifiersAction.handler(args)).toMatchObject(identifiers) 28 | 29 | expect(diiaIdServiceMock.getIdentifiersV1).toHaveBeenCalledWith(args.session.user, args.headers) 30 | }) 31 | }) 32 | }) 33 | -------------------------------------------------------------------------------- /src/actions/v1/userVerification/getEResidentFeatures.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { BadRequestError } from '@diia-inhouse/errors' 4 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 5 | 6 | import OnboardingService from '@services/onboarding' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userVerification/getFeatures' 9 | 10 | export default class GetEResidentFeaturesAction implements AppAction { 11 | constructor(private readonly onboardingService: OnboardingService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'getEResidentFeatures' 18 | 19 | async handler(args: CustomActionArguments): Promise { 20 | const { 21 | headers: { mobileUid, appVersion, platformType }, 22 | } = args 23 | 24 | if (!mobileUid || !appVersion || !platformType) { 25 | throw new BadRequestError('Missing mobileUid, appVersion or platformType', { mobileUid, appVersion, platformType }) 26 | } 27 | 28 | return await this.onboardingService.getFeatures(mobileUid, appVersion, platformType, SessionType.EResident) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/actions/v1/userHistory/getSessionHistoryScreen.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import UserHistoryService from '@services/userHistory' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userHistory/getSessionHistoryScreen' 9 | 10 | export default class GetSessionHistoryScreenAction implements AppAction { 11 | constructor(private readonly userHistoryService: UserHistoryService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.User 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'getSessionHistoryScreen' 18 | 19 | readonly validationRules: ValidationSchema = { 20 | sessionId: { type: 'string' }, 21 | } 22 | 23 | async handler(args: CustomActionArguments): Promise { 24 | const { 25 | params: { sessionId }, 26 | session: { 27 | user: { identifier: userIdentifier }, 28 | }, 29 | } = args 30 | 31 | return await this.userHistoryService.getHistoryScreen(userIdentifier, sessionId) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/mocks/grpc/clients.ts: -------------------------------------------------------------------------------- 1 | import { GrpcClientFactory } from '@diia-inhouse/diia-app' 2 | 3 | import { CryptoDocServiceDefinition } from '@diia-inhouse/diia-crypto-client' 4 | import DiiaLogger from '@diia-inhouse/diia-logger' 5 | import { MetricsService } from '@diia-inhouse/diia-metrics' 6 | import { DocumentsServiceDefinition } from '@diia-inhouse/documents-service-client' 7 | import { mockInstance } from '@diia-inhouse/test' 8 | import { SessionType } from '@diia-inhouse/types' 9 | 10 | const grpcClientFactory = new GrpcClientFactory('User', new DiiaLogger(), mockInstance(MetricsService)) 11 | 12 | export const cryptoDocServiceClient = grpcClientFactory.createGrpcClient(CryptoDocServiceDefinition, 'test') 13 | 14 | export const documentsDocServiceClient = grpcClientFactory.createGrpcClient(DocumentsServiceDefinition, 'test') 15 | 16 | jest.spyOn(documentsDocServiceClient, 'getSortedByDefaultDocumentTypes').mockResolvedValue({ 17 | sortedDocumentTypes: { [SessionType.User]: { items: ['birth-record'] }, [SessionType.EResident]: { items: [] } }, 18 | }) 19 | 20 | jest.spyOn(documentsDocServiceClient, 'getDocumentNames').mockResolvedValue({ 21 | documentTypeToName: {}, 22 | }) 23 | 24 | jest.spyOn(documentsDocServiceClient, 'getDocumentTypes').mockResolvedValue({ 25 | documentTypes: [], 26 | }) 27 | -------------------------------------------------------------------------------- /tests/unit/actions/v1/diiaId/hasIdentifier.spec.ts: -------------------------------------------------------------------------------- 1 | import TestKit, { mockInstance } from '@diia-inhouse/test' 2 | 3 | import HasDiiaIdIdentifierAction from '@actions/v1/diiaId/hasIdentifier' 4 | 5 | import DiiaIdService from '@services/diiaId' 6 | 7 | describe(`Action ${HasDiiaIdIdentifierAction.name}`, () => { 8 | const testKit = new TestKit() 9 | const diiaIdServiceMock = mockInstance(DiiaIdService) 10 | 11 | const hasDiiaIdIdentifierAction = new HasDiiaIdIdentifierAction(diiaIdServiceMock) 12 | 13 | describe('Method `handler`', () => { 14 | it('should return true if has identifier', async () => { 15 | const args = { 16 | params: { 17 | userIdentifier: 'userIdentifier', 18 | mobileUidToFilter: 'mobileUidToFilter', 19 | }, 20 | session: testKit.session.getUserSession(), 21 | headers: testKit.session.getHeaders(), 22 | } 23 | 24 | jest.spyOn(diiaIdServiceMock, 'hasIdentifier').mockResolvedValueOnce(true) 25 | 26 | expect(await hasDiiaIdIdentifierAction.handler(args)).toBeTruthy() 27 | 28 | expect(diiaIdServiceMock.hasIdentifier).toHaveBeenCalledWith(args.params.userIdentifier, args.params.mobileUidToFilter) 29 | }) 30 | }) 31 | }) 32 | -------------------------------------------------------------------------------- /src/actions/v1/actionAccess/hasActionAccess.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import UserActionAccessService from '@services/userActionAccess' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/actionAccess/hasActionAccess' 9 | import { ActionAccessType } from '@interfaces/services/userActionAccess' 10 | 11 | export default class HasActionAccessAction implements AppAction { 12 | constructor(private readonly userActionAccessService: UserActionAccessService) {} 13 | 14 | readonly sessionType: SessionType = SessionType.None 15 | 16 | readonly actionVersion: ActionVersion = ActionVersion.V1 17 | 18 | readonly name: string = 'hasActionAccess' 19 | 20 | readonly validationRules: ValidationSchema = { 21 | userIdentifier: { type: 'string' }, 22 | actionAccessType: { type: 'string', enum: Object.values(ActionAccessType) }, 23 | } 24 | 25 | async handler(args: CustomActionArguments): Promise { 26 | const { userIdentifier, actionAccessType } = args.params 27 | 28 | return await this.userActionAccessService.hasActionAccess(userIdentifier, actionAccessType) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/actions/v1/userDocument/removeFromStorageByHashData.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import UserDocumentStorageService from '@services/userDocumentStorage' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userDocument/removeFromStorageByHashData' 9 | 10 | export default class RemoveFromStorageByHashDataAction implements AppAction { 11 | constructor(private readonly userDocumentStorageService: UserDocumentStorageService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'removeFromStorageByHashData' 18 | 19 | readonly validationRules: ValidationSchema = { 20 | userIdentifier: { type: 'string' }, 21 | documentType: { type: 'string' }, 22 | hashData: { type: 'string' }, 23 | } 24 | 25 | async handler(args: CustomActionArguments): Promise { 26 | const { userIdentifier, documentType, hashData } = args.params 27 | 28 | await this.userDocumentStorageService.removeFromStorageByHashData(userIdentifier, documentType, hashData) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/eventListeners/removeDocumentPhoto.ts: -------------------------------------------------------------------------------- 1 | import { EventBusListener } from '@diia-inhouse/diia-queue' 2 | import { ValidationSchema } from '@diia-inhouse/validators' 3 | 4 | import DocumentFeaturePointsService from '@services/documentFeaturePoints' 5 | 6 | import { EventPayload } from '@interfaces/eventListeners/removeDocumentPhoto' 7 | import { InternalEvent } from '@interfaces/queue' 8 | 9 | export default class RemoveDocumentPhotoEventListener implements EventBusListener { 10 | constructor( 11 | private readonly documentFeaturePointsService: DocumentFeaturePointsService, 12 | private readonly documentTypes: string[], 13 | ) { 14 | this.validationRules = { 15 | userIdentifier: { type: 'string' }, 16 | documentType: { type: 'string', enum: this.documentTypes }, 17 | documentIdentifier: { type: 'string' }, 18 | } 19 | } 20 | 21 | readonly event: InternalEvent = InternalEvent.DocumentsRemoveDocumentPhoto 22 | 23 | readonly validationRules: ValidationSchema 24 | 25 | async handler(message: EventPayload): Promise { 26 | const { userIdentifier, documentType, documentIdentifier } = message 27 | 28 | await this.documentFeaturePointsService.removeDocumentFeaturePoints(userIdentifier, documentType, documentIdentifier) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/unit/actions/v2/userDocument/getDocumentsTypeOrder.spec.ts: -------------------------------------------------------------------------------- 1 | import TestKit, { mockInstance } from '@diia-inhouse/test' 2 | 3 | import GetDocumentsTypeOrderAction from '@actions/v2/userDocument/getDocumentsTypeOrder' 4 | 5 | import UserDocumentSettingsService from '@services/userDocumentSettings' 6 | 7 | describe(`Action ${GetDocumentsTypeOrderAction.name}`, () => { 8 | const testKit = new TestKit() 9 | const userDocumentSettingsService = mockInstance(UserDocumentSettingsService) 10 | const action = new GetDocumentsTypeOrderAction(userDocumentSettingsService) 11 | 12 | it('should call getDocumentsTypeOrder', async () => { 13 | const headers = testKit.session.getHeaders() 14 | const session = testKit.session.getDiiaOfficeUserSession() 15 | const { user, features } = session 16 | const { identifier: userIdentifier } = user 17 | const documentsTypeOrder = ['uId', 'idCard', 'taxpayerCard'] 18 | 19 | jest.spyOn(userDocumentSettingsService, 'getDocumentsTypeOrder').mockResolvedValueOnce(documentsTypeOrder) 20 | 21 | const result = await action.handler({ session, headers }) 22 | 23 | expect(userDocumentSettingsService.getDocumentsTypeOrder).toHaveBeenCalledWith({ userIdentifier, features }) 24 | expect(result).toEqual({ documentsTypeOrder }) 25 | }) 26 | }) 27 | -------------------------------------------------------------------------------- /tests/unit/actions/v2/userDocument/hasDocuments.spec.ts: -------------------------------------------------------------------------------- 1 | import TestKit, { mockInstance } from '@diia-inhouse/test' 2 | 3 | import HasDocumentsAction from '@actions/v2/userDocument/hasDocuments' 4 | 5 | import UserDocumentService from '@services/userDocument' 6 | 7 | describe(`Action ${HasDocumentsAction.name}`, () => { 8 | const testKit = new TestKit() 9 | const userDocumentService = mockInstance(UserDocumentService) 10 | 11 | const action = new HasDocumentsAction(userDocumentService, []) 12 | 13 | describe('Method `handler`', () => { 14 | it('should return true if user has documents', async () => { 15 | const args = { 16 | params: { 17 | userIdentifier: 'userIdentifier', 18 | documentTypes: [['internal-passport', 'driver-license'], ['driver-license']], 19 | }, 20 | session: testKit.session.getUserSession(), 21 | headers: testKit.session.getHeaders(), 22 | } 23 | 24 | jest.spyOn(userDocumentService, 'hasDocuments').mockResolvedValueOnce(true) 25 | 26 | expect(await action.handler(args)).toBeTruthy() 27 | 28 | expect(userDocumentService.hasDocuments).toHaveBeenCalledWith(args.params.userIdentifier, args.params.documentTypes) 29 | }) 30 | }) 31 | }) 32 | -------------------------------------------------------------------------------- /src/actions/v1/diiaId/deleteIdentifier.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | 5 | import DiiaIdService from '@services/diiaId' 6 | 7 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/diiaId/deleteIdentifier' 8 | import { ProcessCode } from '@interfaces/services' 9 | 10 | export default class DeleteDiiaIdIdentifierAction implements AppAction { 11 | constructor(private readonly diiaIdService: DiiaIdService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.User 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'deleteDiiaIdIdentifier' 18 | 19 | async handler(args: CustomActionArguments): Promise { 20 | const { 21 | session: { 22 | user: { identifier: userIdentifier }, 23 | }, 24 | headers: { mobileUid }, 25 | } = args 26 | 27 | const success: boolean = await this.diiaIdService.softDeleteIdentifiers(userIdentifier, { mobileUid }) 28 | const processCode: ProcessCode = success ? ProcessCode.DiiaIdSuccessfullyDeleted : ProcessCode.DiiaIdNotFound 29 | 30 | return { 31 | success: true, 32 | processCode, 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/unit/actions/v1/userDocument/hasOneOfDocuments.spec.ts: -------------------------------------------------------------------------------- 1 | import TestKit, { mockInstance } from '@diia-inhouse/test' 2 | 3 | import HasOneOfDocumentsAction from '@actions/v1/userDocument/hasOneOfDocuments' 4 | 5 | import UserDocumentService from '@services/userDocument' 6 | 7 | describe(`Action ${HasOneOfDocumentsAction.name}`, () => { 8 | const testKit = new TestKit() 9 | const headers = testKit.session.getHeaders() 10 | const userDocumentServiceMock = mockInstance(UserDocumentService) 11 | 12 | const hasOneOfDocumentsAction = new HasOneOfDocumentsAction(userDocumentServiceMock, []) 13 | 14 | describe('method `handler`', () => { 15 | it('should return true if user has one of given documents', async () => { 16 | const args = { 17 | params: { userIdentifier: 'userIdentifier', documentTypes: ['taxpayer-card', 'driver-license'] }, 18 | session: testKit.session.getUserSession(), 19 | headers, 20 | } 21 | 22 | jest.spyOn(userDocumentServiceMock, 'hasOneOfDocuments').mockResolvedValueOnce(true) 23 | 24 | expect(await hasOneOfDocumentsAction.handler(args)).toBeTruthy() 25 | 26 | expect(userDocumentServiceMock.hasOneOfDocuments).toHaveBeenCalledWith(args.params.userIdentifier, args.params.documentTypes) 27 | }) 28 | }) 29 | }) 30 | -------------------------------------------------------------------------------- /src/actions/v1/userInfo/getUserProfiles.ts: -------------------------------------------------------------------------------- 1 | import { GrpcAppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import UserProfileService from '@services/userProfile' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userInfo/getUserProfiles' 9 | 10 | export default class GetUserProfilesAction implements GrpcAppAction { 11 | constructor(private readonly userProfileService: UserProfileService) {} 12 | 13 | readonly sessionType: SessionType = SessionType.None 14 | 15 | readonly actionVersion: ActionVersion = ActionVersion.V1 16 | 17 | readonly name: string = 'getUserProfiles' 18 | 19 | readonly validationRules: ValidationSchema = { 20 | userIdentifiers: { type: 'array', items: { type: 'string' } }, 21 | } 22 | 23 | async handler(args: CustomActionArguments): Promise { 24 | const { 25 | params: { userIdentifiers }, 26 | } = args 27 | 28 | const userProfiles = await this.userProfileService.getUserProfiles(userIdentifiers) 29 | 30 | return { 31 | userProfiles: userProfiles.map(({ identifier, gender, birthDay }) => ({ identifier, gender, birthDay })), 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/interfaces/services/index.ts: -------------------------------------------------------------------------------- 1 | export enum ProcessCode { 2 | OtpVerifyAttemptsExceeded = 16101006, 3 | OtpSendAttemptsExceeded = 16101007, 4 | DiiaIdSuccessfullyDeleted = 19101004, 5 | DiiaIdNotFound = 19101005, 6 | DiiaIdInCreationProcess = 19101006, 7 | DiiaIdCreated = 19101007, 8 | NoValidCertificateDetected = 19101010, 9 | NoRequiredDocument = 19101011, 10 | UnknownRequestToSignDocument = 19101012, 11 | RegistryUnavailableWhenDiiaIdCreating = 19101031, 12 | RegistryUnavailableWhenSigning = 19101032, 13 | SignedDocumentsIntegrityViolated = 19101013, 14 | SubscribedCreditHistory = 25101001, 15 | FailedSubscribeCreditHistory = 25101002, 16 | FailedUnsubscribeCreditHistory = 25101003, 17 | UnsubscribedCreditHistory = 25101004, 18 | } 19 | 20 | export enum AttentionMessageParameterType { 21 | Link = 'link', 22 | Phone = 'phone', 23 | Email = 'email', 24 | } 25 | 26 | export interface AttentionMessageParameter { 27 | type: AttentionMessageParameterType 28 | data: { 29 | name: string 30 | alt: string 31 | resource: string 32 | } 33 | } 34 | 35 | export interface AttentionMessage { 36 | title?: string 37 | text?: string 38 | icon: string 39 | parameters?: AttentionMessageParameter[] 40 | } 41 | 42 | export enum UserIdentifierPrefix { 43 | Ru = 'ru.', 44 | } 45 | -------------------------------------------------------------------------------- /src/actions/v1/actionAccess/nullifyCounterActionAccess.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import UserActionAccessService from '@services/userActionAccess' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/actionAccess/nullifyCounterActionAccess' 9 | import { ActionAccessType } from '@interfaces/services/userActionAccess' 10 | 11 | export default class NullifyCounterActionAccessAction implements AppAction { 12 | constructor(private readonly userActionAccessService: UserActionAccessService) {} 13 | 14 | readonly sessionType: SessionType = SessionType.None 15 | 16 | readonly actionVersion: ActionVersion = ActionVersion.V1 17 | 18 | readonly name: string = 'nullifyCounterActionAccess' 19 | 20 | readonly validationRules: ValidationSchema = { 21 | userIdentifier: { type: 'string' }, 22 | actionAccessType: { type: 'string', enum: Object.values(ActionAccessType) }, 23 | } 24 | 25 | async handler(args: CustomActionArguments): Promise { 26 | const { userIdentifier, actionAccessType } = args.params 27 | 28 | return await this.userActionAccessService.nullifyCounterActionAccess(userIdentifier, actionAccessType) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/actions/v1/actionAccess/increaseCounterActionAccess.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import UserActionAccessService from '@services/userActionAccess' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/actionAccess/increaseCounterActionAccess' 9 | import { ActionAccessType } from '@interfaces/services/userActionAccess' 10 | 11 | export default class IncreaseCounterActionAccessAction implements AppAction { 12 | constructor(private readonly userActionAccessService: UserActionAccessService) {} 13 | 14 | readonly sessionType: SessionType = SessionType.None 15 | 16 | readonly actionVersion: ActionVersion = ActionVersion.V1 17 | 18 | readonly name: string = 'increaseCounterActionAccess' 19 | 20 | readonly validationRules: ValidationSchema = { 21 | userIdentifier: { type: 'string' }, 22 | actionAccessType: { type: 'string', enum: Object.values(ActionAccessType) }, 23 | } 24 | 25 | async handler(args: CustomActionArguments): Promise { 26 | const { userIdentifier, actionAccessType } = args.params 27 | 28 | return await this.userActionAccessService.increaseCounterActionAccess(userIdentifier, actionAccessType) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/eventListeners/addDocumentPhoto.ts: -------------------------------------------------------------------------------- 1 | import { EventBusListener } from '@diia-inhouse/diia-queue' 2 | import { ValidationSchema } from '@diia-inhouse/validators' 3 | 4 | import DocumentFeaturePointsService from '@services/documentFeaturePoints' 5 | 6 | import { EventPayload } from '@interfaces/eventListeners/addDocumentPhoto' 7 | import { InternalEvent } from '@interfaces/queue' 8 | 9 | export default class AddDocumentPhotoEventListener implements EventBusListener { 10 | constructor( 11 | private readonly documentFeaturePointsService: DocumentFeaturePointsService, 12 | private readonly documentTypes: string[], 13 | ) { 14 | this.validationRules = { 15 | userIdentifier: { type: 'string' }, 16 | documentType: { type: 'string', enum: this.documentTypes }, 17 | documentIdentifier: { type: 'string' }, 18 | photo: { type: 'string' }, 19 | } 20 | } 21 | 22 | readonly event: InternalEvent = InternalEvent.DocumentsAddDocumentPhoto 23 | 24 | readonly validationRules: ValidationSchema 25 | 26 | async handler(message: EventPayload): Promise { 27 | const { userIdentifier, documentType, documentIdentifier, photo } = message 28 | 29 | await this.documentFeaturePointsService.createDocumentFeaturePointsEntity(userIdentifier, documentType, documentIdentifier, photo) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/unit/actions/v1/userInfo/loadUserProfileFeaturesAsync.spec.ts: -------------------------------------------------------------------------------- 1 | import TestKit, { mockInstance } from '@diia-inhouse/test' 2 | 3 | import LoadUserProfilesFeaturesAsyncAction from '@actions/v1/userInfo/loadUserProfileFeaturesAsync' 4 | 5 | import UserProfileService from '@services/userProfile' 6 | 7 | describe(`Action ${LoadUserProfilesFeaturesAsyncAction.name}`, () => { 8 | const testKit = new TestKit() 9 | const headers = testKit.session.getHeaders() 10 | const userProfileServiceMock = mockInstance(UserProfileService) 11 | 12 | const loadUserProfilesFeaturesAsyncAction = new LoadUserProfilesFeaturesAsyncAction(userProfileServiceMock) 13 | 14 | describe('method `handler`', () => { 15 | it('should successfully load user profile features', async () => { 16 | const args = { 17 | params: { itn: testKit.session.generateItn(testKit.session.getBirthDate(), testKit.session.getGender(), false) }, 18 | session: testKit.session.getUserSession(), 19 | headers, 20 | } 21 | 22 | jest.spyOn(userProfileServiceMock, 'checkForUserProfileFeatures').mockResolvedValueOnce() 23 | 24 | await loadUserProfilesFeaturesAsyncAction.handler(args) 25 | 26 | expect(userProfileServiceMock.checkForUserProfileFeatures).toHaveBeenCalledWith(args.params.itn) 27 | }) 28 | }) 29 | }) 30 | -------------------------------------------------------------------------------- /tests/unit/actions/v2/diiaId/getIdentifiers.spec.ts: -------------------------------------------------------------------------------- 1 | import TestKit, { mockInstance } from '@diia-inhouse/test' 2 | 3 | import GetDiiaIdIdentifiersAction from '@actions/v2/diiaId/getIdentifiers' 4 | 5 | import DiiaIdService from '@services/diiaId' 6 | 7 | import { SignAlgo } from '@interfaces/models/diiaId' 8 | 9 | describe(`Action ${GetDiiaIdIdentifiersAction.name}`, () => { 10 | const testKit = new TestKit() 11 | const diiaIdService = mockInstance(DiiaIdService) 12 | 13 | const action = new GetDiiaIdIdentifiersAction(diiaIdService) 14 | 15 | describe('Method `handler`', () => { 16 | it('should return identifier', async () => { 17 | const args = { 18 | params: { signAlgo: SignAlgo.DSTU }, 19 | session: testKit.session.getUserSession(), 20 | headers: testKit.session.getHeaders(), 21 | } 22 | 23 | const response = { 24 | identifiers: [{ identifier: 'identifier', signAlgo: SignAlgo.DSTU }], 25 | buttonHistoryName: 'buttonHistoryName', 26 | } 27 | 28 | jest.spyOn(diiaIdService, 'getIdentifiers').mockResolvedValueOnce(response) 29 | 30 | expect(await action.handler(args)).toMatchObject(response) 31 | 32 | expect(diiaIdService.getIdentifiers).toHaveBeenCalledWith(args.session.user, args.headers) 33 | }) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /src/actions/v1/subscription/isSubscribed.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import SubscriptionService from '@services/subscription' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/subscription/isSubscribed' 9 | import { PublicServiceCode } from '@interfaces/models/subscription' 10 | 11 | export default class IsSubscribedAction implements AppAction { 12 | constructor(private readonly subscriptionService: SubscriptionService) {} 13 | 14 | readonly sessionType: SessionType = SessionType.User 15 | 16 | readonly actionVersion: ActionVersion = ActionVersion.V1 17 | 18 | readonly name: string = 'isSubscribed' 19 | 20 | readonly validationRules: ValidationSchema = { 21 | userIdentifier: { type: 'string' }, 22 | publicService: { type: 'string', enum: Object.values(PublicServiceCode) }, 23 | subscriptionKey: { type: 'string', optional: true }, 24 | } 25 | 26 | async handler(args: CustomActionArguments): Promise { 27 | const { 28 | params: { userIdentifier, publicService, subscriptionKey }, 29 | } = args 30 | 31 | return await this.subscriptionService.isSubscribed(userIdentifier, publicService, subscriptionKey) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/actions/v1/userInfo/saveUserCitizenship.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import UserProfileService from '@services/userProfile' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userInfo/saveUserCitizenship' 9 | import { CitizenshipSource } from '@interfaces/models/userProfile' 10 | 11 | export default class SaveUserCitizenshipAction implements AppAction { 12 | constructor(private readonly userProfileService: UserProfileService) {} 13 | 14 | readonly sessionType: SessionType = SessionType.None 15 | 16 | readonly actionVersion: ActionVersion = ActionVersion.V1 17 | 18 | readonly name: string = 'saveUserCitizenship' 19 | 20 | readonly validationRules: ValidationSchema = { 21 | userIdentifier: { type: 'string' }, 22 | source: { type: 'string', enum: Object.values(CitizenshipSource) }, 23 | sourceId: { type: 'string' }, 24 | } 25 | 26 | async handler(args: CustomActionArguments): Promise { 27 | const { 28 | params: { userIdentifier, source, sourceId }, 29 | } = args 30 | 31 | await this.userProfileService.updateUserCitizenship(userIdentifier, source, sourceId) 32 | 33 | return { success: true } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/actions/v1/userDocument/processUserDocuments.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import UserDocumentService from '@services/userDocument' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userDocument/processUserDocuments' 9 | 10 | export default class ProcessUserDocuments implements AppAction { 11 | constructor( 12 | private readonly userDocumentService: UserDocumentService, 13 | private readonly documentTypes: string[], 14 | ) { 15 | this.validationRules = { 16 | userIdentifier: { type: 'string' }, 17 | documentTypes: { type: 'array', items: { type: 'string', enum: this.documentTypes } }, 18 | } 19 | } 20 | 21 | readonly sessionType: SessionType = SessionType.None 22 | 23 | readonly actionVersion: ActionVersion = ActionVersion.V1 24 | 25 | readonly name: string = 'processUserDocuments' 26 | 27 | readonly validationRules: ValidationSchema 28 | 29 | async handler(args: CustomActionArguments): Promise { 30 | const { 31 | params: { userIdentifier, documentTypes }, 32 | } = args 33 | 34 | return await this.userDocumentService.processUserDocuments(userIdentifier, documentTypes) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/interfaces/models/subscription.ts: -------------------------------------------------------------------------------- 1 | import { Document } from '@diia-inhouse/db' 2 | 3 | export enum SubscriptionType { 4 | Push = 'push', 5 | Segment = 'segment', 6 | } 7 | 8 | export enum SubscriptionSubType { 9 | Documents = 'documents', 10 | PublicServices = 'publicServices', 11 | } 12 | 13 | export enum PublicServiceCode { 14 | Debts = 'debts', 15 | 16 | CreditHistory = 'creditHistory', 17 | } 18 | 19 | export type SubscriptionItems = Record 20 | 21 | export type DocumentsSubs = Record 22 | 23 | export type PublicServicesSubs = Record 24 | 25 | export interface PushSubscriptionBySubType { 26 | [SubscriptionSubType.Documents]: DocumentsSubs 27 | [SubscriptionSubType.PublicServices]: PublicServicesSubs 28 | } 29 | 30 | export interface SegmentSubscriptionBySubType { 31 | [SubscriptionSubType.PublicServices]: string[] 32 | } 33 | 34 | export enum SubscriptionSource { 35 | Ubch = 'ubch', 36 | } 37 | 38 | export type SubscriptionIds = Partial> 39 | 40 | export interface Subscription { 41 | userIdentifier: string 42 | subscriptionIds: SubscriptionIds 43 | [SubscriptionType.Push]: PushSubscriptionBySubType 44 | [SubscriptionType.Segment]?: SegmentSubscriptionBySubType 45 | } 46 | 47 | export interface SubscriptionModel extends Subscription, Document {} 48 | -------------------------------------------------------------------------------- /src/actions/v1/diiaId/getIdentifier.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import DiiaIdService from '@services/diiaId' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/diiaId/getIdentifier' 9 | import { SignAlgo } from '@interfaces/models/diiaId' 10 | import { DiiaIdResponse } from '@interfaces/services/diiaId' 11 | 12 | export default class GetDiiaIdIdentifierAction implements AppAction { 13 | constructor(private readonly diiaIdService: DiiaIdService) {} 14 | 15 | readonly sessionType: SessionType = SessionType.User 16 | 17 | readonly actionVersion: ActionVersion = ActionVersion.V1 18 | 19 | readonly name: string = 'getDiiaIdIdentifier' 20 | 21 | readonly validationRules: ValidationSchema = { 22 | signAlgo: { type: 'string', enum: Object.values(SignAlgo), default: SignAlgo.DSTU }, 23 | } 24 | 25 | async handler(args: CustomActionArguments): Promise { 26 | const { 27 | params: { signAlgo }, 28 | session: { user }, 29 | headers: { mobileUid }, 30 | } = args 31 | 32 | const diiaId: DiiaIdResponse | undefined = await this.diiaIdService.getIdentifierV1(user, mobileUid, signAlgo) 33 | 34 | return { diiaId } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/validation/index.ts: -------------------------------------------------------------------------------- 1 | import { OwnerType } from '@diia-inhouse/types' 2 | import { ValidationSchema } from '@diia-inhouse/validators' 3 | 4 | import { UserProfileDocument } from '@interfaces/services/documents' 5 | 6 | export const userProfileDocumentValidationSchema: ValidationSchema = { 7 | documentIdentifier: { type: 'string' }, 8 | documentSubType: { type: 'string', optional: true }, 9 | ownerType: { type: 'string', enum: Object.values(OwnerType) }, 10 | docId: { type: 'string' }, 11 | docStatus: { type: 'number' }, 12 | compoundDocument: { 13 | type: 'object', 14 | optional: true, 15 | props: { 16 | documentType: { type: 'string' }, 17 | documentIdentifier: { type: 'string' }, 18 | }, 19 | }, 20 | registrationDate: { type: 'date', convert: true, optional: true }, 21 | issueDate: { type: 'date', convert: true, optional: true }, 22 | expirationDate: { type: 'date', convert: true, optional: true }, 23 | normalizedDocumentIdentifier: { type: 'string', optional: true }, 24 | fullNameHash: { type: 'string', optional: true }, 25 | comparedTo: { 26 | type: 'object', 27 | optional: true, 28 | props: { 29 | documentType: { type: 'string' }, 30 | fullNameHash: { type: 'string' }, 31 | }, 32 | }, 33 | documentData: { type: 'object', optional: true }, 34 | } 35 | -------------------------------------------------------------------------------- /src/actions/v1/userDocument/hasOneOfDocuments.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import UserDocumentService from '@services/userDocument' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/userDocument/hasOneOfDocuments' 9 | 10 | export default class HasOneOfDocumentsAction implements AppAction { 11 | constructor( 12 | private readonly userDocumentService: UserDocumentService, 13 | private readonly documentTypes: string[], 14 | ) { 15 | this.validationRules = { 16 | userIdentifier: { type: 'string' }, 17 | documentTypes: { 18 | type: 'array', 19 | items: { type: 'string', enum: this.documentTypes }, 20 | }, 21 | } 22 | } 23 | 24 | readonly sessionType: SessionType = SessionType.None 25 | 26 | readonly actionVersion: ActionVersion = ActionVersion.V1 27 | 28 | readonly name: string = 'hasOneOfDocuments' 29 | 30 | readonly validationRules: ValidationSchema 31 | 32 | async handler(args: CustomActionArguments): Promise { 33 | const { userIdentifier, documentTypes } = args.params 34 | 35 | return await this.userDocumentService.hasOneOfDocuments(userIdentifier, documentTypes) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/models/diiaId.ts: -------------------------------------------------------------------------------- 1 | import { Model, Schema, model, models } from '@diia-inhouse/db' 2 | 3 | import { DiiaId, DiiaIdRevoking, SignAlgo } from '@interfaces/models/diiaId' 4 | import { IdentityDocumentType } from '@interfaces/services/documents' 5 | 6 | const revokingSchema = new Schema( 7 | { 8 | eventUuid: { type: String, unique: true, sparse: true, required: true }, 9 | error: { type: String }, 10 | }, 11 | { 12 | _id: false, 13 | }, 14 | ) 15 | 16 | const diiaIdSchema = new Schema( 17 | { 18 | userIdentifier: { type: String, index: true, required: true }, 19 | mobileUid: { type: String, index: true, required: true }, 20 | identifier: { type: String, unique: true, required: true }, 21 | creationDate: { type: Date }, 22 | expirationDate: { type: Date }, 23 | isDeleted: { type: Boolean, required: true }, 24 | deletedAt: { type: Date }, 25 | revoking: { type: revokingSchema }, 26 | identityDocumentType: { type: String, enum: Object.values(IdentityDocumentType) }, 27 | signAlgo: { type: String, enum: Object.values(SignAlgo) }, 28 | registryUserIdentifier: { type: String, index: true }, 29 | certificateSerialNumber: { type: String }, 30 | }, 31 | { 32 | timestamps: true, 33 | }, 34 | ) 35 | 36 | export default >models.DiiaId || model('DiiaId', diiaIdSchema) 37 | -------------------------------------------------------------------------------- /tests/unit/actions/v1/userVerification/areFeaturePointsExist.spec.ts: -------------------------------------------------------------------------------- 1 | import TestKit, { mockInstance } from '@diia-inhouse/test' 2 | 3 | import AreFeaturePointsExistAction from '@actions/v1/userVerification/areFeaturePointsExist' 4 | 5 | import DocumentFeaturePointsService from '@services/documentFeaturePoints' 6 | 7 | describe(`Action ${AreFeaturePointsExistAction.name}`, () => { 8 | const testKit = new TestKit() 9 | const headers = testKit.session.getHeaders() 10 | const documentFeaturePointsServiceMock = mockInstance(DocumentFeaturePointsService) 11 | 12 | const areFeaturePointsExistAction = new AreFeaturePointsExistAction(documentFeaturePointsServiceMock) 13 | 14 | describe('method `handler`', () => { 15 | it('should return true when subscription is added', async () => { 16 | const args = { 17 | params: { userIdentifier: testKit.session.getUserSession().user.identifier }, 18 | session: testKit.session.getUserSession(), 19 | headers, 20 | } 21 | 22 | jest.spyOn(documentFeaturePointsServiceMock, 'areFeaturePointsExistByUserIdentifier').mockResolvedValueOnce(true) 23 | 24 | expect(await areFeaturePointsExistAction.handler(args)).toBe(true) 25 | 26 | expect(documentFeaturePointsServiceMock.areFeaturePointsExistByUserIdentifier).toHaveBeenCalledWith(args.params.userIdentifier) 27 | }) 28 | }) 29 | }) 30 | -------------------------------------------------------------------------------- /src/actions/v1/diiaId/getDpsPreparedPackage.ts: -------------------------------------------------------------------------------- 1 | import { AppAction } from '@diia-inhouse/diia-app' 2 | 3 | import { ActionVersion, SessionType } from '@diia-inhouse/types' 4 | import { ValidationSchema } from '@diia-inhouse/validators' 5 | 6 | import DiiaIdService from '@services/diiaId' 7 | 8 | import { ActionResult, CustomActionArguments } from '@interfaces/actions/v1/diiaId/getDpsPreparedPackage' 9 | import { SignAlgo } from '@interfaces/models/diiaId' 10 | 11 | export default class GetDpsPreparedPackageAction implements AppAction { 12 | constructor(private readonly diiaIdService: DiiaIdService) {} 13 | 14 | readonly sessionType: SessionType = SessionType.User 15 | 16 | readonly actionVersion: ActionVersion = ActionVersion.V1 17 | 18 | readonly name: string = 'getDpsPreparedPackage' 19 | 20 | readonly validationRules: ValidationSchema = { 21 | signAlgo: { type: 'string', enum: Object.values(SignAlgo), default: SignAlgo.DSTU }, 22 | } 23 | 24 | async handler(args: CustomActionArguments): Promise { 25 | const { 26 | params: { signAlgo }, 27 | headers: { mobileUid }, 28 | session: { 29 | user: { identifier: userIdentifier }, 30 | }, 31 | } = args 32 | 33 | const taxPackage = await this.diiaIdService.getDpsPreparedPackage(userIdentifier, mobileUid, signAlgo) 34 | 35 | return { taxPackage } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/unit/actions/v1/subscription/getSubscribedSegments.spec.ts: -------------------------------------------------------------------------------- 1 | import TestKit, { mockInstance } from '@diia-inhouse/test' 2 | 3 | import GetSubscribedSegmentsAction from '@actions/v1/subscription/getSubscribedSegments' 4 | 5 | import SubscriptionService from '@services/subscription' 6 | 7 | describe(`Action ${GetSubscribedSegmentsAction.name}`, () => { 8 | const testKit = new TestKit() 9 | const headers = testKit.session.getHeaders() 10 | const subscriptionServiceMock = mockInstance(SubscriptionService) 11 | 12 | const getSubscribedSegmentsAction = new GetSubscribedSegmentsAction(subscriptionServiceMock) 13 | 14 | describe('method `handler`', () => { 15 | it('should return subscribed segments', async () => { 16 | const args = { 17 | params: { 18 | userIdentifier: 'userIdentifier', 19 | }, 20 | session: testKit.session.getUserSession(), 21 | headers, 22 | } 23 | 24 | const subscribedSegments = ['segment1', 'segment2'] 25 | 26 | jest.spyOn(subscriptionServiceMock, 'getSubscribedSegments').mockResolvedValueOnce(subscribedSegments) 27 | 28 | expect(await getSubscribedSegmentsAction.handler(args)).toMatchObject(subscribedSegments) 29 | 30 | expect(subscriptionServiceMock.getSubscribedSegments).toHaveBeenCalledWith(args.params.userIdentifier) 31 | }) 32 | }) 33 | }) 34 | --------------------------------------------------------------------------------