Files
cloudron-box/src/routes/test/profile-test.js
2024-02-26 13:30:35 +01:00

425 lines
17 KiB
JavaScript

/* jslint node:true */
/* global it:false */
/* global describe:false */
/* global before:false */
/* global after:false */
'use strict';
const common = require('./common.js'),
expect = require('expect.js'),
speakeasy = require('speakeasy'),
superagent = require('superagent'),
fs = require('fs'),
path = require('path'),
paths = require('../../paths.js'),
tokens = require('../../tokens.js');
describe('Profile API', function () {
const { setup, cleanup, serverUrl, owner, user } = common;
before(setup);
after(cleanup);
describe('get profile', function () {
it('fails without token', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/profile`)
.ok(() => true);
expect(response.statusCode).to.equal(401);
});
it('fails with empty token', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/profile`)
.query({ access_token: '' })
.ok(() => true);
expect(response.statusCode).to.equal(401);
});
it('fails with invalid token', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/profile`)
.query({ access_token: 'some token' })
.ok(() => true);
expect(response.statusCode).to.equal(401);
});
it('succeeds', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/profile`)
.query({ access_token: owner.token });
expect(response.statusCode).to.equal(200);
expect(response.body.username).to.equal(owner.username.toLowerCase());
expect(response.body.email).to.equal(owner.email.toLowerCase());
expect(response.body.fallbackEmail).to.equal('');
expect(response.body.displayName).to.be.a('string');
expect(response.body.password).to.not.be.ok();
expect(response.body.salt).to.not.be.ok();
expect(response.body.language).to.be('');
});
it('fails with expired token', async function () {
const token = await tokens.add({ identifier: '0', clientId: 'clientid-0', expires: Date.now() - 2000 });
expect(token.accessToken).to.be.a('string');
const response = await superagent.get(`${serverUrl}/api/v1/profile`)
.query({ access_token: token.accessToken })
.ok(() => true);
expect(response.statusCode).to.equal(401);
});
it('fails with invalid token in auth header', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/profile`)
.set('Authorization', 'Bearer ' + 'x' + owner.token)
.ok(() => true);
expect(response.statusCode).to.equal(401);
});
it('succeeds with token in auth header', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/profile`).set('Authorization', 'Bearer ' + owner.token);
expect(response.statusCode).to.equal(200);
expect(response.body.username).to.equal(owner.username.toLowerCase());
expect(response.body.email).to.equal(owner.email.toLowerCase());
expect(response.body.displayName).to.be.a('string');
expect(response.body.password).to.not.be.ok();
expect(response.body.salt).to.not.be.ok();
});
});
describe('email', function () {
it('change email fails due to missing token', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/email`)
.send({ email: 'newemail@example.com' })
.ok(() => true);
expect(response.statusCode).to.equal(401);
});
it('change email fails due to missing password', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/email`)
.query({ access_token: owner.token })
.send({ email: 'newemail@example.com' })
.ok(() => true);
expect(response.statusCode).to.equal(400);
});
it('change email fails due to invalid password', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/email`)
.query({ access_token: owner.token })
.send({ email: 'foo@bar.com', password: 'this is wrong' })
.ok(() => true);
expect(response.statusCode).to.equal(412);
});
it('change email fails due to invalid email', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/email`)
.query({ access_token: owner.token })
.send({ email: 'foo@bar' })
.ok(() => true);
expect(response.statusCode).to.equal(400);
});
it('change email succeeds', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/email`)
.query({ access_token: owner.token })
.send({ email: 'newemail@example.Com', password: owner.password });
expect(response.statusCode).to.equal(204);
const response2 = await superagent.get(`${serverUrl}/api/v1/profile`)
.query({ access_token: owner.token });
expect(response2.statusCode).to.equal(200);
expect(response2.body.username).to.equal(owner.username);
expect(response2.body.email).to.equal('newemail@example.com'); // lower cased
expect(response2.body.displayName).to.equal('');
});
});
describe('fallbackEmail', function () {
it('change fallback email fails due to missing password', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/fallback_email`)
.query({ access_token: owner.token })
.send({ fallbackEmail: 'newemail@example.com' })
.ok(() => true);
expect(response.statusCode).to.equal(400);
});
it('change fallback email fails due to invalid password', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/fallback_email`)
.query({ access_token: owner.token })
.send({ fallbackEmail: 'foo@bar.com', password: 'this is wrong' })
.ok(() => true);
expect(response.statusCode).to.equal(412);
});
it('change fallback email succeeds', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/fallback_email`)
.query({ access_token: owner.token })
.send({ fallbackEmail: 'NewFallbackemail@example.com', password: owner.password });
expect(response.statusCode).to.equal(204);
const response2 = await superagent.get(`${serverUrl}/api/v1/profile`)
.query({ access_token: owner.token });
expect(response2.statusCode).to.equal(200);
expect(response2.body.username).to.equal(owner.username);
expect(response2.body.fallbackEmail).to.equal('newfallbackemail@example.com'); // lowercase
});
});
describe('displayName', function () {
it('change displayName succeeds', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/display_name`)
.query({ access_token: owner.token })
.send({ displayName: 'Agent Smith' });
expect(response.statusCode).to.equal(204);
const response2 = await superagent.get(`${serverUrl}/api/v1/profile`)
.query({ access_token: owner.token });
expect(response2.statusCode).to.equal(200);
expect(response2.body.username).to.equal(owner.username);
expect(response2.body.email).to.equal('newemail@example.com'); // lower cased
expect(response2.body.displayName).to.equal('Agent Smith');
});
});
describe('password change', function () {
it('fails due to missing current password', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/password`)
.query({ access_token: owner.token })
.send({ newPassword: 'some wrong password' })
.ok(() => true);
expect(response.statusCode).to.equal(400);
});
it('fails due to missing new password', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/password`)
.query({ access_token: owner.token })
.send({ password: owner.password })
.ok(() => true);
expect(response.statusCode).to.equal(400);
});
it('fails due to wrong password', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/password`)
.query({ access_token: owner.token })
.send({ password: 'some wrong password', newPassword: 'MOre#$%34' })
.ok(() => true);
expect(response.statusCode).to.equal(412);
});
it('fails due to invalid password', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/password`)
.query({ access_token: owner.token })
.send({ password: owner.password, newPassword: 'five' })
.ok(() => true);
expect(response.statusCode).to.equal(400);
});
it('succeeds', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/password`)
.query({ access_token: owner.token })
.send({ password: owner.password, newPassword: 'MOre#$%34' });
expect(response.statusCode).to.equal(204);
});
});
describe('2fa login', function () {
let secret;
it('can get secret', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/twofactorauthentication_secret`)
.query({ access_token: user.token });
secret = response.body.secret;
});
it('can enable 2fa', async function () {
const totpToken = speakeasy.totp({ secret, encoding: 'base32' });
await superagent.post(`${serverUrl}/api/v1/profile/twofactorauthentication_enable`)
.query({ access_token: user.token })
.send({ totpToken });
});
it('fails due to missing token', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/auth/login`)
.send({ username: user.username, password: user.password })
.ok(() => true);
expect(response.statusCode).to.equal(401);
});
it('fails due to wrong token', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/auth/login`)
.send({ username: user.username, password: user.password, totpToken: '12345' })
.ok(() => true);
expect(response.statusCode).to.equal(401);
});
it('succeeds', async function () {
const totpToken = speakeasy.totp({
secret: secret,
encoding: 'base32'
});
const response = await superagent.post(`${serverUrl}/api/v1/auth/login`)
.send({ username: user.username, password: user.password, totpToken: totpToken });
expect(response.statusCode).to.equal(200);
expect(response.body).to.be.an(Object);
expect(response.body.accessToken).to.be.a('string');
});
it('can disable 2fa', async function () {
await superagent.post(`${serverUrl}/api/v1/profile/twofactorauthentication_disable`)
.query({ access_token: user.token })
.send({ password: user.password });
});
it('did disable 2fa', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/auth/login`)
.send({ username: user.username, password: user.password });
expect(response.statusCode).to.equal(200);
expect(response.body).to.be.an(Object);
expect(response.body.accessToken).to.be.a('string');
});
});
describe('avatar', function () {
let customAvatarSize = 0;
it('placeholder by default', async function () {
const defaultAvatar = fs.readFileSync(path.join(paths.DASHBOARD_DIR, '/img/avatar-default-symbolic.svg'));
const response = await superagent.get(`${serverUrl}/api/v1/profile/avatar/${user.id}`);
expect(response.headers['content-type']).to.equal('image/svg+xml');
expect(response.body).to.eql(defaultAvatar);
});
it('can set custom avatar', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/avatar`)
.query({ access_token: user.token })
.attach('avatar', './logo.png');
customAvatarSize = require('fs').readFileSync('./logo.png').length;
expect(response.statusCode).to.be(202);
});
it('did set custom avatar', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/profile`)
.query({ access_token: user.token });
expect(response.body.avatarUrl).to.contain('/api/v1/profile/avatar/');
const response2 = await superagent.get(`${serverUrl}/api/v1/profile/avatar/${user.id}`)
.ok(() => true);
expect(parseInt(response2.headers['content-length'])).to.equal(customAvatarSize);
expect(response2.statusCode).to.equal(200);
});
it('can set gravatar', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/avatar`)
.query({ access_token: user.token })
.send({ avatar: 'gravatar' });
expect(response.statusCode).to.be(202);
});
it('did set gravatar', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/profile`)
.query({ access_token: user.token });
expect(response.body.avatarType).to.contain('gravatar');
});
it('can unset avatar', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/avatar`)
.query({ access_token: user.token })
.send({ avatar: '' });
expect(response.statusCode).to.be(202);
});
it('did unset avatar', async function () {
const defaultAvatar = fs.readFileSync(path.join(paths.DASHBOARD_DIR, '/img/avatar-default-symbolic.svg'));
const response = await superagent.get(`${serverUrl}/api/v1/profile/avatar/${user.id}`);
expect(response.headers['content-type']).to.equal('image/svg+xml');
expect(response.body).to.eql(defaultAvatar);
});
});
describe('language', function () {
it('fails to set unknown language', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/language`)
.query({ access_token: user.token })
.send({ language: 'ta' })
.ok(() => true);
expect(response.statusCode).to.be(400);
});
it('fails to set bad language', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/language`)
.query({ access_token: user.token })
.send({ language: 123 })
.ok(() => true);
expect(response.statusCode).to.be(400);
});
it('fails to set unknown language', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/language`)
.query({ access_token: user.token })
.send({ language: 'ta' })
.ok(() => true);
expect(response.statusCode).to.be(400);
});
it('set valid language', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/language`)
.query({ access_token: user.token })
.send({ language: 'en' });
expect(response.statusCode).to.be(204);
});
it('did set language', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/profile`).query({ access_token: user.token });
expect(response.body.language).to.contain('en');
});
it('reset valid language', async function () {
const response = await superagent.post(`${serverUrl}/api/v1/profile/language`)
.query({ access_token: user.token })
.send({ language: '' });
expect(response.statusCode).to.be(204);
});
it('did reset language', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/profile`).query({ access_token: user.token });
expect(response.body.language).to.contain('');
});
});
});