diff --git a/api.MD b/api.MD index 3520775..a875492 100644 --- a/api.MD +++ b/api.MD @@ -1,7 +1,8 @@ //location //get all 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 @@ -10,18 +11,23 @@ curl http://localhost/api/v0/location/3 //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" -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 added_name allowed: system , admin name allowed: shld contain alphanumeric only //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 "message": "Location 13 updated" //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 { "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/apikey/new -H "Content-Type: application/json" -X POST -d '{"userid": 1, "permission": "canWrite"' +curl localhost/api/v0/apikey/new -H "Content-Type: application/json" -X POST -d '{"userid": "2", "permission": "canRead"}' diff --git a/consumerWebsite/database/model/apiKeyModel.js b/consumerWebsite/database/model/apiKeyModel.js index b481881..03bcb95 100644 --- a/consumerWebsite/database/model/apiKeyModel.js +++ b/consumerWebsite/database/model/apiKeyModel.js @@ -3,7 +3,7 @@ const { Sequelize, DataTypes } = require("sequelize"); const { sequelize } = require("../mySQL"); const { userModel } = require("./userModel"); -sequelize.sync(); +//sequelize.sync(); const apikeyModel = sequelize.define( "apikey", { diff --git a/consumerWebsite/database/model/userModel.js b/consumerWebsite/database/model/userModel.js index f9b3fee..561890c 100644 --- a/consumerWebsite/database/model/userModel.js +++ b/consumerWebsite/database/model/userModel.js @@ -6,7 +6,7 @@ const { isAddress, } = require("../../functions/validateData"); -sequelize.sync(); +//sequelize.sync(); const userModel = sequelize.define( "user", { diff --git a/consumerWebsite/functions/apiDatabase.js b/consumerWebsite/functions/apiDatabase.js index 859d110..71a1c2f 100644 --- a/consumerWebsite/functions/apiDatabase.js +++ b/consumerWebsite/functions/apiDatabase.js @@ -1,30 +1,58 @@ -const { sequelize } = require("../database/mySql.js"); +const { sequelize } = require("../database/mySql.js"); const { apikeyModel } = require("../database/model/apikeyModel.js"); const { userModel } = require("../database/model/userModel.js"); const { Op, Sequelize } = require("sequelize"); +const { hashAPIKey } = require("../functions/bcrypt.js"); +const { generateUUID } = require("../functions/generateUUID.js"); async function getUser() { - const user = await userModel.findAll(); - return user; + const user = await userModel.findAll(); + return user; } async function addUser(user) { - //console.log(user); - await userModel.create(user); + //console.log(user); + await userModel.create(user); } async function getAPIKey() { - const apikey = await apikeyModel.findAll(); - return apikey; + const apikey = await apikeyModel.findAll(); + 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 = { - getUser, - addUser, - getAPIKey, - addAPIKey, + getUser, + addUser, + getAPIKey, + addAPIKey, }; diff --git a/consumerWebsite/routes/apikey.js b/consumerWebsite/routes/apikey.js index 48df481..3ee6c43 100644 --- a/consumerWebsite/routes/apikey.js +++ b/consumerWebsite/routes/apikey.js @@ -1,6 +1,5 @@ const { getAPIKey , addAPIKey } = require("../functions/apiDatabase.js"); -const { hashAPIKey } = require("../functions/bcrypt.js"); -const { generateUUID } = require("../functions/generateUUID.js"); + const express = require("express"); 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) -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 4) store the api key in database */ router.post("/new", async (req, res, next) => { try { - let uuid = await generateUUID() - //attach uuid to req.body - req.body.apikey = uuid - //hash apikey - req.body.apikey = await hashAPIKey(req.body.apikey) - - await addAPIKey(req.body); - res.sendStatus(200); - + //curl localhost/api/v0/apikey/new -H "Content-Type: application/json" -X POST -d + //'{"userid": 1, "permission": "canWrite"}' + const apikey = await addAPIKey(req.body.userid, req.body.permission); + //console.log(typeof req.body.userid); + //console.log(typeof req.body.permission); + res.json({apikey: apikey}); } catch (error) { console.error(error); next(error); @@ -44,26 +40,3 @@ router.post("/new", async (req, res, next) => { 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); - } -}); - - -*/ \ No newline at end of file diff --git a/webserver/functions/Database.js b/webserver/functions/Database.js index 255c15d..2c73813 100644 --- a/webserver/functions/Database.js +++ b/webserver/functions/Database.js @@ -1,53 +1,55 @@ -const { sequelize } = require("../Database/mySql.js"); -const { api_log_Model } = require("../Database/model/apiLogModel.js"); +const { sequelize } = require("../Database/mySql.js"); +const { api_log_Model } = require("../Database/model/apiLogModel.js"); const { sensorDataModel } = require("../Database/model/sensorDataModel.js"); const { apikeyModel } = require("../Database/model/apiKeyModel.js"); +const { compareAPIKey } = require("../functions/bcrypt.js"); -async function insertLogData(log){ - try{ - api_log_Model.create({ - ip: log.ip, - time: log.time, - method: log.method, - host: log.host, - statusCode: log.statusCode, - Responsesize: log.Responsesize, - referrer: log.referrer, - userAgent: log.userAgent, - }); - } - catch - (error){ - console.error(error); - } +async function insertLogData(log) { + try { + api_log_Model.create({ + ip: log.ip, + time: log.time, + method: log.method, + host: log.host, + statusCode: log.statusCode, + Responsesize: log.Responsesize, + referrer: log.referrer, + userAgent: log.userAgent, + }); + } catch (error) { + console.error(error); + } } async function insertDatatoDB(data) { - try { - sensorDataModel.create({ - sensorid: data.sensorid, - locationid: data.locationid, - measurement: data.measurement, - }); - } - catch (error) { - console.error(error); - } + try { + sensorDataModel.create({ + sensorid: data.sensorid, + locationid: data.locationid, + measurement: data.measurement, + }); + } catch (error) { + console.error(error); + } } -async function checkAPikey(unverified){ - const apikey = apikeyModel.findOne({ - where: { - apikey: unverified - } - }); - return apikey; - +async function checkAPikey(SuppliedKey, rowid) { + try { + const retrivedKey = await apikeyModel.findOne({ + raw: true, + attributes: ["apikey" , "permission"], + where: { + userid: rowid, + }, + }); + //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 }; diff --git a/webserver/middleware/apiKey.js b/webserver/middleware/apiKey.js index 28aca0c..150d8c1 100644 --- a/webserver/middleware/apiKey.js +++ b/webserver/middleware/apiKey.js @@ -1,17 +1,35 @@ -const { compareAPIKey } = require('../functions/bcrypt.js'); const { checkAPikey } = require('../functions/database.js'); async function apikeyCheck(req, res, next) { //const authHeader = req.headers.authorization try{ let apikey = req.headers.authorization if(!apikey){ - throw new Error('NotAuthed') + throw new Error('No API key was supplied. Invalid request') } 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){ next(error); } @@ -21,13 +39,15 @@ async function apikeyCheck(req, res, next) { module.exports = { apikeyCheck }; /* -1) take user supplied api key -2) hash and salt -3) compare to stored hash and salt in db -4) if match, check permissions -5) if permissions allow, continue -6) else throw error +//web server microservice +1) take user supplied rowid-apikey +2) split the string by - +3) get the rowid +4) get the apikey +5) compare the apikey with the one in database +6) if match, return true */ + /* 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 -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); - } -} - - - */ \ No newline at end of file