Merge pull request #26 from Newtbot/Dev-branch

apimiddleware done?
This commit is contained in:
noot 2024-01-16 20:55:08 +08:00 committed by GitHub
commit e9409f8560
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 139 additions and 132 deletions

17
api.MD
View File

@ -1,7 +1,8 @@
//location //location
//get all //get all
curl localhost/api/v0/location curl localhost/api/v0/location
curl localhost/api/v0/location -H "Authorization: ${1a3eabe1-e1b2-46df-b846-585540c68368}" curl localhost/api/v0/location -H "Authorization: 1-1ec4ce9d-bcff-46c4-a023-c34171b9ca51"
curl localhost/api/v0/location -H "Authorization: 2-eb0c08b0-250a-4249-8a87-11141e2ff8fb"
//get id //get id
@ -10,18 +11,23 @@ curl http://localhost/api/v0/location/3
//post //post
curl localhost/api/v0/location/new -H "Content-Type: application/json" -X POST -d '{"name": "SAMPLE", "added_by": "system" , "description": "test"}' curl localhost/api/v0/location/new -H "Content-Type: application/json" -X POST -d '{"name": "SAMPLE", "added_by": "system" , "description": "test"}'
curl localhost/api/v0/location/new -H "Content-Type: application/json" -H "Authorization: 1-1ec4ce9d-bcff-46c4-a023-c34171b9ca51" -X POST -d '{"name": "SAMPLE", "added_by": "system", "description": "test"}'
curl localhost/api/v0/location/new -H "Content-Type: application/json" -H "Authorization: 2-eb0c08b0-250a-4249-8a87-11141e2ff8fb" -X POST -d '{"name": "SAMPLE", "added_by": "system", "description": "test"}'
status: 200 status: 200
added_name allowed: system , admin added_name allowed: system , admin
name allowed: shld contain alphanumeric only name allowed: shld contain alphanumeric only
//put //put
curl localhost/api/v0/location/update -X PUT -H "Content-Type: application/json" -d '{"id": "2" , "name": "test", "added_by": "noot", "description": "test12344444444"}' curl localhost/api/v0/location/update -X PUT -H "Content-Type: application/json" -H "Authorization: 1-1ec4ce9d-bcff-46c4-a023-c34171b9ca51" -d '{"id": "7", "name": "test", "added_by": "system", "description": "test12344444444"}'
status: 200 status: 200
"message": "Location 13 updated" "message": "Location 13 updated"
//delete //delete
curl localhost/api/v0/location/delete -X DELETE -H "Content-Type: application/json" -d '{"id": "6" }' curl localhost/api/v0/location/delete -X DELETE -H "Content-Type: application/json" -H "Authorization: 1-1ec4ce9d-bcff-46c4-a023-c34171b9ca51" -d '{"id": "7"}'
status: 200 status: 200
{ {
"message": "Location 13 deleted" "message": "Location 13 deleted"
@ -166,8 +172,9 @@ http://localhost/api/v0/sensor-data/data?week=1&sensorid=1&locationid=1&page=2&p
curl localhost/api/v0/user/new -H "Content-Type: application/json" -X POST -d '{"username": "system", "password": "thisisthesystemuserpasswordnoob", "email": "system@ecosaver.com", "address": "Nanyang Polytechnic 180 Ang Mo Kio Avenue 8 Singapore 569830", "phone": "12345678"}'
curl localhost/api/v0/user/new -H "Content-Type: application/json" -X POST -d '{"username": "testuser", "password": "thisisthesystemuserpasswordnoob", "email": "testuser@ecosaver.com", "address": "Nanyang Polytechnic 180 Ang Mo Kio Avenue 8 Singapore 569830", "phone": "12345678"}' curl localhost/api/v0/user/new -H "Content-Type: application/json" -X POST -d '{"username": "testuser", "password": "thisisthesystemuserpasswordnoob", "email": "testuser@ecosaver.com", "address": "Nanyang Polytechnic 180 Ang Mo Kio Avenue 8 Singapore 569830", "phone": "12345678"}'
curl localhost/api/v0/apikey/new -H "Content-Type: application/json" -X POST -d '{"userid": "2", "permission": "canRead"}'
curl localhost/api/v0/apikey/new -H "Content-Type: application/json" -X POST -d '{"userid": 1, "permission": "canWrite"'

View File

@ -3,7 +3,7 @@ const { Sequelize, DataTypes } = require("sequelize");
const { sequelize } = require("../mySQL"); const { sequelize } = require("../mySQL");
const { userModel } = require("./userModel"); const { userModel } = require("./userModel");
sequelize.sync(); //sequelize.sync();
const apikeyModel = sequelize.define( const apikeyModel = sequelize.define(
"apikey", "apikey",
{ {

View File

@ -6,7 +6,7 @@ const {
isAddress, isAddress,
} = require("../../functions/validateData"); } = require("../../functions/validateData");
sequelize.sync(); //sequelize.sync();
const userModel = sequelize.define( const userModel = sequelize.define(
"user", "user",
{ {

View File

@ -2,6 +2,8 @@ const { sequelize } = require("../database/mySql.js");
const { apikeyModel } = require("../database/model/apikeyModel.js"); const { apikeyModel } = require("../database/model/apikeyModel.js");
const { userModel } = require("../database/model/userModel.js"); const { userModel } = require("../database/model/userModel.js");
const { Op, Sequelize } = require("sequelize"); const { Op, Sequelize } = require("sequelize");
const { hashAPIKey } = require("../functions/bcrypt.js");
const { generateUUID } = require("../functions/generateUUID.js");
async function getUser() { async function getUser() {
const user = await userModel.findAll(); const user = await userModel.findAll();
@ -18,8 +20,34 @@ async function getAPIKey() {
return apikey; return apikey;
} }
async function addAPIKey(apikey) { /*
await apikeyModel.create(apikey); 1) take userid
2) generate random api key
3) hash the api key
4) append userid with - and api key
5) you give the user rowid-uuidv4
6) store in database
*/
async function addAPIKey(userId, permission) {
let token = await generateUUID();
let usertoken = userId + "-" + token;
let apikey = await hashAPIKey(token);
console.log(token);
console.log(apikey);
await apikeyModel.create({
userid: userId,
apikey: apikey,
permission: permission
});
//user token with -
//"apikey": "1-9beba05f-1bf1-4d8a-9ee8-9f61e1428e20"
return usertoken;
} }
module.exports = { module.exports = {

View File

@ -1,6 +1,5 @@
const { getAPIKey , addAPIKey } = require("../functions/apiDatabase.js"); const { getAPIKey , addAPIKey } = require("../functions/apiDatabase.js");
const { hashAPIKey } = require("../functions/bcrypt.js");
const { generateUUID } = require("../functions/generateUUID.js");
const express = require("express"); const express = require("express");
const router = express.Router(); const router = express.Router();
@ -17,21 +16,18 @@ router.get("/", async (req, res, next) => {
/* /*
1) ensure user is logged in (frontend session validation blah or wtv) 1) ensure user is logged in (frontend session validation blah or wtv)
2) when user click on generate api key button, it will generate a random api key 2) when user click on generate api key button, it will generate a random api key. how to get userid can be done by session or wtv
3) hash the api key 3) hash the api key
4) store the api key in database 4) store the api key in database
*/ */
router.post("/new", async (req, res, next) => { router.post("/new", async (req, res, next) => {
try { try {
let uuid = await generateUUID() //curl localhost/api/v0/apikey/new -H "Content-Type: application/json" -X POST -d
//attach uuid to req.body //'{"userid": 1, "permission": "canWrite"}'
req.body.apikey = uuid const apikey = await addAPIKey(req.body.userid, req.body.permission);
//hash apikey //console.log(typeof req.body.userid);
req.body.apikey = await hashAPIKey(req.body.apikey) //console.log(typeof req.body.permission);
res.json({apikey: apikey});
await addAPIKey(req.body);
res.sendStatus(200);
} catch (error) { } catch (error) {
console.error(error); console.error(error);
next(error); next(error);
@ -44,26 +40,3 @@ router.post("/new", async (req, res, next) => {
module.exports = router; module.exports = router;
/*
async function addAPIKey(userId) {
let apikey = await generateUUID()
apikey = await hashAPIKey(req.body.apikey)
let token = await apikeyModel.create({apikey, userId});
return `${token.id}-${apikey}`
}
router.post("/new", async (req, res, next) => {
try {
let apikey = await addAPIKey(req.body.userid)
res.json({apiKey: apikey})
} catch (error) {
console.error(error);
next(error);
}
});
*/

View File

@ -2,9 +2,10 @@ const { sequelize } = require("../Database/mySql.js");
const { api_log_Model } = require("../Database/model/apiLogModel.js"); const { api_log_Model } = require("../Database/model/apiLogModel.js");
const { sensorDataModel } = require("../Database/model/sensorDataModel.js"); const { sensorDataModel } = require("../Database/model/sensorDataModel.js");
const { apikeyModel } = require("../Database/model/apiKeyModel.js"); const { apikeyModel } = require("../Database/model/apiKeyModel.js");
const { compareAPIKey } = require("../functions/bcrypt.js");
async function insertLogData(log){ async function insertLogData(log) {
try{ try {
api_log_Model.create({ api_log_Model.create({
ip: log.ip, ip: log.ip,
time: log.time, time: log.time,
@ -15,9 +16,7 @@ async function insertLogData(log){
referrer: log.referrer, referrer: log.referrer,
userAgent: log.userAgent, userAgent: log.userAgent,
}); });
} } catch (error) {
catch
(error){
console.error(error); console.error(error);
} }
} }
@ -29,25 +28,28 @@ async function insertDatatoDB(data) {
locationid: data.locationid, locationid: data.locationid,
measurement: data.measurement, measurement: data.measurement,
}); });
} } catch (error) {
catch (error) {
console.error(error); console.error(error);
} }
} }
async function checkAPikey(unverified){ async function checkAPikey(SuppliedKey, rowid) {
const apikey = apikeyModel.findOne({ try {
const retrivedKey = await apikeyModel.findOne({
raw: true,
attributes: ["apikey" , "permission"],
where: { where: {
apikey: unverified userid: rowid,
} },
}); });
return apikey; //console.log(retrivedKey.apikey);
if (compareAPIKey(SuppliedKey, retrivedKey.apikey)) {
//return true;
return retrivedKey.permission;
}
} catch (error) {
console.error(error);
}
} }
module.exports = { insertLogData , insertDatatoDB , checkAPikey}; module.exports = { insertLogData, insertDatatoDB, checkAPikey };

View File

@ -1,17 +1,35 @@
const { compareAPIKey } = require('../functions/bcrypt.js');
const { checkAPikey } = require('../functions/database.js'); const { checkAPikey } = require('../functions/database.js');
async function apikeyCheck(req, res, next) { async function apikeyCheck(req, res, next) {
//const authHeader = req.headers.authorization //const authHeader = req.headers.authorization
try{ try{
let apikey = req.headers.authorization let apikey = req.headers.authorization
if(!apikey){ if(!apikey){
throw new Error('NotAuthed') throw new Error('No API key was supplied. Invalid request')
} }
else{ else{
//compare apikey to db //split the string by the -
let splitAPIkey = apikey.split('-');
let rowid = splitAPIkey[0];
//rejoin withouth the rowid
let SuppliedKey = splitAPIkey.slice(1).join('-');
if (checkAPikey(SuppliedKey , rowid))
{
//get permission
let permission = await checkAPikey(SuppliedKey , rowid);
console.log(permission);
if (req.method === 'GET' && permission === 'canRead'){
return next()
}
//['POST', 'PUT', 'PATCH', 'DELETE'].includes(req.method)
if (["GET" , "POST" , "PUT" , "DELETE"].includes(req.method) && permission === 'canWrite'){
console.log('write')
return next()
}
throw new Error('Your API key does not have the correct permissions to access this resource')
} }
next() }
}catch(error){ }catch(error){
next(error); next(error);
} }
@ -21,13 +39,15 @@ async function apikeyCheck(req, res, next) {
module.exports = { apikeyCheck }; module.exports = { apikeyCheck };
/* /*
1) take user supplied api key //web server microservice
2) hash and salt 1) take user supplied rowid-apikey
3) compare to stored hash and salt in db 2) split the string by -
4) if match, check permissions 3) get the rowid
5) if permissions allow, continue 4) get the apikey
6) else throw error 5) compare the apikey with the one in database
6) if match, return true
*/ */
/* /*
I plan to seed some data in user and api I plan to seed some data in user and api
@ -36,27 +56,4 @@ If it's correct API key and has canWrite perms
I allow it to access put and post I allow it to access put and post
async function auth(req, res, next){
try{
let token = // get token
req.token = token
if(req.method === 'GET' && token.canRead){
return next()
}
if(req.method === 'POST' && token.canWrite){
return next()
}
throw new Error('NotAuthed')
}catch(error){
next(error);
}
}
*/ */