Skip to content

Commit

Permalink
feat(general): permissions check for body campaigns
Browse files Browse the repository at this point in the history
  • Loading branch information
serge1peshcoff committed Mar 5, 2020
1 parent 25fb9b9 commit 5ba50c6
Show file tree
Hide file tree
Showing 6 changed files with 287 additions and 17 deletions.
25 changes: 21 additions & 4 deletions middlewares/body-campaigns.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
const { Campaign } = require('../models');
const helpers = require('../lib/helpers');
const errors = require('../lib/errors');

exports.listAllCampaigns = async (req, res) => {
if (!req.permissions.hasPermission('view:campaign')) {
return errors.makeForbiddenError(res, 'Permission view:campaign is required, but not present.');
}

const result = await Campaign.findAndCountAll({
where: { autojoin_body_id: req.currentBody.id },
...helpers.getPagination(req.query),
Expand All @@ -16,15 +21,21 @@ exports.listAllCampaigns = async (req, res) => {
};

exports.getCampaign = async (req, res) => {
// TODO: check permissions
if (!req.permissions.hasPermission('view:campaign')) {
return errors.makeForbiddenError(res, 'Permission view:campaign is required, but not present.');
}

return res.json({
success: true,
data: req.currentBodyCampaign
});
};

exports.createCampaign = async (req, res) => {
// TODO: check permissions
if (!req.permissions.hasPermission('create:campaign')) {
return errors.makeForbiddenError(res, 'Permission create:campaign is required, but not present.');
}

// TODO: filter out fields that are changed in the other way
const circle = await Campaign.create({
...req.body,
Expand All @@ -38,7 +49,10 @@ exports.createCampaign = async (req, res) => {
};

exports.updateCampaign = async (req, res) => {
// TODO: check permissions
if (!req.permissions.hasPermission('update:campaign')) {
return errors.makeForbiddenError(res, 'Permission update:campaign is required, but not present.');
}

// TODO: filter out fields that are changed in the other way
await req.currentBodyCampaign.update(req.body);
return res.json({
Expand All @@ -48,7 +62,10 @@ exports.updateCampaign = async (req, res) => {
};

exports.deleteCampaign = async (req, res) => {
// TODO: check permissions
if (!req.permissions.hasPermission('delete:campaign')) {
return errors.makeForbiddenError(res, 'Permission delete:campaign is required, but not present.');
}

await req.currentBodyCampaign.destroy();
return res.json({
success: true,
Expand Down
58 changes: 55 additions & 3 deletions test/api/body-campaigns-creating.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ describe('Campaigns creating', () => {
});

test('should fail if there are validation errors', async () => {
const user = await generator.createUser({ username: 'test', mail_confirmed_at: new Date() });
const user = await generator.createUser({ superadmin: true });
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();

await generator.createPermission({ scope: 'global', action: 'create', object: 'campaign' });

const campaign = generator.generateCampaign({ name: '' });

const res = await request({
Expand All @@ -37,10 +39,12 @@ describe('Campaigns creating', () => {
});

test('should succeed if everything is okay', async () => {
const user = await generator.createUser({ username: 'test', mail_confirmed_at: new Date() });
const user = await generator.createUser({ superadmin: true });
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();

await generator.createPermission({ scope: 'global', action: 'create', object: 'campaign' });

const campaign = generator.generateCampaign();

const res = await request({
Expand All @@ -58,10 +62,12 @@ describe('Campaigns creating', () => {
});

test('should override body id', async () => {
const user = await generator.createUser({ username: 'test', mail_confirmed_at: new Date() });
const user = await generator.createUser({ superadmin: true });
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();

await generator.createPermission({ scope: 'global', action: 'create', object: 'campaign' });

const campaign = generator.generateCampaign({ body_id: 1337 });

const res = await request({
Expand All @@ -77,4 +83,50 @@ describe('Campaigns creating', () => {
expect(res.body).toHaveProperty('data');
expect(res.body.data.body_id).not.toEqual(1337);
});

test('should succeed on local permission', async () => {
const user = await generator.createUser();
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();
const circle = await generator.createCircle({ body_id: body.id });
const permission = await generator.createPermission({ scope: 'local', action: 'create', object: 'campaign' });

await generator.createCircleMembership(circle, user);
await generator.createCirclePermission(circle, permission);

const campaign = generator.generateCampaign({ body_id: 1337 });

const res = await request({
uri: '/bodies/' + body.id + '/campaigns',
method: 'POST',
headers: { 'X-Auth-Token': token.value },
body: campaign
});

expect(res.statusCode).toEqual(200);
expect(res.body.success).toEqual(true);
expect(res.body).not.toHaveProperty('errors');
expect(res.body).toHaveProperty('data');
expect(res.body.data.body_id).not.toEqual(1337);
});

test('should fail if no permission', async () => {
const user = await generator.createUser();
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();

const campaign = generator.generateCampaign({ body_id: 1337 });

const res = await request({
uri: '/bodies/' + body.id + '/campaigns',
method: 'POST',
headers: { 'X-Auth-Token': token.value },
body: campaign
});

expect(res.statusCode).toEqual(403);
expect(res.body.success).toEqual(false);
expect(res.body).not.toHaveProperty('data');
expect(res.body).toHaveProperty('message');
});
});
56 changes: 54 additions & 2 deletions test/api/body-campaigns-deleting.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ describe('Body campaigns deleting', () => {
});

test('should return 404 if the campaign is not found', async () => {
const user = await generator.createUser();
const user = await generator.createUser({ superadmin: true });
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();

await generator.createPermission({ scope: 'global', action: 'delete', object: 'campaign' });

const res = await request({
uri: '/bodies/' + body.id + '/campaigns/1337',
method: 'DELETE',
Expand All @@ -34,11 +36,13 @@ describe('Body campaigns deleting', () => {
});

test('should fail for other body\'s campaign', async () => {
const user = await generator.createUser();
const user = await generator.createUser({ superadmin: true });
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();
const otherBody = await generator.createBody();

await generator.createPermission({ scope: 'global', action: 'delete', object: 'campaign' });

const campaign = await generator.createCampaign({ autojoin_body_id: otherBody.id });

const res = await request({
Expand All @@ -54,9 +58,38 @@ describe('Body campaigns deleting', () => {
});

test('should succeed if everything is okay', async () => {
const user = await generator.createUser({ superadmin: true });
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();

await generator.createPermission({ scope: 'global', action: 'delete', object: 'campaign' });

const campaign = await generator.createCampaign({ autojoin_body_id: body.id });

const res = await request({
uri: '/bodies/' + body.id + '/campaigns/' + campaign.id,
method: 'DELETE',
headers: { 'X-Auth-Token': token.value }
});

expect(res.statusCode).toEqual(200);
expect(res.body.success).toEqual(true);
expect(res.body).not.toHaveProperty('errors');
expect(res.body).toHaveProperty('message');

const campaignFromDb = await Campaign.findByPk(campaign.id);
expect(campaignFromDb).toEqual(null);
});

test('should succeed on local permission', async () => {
const user = await generator.createUser();
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();
const circle = await generator.createCircle({ body_id: body.id });
const permission = await generator.createPermission({ scope: 'local', action: 'delete', object: 'campaign' });

await generator.createCircleMembership(circle, user);
await generator.createCirclePermission(circle, permission);

const campaign = await generator.createCampaign({ autojoin_body_id: body.id });

Expand All @@ -74,4 +107,23 @@ describe('Body campaigns deleting', () => {
const campaignFromDb = await Campaign.findByPk(campaign.id);
expect(campaignFromDb).toEqual(null);
});

test('should fail if no permission', async () => {
const user = await generator.createUser();
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();

const campaign = await generator.createCampaign({ autojoin_body_id: body.id });

const res = await request({
uri: '/bodies/' + body.id + '/campaigns/' + campaign.id,
method: 'DELETE',
headers: { 'X-Auth-Token': token.value }
});

expect(res.statusCode).toEqual(403);
expect(res.body.success).toEqual(false);
expect(res.body).not.toHaveProperty('data');
expect(res.body).toHaveProperty('message');
});
});
50 changes: 48 additions & 2 deletions test/api/body-campaigns-details.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,13 @@ describe('Body campaign details', () => {
expect(res.body).not.toHaveProperty('data');
});

test('should find the campaign by id', async () => {
const user = await generator.createUser();
test('should succeed on global permission', async () => {
const user = await generator.createUser({ superadmin: true });
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();

await generator.createPermission({ scope: 'global', action: 'view', object: 'campaign' });

const campaign = await generator.createCampaign({ autojoin_body_id: body.id });

const res = await request({
Expand All @@ -88,4 +90,48 @@ describe('Body campaign details', () => {
expect(res.body).not.toHaveProperty('errors');
expect(res.body.data.id).toEqual(campaign.id);
});

test('should succeed on local permission', async () => {
const user = await generator.createUser({ superadmin: true });
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();
const circle = await generator.createCircle({ body_id: body.id });
const permission = await generator.createPermission({ scope: 'local', action: 'view', object: 'campaign' });

await generator.createCircleMembership(circle, user);
await generator.createCirclePermission(circle, permission);

const campaign = await generator.createCampaign({ autojoin_body_id: body.id });

const res = await request({
uri: '/bodies/' + body.id + '/campaigns/' + campaign.id,
method: 'GET',
headers: { 'X-Auth-Token': token.value }
});

expect(res.statusCode).toEqual(200);
expect(res.body.success).toEqual(true);
expect(res.body).toHaveProperty('data');
expect(res.body).not.toHaveProperty('errors');
expect(res.body.data.id).toEqual(campaign.id);
});

test('should fail if no permission', async () => {
const user = await generator.createUser({ superadmin: true });
const token = await generator.createAccessToken({}, user);
const body = await generator.createBody();

const campaign = await generator.createCampaign({ autojoin_body_id: body.id });

const res = await request({
uri: '/bodies/' + body.id + '/campaigns/' + campaign.id,
method: 'GET',
headers: { 'X-Auth-Token': token.value }
});

expect(res.statusCode).toEqual(403);
expect(res.body.success).toEqual(false);
expect(res.body).not.toHaveProperty('data');
expect(res.body).toHaveProperty('message');
});
});
Loading

0 comments on commit 5ba50c6

Please sign in to comment.