Skip to content

Commit

Permalink
Fix: FORMS-1012 make add team member in team management case insensit…
Browse files Browse the repository at this point in the history
…ive (bcgov#1475)

* Fix Team management - Add a new member - type BCEID - Business/Basic textfield is case sensitive - FORMS-1012
Fix copy submission option not visible for submissions other than SUBMITTED state. - FORMS-1277

* Fix Team management - Add a new member - type BCEID - Business/Basic textfield is case sensitive - FORMS-1012
Fix copy submission option not visible for submissions other than SUBMITTED state. - FORMS-1277

* Fix PR comments.

* Fix unit test cases.

* Fix PR comments, update query builder to match variables.

---------

Co-authored-by: “bhuvan-aot” <“[email protected]”>
  • Loading branch information
bhuvan-aot and “bhuvan-aot” authored Sep 19, 2024
1 parent 27d0105 commit 267c9d6
Show file tree
Hide file tree
Showing 11 changed files with 186 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ defineExpose({
<span
v-if="
submission.status === 'SUBMITTED' &&
(submission.status === 'SUBMITTED' ||
submission.status === 'COMPLETED') &&
isCopyFromExistingSubmissionEnabled === true
"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ const BCEIDBASIC = {
param: 'username',
exact: true,
required: 2,
caseSensitive: false,
},
{
name: 'filterFullName',
Expand All @@ -104,6 +105,7 @@ const BCEIDBASIC = {
exact: true,
param: 'email',
required: 2,
caseSensitive: false,
},
{
name: 'filterSearch',
Expand Down Expand Up @@ -164,6 +166,7 @@ const BCEIDBUSINESS = {
param: 'username',
exact: true,
required: 2,
caseSensitive: false,
},
{
name: 'filterFullName',
Expand All @@ -185,6 +188,7 @@ const BCEIDBUSINESS = {
exact: true,
param: 'email',
required: 2,
caseSensitive: false,
},
{
name: 'filterSearch',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ const BCEIDBASIC = {
param: 'username',
exact: true,
required: 2,
caseSensitive: false,
},
{
name: 'filterFullName',
Expand All @@ -129,6 +130,7 @@ const BCEIDBASIC = {
exact: true,
param: 'email',
required: 2,
caseSensitive: false,
},
{
name: 'filterSearch',
Expand Down Expand Up @@ -189,6 +191,7 @@ const BCEIDBUSINESS = {
param: 'username',
exact: true,
required: 2,
caseSensitive: false,
},
{
name: 'filterFullName',
Expand All @@ -210,6 +213,7 @@ const BCEIDBUSINESS = {
exact: true,
param: 'email',
required: 2,
caseSensitive: false,
},
{
name: 'filterSearch',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ describe('MySubmissionsActions', () => {
);
});

it('renders if this is a submitted submission and isCopyFromExistingSubmissionEnabled is true', () => {
it('renders if this is a completed submission and isCopyFromExistingSubmissionEnabled is true', () => {
const SUBMISSION = {
status: 'SUBMITTED',
status: 'COMPLETED',
};
formStore.form = {
enableCopyExistingSubmission: true,
Expand All @@ -103,6 +103,30 @@ describe('MySubmissionsActions', () => {
);
});

it('renders if this is a completed submission and isCopyFromExistingSubmissionEnabled is true', () => {
const SUBMISSION = {
status: 'ASSIGNED',
};
formStore.form = {
enableCopyExistingSubmission: true,
};

const wrapper = shallowMount(MySubmissionsActions, {
props: {
formId: FORM_ID,
submission: SUBMISSION,
},
global: {
plugins: [pinia, router],
stubs: STUBS,
},
});

expect(wrapper.html()).not.toContain(
'trans.mySubmissionsActions.copyThisSubmission'
);
});

it('hasDeletePermission returns true if the submission has the create permission', () => {
let SUBMISSION = {
permissions: [FormPermissions.SUBMISSION_CREATE],
Expand Down
30 changes: 18 additions & 12 deletions app/src/components/idpService.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,19 +156,11 @@ class IdpService {
let groupValid = reqd === 1 ? true : false;
for (const f of filters) {
// add the filter to the query...
const filterName = f.name;
const paramName = f.param;
const value = params[paramName];
if ('exact' in f) {
const exact = f.exact;
q.modify(filterName, value, exact);
} else {
q.modify(filterName, value);
}

this.applyUserSearchFilters(f, params, q);
//
// ok, check for required...
//
const value = params[f.param];
if (reqd < 1) {
// if required < 1, do nothing, always valid
groupValid = true;
Expand Down Expand Up @@ -198,14 +190,28 @@ class IdpService {
return User.query()
.modify('filterIdpUserId', params.idpUserId)
.modify('filterIdpCode', params.idpCode)
.modify('filterUsername', params.username, false)
.modify('filterUsername', params.username, false, false)
.modify('filterFullName', params.fullName)
.modify('filterFirstName', params.firstName)
.modify('filterLastName', params.lastName)
.modify('filterEmail', params.email, false)
.modify('filterEmail', params.email, false, false)
.modify('filterSearch', params.search)
.modify('orderLastFirstAscending');
}

applyUserSearchFilters(filter, params, query) {
const filterName = filter.name;
const paramName = filter.param;
const value = params[paramName];
let exact = 'exact' in filter ? filter.exact : false;
let caseSensitive = 'caseSensitive' in filter ? filter.caseSensitive : true;
if (exact || caseSensitive) {
query.modify(filterName, value, exact, caseSensitive);
} else {
query.modify(filterName, value);
}
return value;
}
}

let idpService = new IdpService();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
const BCEID_EXTRAS_EXACT_IGNORE_CASE = {
formAccessSettings: 'idim',
addTeamMemberSearch: {
text: {
minLength: 6,
message: 'trans.manageSubmissionUsers.searchInputLength',
},
email: {
exact: true,
message: 'trans.manageSubmissionUsers.exactBCEIDSearch',
},
},
userSearch: {
filters: [
{ name: 'filterIdpUserId', param: 'idpUserId', required: 0 },
{ name: 'filterIdpCode', param: 'idpCode', required: 0 },
{ name: 'filterUsername', param: 'username', required: 2, exact: true, caseSensitive: false },
{ name: 'filterFullName', param: 'fullName', required: 0 },
{ name: 'filterFirstName', param: 'firstName', required: 0 },
{ name: 'filterLastName', param: 'lastName', required: 0 },
{ name: 'filterEmail', param: 'email', required: 2, exact: true, caseSensitive: false },
{ name: 'filterSearch', param: 'search', required: 0 },
],
detail: 'Could not retrieve BCeID users. Invalid options provided.',
},
};

const BCEID_EXTRAS_EXACT = {
formAccessSettings: 'idim',
addTeamMemberSearch: {
text: {
minLength: 6,
message: 'trans.manageSubmissionUsers.searchInputLength',
},
email: {
exact: true,
message: 'trans.manageSubmissionUsers.exactBCEIDSearch',
},
},
userSearch: {
filters: [
{ name: 'filterIdpUserId', param: 'idpUserId', required: 0 },
{ name: 'filterIdpCode', param: 'idpCode', required: 0 },
{ name: 'filterUsername', param: 'username', required: 2, exact: true },
{ name: 'filterFullName', param: 'fullName', required: 0 },
{ name: 'filterFirstName', param: 'firstName', required: 0 },
{ name: 'filterLastName', param: 'lastName', required: 0 },
{ name: 'filterEmail', param: 'email', required: 2, exact: true },
{ name: 'filterSearch', param: 'search', required: 0 },
],
detail: 'Could not retrieve BCeID users. Invalid options provided.',
},
};
/**
* @param { import("knex").Knex } knex
* @returns { Promise<void> }
*/
exports.up = function (knex) {
return Promise.resolve().then(() =>
knex.schema
.hasTable('identity_provider')
.then(() =>
knex('identity_provider').where({ code: 'bceid-business' }).update({
extra: BCEID_EXTRAS_EXACT_IGNORE_CASE,
})
)
.then(() =>
knex('identity_provider').where({ code: 'bceid-basic' }).update({
extra: BCEID_EXTRAS_EXACT_IGNORE_CASE,
})
)
);
};
exports.down = function (knex) {
return Promise.resolve().then(() =>
knex.schema
.hasTable('identity_provider')
.then(() =>
knex('identity_provider').where({ code: 'bceid-business' }).update({
extra: BCEID_EXTRAS_EXACT,
})
)
.then(() =>
knex('identity_provider').where({ code: 'bceid-basic' }).update({
extra: BCEID_EXTRAS_EXACT,
})
)
);
};
12 changes: 8 additions & 4 deletions app/src/forms/common/models/tables/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@ class User extends Timestamps(Model) {
query.where('idpCode', value);
}
},
filterUsername(query, value, exact = false) {
filterUsername(query, value, exact = false, caseSensitive = true) {
if (value) {
if (exact) query.where('username', value);
if (exact && caseSensitive) query.where('username', value);
// ilike is postgres case insensitive like
else if (exact && !caseSensitive) query.where('username', 'ilike', value);
else if (!exact && caseSensitive) query.where('username', 'like', `%${value}%`);
else query.where('username', 'ilike', `%${value}%`);
}
},
Expand All @@ -65,10 +67,12 @@ class User extends Timestamps(Model) {
query.where('fullName', 'ilike', `%${value}%`);
}
},
filterEmail(query, value, exact = false) {
filterEmail(query, value, exact = false, caseSensitive = true) {
if (value) {
if (exact) query.where('email', value);
if (exact && caseSensitive) query.where('email', value);
// ilike is postgres case insensitive like
else if (exact && !caseSensitive) query.where('email', 'ilike', value);
else if (!exact && caseSensitive) query.where('email', 'like', `%${value}%`);
else query.where('email', 'ilike', `%${value}%`);
}
},
Expand Down
12 changes: 8 additions & 4 deletions app/tests/fixtures/form/identity_providers.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@
"name": "filterUsername",
"exact": true,
"param": "username",
"required": 2
"required": 2,
"caseSensitive": false
},
{
"name": "filterFullName",
Expand All @@ -98,7 +99,8 @@
"name": "filterEmail",
"exact": true,
"param": "email",
"required": 2
"required": 2,
"caseSensitive": false
},
{
"name": "filterSearch",
Expand Down Expand Up @@ -161,7 +163,8 @@
"name": "filterUsername",
"exact": true,
"param": "username",
"required": 2
"required": 2,
"caseSensitive": false
},
{
"name": "filterFullName",
Expand All @@ -182,7 +185,8 @@
"name": "filterEmail",
"exact": true,
"param": "email",
"required": 2
"required": 2,
"caseSensitive": false
},
{
"name": "filterSearch",
Expand Down
6 changes: 3 additions & 3 deletions app/tests/unit/components/idpService.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,15 @@ describe('idpService', () => {
expect(MockModel.query).toBeCalledTimes(1);
expect(MockModel.modify).toBeCalledTimes(9);
expect(MockModel.modify).toBeCalledWith('filterIdpCode', 'idir');
expect(MockModel.modify).toBeCalledWith('filterEmail', '[email protected]', false);
expect(MockModel.modify).toBeCalledWith('filterEmail', '[email protected]', false, false);
});

it('should return a customized user search', async () => {
const s = await idpService.userSearch({ idpCode: 'bceid-business', email: '[email protected]' });
expect(s).toBeFalsy();
expect(MockModel.query).toBeCalledTimes(1);
expect(MockModel.modify).toBeCalledWith('filterIdpCode', 'bceid-business');
expect(MockModel.modify).toBeCalledWith('filterEmail', '[email protected]', true);
expect(MockModel.modify).toBeCalledWith('filterIdpCode', 'bceid-business', false, true);
expect(MockModel.modify).toBeCalledWith('filterEmail', '[email protected]', true, false);
expect(MockModel.modify).toBeCalledTimes(9);
});

Expand Down
4 changes: 2 additions & 2 deletions app/tests/unit/forms/user/service.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ describe('list', () => {
expect(MockModel.modify).toBeCalledTimes(9);
expect(MockModel.modify).toBeCalledWith('filterIdpUserId', params.idpUserId);
expect(MockModel.modify).toBeCalledWith('filterIdpCode', params.idpCode);
expect(MockModel.modify).toBeCalledWith('filterUsername', params.username, false);
expect(MockModel.modify).toBeCalledWith('filterUsername', params.username, false, false);
expect(MockModel.modify).toBeCalledWith('filterFullName', params.fullName);
expect(MockModel.modify).toBeCalledWith('filterFirstName', params.firstName);
expect(MockModel.modify).toBeCalledWith('filterLastName', params.lastName);
expect(MockModel.modify).toBeCalledWith('filterEmail', params.email, false);
expect(MockModel.modify).toBeCalledWith('filterEmail', params.email, false, false);
expect(MockModel.modify).toBeCalledWith('filterSearch', params.search);
expect(MockModel.modify).toBeCalledWith('orderLastFirstAscending');
});
Expand Down
Loading

0 comments on commit 267c9d6

Please sign in to comment.