fallbackEmail is now independent from email

This commit is contained in:
Johannes Zellner
2021-10-26 22:50:02 +02:00
parent 2f510c2625
commit daf212468f
5 changed files with 40 additions and 7 deletions
+18
View File
@@ -76,6 +76,15 @@ describe('Users API', function () {
expect(response.statusCode).to.equal(400);
});
it('cannot create user with non email fallbackEmail', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users`)
.query({ access_token: owner.token })
.send({ username: user2.username, email: user2.email, fallbackEmail: 'notanemail' })
.ok(() => true);
expect(response.statusCode).to.equal(400);
});
it('create second user succeeds', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users`)
.query({ access_token: owner.token })
@@ -299,6 +308,15 @@ describe('Users API', function () {
expect(response.statusCode).to.equal(400);
});
it('change fallbackEmail fails due to invalid email', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}`)
.query({ access_token: owner.token })
.send({ fallbackEmail: 'newemail@cloudron' })
.ok(() => true);
expect(response.statusCode).to.equal(400);
});
it('change user succeeds without email nor displayName', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/users/${user2.id}`)
.query({ access_token: owner.token })
+3 -1
View File
@@ -43,6 +43,7 @@ async function add(req, res, next) {
if (typeof req.body.email !== 'string') return next(new HttpError(400, 'email must be string'));
if ('username' in req.body && typeof req.body.username !== 'string') return next(new HttpError(400, 'username must be string'));
if ('fallbackEmail' in req.body && typeof req.body.fallbackEmail !== 'string') return next(new HttpError(400, 'fallbackEmail must be string'));
if ('displayName' in req.body && typeof req.body.displayName !== 'string') return next(new HttpError(400, 'displayName must be string'));
if ('password' in req.body && typeof req.body.password !== 'string') return next(new HttpError(400, 'password must be string'));
if ('role' in req.body) {
@@ -54,8 +55,9 @@ async function add(req, res, next) {
const email = req.body.email;
const username = 'username' in req.body ? req.body.username : null;
const displayName = req.body.displayName || '';
const fallbackEmail = req.body.fallbackEmail || '';
const [error, id] = await safe(users.add(email, { username, password, displayName, invitor: req.user, role: req.body.role || users.ROLE_USER }, AuditSource.fromRequest(req)));
const [error, id] = await safe(users.add(email, { username, password, displayName, fallbackEmail, invitor: req.user, role: req.body.role || users.ROLE_USER }, AuditSource.fromRequest(req)));
if (error) return next(BoxError.toHttpError(error));
next(new HttpSuccess(201, { id }));
+2 -2
View File
@@ -63,7 +63,7 @@ const admin = {
username: 'testadmin',
password: 'secret123',
email: 'admin@me.com',
fallbackEmail: 'admin@me.com',
fallbackEmail: 'admin@external.com',
salt: 'morton',
createdAt: 'sometime back',
resetToken: '',
@@ -80,7 +80,7 @@ const user = {
username: 'user',
password: '123secret',
email: 'user@me.com',
fallbackEmail: 'user@me.com',
fallbackEmail: 'user@external.com',
role: 'user',
salt: 'morton',
createdAt: 'sometime back',
+7 -1
View File
@@ -83,6 +83,12 @@ describe('User', function () {
expect(error.reason).to.equal(BoxError.BAD_FIELD);
});
it('fails because fallbackEmail is not an email', async function () {
const user = Object.assign({}, admin, { fallbackEmail: 'notanemail' });
const [error] = await safe(users.add(user.email, user, auditSource));
expect(error.reason).to.equal(BoxError.BAD_FIELD);
});
it('can add user', async function () {
const id = await users.add(admin.email, admin, auditSource);
admin.id = id;
@@ -403,7 +409,7 @@ describe('User', function () {
const result = await users.get(admin.id);
expect(result.id).to.equal(admin.id);
expect(result.email).to.equal(admin.email.toLowerCase());
expect(result.fallbackEmail).to.equal(admin.email.toLowerCase());
expect(result.fallbackEmail).to.equal(admin.fallbackEmail.toLowerCase());
expect(result.username).to.equal(admin.username.toLowerCase());
expect(result.displayName).to.equal(admin.displayName);
});
+10 -3
View File
@@ -180,8 +180,9 @@ async function add(email, data, auditSource) {
assert(data.username === null || typeof data.username === 'string');
assert(data.password === null || typeof data.password === 'string');
assert.strictEqual(typeof data.displayName, 'string');
assert.strictEqual(typeof data.fallbackEmail, 'string');
let { username, password, displayName } = data;
let { username, password, displayName, fallbackEmail } = data;
const source = data.source || ''; // empty is local user
const role = data.role || exports.ROLE_USER;
@@ -204,6 +205,12 @@ async function add(email, data, auditSource) {
error = validateEmail(email);
if (error) throw error;
fallbackEmail = fallbackEmail.toLowerCase();
if (fallbackEmail) {
let error = validateEmail(fallbackEmail);
if (error) throw error;
}
error = validateDisplayName(displayName);
if (error) throw error;
@@ -222,7 +229,7 @@ async function add(email, data, auditSource) {
id: 'uid-' + uuid.v4(),
username: username,
email: email,
fallbackEmail: email,
fallbackEmail: fallbackEmail,
password: Buffer.from(derivedKey, 'binary').toString('hex'),
salt: salt.toString('hex'),
resetToken: '',
@@ -701,7 +708,7 @@ async function createOwner(email, username, password, displayName, auditSource)
const activated = await isActivated();
if (activated) throw new BoxError(BoxError.ALREADY_EXISTS, 'Cloudron already activated');
return await add(email, { username, password, displayName, role: exports.ROLE_OWNER }, auditSource);
return await add(email, { username, password, fallbackEmail: '', displayName, role: exports.ROLE_OWNER }, auditSource);
}
async function sendInvite(user, options, auditSource) {