@@ -1700,4 +1700,106 @@ describe('ProtectedFields', function () {
17001700 done ( ) ;
17011701 } ) ;
17021702 } ) ;
1703+
1704+ describe ( 'query on protected fields via logical operators' , function ( ) {
1705+ let user ;
1706+ let otherUser ;
1707+ const testEmail = 'victim@example.com' ;
1708+ const otherEmail = 'other@example.com' ;
1709+
1710+ beforeEach ( async function ( ) {
1711+ await reconfigureServer ( {
1712+ protectedFields : {
1713+ _User : { '*' : [ 'email' ] } ,
1714+ } ,
1715+ } ) ;
1716+ user = new Parse . User ( ) ;
1717+ user . setUsername ( 'victim' + Date . now ( ) ) ;
1718+ user . setPassword ( 'password' ) ;
1719+ user . setEmail ( testEmail ) ;
1720+ const acl = new Parse . ACL ( ) ;
1721+ acl . setPublicReadAccess ( true ) ;
1722+ user . setACL ( acl ) ;
1723+ await user . save ( null , { useMasterKey : true } ) ;
1724+
1725+ otherUser = new Parse . User ( ) ;
1726+ otherUser . setUsername ( 'attacker' + Date . now ( ) ) ;
1727+ otherUser . setPassword ( 'password' ) ;
1728+ otherUser . setEmail ( otherEmail ) ;
1729+ const acl2 = new Parse . ACL ( ) ;
1730+ acl2 . setPublicReadAccess ( true ) ;
1731+ otherUser . setACL ( acl2 ) ;
1732+ await otherUser . save ( null , { useMasterKey : true } ) ;
1733+ await Parse . User . logIn ( otherUser . getUsername ( ) , 'password' ) ;
1734+ } ) ;
1735+
1736+ it ( 'should deny query on protected field via $or' , async function ( ) {
1737+ const q1 = new Parse . Query ( Parse . User ) ;
1738+ q1 . equalTo ( 'email' , testEmail ) ;
1739+ const query = Parse . Query . or ( q1 ) ;
1740+ await expectAsync ( query . find ( ) ) . toBeRejectedWith (
1741+ jasmine . objectContaining ( {
1742+ code : Parse . Error . OPERATION_FORBIDDEN ,
1743+ } )
1744+ ) ;
1745+ } ) ;
1746+
1747+ it ( 'should deny query on protected field via $and' , async function ( ) {
1748+ const query = new Parse . Query ( Parse . User ) ;
1749+ query . withJSON ( { where : { $and : [ { email : testEmail } ] } } ) ;
1750+ await expectAsync ( query . find ( ) ) . toBeRejectedWith (
1751+ jasmine . objectContaining ( {
1752+ code : Parse . Error . OPERATION_FORBIDDEN ,
1753+ } )
1754+ ) ;
1755+ } ) ;
1756+
1757+ it ( 'should deny query on protected field via $nor' , async function ( ) {
1758+ const query = new Parse . Query ( Parse . User ) ;
1759+ query . withJSON ( { where : { $nor : [ { email : testEmail } ] } } ) ;
1760+ await expectAsync ( query . find ( ) ) . toBeRejectedWith (
1761+ jasmine . objectContaining ( {
1762+ code : Parse . Error . OPERATION_FORBIDDEN ,
1763+ } )
1764+ ) ;
1765+ } ) ;
1766+
1767+ it ( 'should deny query on protected field via nested $or inside $and' , async function ( ) {
1768+ const query = new Parse . Query ( Parse . User ) ;
1769+ query . withJSON ( { where : { $and : [ { $or : [ { email : testEmail } ] } ] } } ) ;
1770+ await expectAsync ( query . find ( ) ) . toBeRejectedWith (
1771+ jasmine . objectContaining ( {
1772+ code : Parse . Error . OPERATION_FORBIDDEN ,
1773+ } )
1774+ ) ;
1775+ } ) ;
1776+
1777+ it ( 'should deny query on protected field via $or with $regex' , async function ( ) {
1778+ const query = new Parse . Query ( Parse . User ) ;
1779+ query . withJSON ( { where : { $or : [ { email : { $regex : '^victim' } } ] } } ) ;
1780+ await expectAsync ( query . find ( ) ) . toBeRejectedWith (
1781+ jasmine . objectContaining ( {
1782+ code : Parse . Error . OPERATION_FORBIDDEN ,
1783+ } )
1784+ ) ;
1785+ } ) ;
1786+
1787+ it ( 'should allow $or query on non-protected fields' , async function ( ) {
1788+ const q1 = new Parse . Query ( Parse . User ) ;
1789+ q1 . equalTo ( 'username' , user . getUsername ( ) ) ;
1790+ const query = Parse . Query . or ( q1 ) ;
1791+ const results = await query . find ( ) ;
1792+ expect ( results . length ) . toBe ( 1 ) ;
1793+ expect ( results [ 0 ] . id ) . toBe ( user . id ) ;
1794+ } ) ;
1795+
1796+ it ( 'should allow master key to query on protected fields via $or' , async function ( ) {
1797+ const q1 = new Parse . Query ( Parse . User ) ;
1798+ q1 . equalTo ( 'email' , testEmail ) ;
1799+ const query = Parse . Query . or ( q1 ) ;
1800+ const results = await query . find ( { useMasterKey : true } ) ;
1801+ expect ( results . length ) . toBe ( 1 ) ;
1802+ expect ( results [ 0 ] . id ) . toBe ( user . id ) ;
1803+ } ) ;
1804+ } ) ;
17031805} ) ;
0 commit comments