Support updating profile via /account/data
This commit is contained in:
parent
9e3426633d
commit
4db78deda3
|
@ -44,6 +44,15 @@ class AccountController {
|
||||||
requirePassword = true;
|
requirePassword = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (updates.profile) {
|
||||||
|
validateProfile(updates.profile);
|
||||||
|
|
||||||
|
fields.profile = {
|
||||||
|
image: updates.profile.image.trim(),
|
||||||
|
text: updates.profile.text
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (requirePassword) {
|
if (requirePassword) {
|
||||||
if (!password) {
|
if (!password) {
|
||||||
throw new InvalidRequestError('Password required');
|
throw new InvalidRequestError('Password required');
|
||||||
|
@ -67,4 +76,28 @@ class AccountController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function validateProfile(profile) {
|
||||||
|
// TODO: replace all of these errors with a standard errorcode + field checker
|
||||||
|
if (profile.toString() !== '[object Object]')
|
||||||
|
throw new InvalidRequestError('Invalid profile');
|
||||||
|
if (typeof profile.text !== 'string')
|
||||||
|
throw new InvalidRequestError('Invalid profile');
|
||||||
|
if (typeof profile.image !== 'string')
|
||||||
|
throw new InvalidRequestError('Invalid profile');
|
||||||
|
if (profile.text.length > 255)
|
||||||
|
throw new InvalidRequestError('Profile text must not exceed 255 characters');
|
||||||
|
if (profile.image.length > 255)
|
||||||
|
throw new InvalidRequestError('Profile image URL must not exceed 255 characters');
|
||||||
|
|
||||||
|
if (profile.image.trim() === '') return true;
|
||||||
|
|
||||||
|
const url = parseURL(profile.image);
|
||||||
|
if (!url.host)
|
||||||
|
throw new InvalidRequestError('Invalid profile image URL');
|
||||||
|
if (url.protocol !== 'https:')
|
||||||
|
throw new InvalidRequestError('Profile image URL must start with "https:"');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
export { AccountController };
|
export { AccountController };
|
||||||
|
|
|
@ -278,6 +278,33 @@ describe('AccountDataRoute', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('updates profile', () => {
|
||||||
|
accountDB.expects('updateByName').withArgs(
|
||||||
|
'test',
|
||||||
|
{
|
||||||
|
profile: {
|
||||||
|
text: 'testing',
|
||||||
|
image: 'https://example.com/image.jpg'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return request('PATCH', `${URL_BASE}/account/data/test`, {
|
||||||
|
body: {
|
||||||
|
updates: {
|
||||||
|
profile: {
|
||||||
|
text: 'testing',
|
||||||
|
image: 'https://example.com/image.jpg'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
assert.strictEqual(res.statusCode, 204);
|
||||||
|
|
||||||
|
accountDB.verify();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('rejects invalid email address', () => {
|
it('rejects invalid email address', () => {
|
||||||
return request('PATCH', `${URL_BASE}/account/data/test`, {
|
return request('PATCH', `${URL_BASE}/account/data/test`, {
|
||||||
body: {
|
body: {
|
||||||
|
@ -377,6 +404,133 @@ describe('AccountDataRoute', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('rejects invalid profile', () => {
|
||||||
|
return request('PATCH', `${URL_BASE}/account/data/test`, {
|
||||||
|
body: {
|
||||||
|
updates: {
|
||||||
|
profile: 'not valid'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
assert.strictEqual(res.statusCode, 400);
|
||||||
|
assert.strictEqual(
|
||||||
|
JSON.parse(res.body).error,
|
||||||
|
'Invalid profile'
|
||||||
|
);
|
||||||
|
|
||||||
|
accountDB.verify();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects wrongly typed profile text', () => {
|
||||||
|
return request('PATCH', `${URL_BASE}/account/data/test`, {
|
||||||
|
body: {
|
||||||
|
updates: {
|
||||||
|
profile: {
|
||||||
|
text: ['wrong'],
|
||||||
|
image: 'https://example.com'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
assert.strictEqual(res.statusCode, 400);
|
||||||
|
assert.strictEqual(
|
||||||
|
JSON.parse(res.body).error,
|
||||||
|
'Invalid profile'
|
||||||
|
);
|
||||||
|
|
||||||
|
accountDB.verify();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects too long profile text', () => {
|
||||||
|
let longText = ''; for (let i = 0; i < 256; i++) longText += 'a';
|
||||||
|
|
||||||
|
return request('PATCH', `${URL_BASE}/account/data/test`, {
|
||||||
|
body: {
|
||||||
|
updates: {
|
||||||
|
profile: {
|
||||||
|
text: longText,
|
||||||
|
image: 'https://example.com'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
assert.strictEqual(res.statusCode, 400);
|
||||||
|
assert.strictEqual(
|
||||||
|
JSON.parse(res.body).error,
|
||||||
|
'Profile text must not exceed 255 characters'
|
||||||
|
);
|
||||||
|
|
||||||
|
accountDB.verify();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects wrongly typed profile image', () => {
|
||||||
|
return request('PATCH', `${URL_BASE}/account/data/test`, {
|
||||||
|
body: {
|
||||||
|
updates: {
|
||||||
|
profile: {
|
||||||
|
text: 'test',
|
||||||
|
image: 42
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
assert.strictEqual(res.statusCode, 400);
|
||||||
|
assert.strictEqual(
|
||||||
|
JSON.parse(res.body).error,
|
||||||
|
'Invalid profile'
|
||||||
|
);
|
||||||
|
|
||||||
|
accountDB.verify();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects too long profile image', () => {
|
||||||
|
let longText = 'https://'; for (let i = 0; i < 256; i++) longText += 'a';
|
||||||
|
|
||||||
|
return request('PATCH', `${URL_BASE}/account/data/test`, {
|
||||||
|
body: {
|
||||||
|
updates: {
|
||||||
|
profile: {
|
||||||
|
text: 'test',
|
||||||
|
image: longText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
assert.strictEqual(res.statusCode, 400);
|
||||||
|
assert.strictEqual(
|
||||||
|
JSON.parse(res.body).error,
|
||||||
|
'Profile image URL must not exceed 255 characters'
|
||||||
|
);
|
||||||
|
|
||||||
|
accountDB.verify();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('rejects non-https profile image', () => {
|
||||||
|
return request('PATCH', `${URL_BASE}/account/data/test`, {
|
||||||
|
body: {
|
||||||
|
updates: {
|
||||||
|
profile: {
|
||||||
|
text: 'test',
|
||||||
|
image: 'http://example.com/image.jpg'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).then(res => {
|
||||||
|
assert.strictEqual(res.statusCode, 400);
|
||||||
|
assert.strictEqual(
|
||||||
|
JSON.parse(res.body).error,
|
||||||
|
'Profile image URL must start with "https:"'
|
||||||
|
);
|
||||||
|
|
||||||
|
accountDB.verify();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
checkDefaults('/account/data/test', 'PATCH');
|
checkDefaults('/account/data/test', 'PATCH');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue