Adding API and adjusting admin view

This commit is contained in:
Fabian Stamm 2020-03-18 14:41:22 +01:00
parent 112a65378d
commit 315cbb6bf5
3 changed files with 180 additions and 51 deletions

View File

@ -24,14 +24,16 @@ PermissionRoute.route("/")
* @apiSuccess {String} permissions.description A description, that makes it clear to the user, what this Permission allows to do * @apiSuccess {String} permissions.description A description, that makes it clear to the user, what this Permission allows to do
* @apiSuccess {String} permissions.client The ID of the owning client * @apiSuccess {String} permissions.client The ID of the owning client
*/ */
.get(promiseMiddleware(async (req, res) => { .get(
let query = {}; promiseMiddleware(async (req, res) => {
if (req.query.client) { let query = {};
query = { client: new ObjectID(req.query.client) } if (req.query.client) {
} query = { client: new ObjectID(req.query.client) };
let permission = await Permission.find(query); }
res.json(permission); let permissions = await Permission.find(query);
})) res.json(permissions);
})
)
/** /**
* @api {post} /admin/permission * @api {post} /admin/permission
* @apiName AdminAddPermission * @apiName AdminAddPermission
@ -48,30 +50,45 @@ PermissionRoute.route("/")
* @apiSuccess {String} permissions.name Permission name * @apiSuccess {String} permissions.name Permission name
* @apiSuccess {String} permissions.description A description, that makes it clear to the user, what this Permission allows to do * @apiSuccess {String} permissions.description A description, that makes it clear to the user, what this Permission allows to do
* @apiSuccess {String} permissions.client The ID of the owning client * @apiSuccess {String} permissions.client The ID of the owning client
* @apiSuccess {String} permissions.grant_type The type of the permission. "user" | "client" granted
*/ */
.post(verify({ .post(
client: { verify(
type: Types.STRING {
}, client: {
name: { type: Types.STRING
type: Types.STRING },
}, name: {
description: { type: Types.STRING
type: Types.STRING },
} description: {
}, true), promiseMiddleware(async (req, res) => { type: Types.STRING
let client = await Client.findById(req.body.client); },
if (!client) { type: {
throw new RequestError("Client not found", HttpStatusCode.BAD_REQUEST); type: Types.ENUM,
} values: ["user", "client"]
let permission = Permission.new({ }
description: req.body.description, },
name: req.body.name, true
client: client._id ),
}); promiseMiddleware(async (req, res) => {
await Permission.save(permission); let client = await Client.findById(req.body.client);
res.json(permission); if (!client) {
})) throw new RequestError(
"Client not found",
HttpStatusCode.BAD_REQUEST
);
}
let permission = Permission.new({
description: req.body.description,
name: req.body.name,
client: client._id,
grant_type: req.body.type
});
await Permission.save(permission);
res.json(permission);
})
)
/** /**
* @api {delete} /admin/permission * @api {delete} /admin/permission
* @apiName AdminDeletePermission * @apiName AdminDeletePermission
@ -83,10 +100,12 @@ PermissionRoute.route("/")
* *
* @apiSuccess {Boolean} success * @apiSuccess {Boolean} success
*/ */
.delete(promiseMiddleware(async (req, res) => { .delete(
let { id } = req.query; promiseMiddleware(async (req, res) => {
await Permission.delete(id); let { id } = req.query;
res.json({ success: true }); await Permission.delete(id);
})); res.json({ success: true });
})
);
export default PermissionRoute; export default PermissionRoute;

View File

@ -0,0 +1,98 @@
import { Request, Response } from "express";
import Stacker from "../middlewares/stacker";
import {
ClientAuthMiddleware,
GetClientAuthMiddleware
} from "../middlewares/client";
import Permission from "../../models/permissions";
import User from "../../models/user";
import RequestError, { HttpStatusCode } from "../../helper/request_error";
import Grant from "../../models/grants";
import { ObjectID } from "mongodb";
export const GetPermissions = Stacker(
GetClientAuthMiddleware(true),
async (req: Request, res: Response) => {
const { user, permission } = req.query;
let permissions: { id: string; name: string; description: string }[];
let users: string[];
if (user) {
const grant = await Grant.findOne({
client: req.client._id,
user: user
});
permissions = await Promise.all(
grant.permissions.map(perm => Permission.findById(perm))
).then(res =>
res
.filter(e => e.grant_type === "client")
.map(e => {
return {
id: e._id.toHexString(),
name: e.name,
description: e.description
};
})
);
}
if (permission) {
const grants = await Grant.find({
client: req.client._id,
permissions: new ObjectID(permission)
});
users = grants.map(grant => grant.user.toHexString());
}
res.json({ permissions, users });
}
);
export const PostPermissions = Stacker(
GetClientAuthMiddleware(true),
async (req: Request, res: Response) => {
const { permission, uid } = req.body;
const user = await User.findOne({ uid });
if (!user) {
throw new RequestError("User not found!", HttpStatusCode.BAD_REQUEST);
}
const permissionDoc = await Permission.findById(permission);
if (!permissionDoc || !permissionDoc.client.equals(req.client._id)) {
throw new RequestError(
"Permission not found!",
HttpStatusCode.BAD_REQUEST
);
}
let grant = await Grant.findOne({
client: req.client._id,
user: req.user._id
});
if (!grant) {
grant = Grant.new({
client: req.client._id,
user: req.user._id,
permissions: []
});
}
//TODO: Fix clients getting user data without consent, when a grant is created and no additional permissions are requested, since for now, it is only checked for grant existance to make client access user data
if (grant.permissions.indexOf(permission) < 0)
grant.permissions.push(permission);
await Grant.save(grant);
res.json({
success: true
});
}
);

View File

@ -7,8 +7,10 @@
<meta name="viewport" content="width=device-width,initial-scale=1" /> <meta name="viewport" content="width=device-width,initial-scale=1" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" type="text/javascript"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" type="text/javascript"></script>
<script src="https://unpkg.com/popper.js@1.12.6/dist/umd/popper.js" type="text/javascript"></script> <script src="https://unpkg.com/popper.js@1.12.6/dist/umd/popper.js" type="text/javascript"></script>
<script src="https://unpkg.com/bootstrap-material-design@4.1.1/dist/js/bootstrap-material-design.js" type="text/javascript"></script> <script src="https://unpkg.com/bootstrap-material-design@4.1.1/dist/js/bootstrap-material-design.js"
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.11/handlebars.min.js" type="text/javascript"></script> type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.11/handlebars.min.js"
type="text/javascript"></script>
<script> <script>
$(document).ready(() => $('body').bootstrapMaterialDesign()) $(document).ready(() => $('body').bootstrapMaterialDesign())
</script> </script>
@ -251,6 +253,7 @@
<th scope="col">ID</th> <th scope="col">ID</th>
<th scope="col">Name</th> <th scope="col">Name</th>
<th scope="col">Description</th> <th scope="col">Description</th>
<th scope="col" style="width: 10ch">Type</th>
<th scope="col" style="width: 2.5rem"></th> <th scope="col" style="width: 2.5rem"></th>
</tr> </tr>
</thead> </thead>
@ -260,6 +263,7 @@
<td>\{{ _id }}</td> <td>\{{ _id }}</td>
<td>\{{ name }}</td> <td>\{{ name }}</td>
<td>\{{ description }}</td> <td>\{{ description }}</td>
<td>\{{ grant_type }}</td>
<td style="padding: 0.25em"> <td style="padding: 0.25em">
<button style="border: 0; background-color: rgba(0, 0, 0, 0); padding: 0; text-align: center;" onclick="deletePermission('\{{_id}}')"> <button style="border: 0; background-color: rgba(0, 0, 0, 0); padding: 0; text-align: center;" onclick="deletePermission('\{{_id}}')">
<i class="material-icons" style="font-size: 2rem; display: inline"> <i class="material-icons" style="font-size: 2rem; display: inline">
@ -280,8 +284,16 @@
<input type="text" class="form-control" id="name_input" name=name value=""> <input type="text" class="form-control" id="name_input" name=name value="">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for=name class="bmd-label-floating">Description</label> <label for=description class="bmd-label-floating">Description</label>
<input type="text" class="form-control" id=name name=description value=""> <input type="text" class="form-control" id=description name=description value="">
</div>
<div class="form-group">
<label for=type class="bmd-label-floating">Type</label>
<select type="text" class="form-control" id=type name=type>
<option value="user">User granted</option>
<option value="client">Client granted</option>
</select>
</div> </div>
<span class="form-group bmd-form-group"> <span class="form-group bmd-form-group">
<!-- needed to match padding for floating labels --> <!-- needed to match padding for floating labels -->