mirror of
https://github.com/xfarrow/blink
synced 2025-02-18 08:20:36 +01:00
Following API best practices
This commit is contained in:
parent
4f53ef7561
commit
ae14f04949
File diff suppressed because one or more lines are too long
@ -1,8 +1,5 @@
|
|||||||
# APIs
|
# APIs
|
||||||
|
|
||||||
## Programming language
|
|
||||||
The Blink APIs are currently written in NodeJS only.
|
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
* PostgreSQL;
|
* PostgreSQL;
|
||||||
* NodeJS.
|
* NodeJS.
|
||||||
@ -16,3 +13,8 @@ In order to deploy the Blink APIs, follow these steps:
|
|||||||
You can test the APIs in two ways:
|
You can test the APIs in two ways:
|
||||||
* Open `BlinkApiUsageExample.json` with Insomnia or Bruno in order to have the collection of APIs already configured and ready to be seen in action;
|
* Open `BlinkApiUsageExample.json` with Insomnia or Bruno in order to have the collection of APIs already configured and ready to be seen in action;
|
||||||
* Run `npm test` in `./nodejs` to run a suite of automated tests.
|
* Run `npm test` in `./nodejs` to run a suite of automated tests.
|
||||||
|
|
||||||
|
## For Developers
|
||||||
|
The current implementation of the Blink APIs is written in NodeJS. Feel free to develop them in any other
|
||||||
|
programming language (you can paste the folder here) but make sure to make them compatible with one another
|
||||||
|
and please follow the API design [best practices](https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design)
|
||||||
|
@ -38,8 +38,9 @@ async function isPersonOrganizationAdministrator(personId, organizationId) {
|
|||||||
*/
|
*/
|
||||||
async function addOrganizationAdministrator(personId, organizationId, requester) {
|
async function addOrganizationAdministrator(personId, organizationId, requester) {
|
||||||
|
|
||||||
const isPersonAdmin = await organization_admin_model.isPersonAdmin(requester, organizationId);
|
const isRequesterAdmin = await isPersonOrganizationAdministrator(requester, organizationId);
|
||||||
if (isPersonAdmin) {
|
const isPersonAdmin = await isPersonOrganizationAdministrator(personId, organizationId);
|
||||||
|
if (isRequesterAdmin && !isPersonAdmin) {
|
||||||
await knex('OrganizationAdministrator')
|
await knex('OrganizationAdministrator')
|
||||||
.insert({
|
.insert({
|
||||||
id_person: personId,
|
id_person: personId,
|
||||||
|
@ -25,14 +25,14 @@ const jwtUtils = require('../utils/middleware_utils');
|
|||||||
*/
|
*/
|
||||||
async function addOrganizationAdmin(req, res) {
|
async function addOrganizationAdmin(req, res) {
|
||||||
// Ensure that the required fields are present before proceeding
|
// Ensure that the required fields are present before proceeding
|
||||||
if (!req.body.organization_id || !req.body.person_id) {
|
if (!req.params.id || !req.body.person_id) {
|
||||||
return res.status(400).json({
|
return res.status(400).json({
|
||||||
error: 'Invalid request'
|
error: 'Invalid request'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const success = await organizationAdminModel.addOrganizationAdministrator(req.body.person_id, req.body.organization_id, req.jwt.person_id);
|
const success = await organizationAdminModel.addOrganizationAdministrator(req.body.person_id, req.params.id, req.jwt.person_id);
|
||||||
if (success) {
|
if (success) {
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
success: true
|
success: true
|
||||||
@ -60,14 +60,14 @@ async function addOrganizationAdmin(req, res) {
|
|||||||
*/
|
*/
|
||||||
async function removeOrganizationAdmin(req, res) {
|
async function removeOrganizationAdmin(req, res) {
|
||||||
// Ensure that the required fields are present before proceeding
|
// Ensure that the required fields are present before proceeding
|
||||||
if (!req.body.organization_id) {
|
if (!req.params.organizationId) {
|
||||||
return res.status(400).json({
|
return res.status(400).json({
|
||||||
error: 'Invalid request'
|
error: 'Invalid request'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await organizationAdminModel.removeOrganizationAdmin(req.jwt.person_id, req.body.organization_id);
|
await organizationAdminModel.removeOrganizationAdmin(req.jwt.person_id, req.params.organizationId);
|
||||||
return res.status(200).json({
|
return res.status(200).json({
|
||||||
success: true
|
success: true
|
||||||
});
|
});
|
||||||
@ -81,8 +81,8 @@ async function removeOrganizationAdmin(req, res) {
|
|||||||
|
|
||||||
const protectedRoutes = express.Router();
|
const protectedRoutes = express.Router();
|
||||||
protectedRoutes.use(jwtUtils.verifyToken);
|
protectedRoutes.use(jwtUtils.verifyToken);
|
||||||
protectedRoutes.post('/organization/admin', addOrganizationAdmin);
|
protectedRoutes.post('/organizations/:id/admins', addOrganizationAdmin);
|
||||||
protectedRoutes.delete('/organization/admin', removeOrganizationAdmin);
|
protectedRoutes.delete('/organizations/:organizationId/admins/me', removeOrganizationAdmin);
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
protectedRoutes
|
protectedRoutes
|
||||||
|
@ -25,20 +25,25 @@ const jwtUtils = require('../utils/middleware_utils');
|
|||||||
*/
|
*/
|
||||||
async function createOrganizationPost(req, res) {
|
async function createOrganizationPost(req, res) {
|
||||||
// Ensure that the required fields are present before proceeding
|
// Ensure that the required fields are present before proceeding
|
||||||
if (!req.body.organization_id || !req.body.content) {
|
if (!req.params.idOrganization || !req.body.content) {
|
||||||
return res.status(400).json({
|
return res.status(400).json({
|
||||||
error: 'Invalid request'
|
error: 'Invalid request'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const organization = organizationPostModel.createOrganizationPost(
|
const organizationPost = organizationPostModel.createOrganizationPost(
|
||||||
req.body.organization_id,
|
req.params.idOrganization,
|
||||||
req.body.content,
|
req.body.content,
|
||||||
req.jwt.person_id);
|
req.jwt.person_id);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const insertedOrganization = await organizationPostModel.insertOrganizationPost(organization);
|
const insertedOrganization = await organizationPostModel.insertOrganizationPost(organizationPost);
|
||||||
return res.status(200).json(insertedOrganization);
|
if(!!insertedOrganization){
|
||||||
|
return res.status(200).json(insertedOrganization);
|
||||||
|
}
|
||||||
|
return res.status(401).json({
|
||||||
|
error: 'Forbidden'
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error in function ${createOrganizationPost.name}: ${error}`);
|
console.error(`Error in function ${createOrganizationPost.name}: ${error}`);
|
||||||
return res.status(500).json({
|
return res.status(500).json({
|
||||||
@ -78,8 +83,8 @@ async function deleteOrganizationPost(req, res) {
|
|||||||
|
|
||||||
const protectedRoutes = express.Router();
|
const protectedRoutes = express.Router();
|
||||||
protectedRoutes.use(jwtUtils.verifyToken);
|
protectedRoutes.use(jwtUtils.verifyToken);
|
||||||
protectedRoutes.post('/organization/post', createOrganizationPost);
|
protectedRoutes.post('/organizations/:idOrganization/posts', createOrganizationPost);
|
||||||
protectedRoutes.delete('/organization/post/:id', deleteOrganizationPost);
|
protectedRoutes.delete('/organizations/posts/:id', deleteOrganizationPost);
|
||||||
|
|
||||||
// Exporting a function
|
// Exporting a function
|
||||||
// means making a JavaScript function defined in one
|
// means making a JavaScript function defined in one
|
||||||
|
@ -147,13 +147,13 @@ async function getOrganization(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const publicRoutes = express.Router();
|
const publicRoutes = express.Router();
|
||||||
publicRoutes.get('/organization/:id', getOrganization);
|
publicRoutes.get('/organizations/:id', getOrganization);
|
||||||
|
|
||||||
const protectedRoutes = express.Router();
|
const protectedRoutes = express.Router();
|
||||||
protectedRoutes.use(jwtUtils.verifyToken);
|
protectedRoutes.use(jwtUtils.verifyToken);
|
||||||
protectedRoutes.post('/organization', createOrganization);
|
protectedRoutes.post('/organizations', createOrganization);
|
||||||
protectedRoutes.put('/organization/:id', updateOrganization);
|
protectedRoutes.put('/organizations/:id', updateOrganization);
|
||||||
protectedRoutes.delete('/organization/:id', deleteOrganization);
|
protectedRoutes.delete('/organizations/:id', deleteOrganization);
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
publicRoutes,
|
publicRoutes,
|
||||||
|
@ -92,7 +92,7 @@ async function registerPerson(req, res) {
|
|||||||
*
|
*
|
||||||
* @returns The token
|
* @returns The token
|
||||||
*/
|
*/
|
||||||
async function login(req, res) {
|
async function createTokenByEmailAndPassword(req, res) {
|
||||||
// Ensure that the required fields are present before proceeding
|
// Ensure that the required fields are present before proceeding
|
||||||
if (!req.body.email || !req.body.password) {
|
if (!req.body.email || !req.body.password) {
|
||||||
return res.status(400).json({
|
return res.status(400).json({
|
||||||
@ -113,7 +113,7 @@ async function login(req, res) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error in function ${login.name}: ${error}`);
|
console.error(`Error in function ${createTokenByEmailAndPassword.name}: ${error}`);
|
||||||
return res.status(500).json({
|
return res.status(500).json({
|
||||||
error: 'Internal server error'
|
error: 'Internal server error'
|
||||||
});
|
});
|
||||||
@ -312,16 +312,16 @@ async function confirmActivation(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const publicRoutes = express.Router(); // Routes not requiring token
|
const publicRoutes = express.Router(); // Routes not requiring token
|
||||||
publicRoutes.post('/register', registerPerson);
|
publicRoutes.post('/persons', registerPerson);
|
||||||
publicRoutes.post('/login', login);
|
publicRoutes.post('/persons/me/token', createTokenByEmailAndPassword);
|
||||||
publicRoutes.get('/person/:id/details', getPerson);
|
publicRoutes.get('/persons/:id/details', getPerson);
|
||||||
publicRoutes.get('/person/activation', confirmActivation);
|
publicRoutes.get('/persons/me/activation', confirmActivation);
|
||||||
|
|
||||||
const protectedRoutes = express.Router(); // Routes requiring token
|
const protectedRoutes = express.Router(); // Routes requiring token
|
||||||
protectedRoutes.use(jwtUtils.verifyToken);
|
protectedRoutes.use(jwtUtils.verifyToken);
|
||||||
protectedRoutes.get('/person/myself', getMyself);
|
protectedRoutes.get('/persons/me', getMyself);
|
||||||
protectedRoutes.put('/person', updatePerson);
|
protectedRoutes.put('/persons/me', updatePerson);
|
||||||
protectedRoutes.delete('/person', deletePerson);
|
protectedRoutes.delete('/persons/me', deletePerson);
|
||||||
|
|
||||||
// Exporting a function
|
// Exporting a function
|
||||||
// means making a JavaScript function defined in one
|
// means making a JavaScript function defined in one
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
alert('Please fill in all fields');
|
alert('Please fill in all fields');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const response = await fetch(`${API_URL}/login`, {
|
const response = await fetch(`${API_URL}/persons/me/token`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
email: email,
|
email: email,
|
||||||
@ -59,7 +59,7 @@
|
|||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
console.log(`Login was successful. Token is ${data.token}`);
|
console.log(`Login was successful. Token is ${data.token}`);
|
||||||
document.cookie = `token=${data.token};`;
|
document.cookie = `token=${data.token};`;
|
||||||
window.location.href = 'userprofile.html?id=myself';
|
window.location.href = 'userprofile.html?id=me';
|
||||||
} else {
|
} else {
|
||||||
alert(data.error);
|
alert(data.error);
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@
|
|||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
fetch(`${API_URL}/register`, options)
|
fetch(`${API_URL}/persons`, options)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
alert("Congratulations! You've successfully registered to Blink." +
|
alert("Congratulations! You've successfully registered to Blink." +
|
||||||
|
@ -58,21 +58,21 @@
|
|||||||
let response;
|
let response;
|
||||||
|
|
||||||
// Retrieving the logged in user's profile
|
// Retrieving the logged in user's profile
|
||||||
if (!idToDisplay || idToDisplay === 'myself') {
|
if (!idToDisplay || idToDisplay === 'me') {
|
||||||
document.getElementById('editBadge').style.display = 'block'; // show edit button
|
document.getElementById('editBadge').style.display = 'block'; // show edit button
|
||||||
const token = getCookie('token');
|
const token = getCookie('token');
|
||||||
// Check whether the token exists
|
// Check whether the token exists
|
||||||
if (!token) {
|
if (!token) {
|
||||||
window.location.href = 'login.html';
|
window.location.href = 'login.html';
|
||||||
}
|
}
|
||||||
response = await fetch(`${API_URL}/person/myself`, {
|
response = await fetch(`${API_URL}/persons/me`, {
|
||||||
headers: {
|
headers: {
|
||||||
"Content-type": "application/json; charset=UTF-8",
|
"Content-type": "application/json; charset=UTF-8",
|
||||||
"authorization": token
|
"authorization": token
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
response = await fetch(`${API_URL}/person/${idToDisplay}/details`, {
|
response = await fetch(`${API_URL}/persons/${idToDisplay}/details`, {
|
||||||
headers: {
|
headers: {
|
||||||
"Content-type": "application/json; charset=UTF-8",
|
"Content-type": "application/json; charset=UTF-8",
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user