Skip to content

Commit

Permalink
feat(campaigns): list campaign members
Browse files Browse the repository at this point in the history
  • Loading branch information
serge1peshcoff committed May 3, 2020
1 parent c6d88df commit 2384274
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 1 deletion.
1 change: 1 addition & 0 deletions lib/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ PermissionsRouter.delete('/', permissions.deletePermission);

// Everything related to a specific campaign. Auth only.
CampaignsRouter.use(middlewares.maybeAuthorize, middlewares.ensureAuthorized, fetch.fetchCampaign);
CampaignsRouter.get('/members', campaigns.listCampaignMembers);
CampaignsRouter.get('/', campaigns.getCampaign);
CampaignsRouter.put('/', campaigns.updateCampaign);
CampaignsRouter.delete('/', campaigns.deleteCampaign);
Expand Down
21 changes: 21 additions & 0 deletions middlewares/campaigns.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,24 @@ exports.deleteCampaign = async (req, res) => {
message: 'Campaign is deleted.'
});
};

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

const result = await User.findAndCountAll({
where: {
...helpers.filterBy(req.query.query, constants.FIELDS_TO_QUERY.MEMBER),
campaign_id: req.currentCampaign.id
},
...helpers.getPagination(req.query),
order: helpers.getSorting(req.query)
});

return res.json({
success: true,
data: result.rows,
meta: { count: result.count }
});
};
120 changes: 120 additions & 0 deletions test/api/campaigns-members.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
const { startServer, stopServer } = require('../../lib/server.js');
const { request } = require('../scripts/helpers');
const generator = require('../scripts/generator');

describe('Campaign users list', () => {
beforeAll(async () => {
await startServer();
});

afterAll(async () => {
await stopServer();
});

afterEach(async () => {
await generator.clearAll();
});

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

const campaign = await generator.createCampaign();

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

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

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

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

const campaign = await generator.createCampaign();
const otherUser = await generator.createUser({ campaign_id: campaign.id });

const res = await request({
uri: '/campaigns/' + campaign.id + '/members',
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.length).toEqual(1);
expect(res.body.data[0].id).toEqual(otherUser.id);
});

test('should respect limit and offset', async () => {
const user = await generator.createUser({ superadmin: true });
const token = await generator.createAccessToken({}, user);

const campaign = await generator.createCampaign();

await generator.createUser({ campaign_id: campaign.id });
const member = await generator.createUser({ campaign_id: campaign.id });

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

const res = await request({
uri: '/campaigns/' + campaign.id + '/members?limit=1&offset=1', // second one should be returned
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).toHaveProperty('meta');
expect(res.body).not.toHaveProperty('errors');

expect(res.body.data.length).toEqual(1);
expect(res.body.data[0].id).toEqual(member.id);

expect(res.body.meta.count).toEqual(2);
});

test('should respect sorting', async () => {
const campaign = await generator.createCampaign();

const firstUser = await generator.createUser({
first_name: 'aaa',
mail_confirmed_at: new Date(),
superadmin: true,
campaign_id: campaign.id
});
const token = await generator.createAccessToken({}, firstUser);

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

const secondUser = await generator.createUser({ first_name: 'bbb', campaign_id: campaign.id });

const res = await request({
uri: '/campaigns/' + campaign.id + '/members?sort=first_name&direction=desc', // second one should be returned
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).toHaveProperty('meta');
expect(res.body).not.toHaveProperty('errors');

expect(res.body.data.length).toEqual(2);
expect(res.body.data[0].id).toEqual(secondUser.id);
expect(res.body.data[1].id).toEqual(firstUser.id);
});
});
2 changes: 1 addition & 1 deletion test/api/users-listing.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe('Users list', () => {
await generator.clearAll();
});

test('should succeed when everything is okay', async () => {
test('should fail if no permission', async () => {
const user = await generator.createUser();
const token = await generator.createAccessToken({}, user);

Expand Down

0 comments on commit 2384274

Please sign in to comment.