Skip to content

Commit 15ef2b6

Browse files
authored
Form with truthy expression displayed despite permissions (#7466)
1 parent 4980b8b commit 15ef2b6

File tree

2 files changed

+103
-21
lines changed

2 files changed

+103
-21
lines changed

webapp/src/ts/services/xml-forms.service.ts

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,32 @@ export class XmlFormsService {
137137
});
138138
}
139139

140+
private checkFormExpression(form, doc, user, contactSummary) {
141+
if (!form.context.expression) {
142+
return true;
143+
}
144+
145+
try {
146+
return this.evaluateExpression(
147+
form.context.expression,
148+
doc,
149+
user,
150+
contactSummary
151+
);
152+
} catch(err) {
153+
console.error(`Unable to evaluate expression for form: ${form._id}`, err);
154+
return false;
155+
}
156+
}
157+
158+
private checkFormPermissions(form) {
159+
if (!form.context.permission) {
160+
return true;
161+
}
162+
163+
return this.authService.has(form.context.permission);
164+
}
165+
140166
private filter(form, options, user) {
141167
if (!options.includeCollect && form.context && form.context.collect) {
142168
return false;
@@ -158,27 +184,10 @@ export class XmlFormsService {
158184
return true;
159185
}
160186

161-
return this.filterContactTypes(form.context, options.doc).then(validSoFar => {
162-
if (!validSoFar) {
163-
return false;
164-
}
165-
if (form.context.expression) {
166-
try {
167-
return this.evaluateExpression(form.context.expression, options.doc, user, options.contactSummary);
168-
} catch(err) {
169-
console.error(`Unable to evaluate expression for form: ${form._id}`, err);
170-
return false;
171-
}
172-
}
173-
if (form.context.expression &&
174-
!this.evaluateExpression(form.context.expression, options.doc, user, options.contactSummary)) {
175-
return false;
176-
}
177-
if (!form.context.permission) {
178-
return true;
179-
}
180-
return this.authService.has(form.context.permission);
181-
});
187+
return this
188+
.filterContactTypes(form.context, options.doc)
189+
.then(valid => valid && this.checkFormPermissions(form))
190+
.then(valid => valid && this.checkFormExpression(form, options.doc, user, options.contactSummary));
182191
}
183192

184193
private notify(error, forms?) {

webapp/tests/karma/ts/services/xml-forms.service.spec.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,79 @@ describe('XmlForms service', () => {
777777

778778
});
779779

780+
it('does not return a form with a truthy expression if the user does not have relevant permissions', () => {
781+
const given = [
782+
{
783+
id: 'visit',
784+
doc: {
785+
_id: 'visit',
786+
internalId: 'visit',
787+
_attachments: { xml: { something: true } },
788+
context: {
789+
expression: 'true',
790+
permission: [ 'national_admin' ]
791+
},
792+
},
793+
},
794+
{
795+
id: 'registration',
796+
doc: {
797+
_id: 'visit',
798+
internalId: 'visit',
799+
_attachments: { xml: { something: true } },
800+
context: {
801+
expression: 'true',
802+
permission: [ 'district_admin' ]
803+
},
804+
},
805+
}
806+
];
807+
dbQuery.resolves({ rows: given });
808+
hasAuth.withArgs([ 'national_admin' ]).resolves(true);
809+
UserContact.resolves();
810+
const service = getService();
811+
return service.list().then(actual => {
812+
expect(actual.length).to.equal(1);
813+
expect(actual[0]).to.deep.equal(given[0].doc);
814+
});
815+
});
816+
817+
it('does not return a form with a false expression if the user has the relevant permissions', () => {
818+
const given = [
819+
{
820+
id: 'visit',
821+
doc: {
822+
_id: 'visit',
823+
internalId: 'visit',
824+
_attachments: { xml: { something: true } },
825+
context: {
826+
expression: 'false',
827+
permission: [ 'national_admin' ]
828+
},
829+
},
830+
},
831+
{
832+
id: 'registration',
833+
doc: {
834+
_id: 'visit',
835+
internalId: 'visit',
836+
_attachments: { xml: { something: true } },
837+
context: {
838+
expression: 'false',
839+
permission: [ 'district_admin' ]
840+
},
841+
},
842+
}
843+
];
844+
dbQuery.resolves({ rows: given });
845+
hasAuth.withArgs([ 'national_admin' ]).resolves(true);
846+
UserContact.resolves();
847+
const service = getService();
848+
return service.list().then(actual => {
849+
expect(actual.length).to.equal(0);
850+
});
851+
});
852+
780853
});
781854

782855
describe('listen', () => {

0 commit comments

Comments
 (0)