Skip to content

Commit

Permalink
[ENG-1037] - Added more user & group API endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
Phara0h committed Aug 20, 2019
1 parent 83de3fd commit 5cfc766
Show file tree
Hide file tree
Showing 7 changed files with 256 additions and 90 deletions.
14 changes: 11 additions & 3 deletions include/database/models/group.js
Expand Up @@ -49,22 +49,30 @@ class Group extends Base(BaseModel, 'groups', {
return await this.findLimtedBy({is_default: true}, 'AND', 1);
}

async addRoute(route) {
addRoute(route) {
if (!route.method) {
route.method = '*';
}
route.method = route.method.toUpperCase();

if (!route.name) {
route.name = (route.method == '*' ? 'all' : route.method) + route.route.replace(/\//g, '-');
route.name = route.method + route.route.replace(/\//g, '-');
}
route.name = route.name.toLowerCase();

if(!this.allowed || this.allowed.length <= 0) {
this.allowed = [];
}

for (var i = 0; i < this.allowed.length; i++) {
if(this.allowed[i].name == route.name || this.allowed[i].route == route.route) {
return false;
}
}

this.allowed.push(route);
this.allowed = [...this.allowed]
this.allowed = [...this.allowed]
return true;
}

}
Expand Down
164 changes: 119 additions & 45 deletions include/routes/v1/groups.js
@@ -1,83 +1,146 @@
'use strict';

const Group = require('../../database/models/group');
const regex = require('../../utils/regex');

var setGroup = function(req, group, router) {
var invalidGroup = false;

if (regex.safeName.exec(req.body.name)) {
group.name = req.body.name;
} else {
invalidGroup = {
type: 'group-name-error',
msg: 'Group name contain invaild characters.',
};
}

if (req.body.inherited) {
group.inherited = req.body.inherited.filter(Number);

if (group.inherited.some((val, i) => group.inherited.indexOf(val) !== i) || group.inherited.indexOf(group.id) > -1) {
invalidGroup = {
type: 'group-inherited-duplicate-id-error',
msg: 'Inherited groups array contain duplicate ids or its own id',
};
} else {
var groupIds = router.unmergedGroups.map(g=> g.id);

if (!group.inherited.every(id => groupIds.includes(id))) {
invalidGroup = {
type: 'group-inherited-invalid-ids-error',
msg: 'Inherited groups array contain ids that do not correspond to real groups',
};
}
}
}

if (regex.safeName.exec(req.body.type)) {
group.type = req.body.type;
} else {
invalidGroup = {
type: 'group-type-error',
msg: 'Group type contain invaild characters.',
};
}

if (req.body.is_default) {
group.is_default = Boolean(req.body.is_default);
}

if (req.body.allowed) {
group.allowed = [];
for (var i = 0; i < req.body.allowed.length; i++) {
if (!group.addRoute(req.body.allowed[i])) {
invalidGroup = {
type: 'group-route-duplicate-error',
msg: 'Duplicate Route with same route or name/permission',
};
break;
}
}
}

return {invalidGroup, group};
};

module.exports = function(app, opts, done) {
const router = opts.router;

// Add Group
app.put('/group', async (req, res) => {
if (!req.body.name) {
res.code(400).send(
{
type: 'error',
msg: 'A group requires a name',
});
} else if (req.body.id || req.body.name) {
} else if (req.body.id || regex.safeName.exec(req.body.name)) {
req.body.name = req.body.name.toLowerCase();
if(!req.body.type){
req.body.type = 'group';
if (!req.body.type) {
req.body.type = 'group';
}

var id = req.body.id ? {id: Number(req.body.id)} : {name: req.body.name};

var id = req.body.id ? {id: req.body.id} : {name: req.body.name};
var fgroup = await Group.findLimtedBy(id, 'AND', 1);

var group = await Group.findAllBy(id);

if (group.length > 0) {
if (fgroup.length > 0) {
res.code(400).send(
{
type: 'error',
msg: 'Group with the name or id already exists.',
});
} else {
var ngroup = await Group.create(req.body);
var {invalidGroup, group} = setGroup(req, new Group(req.body), router);

if (invalidGroup) {
res.code(400).send(invalidGroup);
} else {
var ngroup = await Group.create(group.changedProps);

res.code(200).send(ngroup);
// routing.needsGroupUpdate = true;
res.code(200).send(ngroup);
router.needsGroupUpdate = true;
}
}
} else {
res.code(400).send(
{
type: 'group-id-name-error',
msg: 'Group has invaild id or name set',
});
}
});

// Edit Group
app.put('/group/:groupname', async (req, res) => {
if (!req.params.groupname) {
res.code(400).send(
{
type: 'error',
type: 'group-no-name-error',
msg: 'A group requires a name',
});
} else {
var name = req.params.groupname.toLowerCase();
var group = await Group.findLimtedBy({name},'AND', 1);
var fgroup = await Group.findLimtedBy({name}, 'AND', 1);

if (group.length <= 0) {
if (fgroup.length <= 0) {
res.code(400).send(
{
type: 'error',
msg: 'No group with the name or id already exists.',
type: 'group-nonexistent-error',
msg: 'No group with the name or id exists.',
});
} else {
group = group[0];
if(req.body.name) {
group.name = req.body.name;
}
if(req.body.inherited) {
group.inherited = req.body.inherited;
}
if(req.body.type) {
group.type = req.body.type;
}
if(req.body.is_default) {
group.is_default = Boolean(req.body.is_default);
}
if(req.body.allowed) {
group.allowed = [];
for (var i = 0; i < req.body.allowed.length; i++) {
group.addRoute(req.body.allowed[i]);
}
}
await group.save();
var {invalidGroup, group} = setGroup(req, fgroup[0], router);

if (invalidGroup) {
res.code(400).send(invalidGroup);
} else {
await group.save();

res.code(200).send(group);
router.needsGroupUpdate = true;
res.code(200).send(group);
router.needsGroupUpdate = true;
}
}
}
});
Expand All @@ -91,7 +154,7 @@ module.exports = function(app, opts, done) {
});
} else {
var name = req.params.groupname.toLowerCase();
var group = await Group.findLimtedBy({name},'AND', 1);
var group = await Group.findLimtedBy({name}, 'AND', 1);

if (group.length <= 0) {
res.code(400).send(
Expand All @@ -102,20 +165,31 @@ module.exports = function(app, opts, done) {
} else {
group = group[0];

group.addRoute(req.body);
console.log(group)
await group.save();
console.log(group)
res.code(200).send(group);
router.needsGroupUpdate = true;
if (group.addRoute(req.body)) {
await group.save();
router.needsGroupUpdate = true;
res.code(200).send(group);
} else {
res.code(400).send({
type: 'error',
msg: 'Group already has that route or name/permission',
});
}
}
}
});


app.get('/groups', async (req, res) => {
res.send(await Group.findAll());
});

app.get('/groups/type/:type', async (req, res) => {
res.send(await Group.findAllBy({type:req.params.type}));
});

app.get('/groups/types', async (req, res) => {
res.send(Array.from(new Set(router.unmergedGroups.map(g=> g.type))));
});

done();
};
99 changes: 84 additions & 15 deletions include/routes/v1/users.js
@@ -1,21 +1,90 @@
const fp = require('fastify-plugin')
const regex = require('../../utils/regex');
const User = require('../../database/models/user');

module.exports = function (app, opts, done){
const router = opts.router;
module.exports = function(app, opts, done) {
const router = opts.router;

app.get('/user/me',(req, res) => {
res.send(req.session.user);
});
var getUser = async (req, res, resolveGroup = false) => {

app.get('/user/me/route/allowed', async (req, res) => {
var group = router.groups[req.session.user.group.name];
if (req.params.username && !regex.safeName.exec(req.params.username) || req.params.id && Number.isNaN(req.params.id)) {
res.code(400);
return {
type: 'user-find-by-error',
msg: 'No user by that username or id was found.',
};
}

res.send(req.session.user);
});
var id = req.params.username ? {username: req.params.username} : {id: req.params.id};
var user = await User.findLimtedBy(id, 'AND', 1);

app.get('/user/me/permission/allowed/:permission',(req, res) => {
var isAllowed = router.isPermissionAllowed(req.params.permission, router.currentGroup(req,res), req.session.user);
res.code(isAllowed ? 200 : 401).send();
});
done();
if (user && user.length > 0) {

if (resolveGroup) {
await user[0].resolveGroup();
}

if (req.params.prop && !user[0]._.hasOwnProperty(req.params.prop)) {
res.code(400);
return {
type: 'user-prop-error',
msg: 'Not a property of user',
};
}

res.code(200);
return req.params.prop ? user[0][req.params.prop] : user[0];
}

res.code(400);
return {
type: 'user-find-by-error',
msg: 'No user by that username or id was found.',
};
};

var getUserResolveGroup = async (req, res) => {
return await getUser(req, res, true);
};

app.get('/user/username/:username', getUser);
app.get('/user/username/:username/:prop', getUser);
app.get('/user/id/:id', getUser);
app.get('/user/id/:id/:prop', getUser);

app.get('/user/resolve/group/username/:username', getUserResolveGroup);
app.get('/user/resolve/group/username/:username/:prop', getUserResolveGroup);
app.get('/user/resolve/group/id/:id', getUserResolveGroup);
app.get('/user/resolve/group/id/:id/:prop', getUserResolveGroup);

app.get('/users', async (req, res) => {
res.send(await User.findAll());
});

app.get('/user/me', (req, res) => {
res.send(req.session.user);
});

app.get('/user/me/:prop', (req, res) => {
if (req.session.user._.hasOwnProperty(req.params.prop)) {
res.code(200).send(req.session.user._[req.params.prop]);
} else {
res.code(400).send({
type: 'user-prop-error',
msg: 'Not a property of user',
});
}
});

app.get('/user/me/route/allowed', async (req, res) => {
var isAllowed = router.isRouteAllowed(req.query.method, req.query.route, router.currentGroup(req, res), req.session.user);

res.code(isAllowed ? 200 : 401).send();
});

app.get('/user/me/permission/allowed/:permission', (req, res) => {
var isAllowed = router.isPermissionAllowed(req.params.permission, router.currentGroup(req, res), req.session.user);

res.code(isAllowed ? 200 : 401).send();
});
done();
};

0 comments on commit 5cfc766

Please sign in to comment.