Skip to content

Commit

Permalink
MOSIP-25261 : added consent for biometrics. (#684)
Browse files Browse the repository at this point in the history
* MOSIP-25261 : added consent for biometrics.

Signed-off-by: sudeep <sudeep.j7353@gmail.com>

* MOSIP-25261 : added consent for biometrics.

Signed-off-by: sudeep <sudeep.j7353@gmail.com>

* MOSIP-25261 : added consent for biometrics.

Signed-off-by: sudeep <sudeep.j7353@gmail.com>

* MOSIP-25261 : added consent for biometrics.

Signed-off-by: sudeep <sudeep.j7353@gmail.com>

* MOSIP-25261 : added consent for biometrics.

Signed-off-by: sudeep <sudeep.j7353@gmail.com>

* MOSIP-25261 : added consent for biometrics.

Signed-off-by: sudeep <sudeep.j7353@gmail.com>

* MOSIP-25261 : added consent for biometrics.

Signed-off-by: sudeep <sudeep.j7353@gmail.com>

---------

Signed-off-by: sudeep <sudeep.j7353@gmail.com>
Signed-off-by: Mayura Deshmukh <52281514+mayuradesh@users.noreply.github.com>
Co-authored-by: Mayura Deshmukh <52281514+mayuradesh@users.noreply.github.com>
  • Loading branch information
Sudeep7353 and mayuradesh authored Mar 14, 2024
1 parent eed7466 commit d8dbfa6
Show file tree
Hide file tree
Showing 12 changed files with 246 additions and 17 deletions.
1 change: 1 addition & 0 deletions src/app/app.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const TEST_RUN_ADD_ID = 'mosip.toolkit.testrun.add';
export const TEST_RUN_UPDATE_ID = 'mosip.toolkit.testrun.update';
export const TEST_RUN_DETAILS_ADD_ID = 'mosip.toolkit.testrun.details.add';
export const BIOMETRICS_TEST_DATA_ADD_ID = 'mosip.toolkit.biometric.testdata.add';
export const BIOMETRICS_CONSENT_DATA_ADD_ID = 'mosip.toolkit.biometric.consent.add';
export const TEST_RUN_DELETE_ID = 'mosip.toolkit.testrun.delete';
export const DATASHARE_ID = 'mosip.toolkit.abis.datashare.url';
export const ABIS_SEND_TO_QUEUE = 'mosip.toolkit.abis.send';
Expand Down
14 changes: 14 additions & 0 deletions src/app/app.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,20 @@ export default class Utils {
});
}

static getPartnerBiometricConsent(dataService: DataService, resourceBundleJson: any, dialog: MatDialog) {
return new Promise((resolve, reject) => {
dataService.getPartnerConsent().subscribe(
(response: any) => {
resolve(response['response']);
},
(errors: any) => {
this.showErrorMessage(resourceBundleJson, errors, dialog);
resolve(false);
}
)
});
}

static convertBlobToBase64 = (blob: Blob) => new Promise((resolve, reject) => {
const reader = new FileReader;
reader.onerror = reject;
Expand Down
11 changes: 10 additions & 1 deletion src/app/core/components/dialog/dialog.component.css
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,15 @@ img {
margin-left: 10px;
}

.consent-checkbox {
margin-top: 10px;
margin-bottom: 5px;
margin-left: 10px;
}

.consent-checkbox ::ng-deep .mat-checkbox-layout {
white-space: normal;
}
.reviewMessage {
margin-top: -3px;
}
Expand Down Expand Up @@ -275,7 +284,7 @@ ul.reviewMessage li:before {
margin-top: 15px;
margin-bottom: 3px;
}
::ng-deep .mat-dialog-container{
:not(.consent-box) ::ng-deep .mat-dialog-container{
display: flex;
justify-content: center;
}
Expand Down
17 changes: 17 additions & 0 deletions src/app/core/components/dialog/dialog.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -318,4 +318,21 @@ <h2 mat-dialog-title class="mat-dialog-title">{{"dialogMessages.addProject"|tran
<button mat-flat-button color="accent" (click)="onOkClick()">{{ 'dialogMessages.close' | translate }}</button>
</mat-dialog-actions>
</div>
<div *ngIf="input.case === 'PARTNER_BIOMETRIC_CONSENT'" class="consent-box">
<h2 mat-dialog-title class="mat-dialog-title">{{'dialogMessages.consentHead'|translate}}</h2>
<div class="text-box">
<div mat-dialog-content>
<div [innerHTML]="consentTemplate"></div>
</div>
<div class="consent-checkbox">
<mat-checkbox [(ngModel)]="consentCheckbox">{{'dialogMessages.consentCheckbox'|translate}}</mat-checkbox>
</div>
</div>
<div class="button-container-box">
<button mat-flat-button (click)="closeConsent()"
class="back-button">{{'dialogMessages.close'|translate}}</button>
<button mat-flat-button color="accent" [disabled]="!consentCheckbox"
(click)="saveBiometricConsent(input.consentForSbiBiometrics)">{{'dialogMessages.confirm'|translate}}</button>
</div>
</div>
</div>
76 changes: 76 additions & 0 deletions src/app/core/components/dialog/dialog.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export class DialogComponent implements OnInit {
adminRejectComments: string = '';
rejectReport: boolean = false;
isAndroidAppMode = environment.isAndroidAppMode == 'yes' ? true : false;
consentCheckbox: boolean = false;
consentTemplate: string;

constructor(
private router: Router,
Expand Down Expand Up @@ -98,6 +100,7 @@ export class DialogComponent implements OnInit {
this.imageUrls = this.data.selectedDeviceImagesUrl;
this.getSelectedImageUrl();
}
await this.getBiometricConsentTemplate();
this.dataLoaded = true;
}

Expand Down Expand Up @@ -487,4 +490,77 @@ export class DialogComponent implements OnInit {
this.dialogRef.close();
this.logoutservice.logout();
}

getBiometricConsentTemplate() {
return new Promise((resolve, reject) => {
const subscription = this.dataService.getBiometricConsentTemplate().subscribe(
(response: any) => {
this.consentTemplate = response['response'];
resolve(true);
},
(errors: any) => {
console.error('Failed to fetch template:', errors);
Utils.showErrorMessage(this.resourceBundleJson, errors, this.dialog);
resolve(false);
}
);
this.subscriptions.push(subscription);
});
}


saveBiometricConsent(consentForSbiBiometrics: boolean) {
const consentRequest = {
consentForSdkAbisBiometrics: consentForSbiBiometrics ? 'NO' : 'YES',
consentForSbiBiometrics: consentForSbiBiometrics ? 'YES' : 'NO'
};

const reqBody = {
id: appConstants.BIOMETRICS_CONSENT_DATA_ADD_ID,
version: appConstants.VERSION,
requesttime: new Date().toISOString(),
request: consentRequest
};

return new Promise((resolve, reject) => {
const subscription = this.dataService.saveBiometricConsent(reqBody).subscribe(
(response: any) => {
if (response.errors && response.errors.length > 0) {
this.dialogRef.close(false);
Utils.showErrorMessage(this.resourceBundleJson, response.errors, this.dialog);
this.dataLoaded = true;
resolve(true);
} else {
this.dataLoaded = true;
this.dialogRef.close(true);
const msg = 'addConsentDataSuccessMsg';
const resourceBundle = this.resourceBundleJson.dialogMessages;
const successMsg = 'success';
Utils.showSuccessMessage(resourceBundle, successMsg, msg, this.dialog);
resolve(true);
}
},
(errors) => {
this.dialogRef.close(false);
Utils.showErrorMessage(this.resourceBundleJson, errors, this.dialog);
resolve(false);
}
);
this.subscriptions.push(subscription);
});
}

async showDashboard() {
await this.router.navigate([`toolkit/dashboard`]);
}

async closeConsent() {
this.dialogRef.close();
await this.showDashboard();
Utils.showErrorMessage(this.resourceBundleJson,
null,
this.dialog,
'Unable to proceed without biometric consent');
}

}
16 changes: 16 additions & 0 deletions src/app/core/services/data-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,22 @@ export class DataService {
return this.httpClient.get(url, { responseType: 'blob' });
}

getBiometricConsentTemplate() {
let url = `${this.SERVICES_BASE_URL}getBiometricsConsentTemplate`;
return this.httpClient.get(url);
}

saveBiometricConsent(body: any) {
let url = `${this.SERVICES_BASE_URL}savePartnerBiometricConsent`;
return this.httpClient.post(url, body);
}


getPartnerConsent() {
let url = `${this.SERVICES_BASE_URL}getPartnerConsent`;
return this.httpClient.get(url);
}

addBiometricTestData(formdata: FormData) {
let url = `${this.SERVICES_BASE_URL}addBiometricTestData`;
return this.httpClient.post(url, formdata);
Expand Down
54 changes: 41 additions & 13 deletions src/app/features/project/add-project/add-project.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export class AddProjectComponent implements OnInit {
deviceImage4: any = null;
deviceImage5: any = null;
imageUrls: any[] = [null, null, null, null];
consentResponse: any;

constructor(
public authService: AuthService,
Expand Down Expand Up @@ -209,17 +210,34 @@ export class AddProjectComponent implements OnInit {
(closeBtn: boolean) => {
(async () => {
if (!closeBtn) {
if (projectType == appConstants.SBI) {
let request = {
id: appConstants.SBI_PROJECT_ADD_ID,
version: appConstants.VERSION,
requesttime: new Date().toISOString(),
request: Utils.populateSbiProjectData(this.projectForm, '', this.deviceImage1, this.deviceImage2,
this.deviceImage3, this.deviceImage4, this.isAndroidAppMode),
};
this.dataLoaded = false;
this.dataSubmitted = true;
await this.addSbiProject(request);
if (projectType === appConstants.SBI) {
this.consentResponse = await Utils.getPartnerBiometricConsent(this.dataService, this.resourceBundleJson, this.dialog);
let isSbiConsentGiven = false;
if (this.consentResponse['consentForSbiBiometrics'] === 'YES') {
isSbiConsentGiven = true;
} else if (this.consentResponse['consentForSbiBiometrics'] === 'NO') {
isSbiConsentGiven = false;
} else {
console.error("Invalid value for consentForSbiBiometrics:", this.consentResponse['consentForSbiBiometrics']);
}
if (isSbiConsentGiven) {
await this.addSbiProject();
} else {
const dialogRef = this.dialog.open(DialogComponent, {
width: '600px',
data: {
case: "PARTNER_BIOMETRIC_CONSENT",
consentForSbiBiometrics: true,
},
});
dialogRef.afterClosed().subscribe(dialogResult => {
if (dialogResult) {
this.addSbiProject();
} else {
console.log("Consent was not confirmed. Project not saved.");
}
});
}
}
if (projectType == appConstants.SDK) {
let request = {
Expand Down Expand Up @@ -255,7 +273,16 @@ export class AddProjectComponent implements OnInit {
this.projectForm.controls['deviceSubType'].setValue('');
}

async addSbiProject(request: any) {
async addSbiProject() {
let request = {
id: appConstants.SBI_PROJECT_ADD_ID,
version: appConstants.VERSION,
requesttime: new Date().toISOString(),
request: Utils.populateSbiProjectData(this.projectForm, '', this.deviceImage1, this.deviceImage2,
this.deviceImage3, this.deviceImage4, this.isAndroidAppMode),
};
this.dataLoaded = false;
this.dataSubmitted = true;
return new Promise((resolve, reject) => {
this.subscriptions.push(
this.dataService.addSbiProject(request).subscribe(
Expand Down Expand Up @@ -319,10 +346,11 @@ export class AddProjectComponent implements OnInit {
Utils.showErrorMessage(this.resourceBundleJson, response.errors, this.dialog);
return true;
} else {
this.dataLoaded = true;
this.dialog.closeAll();
let resourceBundle = this.resourceBundleJson.dialogMessages;
let successMsg = 'success';
let projectMsg = 'successMessage';
this.dataLoaded = true;
const dialogRef = Utils.showSuccessMessage(
resourceBundle,
successMsg,
Expand Down
24 changes: 24 additions & 0 deletions src/app/features/project/view-project/view-project.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export class ViewProjectComponent implements OnInit {
resourceBundleJson: any = {};
deviceImageUrls: string[] = [];
isReportAlreadySubmitted = false;
consentResponse: any;
constructor(
public authService: AuthService,
private dataService: DataService,
Expand All @@ -86,6 +87,7 @@ export class ViewProjectComponent implements OnInit {
await this.initProjectIdAndType();
await this.getCollections();
if (this.projectType == appConstants.SBI) {
this.displaySbiBiometricConsentDialog();
this.initSbiProjectForm();
this.projectFormData = await Utils.getSbiProjectDetails(this.projectId, this.dataService, this.resourceBundleJson, this.dialog);
Utils.populateSbiProjectForm(this.projectFormData, this.projectForm);
Expand Down Expand Up @@ -458,4 +460,26 @@ export class ViewProjectComponent implements OnInit {
});
dialogRef.afterClosed();
}

async displaySbiBiometricConsentDialog() {
this.consentResponse = await Utils.getPartnerBiometricConsent(this.dataService, this.resourceBundleJson, this.dialog);
let isSbiConsentGiven = false;
if (this.consentResponse['consentForSbiBiometrics'] === 'YES') {
isSbiConsentGiven = true;
} else if (this.consentResponse['consentForSbiBiometrics'] === 'NO') {
isSbiConsentGiven = false;
} else {
console.error("Invalid value for consentForSbiBiometrics:", this.consentResponse['consentForSbiBiometrics']);
}
if (!isSbiConsentGiven) {
const dialogRef = this.dialog.open(DialogComponent, {
width: '600px',
data: {
case: "PARTNER_BIOMETRIC_CONSENT",
consentForSbiBiometrics: true,
},
});
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export class AddTestDataComponent implements OnInit {
allowedFileNameLegth =
this.appConfigService.getConfig()['allowedFileNameLegth'];
allowedFileSize = this.appConfigService.getConfig()['allowedFileSize'];
consentResponse: any;

constructor(
public authService: AuthService,
Expand All @@ -56,6 +57,7 @@ export class AddTestDataComponent implements OnInit {
async ngOnInit() {
this.translate.use(this.userProfileService.getUserPreferredLanguage());
this.resourceBundleJson = await Utils.getResourceBundle(this.userProfileService.getUserPreferredLanguage(), this.dataService);
this.displaySdkAbisConsentDialog();
this.initForm();
this.initBreadCrumb();
this.getAllowedFileTypes(this.allowedFileTypes);
Expand Down Expand Up @@ -340,6 +342,27 @@ export class AddTestDataComponent implements OnInit {
await this.router.navigate([`toolkit/dashboard`]);
}

async displaySdkAbisConsentDialog() {
this.consentResponse = await Utils.getPartnerBiometricConsent(this.dataService, this.resourceBundleJson, this.dialog);
let isSdkAbisConsentGiven = false;
if (this.consentResponse['consentForSdkAbisBiometrics'] === 'YES') {
isSdkAbisConsentGiven = true;
} else if (this.consentResponse['consentForSdkAbisBiometrics'] === 'NO') {
isSdkAbisConsentGiven = false;
} else {
console.error("Invalid value for consentForSdkAbisBiometrics:", this.consentResponse['consentForSdkAbisBiometrics']);
}
if (!isSdkAbisConsentGiven) {
const dialogRef = this.dialog.open(DialogComponent, {
width: '600px',
data: {
case: "PARTNER_BIOMETRIC_CONSENT",
consentForSbiBiometrics: false,
},
});
}
}

ngOnDestroy(): void {
this.subscriptions.forEach((subscription) => subscription.unsubscribe());
}
Expand Down
9 changes: 8 additions & 1 deletion src/assets/i18n/ara.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@
"verifyMessage": "تحقق من قيم التجزئة وموقع الويب قبل المتابعة. إذا كانت القيم صحيحة، فاحفظ المشروع.",
"saveBtn": "يحفظ",
"sessionInactiveMessage": "سيتم مهلة لك بسبب عدم النشاط. الرجاء النقر في أي مكان لإعادة تنشيط جلستك",
"sessionInactivityLogoutMessage": "لقد تم تسجيل الخروج بسبب عدم النشاط."
"sessionInactivityLogoutMessage": "لقد تم تسجيل الخروج بسبب عدم النشاط.",
"addConsentDataSuccessMsg": "لقد تم استلام موافقتك بنجاح",
"consentHead": "موافقة",
"confirm": "يتأكد",
"consentCheckbox": "أقر وأوافق على الشروط والأحكام"
},
"breadcrumb": {
"home": "بيت",
Expand Down Expand Up @@ -2050,6 +2054,9 @@
"TOOLKIT_REPORT_004": "حدث خطأ أثناء تغيير حالة التقرير",
"TOOLKIT_REPORT_005": "حدث خطأ أثناء جلب قائمة التقارير.",
"TOOLKIT_REPORT_006": "حدث خطأ أثناء جلب قائمة التقارير. حالة التقرير غير صالحة: ",
"TOOLKIT_PARTNER_CONSENT_ERR_001": "حدث خطأ أثناء جلب نموذج الموافقة البيومترية.",
"TOOLKIT_PARTNER_CONSENT_ERR_002": "حدث خطأ أثناء حفظ بيانات موافقة الشريك.",
"TOOLKIT_PARTNER_CONSENT_ERR_003": "حدث خطأ أثناء جلب حالة موافقة الشريك.",
"error": "خطأ",
"FILE_WITH_MULTIPLE_EXTENSIONS": "يجب ألا يحتوي اسم الملف على امتدادات متعددة"
}
Expand Down
Loading

0 comments on commit d8dbfa6

Please sign in to comment.