From 7bcb37581af79758e80a097de5af512b78a9524f Mon Sep 17 00:00:00 2001 From: Ben Kiarie Date: Tue, 25 Jun 2024 09:32:55 +0300 Subject: [PATCH] fix(#9203): add facility_id backward compatibility in admin app (#9204) Co-authored-by: latin-panda <66472237+latin-panda@users.noreply.github.com> --- admin/src/js/controllers/edit-user.js | 21 ++++++++++++++++-- .../tests/unit/controllers/edit-user.spec.js | 22 +++++++++++++++++++ config/default/app_settings.json | 1 + .../medic-client/validate_doc_update.js | 4 +++- ddocs/medic-db/medic/validate_doc_update.js | 4 +++- .../contacts/contacts-more-menu.component.ts | 2 +- 6 files changed, 49 insertions(+), 5 deletions(-) diff --git a/admin/src/js/controllers/edit-user.js b/admin/src/js/controllers/edit-user.js index 01ec48af231..babe710669e 100644 --- a/admin/src/js/controllers/edit-user.js +++ b/admin/src/js/controllers/edit-user.js @@ -62,6 +62,22 @@ angular const allowTokenLogin = settings => settings.token_login && settings.token_login.enabled; + /** + * Ensures that facility_id is an array for backward compatibility. + * @returns {Array} The normalized facility_id as an array. + */ + const getFacilityId = function () { + if (!$scope.model.facility_id) { + $scope.model.facility_id = []; + } + + if (!Array.isArray($scope.model.facility_id)) { + $scope.model.facility_id = [$scope.model.facility_id]; + } + + return $scope.model.facility_id; + }; + const determineEditUserModel = function() { // Edit a user that's not the current user. // $scope.model is the user object passed in by controller creating the Modal. @@ -75,6 +91,7 @@ angular return $q.resolve({}); } + const facilityId = getFacilityId(); const tokenLoginData = $scope.model.token_login; const tokenLoginEnabled = tokenLoginData && { @@ -92,8 +109,8 @@ angular phone: $scope.model.phone, // FacilitySelect is what binds to the select, place is there to // compare to later to see if it's changed once we've run computeFields(); - facilitySelect: $scope.model.facility_id || [], - place: $scope.model.facility_id, + facilitySelect: facilityId, + place: facilityId, roles: getRoles($scope.model.roles), // ^ Same with contactSelect vs. contact contactSelect: $scope.model.contact_id, diff --git a/admin/tests/unit/controllers/edit-user.spec.js b/admin/tests/unit/controllers/edit-user.spec.js index a10a725bfa8..5960c6dc0b5 100644 --- a/admin/tests/unit/controllers/edit-user.spec.js +++ b/admin/tests/unit/controllers/edit-user.spec.js @@ -16,6 +16,7 @@ describe('EditUserCtrl controller', () => { let Translate; let Settings; let userToEdit; + let user; let http; beforeEach(() => { @@ -178,6 +179,27 @@ describe('EditUserCtrl controller', () => { }); }); + describe('Initializing existing users', () => { + user = { + _id: 'user.id', + name: 'user.name', + fullname: 'user.fullname', + email: 'user@email.com', + phone: 'user.phone', + facility_id: 'abc', + contact_id: 'xyz', + roles: ['supervisor'], + language: 'zz', + }; + + it('converts string facility_id to Array ', () => { + return mockEditAUser(user).setupPromise.then(() => { + chai.expect(scope.editUserModel.facilitySelect).to.deep.equal(['abc']); + chai.expect(scope.editUserModel.facilitySelect).to.be.an('array'); + }); + }); + }); + describe('$scope.editUser', () => { it('username must be present', () => { return mockEditAUser(userToEdit) diff --git a/config/default/app_settings.json b/config/default/app_settings.json index 3eb440eaedf..29399fdd47f 100644 --- a/config/default/app_settings.json +++ b/config/default/app_settings.json @@ -283,6 +283,7 @@ "can_view_old_filter_and_search": [], "can_view_old_action_bar": [], "can_default_facility_filter": [], + "can_have_multiple_places": [], "can_export_devices_details": [ "national_admin" ] diff --git a/ddocs/medic-db/medic-client/validate_doc_update.js b/ddocs/medic-db/medic-client/validate_doc_update.js index 93b7de99556..ce4bafdf834 100644 --- a/ddocs/medic-db/medic-client/validate_doc_update.js +++ b/ddocs/medic-db/medic-client/validate_doc_update.js @@ -112,7 +112,9 @@ function(newDoc, oldDoc, userCtx, secObj) { if (isDbAdmin(userCtx, secObj)) { return; } - if (userCtx.facility_id === newDoc._id) { + if (userCtx.facility_id === newDoc._id || + (Array.isArray(userCtx.facility_id) && userCtx.facility_id.includes(newDoc._id )) + ) { _err('You are not authorized to edit your own place'); } if (newDoc.type === 'form') { diff --git a/ddocs/medic-db/medic/validate_doc_update.js b/ddocs/medic-db/medic/validate_doc_update.js index 72309bb9e99..863d5e1ad59 100644 --- a/ddocs/medic-db/medic/validate_doc_update.js +++ b/ddocs/medic-db/medic/validate_doc_update.js @@ -78,7 +78,9 @@ function(newDoc, oldDoc, userCtx, secObj) { _err('You are not authorized to edit admin only docs'); } - if (userCtx.facility_id === newDoc._id) { + if (userCtx.facility_id === newDoc._id || + (Array.isArray(userCtx.facility_id) && userCtx.facility_id.includes(newDoc._id )) + ) { _err('You are not authorized to edit your own place'); } }; diff --git a/webapp/src/ts/modules/contacts/contacts-more-menu.component.ts b/webapp/src/ts/modules/contacts/contacts-more-menu.component.ts index a21edd9e54b..ace3a2369dd 100644 --- a/webapp/src/ts/modules/contacts/contacts-more-menu.component.ts +++ b/webapp/src/ts/modules/contacts/contacts-more-menu.component.ts @@ -116,7 +116,7 @@ export class ContactsMoreMenuComponent implements OnInit, OnDestroy { && !this.loadingContent && this.snapshotData?.name === 'contacts.detail' && this.hasEditPermission - && (this.isOnlineOnly || this.userSettings?.facility_id !== this.selectedContactDoc?._id); + && (this.isOnlineOnly || !this.isUserFacility); } displayDeleteOption() {