Skip to content

Commit 99b8258

Browse files
awgeorgeacinader
authored andcommitted
Added negative scenarios for parse-community#5301.
- Public read ACL should never expose PII to authenticated and non-authenticated - Explicit ACL like custom user Role should be able to read PII
1 parent 92f58f6 commit 99b8258

File tree

1 file changed

+193
-71
lines changed

1 file changed

+193
-71
lines changed

spec/UserPII.spec.js

Lines changed: 193 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -521,94 +521,216 @@ describe('Personally Identifiable Information', () => {
521521
.then(done)
522522
.catch(done.fail);
523523
});
524-
});
525-
526-
describe('with privilaged user', () => {
527-
let adminUser;
528524

529-
beforeEach(async done => {
530-
const adminRole = await new Parse.Role(
531-
'Administrator',
532-
new Parse.ACL()
533-
).save(null, { useMasterKey: true });
534-
535-
const managementRole = new Parse.Role(
536-
'managementOf_user' + user.id,
537-
new Parse.ACL(user)
538-
);
539-
managementRole.getRoles().add(adminRole);
540-
await managementRole.save(null, { useMasterKey: true });
525+
// Explict ACL should be able to read sensitive information
526+
describe('with privilaged user', () => {
527+
let adminUser;
528+
529+
beforeEach(async done => {
530+
const adminRole = await new Parse.Role(
531+
'Administrator',
532+
new Parse.ACL()
533+
).save(null, { useMasterKey: true });
534+
535+
const managementRole = new Parse.Role(
536+
'managementOf_user' + user.id,
537+
new Parse.ACL(user)
538+
);
539+
managementRole.getRoles().add(adminRole);
540+
await managementRole.save(null, { useMasterKey: true });
541+
542+
const userACL = new Parse.ACL();
543+
userACL.setReadAccess(managementRole, true);
544+
await user.setACL(userACL).save(null, { useMasterKey: true });
545+
546+
adminUser = await Parse.User.signUp('administrator', 'secure');
547+
adminUser = await Parse.User.logIn(adminUser.get('username'), 'secure');
548+
await adminRole
549+
.getUsers()
550+
.add(adminUser)
551+
.save(null, { useMasterKey: true });
541552

542-
const userACL = new Parse.ACL();
543-
userACL.setReadAccess(managementRole, true);
544-
await user.setACL(userACL).save(null, { useMasterKey: true });
545-
546-
adminUser = await Parse.User.signUp('administrator', 'secure');
547-
adminUser = await Parse.User.logIn(adminUser.get('username'), 'secure');
548-
await adminRole
549-
.getUsers()
550-
.add(adminUser)
551-
.save(null, { useMasterKey: true });
553+
done();
554+
});
552555

553-
done();
554-
});
556+
it('privilaged user should be able to get user PII via API with object', done => {
557+
const userObj = new (Parse.Object.extend(Parse.User))();
558+
userObj.id = user.id;
559+
userObj
560+
.fetch()
561+
.then(
562+
fetchedUser => {
563+
expect(fetchedUser.get('email')).toBe(EMAIL);
564+
},
565+
e => console.error('error', e)
566+
)
567+
.then(done)
568+
.catch(done.fail);
569+
});
555570

556-
it('privilaged user should be able to get user PII via API with object', done => {
557-
const userObj = new (Parse.Object.extend(Parse.User))();
558-
userObj.id = user.id;
559-
userObj
560-
.fetch()
561-
.then(
562-
fetchedUser => {
571+
it('privilaged user should be able to get user PII via API with Find', done => {
572+
new Parse.Query(Parse.User)
573+
.equalTo('objectId', user.id)
574+
.find()
575+
.then(fetchedUser => {
563576
expect(fetchedUser.get('email')).toBe(EMAIL);
564-
},
565-
e => console.error('error', e)
566-
)
567-
.then(done)
568-
.catch(done.fail);
569-
});
577+
expect(fetchedUser.get('zip')).toBe(ZIP);
578+
expect(fetchedUser.get('ssn')).toBe(SSN);
579+
done();
580+
});
581+
});
570582

571-
it('privilaged user should be able to get user PII via API with Find', done => {
572-
new Parse.Query(Parse.User)
573-
.equalTo('objectId', user.id)
574-
.find()
575-
.then(fetchedUser => {
583+
it('privilaged user should be able to get user PII via API with Get', done => {
584+
new Parse.Query(Parse.User).get(user.id).then(fetchedUser => {
576585
expect(fetchedUser.get('email')).toBe(EMAIL);
577586
expect(fetchedUser.get('zip')).toBe(ZIP);
578587
expect(fetchedUser.get('ssn')).toBe(SSN);
579588
done();
580589
});
590+
});
591+
592+
it('privilaged user should get user PII via REST by ID', done => {
593+
request({
594+
url: `http://localhost:8378/1/classes/_User/${user.id}`,
595+
json: true,
596+
headers: {
597+
'X-Parse-Application-Id': 'test',
598+
'X-Parse-Javascript-Key': 'test',
599+
'X-Parse-Session-Token': adminUser.getSessionToken(),
600+
},
601+
})
602+
.then(
603+
response => {
604+
const result = response.data;
605+
const fetchedUser = result;
606+
expect(fetchedUser.zip).toBe(ZIP);
607+
expect(fetchedUser.email).toBe(EMAIL);
608+
},
609+
e => console.error('error', e.message)
610+
)
611+
.then(() => done());
612+
});
581613
});
582614

583-
it('privilaged user should be able to get user PII via API with Get', done => {
584-
new Parse.Query(Parse.User).get(user.id).then(fetchedUser => {
585-
expect(fetchedUser.get('email')).toBe(EMAIL);
586-
expect(fetchedUser.get('zip')).toBe(ZIP);
587-
expect(fetchedUser.get('ssn')).toBe(SSN);
615+
// Public access ACL should always hide sensitive information
616+
describe('with public read ACL', () => {
617+
beforeEach(async done => {
618+
const userACL = new Parse.ACL();
619+
userACL.setPublicReadAccess();
620+
await user.setACL(userACL).save(null, { useMasterKey: true });
588621
done();
589622
});
590-
});
591623

592-
it('privilaged user should get user PII via REST by ID', done => {
593-
request({
594-
url: `http://localhost:8378/1/classes/_User/${user.id}`,
595-
json: true,
596-
headers: {
597-
'X-Parse-Application-Id': 'test',
598-
'X-Parse-Javascript-Key': 'test',
599-
'X-Parse-Session-Token': adminUser.getSessionToken(),
600-
},
601-
})
602-
.then(
603-
response => {
604-
const result = response.data;
605-
const fetchedUser = result;
606-
expect(fetchedUser.zip).toBe(ZIP);
607-
expect(fetchedUser.email).toBe(EMAIL);
624+
it('should not be able to get user PII via API with object', done => {
625+
Parse.User.logOut().then(() => {
626+
const userObj = new (Parse.Object.extend(Parse.User))();
627+
userObj.id = user.id;
628+
userObj
629+
.fetch()
630+
.then(
631+
fetchedUser => {
632+
expect(fetchedUser.get('email')).toBe(undefined);
633+
},
634+
e => console.error('error', e)
635+
)
636+
.then(done)
637+
.catch(done.fail);
638+
});
639+
});
640+
641+
it('should not be able to get user PII via API with Find', done => {
642+
Parse.User.logOut().then(() =>
643+
new Parse.Query(Parse.User)
644+
.equalTo('objectId', user.id)
645+
.find()
646+
.then(fetchedUser => {
647+
expect(fetchedUser.get('email')).toBe(undefined);
648+
expect(fetchedUser.get('zip')).toBe(undefined);
649+
expect(fetchedUser.get('ssn')).toBe(undefined);
650+
done();
651+
})
652+
);
653+
});
654+
655+
it('should not be able to get user PII via API with Get', done => {
656+
Parse.User.logOut().then(() =>
657+
new Parse.Query(Parse.User).get(user.id).then(fetchedUser => {
658+
expect(fetchedUser.get('email')).toBe(undefined);
659+
expect(fetchedUser.get('zip')).toBe(undefined);
660+
expect(fetchedUser.get('ssn')).toBe(undefined);
661+
done();
662+
})
663+
);
664+
});
665+
666+
it('should not get user PII via REST by ID', done => {
667+
request({
668+
url: `http://localhost:8378/1/classes/_User/${user.id}`,
669+
json: true,
670+
headers: {
671+
'X-Parse-Application-Id': 'test',
672+
'X-Parse-Javascript-Key': 'test',
608673
},
609-
e => console.error('error', e.message)
610-
)
611-
.then(() => done());
674+
})
675+
.then(
676+
response => {
677+
const result = response.data;
678+
const fetchedUser = result;
679+
expect(fetchedUser.zip).toBe(undefined);
680+
expect(fetchedUser.email).toBe(undefined);
681+
},
682+
e => console.error('error', e.message)
683+
)
684+
.then(() => done());
685+
});
686+
687+
// Even with an authenticated user, Public read ACL should never expose sensitive data.
688+
describe('with another authenticated user', () => {
689+
let anotherUser;
690+
691+
beforeEach(async done => {
692+
return Parse.User.signUp('another', 'abc')
693+
.then(loggedInUser => (anotherUser = loggedInUser))
694+
.then(() => Parse.User.logIn(anotherUser.get('username'), 'abc'))
695+
.then(() => done());
696+
});
697+
698+
it('should not be able to get user PII via API with object', done => {
699+
const userObj = new (Parse.Object.extend(Parse.User))();
700+
userObj.id = user.id;
701+
userObj
702+
.fetch()
703+
.then(
704+
fetchedUser => {
705+
expect(fetchedUser.get('email')).toBe(undefined);
706+
},
707+
e => console.error('error', e)
708+
)
709+
.then(done)
710+
.catch(done.fail);
711+
});
712+
713+
it('should not be able to get user PII via API with Find', done => {
714+
new Parse.Query(Parse.User)
715+
.equalTo('objectId', user.id)
716+
.find()
717+
.then(fetchedUser => {
718+
expect(fetchedUser.get('email')).toBe(undefined);
719+
expect(fetchedUser.get('zip')).toBe(undefined);
720+
expect(fetchedUser.get('ssn')).toBe(undefined);
721+
done();
722+
});
723+
});
724+
725+
it('should not be able to get user PII via API with Get', done => {
726+
new Parse.Query(Parse.User).get(user.id).then(fetchedUser => {
727+
expect(fetchedUser.get('email')).toBe(undefined);
728+
expect(fetchedUser.get('zip')).toBe(undefined);
729+
expect(fetchedUser.get('ssn')).toBe(undefined);
730+
done();
731+
});
732+
});
733+
});
612734
});
613735
});
614736
});

0 commit comments

Comments
 (0)