mirror of
https://github.com/parse-community/parse-server
synced 2026-08-09 13:03:18 +00:00
fix: Endpoints /login and /verifyPassword ignore _User protectedFields (#10409)
This commit is contained in:
@@ -1973,6 +1973,64 @@ describe('ProtectedFields', function () {
|
||||
expect(response.data.objectId).toBe(user.id);
|
||||
});
|
||||
|
||||
it('/login respects protectedFieldsOwnerExempt: false', async function () {
|
||||
await reconfigureServer({
|
||||
protectedFields: {
|
||||
_User: {
|
||||
'*': ['phone'],
|
||||
},
|
||||
},
|
||||
protectedFieldsOwnerExempt: false,
|
||||
});
|
||||
const user = await Parse.User.signUp('user1', 'password');
|
||||
const sessionToken = user.getSessionToken();
|
||||
user.set('phone', '555-1234');
|
||||
await user.save(null, { sessionToken });
|
||||
|
||||
const response = await request({
|
||||
method: 'POST',
|
||||
url: 'http://localhost:8378/1/login',
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ username: 'user1', password: 'password' }),
|
||||
});
|
||||
expect(response.data.phone).toBeUndefined();
|
||||
expect(response.data.objectId).toBe(user.id);
|
||||
expect(response.data.sessionToken).toBeDefined();
|
||||
});
|
||||
|
||||
it('/verifyPassword respects protectedFieldsOwnerExempt: false', async function () {
|
||||
await reconfigureServer({
|
||||
protectedFields: {
|
||||
_User: {
|
||||
'*': ['phone'],
|
||||
},
|
||||
},
|
||||
protectedFieldsOwnerExempt: false,
|
||||
verifyUserEmails: false,
|
||||
});
|
||||
const user = await Parse.User.signUp('user1', 'password');
|
||||
const sessionToken = user.getSessionToken();
|
||||
user.set('phone', '555-1234');
|
||||
await user.save(null, { sessionToken });
|
||||
|
||||
const response = await request({
|
||||
method: 'POST',
|
||||
url: 'http://localhost:8378/1/verifyPassword',
|
||||
headers: {
|
||||
'X-Parse-Application-Id': 'test',
|
||||
'X-Parse-REST-API-Key': 'rest',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ username: 'user1', password: 'password' }),
|
||||
});
|
||||
expect(response.data.phone).toBeUndefined();
|
||||
expect(response.data.objectId).toBe(user.id);
|
||||
});
|
||||
|
||||
it('owner sees non-protected fields like email when protectedFieldsOwnerExempt is true', async function () {
|
||||
await reconfigureServer({
|
||||
protectedFields: {
|
||||
|
||||
@@ -364,12 +364,39 @@ export class UsersRouter extends ClassesRouter {
|
||||
req.info.context
|
||||
);
|
||||
|
||||
// Re-fetch the user with the caller's auth context so that
|
||||
// protectedFields and CLP apply correctly
|
||||
const userAuth = new Auth.Auth({
|
||||
config: req.config,
|
||||
isMaster: false,
|
||||
user: Parse.Object.fromJSON({ className: '_User', objectId: user.objectId }),
|
||||
installationId: req.info.installationId,
|
||||
});
|
||||
let filteredUser;
|
||||
try {
|
||||
const filteredUserResponse = await rest.get(
|
||||
req.config,
|
||||
userAuth,
|
||||
'_User',
|
||||
user.objectId,
|
||||
{},
|
||||
req.info.clientSDK,
|
||||
req.info.context
|
||||
);
|
||||
filteredUser = filteredUserResponse.results?.[0];
|
||||
} catch {
|
||||
// re-fetch may fail for legacy users without ACL; fall through
|
||||
}
|
||||
if (!filteredUser) {
|
||||
filteredUser = user;
|
||||
}
|
||||
UsersRouter.removeHiddenProperties(filteredUser);
|
||||
filteredUser.sessionToken = user.sessionToken;
|
||||
if (authDataResponse) {
|
||||
user.authDataResponse = authDataResponse;
|
||||
filteredUser.authDataResponse = authDataResponse;
|
||||
}
|
||||
await req.config.authDataManager.runAfterFind(req, user.authData);
|
||||
|
||||
return { response: user };
|
||||
return { response: filteredUser };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -436,8 +463,34 @@ export class UsersRouter extends ClassesRouter {
|
||||
.then(async user => {
|
||||
// Remove hidden properties.
|
||||
UsersRouter.removeHiddenProperties(user);
|
||||
await req.config.authDataManager.runAfterFind(req, user.authData);
|
||||
return { response: user };
|
||||
// Re-fetch the user with the caller's auth context so that
|
||||
// protectedFields and CLP apply correctly
|
||||
const userAuth = new Auth.Auth({
|
||||
config: req.config,
|
||||
isMaster: false,
|
||||
user: Parse.Object.fromJSON({ className: '_User', objectId: user.objectId }),
|
||||
installationId: req.info.installationId,
|
||||
});
|
||||
let filteredUser;
|
||||
try {
|
||||
const filteredUserResponse = await rest.get(
|
||||
req.config,
|
||||
userAuth,
|
||||
'_User',
|
||||
user.objectId,
|
||||
{},
|
||||
req.info.clientSDK,
|
||||
req.info.context
|
||||
);
|
||||
filteredUser = filteredUserResponse.results?.[0];
|
||||
} catch {
|
||||
// re-fetch may fail for legacy users without ACL; fall through
|
||||
}
|
||||
if (!filteredUser) {
|
||||
filteredUser = user;
|
||||
}
|
||||
UsersRouter.removeHiddenProperties(filteredUser);
|
||||
return { response: filteredUser };
|
||||
})
|
||||
.catch(error => {
|
||||
throw error;
|
||||
|
||||
Reference in New Issue
Block a user