Skip to content

Commit 526efa9

Browse files
author
gormanfletcher
committed
6641: PR feedback: grouped /loginAs tests, adjusted their names. Change error code for invalid userId parameter and test against additional invalid values. Adjusted error messages.
1 parent c77059c commit 526efa9

File tree

2 files changed

+134
-123
lines changed

2 files changed

+134
-123
lines changed

spec/ParseUser.spec.js

Lines changed: 128 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -142,123 +142,6 @@ describe('Parse.User testing', () => {
142142
});
143143
});
144144

145-
it('/loginAs allows the master key to manually create a user session for a given user ID', async done => {
146-
await Parse.User.signUp('some_user', 'some_password');
147-
const userId = Parse.User.current().id;
148-
await Parse.User.logOut();
149-
150-
try {
151-
const response = await request({
152-
method: 'POST',
153-
url: 'http://localhost:8378/1/loginAs',
154-
headers: {
155-
'X-Parse-Application-Id': Parse.applicationId,
156-
'X-Parse-REST-API-Key': 'rest',
157-
'X-Parse-Master-Key': 'test',
158-
},
159-
body: {
160-
userId,
161-
},
162-
});
163-
164-
expect(response.data.sessionToken).toBeDefined();
165-
} catch (err) {
166-
fail(`no request should fail: ${JSON.stringify(err)}`);
167-
done();
168-
}
169-
170-
const sessionsQuery = new Parse.Query(Parse.Session);
171-
const sessionsAfterRequest = await sessionsQuery.find({ useMasterKey: true });
172-
expect(sessionsAfterRequest.length).toBe(1);
173-
174-
done();
175-
});
176-
177-
it("/loginAs returns an error if a session is requested for a user ID that doesn't exist", async done => {
178-
try {
179-
await request({
180-
method: 'POST',
181-
url: 'http://localhost:8378/1/loginAs',
182-
headers: {
183-
'X-Parse-Application-Id': Parse.applicationId,
184-
'X-Parse-REST-API-Key': 'rest',
185-
'X-Parse-Master-Key': 'test',
186-
},
187-
body: {
188-
userId: 'bogus-user',
189-
},
190-
});
191-
192-
fail('Request should fail without a valid user ID');
193-
done();
194-
} catch (err) {
195-
expect(err.data.code).toBe(Parse.Error.OBJECT_NOT_FOUND);
196-
}
197-
198-
const sessionsQuery = new Parse.Query(Parse.Session);
199-
const sessionsAfterRequest = await sessionsQuery.find({ useMasterKey: true });
200-
expect(sessionsAfterRequest.length).toBe(0);
201-
202-
done();
203-
});
204-
205-
it('/loginAs returns an error if a session is requested without specifying a user ID', async done => {
206-
try {
207-
await request({
208-
method: 'POST',
209-
url: 'http://localhost:8378/1/loginAs',
210-
headers: {
211-
'X-Parse-Application-Id': Parse.applicationId,
212-
'X-Parse-REST-API-Key': 'rest',
213-
'X-Parse-Master-Key': 'test',
214-
},
215-
body: {},
216-
});
217-
218-
fail('Request should fail without a valid user ID');
219-
done();
220-
} catch (err) {
221-
expect(err.data.code).toBe(Parse.Error.MISSING_OBJECT_ID);
222-
}
223-
224-
const sessionsQuery = new Parse.Query(Parse.Session);
225-
const sessionsAfterRequest = await sessionsQuery.find({ useMasterKey: true });
226-
expect(sessionsAfterRequest.length).toBe(0);
227-
228-
done();
229-
});
230-
231-
it('/loginAs forbids non-master clients from creating sessions', async done => {
232-
await Parse.User.signUp('some_user', 'some_password');
233-
const userId = Parse.User.current().id;
234-
await Parse.User.logOut();
235-
236-
try {
237-
await request({
238-
method: 'POST',
239-
url: 'http://localhost:8378/1/loginAs',
240-
headers: {
241-
'X-Parse-Application-Id': Parse.applicationId,
242-
'X-Parse-REST-API-Key': 'rest',
243-
},
244-
body: {
245-
userId,
246-
},
247-
});
248-
249-
fail('Request should fail without the master key');
250-
done();
251-
} catch (err) {
252-
expect(err.data.code).toBe(Parse.Error.OPERATION_FORBIDDEN);
253-
}
254-
255-
const sessionsQuery = new Parse.Query(Parse.Session);
256-
const sessionsAfterRequest = await sessionsQuery.find({ useMasterKey: true });
257-
expect(sessionsAfterRequest.length).toBe(0);
258-
259-
done();
260-
});
261-
262145
it('user login', async done => {
263146
await Parse.User.signUp('asdf', 'zxcv');
264147
const user = await Parse.User.logIn('asdf', 'zxcv');
@@ -4149,3 +4032,131 @@ describe('Security Advisory GHSA-8w3j-g983-8jh5', function () {
41494032
expect(user.get('authData')).toEqual({ custom: { id: 'linkedID' } });
41504033
});
41514034
});
4035+
4036+
describe('login as other user', () => {
4037+
it('allows creating a session for another user with the master key', async done => {
4038+
await Parse.User.signUp('some_user', 'some_password');
4039+
const userId = Parse.User.current().id;
4040+
await Parse.User.logOut();
4041+
4042+
try {
4043+
const response = await request({
4044+
method: 'POST',
4045+
url: 'http://localhost:8378/1/loginAs',
4046+
headers: {
4047+
'X-Parse-Application-Id': Parse.applicationId,
4048+
'X-Parse-REST-API-Key': 'rest',
4049+
'X-Parse-Master-Key': 'test',
4050+
},
4051+
body: {
4052+
userId,
4053+
},
4054+
});
4055+
4056+
expect(response.data.sessionToken).toBeDefined();
4057+
} catch (err) {
4058+
fail(`no request should fail: ${JSON.stringify(err)}`);
4059+
done();
4060+
}
4061+
4062+
const sessionsQuery = new Parse.Query(Parse.Session);
4063+
const sessionsAfterRequest = await sessionsQuery.find({ useMasterKey: true });
4064+
expect(sessionsAfterRequest.length).toBe(1);
4065+
4066+
done();
4067+
});
4068+
4069+
it('rejects creating a session for another user if the user does not exist', async done => {
4070+
try {
4071+
await request({
4072+
method: 'POST',
4073+
url: 'http://localhost:8378/1/loginAs',
4074+
headers: {
4075+
'X-Parse-Application-Id': Parse.applicationId,
4076+
'X-Parse-REST-API-Key': 'rest',
4077+
'X-Parse-Master-Key': 'test',
4078+
},
4079+
body: {
4080+
userId: 'bogus-user',
4081+
},
4082+
});
4083+
4084+
fail('Request should fail without a valid user ID');
4085+
done();
4086+
} catch (err) {
4087+
expect(err.data.code).toBe(Parse.Error.OBJECT_NOT_FOUND);
4088+
expect(err.data.error).toBe('user not found');
4089+
}
4090+
4091+
const sessionsQuery = new Parse.Query(Parse.Session);
4092+
const sessionsAfterRequest = await sessionsQuery.find({ useMasterKey: true });
4093+
expect(sessionsAfterRequest.length).toBe(0);
4094+
4095+
done();
4096+
});
4097+
4098+
it('rejects creating a session for another user with invalid parameters', async done => {
4099+
const invalidUserIds = [undefined, null, ''];
4100+
4101+
for (const invalidUserId of invalidUserIds) {
4102+
try {
4103+
await request({
4104+
method: 'POST',
4105+
url: 'http://localhost:8378/1/loginAs',
4106+
headers: {
4107+
'X-Parse-Application-Id': Parse.applicationId,
4108+
'X-Parse-REST-API-Key': 'rest',
4109+
'X-Parse-Master-Key': 'test',
4110+
},
4111+
body: {
4112+
userId: invalidUserId,
4113+
},
4114+
});
4115+
4116+
fail('Request should fail without a valid user ID');
4117+
done();
4118+
} catch (err) {
4119+
expect(err.data.code).toBe(Parse.Error.INVALID_VALUE);
4120+
expect(err.data.error).toBe('userId must not be empty, null, or undefined');
4121+
}
4122+
4123+
const sessionsQuery = new Parse.Query(Parse.Session);
4124+
const sessionsAfterRequest = await sessionsQuery.find({ useMasterKey: true });
4125+
expect(sessionsAfterRequest.length).toBe(0);
4126+
}
4127+
4128+
done();
4129+
});
4130+
4131+
it('rejects creating a session for another user without the master key', async done => {
4132+
await Parse.User.signUp('some_user', 'some_password');
4133+
const userId = Parse.User.current().id;
4134+
await Parse.User.logOut();
4135+
4136+
try {
4137+
await request({
4138+
method: 'POST',
4139+
url: 'http://localhost:8378/1/loginAs',
4140+
headers: {
4141+
'X-Parse-Application-Id': Parse.applicationId,
4142+
'X-Parse-REST-API-Key': 'rest',
4143+
},
4144+
body: {
4145+
userId,
4146+
},
4147+
});
4148+
4149+
fail('Request should fail without the master key');
4150+
done();
4151+
} catch (err) {
4152+
expect(err.data.code).toBe(Parse.Error.OPERATION_FORBIDDEN);
4153+
expect(err.data.error).toBe('master key is required');
4154+
}
4155+
4156+
const sessionsQuery = new Parse.Query(Parse.Session);
4157+
const sessionsAfterRequest = await sessionsQuery.find({ useMasterKey: true });
4158+
expect(sessionsAfterRequest.length).toBe(0);
4159+
4160+
done();
4161+
});
4162+
});

src/Routers/UsersRouter.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -269,21 +269,21 @@ export class UsersRouter extends ClassesRouter {
269269
*/
270270
async handleLogInAs(req) {
271271
if (!req.auth.isMaster) {
272-
throw new Parse.Error(
273-
Parse.Error.OPERATION_FORBIDDEN,
274-
'The master key is required to perform the loginAs action'
275-
);
272+
throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, 'master key is required');
276273
}
277274

278275
const userId = req.body.userId || req.query.userId;
279276
if (!userId) {
280-
throw new Parse.Error(Parse.Error.MISSING_OBJECT_ID, 'User ID is required');
277+
throw new Parse.Error(
278+
Parse.Error.INVALID_VALUE,
279+
'userId must not be empty, null, or undefined'
280+
);
281281
}
282282

283283
const queryResults = await req.config.database.find('_User', { objectId: userId });
284284
const user = queryResults[0];
285285
if (!user) {
286-
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'No user with that ID');
286+
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'user not found');
287287
}
288288

289289
this._sanitizeAuthData(user);

0 commit comments

Comments
 (0)