Merge branch 'main' into new
This commit is contained in:
commit
5d39c6d43f
2
api.MD
2
api.MD
@ -174,4 +174,4 @@ http://localhost/api/v0/sensor-data/data?week=1&sensorid=1&locationid=1&page=2&p
|
|||||||
curl localhost/api/v0/user/register -H "Content-Type: application/json" -X POST -d '{"username": "testuser123", "password": "thisisthesystemuserpasswordnoob", "email": "testuser123@ecosaver.com", "address": "Nanyang Polytechnic 180 Ang Mo Kio Avenue 8 Singapore 569830", "phone": "12345678"}'
|
curl localhost/api/v0/user/register -H "Content-Type: application/json" -X POST -d '{"username": "testuser123", "password": "thisisthesystemuserpasswordnoob", "email": "testuser123@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": "5", "permission": "canRead"}'
|
||||||
|
@ -61,6 +61,7 @@ const apikeyModel = sequelize.define(
|
|||||||
timestamps: true,
|
timestamps: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
apikeyModel.belongsTo(userModel);
|
||||||
|
|
||||||
module.exports = { apikeyModel };
|
module.exports = { apikeyModel };
|
||||||
|
|
||||||
|
@ -19,6 +19,26 @@ const userModel = sequelize.define(
|
|||||||
isNumeric: true,
|
isNumeric: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
firstname: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
length: 60,
|
||||||
|
validate: {
|
||||||
|
notEmpty: true,
|
||||||
|
len: [1, 60],
|
||||||
|
isAlpha: true, // will only allow letters
|
||||||
|
},
|
||||||
|
},
|
||||||
|
lastname: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
allowNull: false,
|
||||||
|
length: 60,
|
||||||
|
validate: {
|
||||||
|
notEmpty: true,
|
||||||
|
len: [1, 60],
|
||||||
|
isAlpha: true, // will only allow letters
|
||||||
|
},
|
||||||
|
},
|
||||||
username: {
|
username: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING,
|
||||||
allowNull: false,
|
allowNull: false,
|
||||||
|
@ -3,45 +3,58 @@ 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 { generateUUID } = require("../functions/generateUUID.js");
|
const { generateUUID } = require("../functions/generateUUID.js");
|
||||||
const { hashPassword , comparePassword , hashAPIKey } = require("../functions/bcrypt.js");
|
const {
|
||||||
|
hashPassword,
|
||||||
|
comparePassword,
|
||||||
|
hashAPIKey,
|
||||||
|
} = require("../functions/bcrypt.js");
|
||||||
|
|
||||||
//helper function
|
//getuser
|
||||||
|
//api/v0/user/me
|
||||||
|
async function getUserID(userid) {
|
||||||
|
//console.log(userid);
|
||||||
|
//console.log(userid.id);
|
||||||
|
let userRes = await userModel.findByPk(userid.id, {
|
||||||
|
attributes: {
|
||||||
|
exclude: ["password"],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!userRes) return false;
|
||||||
|
return userRes;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//api/v0/user/register
|
|
||||||
|
|
||||||
|
|
||||||
|
//api/v0/auth/register
|
||||||
/* Registering new user
|
/* Registering new user
|
||||||
1) req.body is taken from html form or wtv
|
1) req.body is taken from html form or wtv
|
||||||
2) bcrpyt and hash the password on the server side
|
2) bcrpyt and hash the password on the server side
|
||||||
3) pass to db
|
3) pass to db
|
||||||
*/
|
*/
|
||||||
async function addUser(user) {
|
async function addUser(user) {
|
||||||
console.log(user);
|
|
||||||
//hash password
|
//hash password
|
||||||
let hash = await hashPassword(user.password);
|
let hash = await hashPassword(user.password);
|
||||||
|
|
||||||
const addRes = await userModel.create({
|
const addRes = await userModel.create({
|
||||||
|
firstname: user.firstname,
|
||||||
|
lastname: user.lastname,
|
||||||
username: user.username,
|
username: user.username,
|
||||||
password: hash,
|
password: hash,
|
||||||
email: user.email,
|
email: user.email,
|
||||||
address: user.address,
|
address: user.address,
|
||||||
phone: user.phone,
|
phone: user.phone,
|
||||||
});
|
});
|
||||||
if (addRes){
|
if (addRes) {
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
else{
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//add token to db
|
|
||||||
async function addToken(userid , token) {
|
|
||||||
console.log(userid);
|
|
||||||
console.log(token);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//api/v0/auth/login
|
||||||
async function loginUser(user) {
|
async function loginUser(user) {
|
||||||
//look up username or email in db
|
//look up username or email in db
|
||||||
const userRes = await userModel.findOne({
|
const userRes = await userModel.findOne({
|
||||||
@ -55,44 +68,19 @@ async function loginUser(user) {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
//if user exists
|
// Make sure user exists
|
||||||
if (userRes){
|
if (!userRes) return false;
|
||||||
//compare password
|
|
||||||
let match = await comparePassword(user.password, userRes.password);
|
|
||||||
if (match){
|
|
||||||
console.log(userRes.id);
|
|
||||||
console.log(userRes.username);
|
|
||||||
|
|
||||||
//generate token
|
// Compare passwords
|
||||||
let token = await generateUUID();
|
let match = await comparePassword(user.password, userRes.password);
|
||||||
|
if (!match) return false;
|
||||||
|
//console.log('loginUser', userRes.id, userRes.username);
|
||||||
|
|
||||||
//add to db
|
//generate token
|
||||||
addToken(userRes.id, token);
|
let token = await addAPIKey(userRes.id, "auto-generated");
|
||||||
|
|
||||||
|
return { token: token, userid: userRes.id, username: userRes.username };
|
||||||
//sucessful login
|
|
||||||
/*
|
|
||||||
1) generate token
|
|
||||||
2) store in db and localstorage (maybe hash it?)
|
|
||||||
3) return userid and username and token and store in localstorage
|
|
||||||
*/
|
|
||||||
return { token: token, userid: userRes.id, username: userRes.username };
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async function getAPIKey() {
|
|
||||||
const apikey = await apikeyModel.findAll();
|
|
||||||
return apikey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -103,27 +91,47 @@ async function getAPIKey() {
|
|||||||
5) you give the user rowid-uuidv4
|
5) you give the user rowid-uuidv4
|
||||||
6) store in database
|
6) store in database
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//can be used for api key or token. Both are the same logic
|
||||||
async function addAPIKey(userId, permission) {
|
async function addAPIKey(userId, permission) {
|
||||||
let token = await generateUUID();
|
let hashtoken = await generateUUID();
|
||||||
let usertoken = userId + "-" + token;
|
let apikey = await hashAPIKey(hashtoken);
|
||||||
let apikey = await hashAPIKey(token);
|
|
||||||
|
|
||||||
console.log(token);
|
let token = await apikeyModel.create({
|
||||||
console.log(apikey);
|
userid: userId,
|
||||||
|
apikey: apikey,
|
||||||
|
permission: permission,
|
||||||
|
});
|
||||||
|
|
||||||
await apikeyModel.create({
|
//user token with - tokenid is table id
|
||||||
userid: userId,
|
return token.id + "-" + hashtoken;
|
||||||
apikey: apikey,
|
|
||||||
permission: permission
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
//user token with -
|
|
||||||
return usertoken;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//api/v0/user/logout
|
||||||
|
async function deleteUserToken(token) {
|
||||||
|
//get row id
|
||||||
|
let splitAuthToken = token.split("-");
|
||||||
|
let rowid = splitAuthToken[0];
|
||||||
|
|
||||||
|
//console.log(rowid);
|
||||||
|
|
||||||
|
//delete from db
|
||||||
|
let delRes = await apikeyModel.destroy({
|
||||||
|
where: {
|
||||||
|
id: rowid,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!delRes) return false;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
getUserID,
|
||||||
addUser,
|
addUser,
|
||||||
loginUser,
|
loginUser,
|
||||||
addAPIKey,
|
addAPIKey,
|
||||||
|
deleteUserToken,
|
||||||
};
|
};
|
||||||
|
@ -21,6 +21,8 @@ bcrypt.hash(myPlaintextPassword, saltRounds, function(err, hash) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//hash for pass or token lol doesnt matter
|
||||||
async function hashPassword(password) {
|
async function hashPassword(password) {
|
||||||
return await bcrypt.hash(password, saltRounds);
|
return await bcrypt.hash(password, saltRounds);
|
||||||
}
|
}
|
||||||
@ -29,6 +31,7 @@ async function hashAPIKey(apikey) {
|
|||||||
return await bcrypt.hash(apikey, saltRounds);
|
return await bcrypt.hash(apikey, saltRounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//can be used to compare password or token
|
||||||
async function comparePassword(password, hash) {
|
async function comparePassword(password, hash) {
|
||||||
return await bcrypt.compare(password, hash);
|
return await bcrypt.compare(password, hash);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,30 @@
|
|||||||
/*v
|
const { apikeyModel } = require("../database/model/apiKeyModel");
|
||||||
1) check if token proided by JSON req is valid against db
|
const { userModel } = require("../database/model/userModel");
|
||||||
2) if valid its passed to next()
|
const { comparePassword } = require("../functions/bcrypt");
|
||||||
*/
|
|
||||||
|
async function auth(req, res, next){
|
||||||
|
try{
|
||||||
|
// let user = await Auth.checkToken({token: req.header('auth-token')});
|
||||||
|
let authToken = req.header('auth-token');
|
||||||
|
let splitAuthToken = authToken.split('-');
|
||||||
|
let rowid = splitAuthToken[0];
|
||||||
|
let suppliedToken = splitAuthToken.slice(1).join('-');
|
||||||
|
|
||||||
|
//get from db
|
||||||
|
let token = await apikeyModel.findByPk(rowid, {include: userModel});
|
||||||
|
|
||||||
|
//compare
|
||||||
|
let isMatch = await comparePassword(suppliedToken, token.apikey);
|
||||||
|
if (!isMatch) return false;
|
||||||
|
|
||||||
|
//else do logic
|
||||||
|
//pass hashed token to req.token (IMPORTANT ITS NOT PASSED TO CLIENT)
|
||||||
|
req.token = token
|
||||||
|
req.user = await token.getUser();
|
||||||
|
next();
|
||||||
|
}catch(error){
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { auth };
|
||||||
|
@ -13,17 +13,17 @@ app.set("views", path.join(__dirname, "../views"));
|
|||||||
app.set("view engine", "ejs");
|
app.set("view engine", "ejs");
|
||||||
|
|
||||||
// Have express server static content( images, CSS, browser JS) from the public
|
// Have express server static content( images, CSS, browser JS) from the public
|
||||||
// local folder.
|
|
||||||
app.use(express.static(path.join(__dirname, "../public")));
|
app.use(express.static(path.join(__dirname, "../public")));
|
||||||
|
|
||||||
//middleware logic ( called by next() )
|
//middleware logic ( called by next() )
|
||||||
//add token middeware upon login to validate routes that require token
|
const auth = require("../middleware/authChecker");
|
||||||
|
|
||||||
|
|
||||||
//route logic
|
//route logic
|
||||||
app.use("/api/v0", require("../routes/api_routes")); //consumerWebsite\routes\api_routes.js
|
app.use("/api/v0", require("../routes/api_routes"));
|
||||||
|
|
||||||
//render logic
|
//render logic
|
||||||
app.use("/", require("../routes/render")); //consumerWebsite\routes\render.js
|
app.use("/", require("../routes/render"));
|
||||||
|
|
||||||
// Catch 404 and forward to error handler. If none of the above routes are
|
// Catch 404 and forward to error handler. If none of the above routes are
|
||||||
// used, this is what will be called.
|
// used, this is what will be called.
|
||||||
|
@ -3801,3 +3801,15 @@
|
|||||||
.fas {
|
.fas {
|
||||||
font-family: 'Font Awesome 5 Free';
|
font-family: 'Font Awesome 5 Free';
|
||||||
font-weight: 900; }
|
font-weight: 900; }
|
||||||
|
|
||||||
|
.contact-right p {
|
||||||
|
/* Your CSS styles here */
|
||||||
|
color: #4e3914;
|
||||||
|
font-size: 16px;
|
||||||
|
/* Add any other styles you need */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.card-text {
|
||||||
|
color: #000000;
|
||||||
|
}
|
||||||
|
526
consumerWebsite/public/css/api.css
Normal file
526
consumerWebsite/public/css/api.css
Normal file
@ -0,0 +1,526 @@
|
|||||||
|
@charset "utf-8";
|
||||||
|
|
||||||
|
/* RESET
|
||||||
|
----------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
html, body, div, span, applet, object, iframe,
|
||||||
|
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||||
|
a, abbr, acronym, address, big, cite, code,
|
||||||
|
del, dfn, em, ins, kbd, q, s, samp,
|
||||||
|
small, strike, strong, sub, sup, tt, var,
|
||||||
|
b, u, i, center,
|
||||||
|
dl, dt, dd, ol, ul, li,
|
||||||
|
fieldset, form, label, legend,
|
||||||
|
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||||
|
article, aside, canvas, details, embed,
|
||||||
|
figure, figcaption, footer, hgroup,
|
||||||
|
menu, nav, output, ruby, section, summary,
|
||||||
|
time, mark, audio, video {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
font-size:100%;
|
||||||
|
font: inherit;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
img, embed, object, video { max-width: 100%; }
|
||||||
|
.ie6 img.full, .ie6 object.full, .ie6 embed, .ie6 video { width: 100%; }
|
||||||
|
|
||||||
|
/* BASE
|
||||||
|
----------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
*{
|
||||||
|
-webkit-transition: all 0.3s ease;
|
||||||
|
-moz-transition: all 0.3s ease;
|
||||||
|
-o-transition: all 0.3s ease;
|
||||||
|
-ms-transition: all 0.3s ease;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
html,
|
||||||
|
body{
|
||||||
|
position:relative;
|
||||||
|
min-height: 100%;
|
||||||
|
height: 100%;
|
||||||
|
-webkit-backface-visibility: hidden;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
}
|
||||||
|
strong{
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
i{
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.overflow-hidden{
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.content a{
|
||||||
|
color: #00a8e3;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.content a:hover{
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.scroll-to-link{
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
p, .content ul, .content ol{
|
||||||
|
font-size: 14px;
|
||||||
|
color: #ffffff;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
line-height: 1.6;
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
.content h1:first-child{
|
||||||
|
font-size: 1.333em;
|
||||||
|
color: #034c8f;
|
||||||
|
padding-top: 2.5em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
border-top: 1px solid rgba(255,255,255,0.3);
|
||||||
|
border-top-width: 0;
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 1.3em;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
code,
|
||||||
|
pre{
|
||||||
|
font-family: 'Source Code Pro', monospace;
|
||||||
|
}
|
||||||
|
.higlighted{
|
||||||
|
background-color: rgba(0,0,0,0.05);
|
||||||
|
padding: 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* LEFT-MENU
|
||||||
|
----------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
.left-menu{
|
||||||
|
position: fixed;
|
||||||
|
z-index: 3;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 300px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background-color: #f4f5f8;
|
||||||
|
overflow-x: hidden;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
.left-menu .content-infos {
|
||||||
|
position: relative;
|
||||||
|
padding: 12px 13.25%;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.left-menu .info {
|
||||||
|
position: relative;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-top: 5px;
|
||||||
|
color: #777A7A;
|
||||||
|
}
|
||||||
|
.left-menu .info b {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #034c8f;
|
||||||
|
}
|
||||||
|
.content-logo{
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 1.425em 11.5%;
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
.content-logo img{
|
||||||
|
display: inline-block;
|
||||||
|
max-width: 70%;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.content-logo span{
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 10px;
|
||||||
|
vertical-align: middle;
|
||||||
|
color: #323F4C;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
.content-menu{
|
||||||
|
margin: 2em auto 2em;
|
||||||
|
padding: 0 0 100px;
|
||||||
|
}
|
||||||
|
.content-menu ul{
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 28px;
|
||||||
|
}
|
||||||
|
.content-menu ul li{
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 0;
|
||||||
|
}
|
||||||
|
.content-menu ul li:hover,
|
||||||
|
.content-menu ul li.active{
|
||||||
|
background-color:#DCDEE9;
|
||||||
|
}
|
||||||
|
.content-menu ul li:hover a,
|
||||||
|
.content-menu ul li.active a{
|
||||||
|
color: #00a8e3;
|
||||||
|
}
|
||||||
|
@media (hover: none) {
|
||||||
|
.content-menu ul li:not(.active):hover {
|
||||||
|
background-color: inherit;
|
||||||
|
}
|
||||||
|
.content-menu ul li:not(.active):hover a {
|
||||||
|
color: #777A7A;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.content-menu ul li a{
|
||||||
|
padding: 12px 13.25%;
|
||||||
|
color: #777A7A;
|
||||||
|
letter-spacing: 0.025em;
|
||||||
|
line-height: 1.1;
|
||||||
|
display: block;
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CONTENT-PAGE
|
||||||
|
----------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
.content-page {
|
||||||
|
position: relative;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin-left: 300px;
|
||||||
|
z-index: 2;
|
||||||
|
background-color: #fff;
|
||||||
|
min-height: 100%;
|
||||||
|
padding-bottom: 1px;
|
||||||
|
}
|
||||||
|
.content-code{
|
||||||
|
width: 50%;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background-color: #323f4c;
|
||||||
|
border-color: #323f4c;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 30;
|
||||||
|
}
|
||||||
|
.content h1,
|
||||||
|
.content h2,
|
||||||
|
.content h3,
|
||||||
|
.content h4,
|
||||||
|
.content h5,
|
||||||
|
.content h6,
|
||||||
|
.content p,
|
||||||
|
.content table,
|
||||||
|
.content aside,
|
||||||
|
.content dl,
|
||||||
|
.content ul,
|
||||||
|
.content ol,
|
||||||
|
.content .central-overflow-x {
|
||||||
|
margin-right: 50%;
|
||||||
|
padding: 0 28px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: block;
|
||||||
|
max-width: 680px;
|
||||||
|
}
|
||||||
|
.content .central-overflow-x {
|
||||||
|
margin-right: calc(50% + 28px);
|
||||||
|
margin-left: 28px;
|
||||||
|
padding: 0;
|
||||||
|
overflow-y: hidden;
|
||||||
|
max-width: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.content p .central-overflow-x {
|
||||||
|
margin-right: 0;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
.break-word {
|
||||||
|
word-break: break-word;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
.content ul,
|
||||||
|
.content ol {
|
||||||
|
padding: 0 44px;
|
||||||
|
}
|
||||||
|
.content h2,
|
||||||
|
.content h3,
|
||||||
|
.content h4,
|
||||||
|
.content h5,
|
||||||
|
.content h6 {
|
||||||
|
font-size: 15px;
|
||||||
|
margin-top: 2.5em;
|
||||||
|
margin-bottom: 0.8em;
|
||||||
|
color: #034c8f;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
.content h2{
|
||||||
|
font-size: 1.333em;
|
||||||
|
}
|
||||||
|
.content h4{
|
||||||
|
color: #00a8e3;
|
||||||
|
margin-top: 0;
|
||||||
|
text-transform: none;
|
||||||
|
font-size: 14px;
|
||||||
|
margin-bottom: 0.2em;
|
||||||
|
}
|
||||||
|
.content-page .content p,
|
||||||
|
.content-page .content pre {
|
||||||
|
max-width: 680px;
|
||||||
|
}
|
||||||
|
.content pre,
|
||||||
|
.content blockquote {
|
||||||
|
background-color: #323f4c;
|
||||||
|
border-color: #323f4c;
|
||||||
|
color: #fff;
|
||||||
|
padding: 0 28px 2em;
|
||||||
|
margin: 0;
|
||||||
|
width: 50%;
|
||||||
|
float: right;
|
||||||
|
clear: right;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.content pre code, .content pre {
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
.content blockquote,
|
||||||
|
.content pre,
|
||||||
|
.content pre code{
|
||||||
|
padding-top: 0;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
.content pre code{
|
||||||
|
margin-top: -2em;
|
||||||
|
}
|
||||||
|
.content table {
|
||||||
|
font-size: 0.825em;
|
||||||
|
margin-bottom: 1.5em;
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
.content table tr:last-child {
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
.content table th {
|
||||||
|
font-size: 0.925em;
|
||||||
|
padding: 5px 18px 5px 0;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
vertical-align: bottom;
|
||||||
|
text-align: left;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
.content table td {
|
||||||
|
padding: 5px 18px 5px 0;
|
||||||
|
text-align: left;
|
||||||
|
vertical-align: top;
|
||||||
|
line-height: 1.6;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
font-weight: 300;
|
||||||
|
color: #777A7A;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* burger-menu-icon
|
||||||
|
----------------------------------------------------------------------------------------*/
|
||||||
|
.burger-menu-icon {
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
padding: 0;
|
||||||
|
position: absolute;
|
||||||
|
right: 26px;
|
||||||
|
top: 26px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.burger-menu-icon .line {
|
||||||
|
fill: none;
|
||||||
|
stroke: #000;
|
||||||
|
stroke-width: 6;
|
||||||
|
transition: stroke-dasharray 600ms cubic-bezier(0.4, 0, 0.2, 1),
|
||||||
|
stroke-dashoffset 600ms cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
.burger-menu-icon .line1 {
|
||||||
|
stroke-dasharray: 60 207;
|
||||||
|
stroke-width: 6;
|
||||||
|
}
|
||||||
|
.burger-menu-icon .line2 {
|
||||||
|
stroke-dasharray: 60 60;
|
||||||
|
stroke-width: 6;
|
||||||
|
}
|
||||||
|
.burger-menu-icon .line3 {
|
||||||
|
stroke-dasharray: 60 207;
|
||||||
|
stroke-width: 6;
|
||||||
|
}
|
||||||
|
html.menu-opened .burger-menu-icon .line1 {
|
||||||
|
stroke-dasharray: 90 207;
|
||||||
|
stroke-dashoffset: -134;
|
||||||
|
stroke-width: 6;
|
||||||
|
}
|
||||||
|
html.menu-opened .burger-menu-icon .line2 {
|
||||||
|
stroke-dasharray: 1 60;
|
||||||
|
stroke-dashoffset: -30;
|
||||||
|
stroke-width: 6;
|
||||||
|
}
|
||||||
|
html.menu-opened .burger-menu-icon .line3 {
|
||||||
|
stroke-dasharray: 90 207;
|
||||||
|
stroke-dashoffset: -134;
|
||||||
|
stroke-width: 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ONE CONTENT COLUMN VERSION
|
||||||
|
----------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
body.one-content-column-version .content h1,
|
||||||
|
body.one-content-column-version .content h2,
|
||||||
|
body.one-content-column-version .content h3,
|
||||||
|
body.one-content-column-version .content h4,
|
||||||
|
body.one-content-column-version .content h5,
|
||||||
|
body.one-content-column-version .content h6,
|
||||||
|
body.one-content-column-version .content p,
|
||||||
|
body.one-content-column-version .content table,
|
||||||
|
body.one-content-column-version .content ul,
|
||||||
|
body.one-content-column-version .content ol,
|
||||||
|
body.one-content-column-version .content aside,
|
||||||
|
body.one-content-column-version .content dl,
|
||||||
|
body.one-content-column-version .content ul,
|
||||||
|
body.one-content-column-version .content ol {
|
||||||
|
margin-right: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
body.one-content-column-version .content-page .content p,
|
||||||
|
body.one-content-column-version .content-page .content pre {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
body.one-content-column-version .content-page {
|
||||||
|
background-color: #323f4c;
|
||||||
|
}
|
||||||
|
body.one-content-column-version .content h1:first-child,
|
||||||
|
body.one-content-column-version .content h2,
|
||||||
|
body.one-content-column-version .content h3,
|
||||||
|
body.one-content-column-version .content h4,
|
||||||
|
body.one-content-column-version .content h5,
|
||||||
|
body.one-content-column-version .content h6 {
|
||||||
|
color: #59C3C3;
|
||||||
|
}
|
||||||
|
body.one-content-column-version p {
|
||||||
|
color: #D6F0F0;
|
||||||
|
}
|
||||||
|
body.one-content-column-version .content table td {
|
||||||
|
color: #D6F0F0;
|
||||||
|
}
|
||||||
|
body.one-content-column-version .content thead {
|
||||||
|
color: #417179;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* RESPONSIVE
|
||||||
|
----------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
@media only screen and (max-width:980px){
|
||||||
|
.content h1, .content h2, .content h3, .content h4, .content h5, .content h6, .content p, .content table, .content ul, .content ol, .content aside, .content dl, .content ul, .content ol {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
.content .central-overflow-x {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 28px;
|
||||||
|
}
|
||||||
|
.content-code{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.content pre, .content blockquote {
|
||||||
|
margin: 20px 0;
|
||||||
|
padding: 28px;
|
||||||
|
display: block;
|
||||||
|
width: auto;
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
.content pre code {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width:680px){
|
||||||
|
html {
|
||||||
|
scroll-padding-top: 83px;
|
||||||
|
}
|
||||||
|
html.menu-opened {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.left-menu {
|
||||||
|
position: relative;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
.left-menu .content-menu {
|
||||||
|
position: fixed;
|
||||||
|
width: 400px;
|
||||||
|
max-width: 90vw;
|
||||||
|
z-index: 3;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: -405px;
|
||||||
|
left: auto;
|
||||||
|
background-color: #fff;
|
||||||
|
margin: 0;
|
||||||
|
overflow-x: hidden;
|
||||||
|
padding-top: 83px;
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
.left-menu .content-menu ul {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.left-menu .mobile-menu-closer {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 2;
|
||||||
|
background-color: rgba(50, 63, 76, .5);
|
||||||
|
opacity: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
html.menu-opened .left-menu .mobile-menu-closer {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
html.menu-opened .left-menu .content-menu {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
.left-menu .content-logo {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 4;
|
||||||
|
background-color: #f4f5f8;
|
||||||
|
}
|
||||||
|
.content-logo .logo {
|
||||||
|
margin-right: 65px;
|
||||||
|
}
|
||||||
|
.content-page{
|
||||||
|
margin-left: 0;
|
||||||
|
padding-top: 83px;
|
||||||
|
}
|
||||||
|
.burger-menu-icon {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BROWSER AND NON-SEMANTIC STYLING
|
||||||
|
----------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
.cf:before, .cf:after { content: ""; display: block; }
|
||||||
|
.cf:after { clear: both; }
|
||||||
|
.ie6 .cf { zoom: 1 }
|
@ -73,6 +73,21 @@ button.btn-secondary:hover{
|
|||||||
color: #ffffff;
|
color: #ffffff;
|
||||||
border-radius: 4.8px;
|
border-radius: 4.8px;
|
||||||
}
|
}
|
||||||
|
.btn-outline-danger{
|
||||||
|
width: 78px;
|
||||||
|
height: 40px;
|
||||||
|
padding-top: 8px;
|
||||||
|
font-size: 16px;
|
||||||
|
|
||||||
|
}
|
||||||
|
.btn-outline-info{
|
||||||
|
width: 78px ;
|
||||||
|
height: 40px ;
|
||||||
|
padding-top: 8px;
|
||||||
|
font-size: 16px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
.navbar-expand-lg.top-nav .navbar-nav .dropdown-menu{
|
.navbar-expand-lg.top-nav .navbar-nav .dropdown-menu{
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
box-shadow: 3px 5px 15px rgba(0,0,0, .15);
|
box-shadow: 3px 5px 15px rgba(0,0,0, .15);
|
||||||
|
BIN
consumerWebsite/public/images/apilogo.png
Normal file
BIN
consumerWebsite/public/images/apilogo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
88
consumerWebsite/public/js/api.js
Normal file
88
consumerWebsite/public/js/api.js
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
|
||||||
|
var elements = [];
|
||||||
|
|
||||||
|
[].forEach.call(document.querySelectorAll('.scroll-to-link'), function (div) {
|
||||||
|
div.onclick = function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var target = this.dataset.target;
|
||||||
|
document.getElementById(target).scrollIntoView({ behavior: 'smooth' });
|
||||||
|
var elems = document.querySelectorAll(".content-menu ul li");
|
||||||
|
[].forEach.call(elems, function (el) {
|
||||||
|
el.classList.remove("active");
|
||||||
|
});
|
||||||
|
this.classList.add("active");
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('button-menu-mobile').onclick = function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
document.querySelector('html').classList.toggle('menu-opened');
|
||||||
|
}
|
||||||
|
document.querySelector('.left-menu .mobile-menu-closer').onclick = function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
document.querySelector('html').classList.remove('menu-opened');
|
||||||
|
}
|
||||||
|
|
||||||
|
function debounce (func) {
|
||||||
|
var timer;
|
||||||
|
return function (event) {
|
||||||
|
if (timer) clearTimeout(timer);
|
||||||
|
timer = setTimeout(func, 100, event);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculElements () {
|
||||||
|
var totalHeight = 0;
|
||||||
|
elements = [];
|
||||||
|
[].forEach.call(document.querySelectorAll('.content-section'), function (div) {
|
||||||
|
var section = {};
|
||||||
|
section.id = div.id;
|
||||||
|
totalHeight += div.offsetHeight;
|
||||||
|
section.maxHeight = totalHeight - 25;
|
||||||
|
elements.push(section);
|
||||||
|
});
|
||||||
|
onScroll();
|
||||||
|
}
|
||||||
|
|
||||||
|
function onScroll () {
|
||||||
|
var scroll = window.pageYOffset;
|
||||||
|
console.log('scroll', scroll, elements)
|
||||||
|
for (var i = 0; i < elements.length; i++) {
|
||||||
|
var section = elements[i];
|
||||||
|
if (scroll <= section.maxHeight) {
|
||||||
|
var elems = document.querySelectorAll(".content-menu ul li");
|
||||||
|
[].forEach.call(elems, function (el) {
|
||||||
|
el.classList.remove("active");
|
||||||
|
});
|
||||||
|
var activeElems = document.querySelectorAll(".content-menu ul li[data-target='" + section.id + "']");
|
||||||
|
[].forEach.call(activeElems, function (el) {
|
||||||
|
el.classList.add("active");
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (window.innerHeight + scroll + 5 >= document.body.scrollHeight) { // end of scroll, last element
|
||||||
|
var elems = document.querySelectorAll(".content-menu ul li");
|
||||||
|
[].forEach.call(elems, function (el) {
|
||||||
|
el.classList.remove("active");
|
||||||
|
});
|
||||||
|
var activeElems = document.querySelectorAll(".content-menu ul li:last-child");
|
||||||
|
[].forEach.call(activeElems, function (el) {
|
||||||
|
el.classList.add("active");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
calculElements();
|
||||||
|
window.onload = () => {
|
||||||
|
calculElements();
|
||||||
|
};
|
||||||
|
window.addEventListener("resize", debounce(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
calculElements();
|
||||||
|
}));
|
||||||
|
window.addEventListener('scroll', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
onScroll();
|
||||||
|
});
|
@ -134,7 +134,6 @@ app.api = (function (app) {
|
|||||||
complete: function (res, text) {
|
complete: function (res, text) {
|
||||||
callback(
|
callback(
|
||||||
text !== "success" ? res.statusText : null,
|
text !== "success" ? res.statusText : null,
|
||||||
//console.log(res.responseText),
|
|
||||||
JSON.parse(res.responseText),
|
JSON.parse(res.responseText),
|
||||||
res.status
|
res.status
|
||||||
);
|
);
|
||||||
@ -151,8 +150,9 @@ app.auth = (function (app) {
|
|||||||
localStorage.setItem("APIToken", token);
|
localStorage.setItem("APIToken", token);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setUserId(userId) {
|
function setUserId(userid) {
|
||||||
localStorage.setItem("userId", userId);
|
console.log("userid", userid);
|
||||||
|
localStorage.setItem("userid", userid);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setUsername(username) {
|
function setUsername(username) {
|
||||||
@ -185,25 +185,39 @@ app.auth = (function (app) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function logOut(callback) {
|
function logOut(callback) {
|
||||||
localStorage.removeItem("APIToken");
|
//call logout route
|
||||||
localStorage.removeItem("userId");
|
$.ajax({
|
||||||
localStorage.removeItem("username");
|
type: "DELETE",
|
||||||
|
url: "/api/v0/user/logout",
|
||||||
|
headers: {
|
||||||
|
"auth-token": app.auth.getToken(),
|
||||||
|
},
|
||||||
|
contentType: "application/json; charset=utf-8",
|
||||||
|
dataType: "json",
|
||||||
|
complete: function (res, text) {
|
||||||
|
callback(
|
||||||
|
text !== "success" ? res.statusText : null,
|
||||||
|
JSON.parse(res.responseText),
|
||||||
|
res.status
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
//remove token from db NOT the api key.
|
localStorage.removeItem("APIToken");
|
||||||
|
localStorage.removeItem("userid");
|
||||||
|
localStorage.removeItem("username");
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
function forceLogin() {
|
function forceLogin() {
|
||||||
$.holdReady(true);
|
app.auth.isLoggedIn(function (error, isLoggedIn) {
|
||||||
app.auth.isLoggedIn(function (error, isLoggedIn) {
|
if (error || !isLoggedIn) {
|
||||||
if (error || !isLoggedIn) {
|
app.auth.logOut(function () {
|
||||||
app.auth.logOut(function () {});
|
location.replace(`/login`);
|
||||||
location.replace(`/login`);
|
});
|
||||||
} else {
|
}
|
||||||
$.holdReady(false);
|
});
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function logInRedirect() {
|
function logInRedirect() {
|
||||||
window.location.href =
|
window.location.href =
|
||||||
@ -215,6 +229,18 @@ app.auth = (function (app) {
|
|||||||
window.location.href = location.href.replace(location.replace(`/`)) || "/";
|
window.location.href = location.href.replace(location.replace(`/`)) || "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if isLoggedin is true, redirect user away from login / register page
|
||||||
|
function redirectIfLoggedIn() {
|
||||||
|
$.holdReady(true);
|
||||||
|
app.auth.isLoggedIn(function (error, isLoggedIn) {
|
||||||
|
if (error || isLoggedIn) {
|
||||||
|
location.replace(`/`);
|
||||||
|
} else {
|
||||||
|
$.holdReady(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getToken: getToken,
|
getToken: getToken,
|
||||||
setToken: setToken,
|
setToken: setToken,
|
||||||
@ -226,6 +252,7 @@ app.auth = (function (app) {
|
|||||||
forceLogin,
|
forceLogin,
|
||||||
logInRedirect,
|
logInRedirect,
|
||||||
homeRedirect,
|
homeRedirect,
|
||||||
|
redirectIfLoggedIn,
|
||||||
};
|
};
|
||||||
})(app);
|
})(app);
|
||||||
|
|
||||||
|
@ -1,193 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
<meta name="description" content="">
|
|
||||||
<meta name="author" content="">
|
|
||||||
<title>N & LW Lawn Care - Landscaping Bootstrap4 HTML5 Responsive Template </title>
|
|
||||||
<!-- Bootstrap core CSS -->
|
|
||||||
<link href="vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">
|
|
||||||
<!-- Fontawesome CSS -->
|
|
||||||
<link href="css/all.css" rel="stylesheet">
|
|
||||||
<!-- Custom styles for this template -->
|
|
||||||
<link href="css/style.css" rel="stylesheet">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<!-- Navigation -->
|
|
||||||
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-light top-nav fixed-top">
|
|
||||||
<div class="container">
|
|
||||||
<a class="navbar-brand" href="index.html">
|
|
||||||
<img src="images/logo.png" alt="logo" />
|
|
||||||
</a>
|
|
||||||
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse"
|
|
||||||
data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false"
|
|
||||||
aria-label="Toggle navigation">
|
|
||||||
<span class="fas fa-bars"></span>
|
|
||||||
</button>
|
|
||||||
<div class="collapse navbar-collapse" id="navbarResponsive">
|
|
||||||
<ul class="navbar-nav ml-auto">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="index.html">Home</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="news.html">News</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="contactform.html">Contact</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="profile.html">Profile</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="signuplogin.html">Logout</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<div class="full-title">
|
|
||||||
<div class="container">
|
|
||||||
<h1 class="mt-4 mb-3">Profile
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
<div class="centered-content">
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-md-3 border-right">
|
|
||||||
<div class="d-flex flex-column align-items-center text-center p-3 py-5"><img
|
|
||||||
class="rounded-circle mt-5" width="150px"
|
|
||||||
src="https://st3.depositphotos.com/15648834/17930/v/600/depositphotos_179308454-stock-illustration-unknown-person-silhouette-glasses-profile.jpg">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-5 border-right">
|
|
||||||
<div class="p-3 py-5">
|
|
||||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
||||||
<h4 class="text-right">Profile Settings</h4>
|
|
||||||
</div>
|
|
||||||
<div class="row mt-2">
|
|
||||||
<div class="col-md-6"><label class="labels">Name</label><input type="text"
|
|
||||||
class="form-control" placeholder="first name" value=""></div>
|
|
||||||
<div class="col-md-6"><label class="labels">Surname</label><input type="text"
|
|
||||||
class="form-control" value="" placeholder="surname"></div>
|
|
||||||
</div>
|
|
||||||
<div class="row mt-3">
|
|
||||||
<div class="col-md-12"><label class="labels">Mobile Number</label><input type="text"
|
|
||||||
class="form-control" placeholder="enter phone number" value=""></div>
|
|
||||||
<div class="col-md-12"><label class="labels">Address</label><input type="text"
|
|
||||||
class="form-control" placeholder="enter address" value=""></div>
|
|
||||||
<div class="col-md-12"><label class="labels">Email</label><input type="text"
|
|
||||||
class="form-control" placeholder="enter email" value=""></div>
|
|
||||||
<div class="col-md-12"><label class="labels">Password</label><input type="text"
|
|
||||||
class="form-control" placeholder="enter password" value=""></div>
|
|
||||||
<div class="col-md-12"><label class="labels">Password</label><input type="text"
|
|
||||||
class="form-control" placeholder="re enter password" value=""></div>
|
|
||||||
</div>
|
|
||||||
<div class="mt-2 text-center">
|
|
||||||
<button class="btn btn-sm btn-secondary change-password-button" type="button">Change
|
|
||||||
Password</button>
|
|
||||||
</div>
|
|
||||||
<div class="mt-5 text-center"><button class="btn btn-primary profile-button" type="button">Save
|
|
||||||
Profile</button></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<br>
|
|
||||||
<footer class="footer">
|
|
||||||
<div class="container bottom_border">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-3 col-md-6 col-sm-6 col">
|
|
||||||
<h5 class="headin5_amrc col_white_amrc pt2">Find us</h5>
|
|
||||||
<p><i class="fa fa-location-arrow"></i> Blk 645 Jalan Tenaga</p>
|
|
||||||
<p><i class="fa fa-phone"></i> +65 90064959</p>
|
|
||||||
<p><i class="fa fa fa-envelope"></i> Leongdingxuan@gmail.com </p>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-3 col-md-6 col-sm-6 col">
|
|
||||||
<h5 class="headin5_amrc col_white_amrc pt2">Follow us</h5>
|
|
||||||
<!--headin5_amrc ends here-->
|
|
||||||
<ul class="footer_ul2_amrc">
|
|
||||||
<li>
|
|
||||||
<a href="#"><i class="fab fa-facebook-f fleft padding-right"></i> </a>
|
|
||||||
<a href="#">https://www.facebook.com/</a></p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#"><i class="fab fa-instagram fleft padding-right"></i> </a>
|
|
||||||
<a href="#">https://www.instagram.com/</a></p>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="#"><i class="fab fa-twitter fleft padding-right"></i> </a>
|
|
||||||
<a href="#">https://twitter.com/</a></p>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<!--footer_ul2_amrc ends here-->
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-3 col-md-6 col-sm-6">
|
|
||||||
<h5 class="headin5_amrc col_white_amrc pt2">Quick links</h5>
|
|
||||||
<!--headin5_amrc-->
|
|
||||||
<ul class="footer_ul_amrc">
|
|
||||||
<li><a href="#">Home</a></li>
|
|
||||||
<li><a href="#">News</a></li>
|
|
||||||
<li><a href="#">Contact</a></li>
|
|
||||||
</ul>
|
|
||||||
<!--footer_ul_amrc ends here-->
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-3 col-md-6 col-sm-6 ">
|
|
||||||
<h5 class="headin5_amrc col_white_amrc pt2">News</h5>
|
|
||||||
<!--headin5_amrc-->
|
|
||||||
<ul class="footer_ul_amrc">
|
|
||||||
<li class="media">
|
|
||||||
<div class="media-left">
|
|
||||||
<img class="img-fluid" src="images/post-img-01.jpg" alt="" />
|
|
||||||
</div>
|
|
||||||
<div class="media-body">
|
|
||||||
<p>Singapore's air quality ...</p>
|
|
||||||
<span>7 oct 2023</span>
|
|
||||||
</div>
|
|
||||||
</ul>
|
|
||||||
<ul class="footer_ul_amrc">
|
|
||||||
<li class="media">
|
|
||||||
<div class="media-left">
|
|
||||||
<img class="img-fluid" src="images/post-img-01.jpg" alt="" />
|
|
||||||
</div>
|
|
||||||
<div class="media-body">
|
|
||||||
<p>Singapore Government ...</p>
|
|
||||||
<span>29 Sep 2023</span>
|
|
||||||
</div>
|
|
||||||
</ul>
|
|
||||||
<ul class="footer_ul_amrc">
|
|
||||||
<li class="media">
|
|
||||||
<div class="media-left">
|
|
||||||
<img class="img-fluid" src="images/post-img-01.jpg" alt="" />
|
|
||||||
</div>
|
|
||||||
<div class="media-body">
|
|
||||||
<p>High risk of severe ...</p>
|
|
||||||
<span>22 Jun 2023</span>
|
|
||||||
</div>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="container text-center">
|
|
||||||
<br>
|
|
||||||
<p>All Rights Reserved. © 2023 <a href="#">EcoSaver</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<!-- Bootstrap core JavaScript -->
|
|
||||||
<script src="vendor/jquery/jquery.min.js"></script>
|
|
||||||
<script src="vendor/bootstrap/js/bootstrap.bundle.min.js"></script>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,10 +1,14 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const router = require('express').Router();
|
const router = require('express').Router();
|
||||||
|
const { auth } = require("../middleware/authChecker")
|
||||||
|
|
||||||
router.use('/user', require('./user'));
|
|
||||||
|
router.use('/auth', require('./auth'));
|
||||||
|
|
||||||
router.use('/apikey', require('./apikey'));
|
router.use('/apikey', require('./apikey'));
|
||||||
|
|
||||||
|
router.use('/user', auth ,require('./user'));
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
||||||
|
|
||||||
|
56
consumerWebsite/routes/auth.js
Normal file
56
consumerWebsite/routes/auth.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
const { addUser, loginUser } = require("../functions/apiDatabase.js");
|
||||||
|
|
||||||
|
const express = require("express");
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
// /user/register
|
||||||
|
router.post("/register", async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
console.log(req.body);
|
||||||
|
let Res = await addUser(req.body);
|
||||||
|
if (Res == false) {
|
||||||
|
let error = new Error("UserRegFailed");
|
||||||
|
error.message = "The user failed to be craated";
|
||||||
|
error.status = 400;
|
||||||
|
return next(error);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return res.json({
|
||||||
|
message: "User created successfully",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//login
|
||||||
|
router.post("/login", async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
let Res = await loginUser(req.body);
|
||||||
|
if (Res == false) {
|
||||||
|
let error = new Error("User Login Failed");
|
||||||
|
error.status = 400;
|
||||||
|
return next(error);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
//pass res back to form to be set in local storage
|
||||||
|
console.log("my res" , Res);
|
||||||
|
return res.json({
|
||||||
|
message: "User login successfully",
|
||||||
|
token: Res.token,
|
||||||
|
userid: Res.userid,
|
||||||
|
username: Res.username,
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
next(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
|
|
@ -77,4 +77,14 @@ router.get('/contact', function(req, res, next) {
|
|||||||
res.render('contact');
|
res.render('contact');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//api doc
|
||||||
|
router.get('/api', function(req, res, next) {
|
||||||
|
res.render('api');
|
||||||
|
});
|
||||||
|
|
||||||
|
//profile page
|
||||||
|
router.get('/profile', function(req, res, next) {
|
||||||
|
res.render('profile');
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
@ -1,100 +1,58 @@
|
|||||||
const { addUser, loginUser } = require("../functions/apiDatabase.js");
|
const { getUserID , deleteUserToken } = require("../functions/apiDatabase.js");
|
||||||
|
|
||||||
const express = require("express");
|
const express = require("express");
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
// /user/register
|
//api/v0/user/me
|
||||||
router.post("/register", async (req, res, next) => {
|
//getbyid
|
||||||
try {
|
router.get("/me", async function (req, res, next) {
|
||||||
let Res = await addUser(req.body);
|
try {
|
||||||
if (Res == false) {
|
|
||||||
let error = new Error("UserRegFailed");
|
//console.log(req.user);
|
||||||
error.message = "The user failed to be craated";
|
let user = await getUserID(req.user);
|
||||||
error.status = 400;
|
if (!user) {
|
||||||
return next(error);
|
let error = new Error("User not found");
|
||||||
}
|
error.status = 400;
|
||||||
else{
|
return next(error);
|
||||||
return res.json({
|
}
|
||||||
message: "User created successfully",
|
res.json({
|
||||||
});
|
user: user,
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
next(error);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
next(error);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
//login
|
//logout
|
||||||
router.post("/login", async (req, res, next) => {
|
router.delete('/logout', async function(req, res, next){
|
||||||
try {
|
try{
|
||||||
let Res = await loginUser(req.body);
|
/*
|
||||||
if (Res == false) {
|
let authToken = req.header('auth-token');
|
||||||
let error = new Error("User Login Failed");
|
let userDel = await deleteUserToken(authToken);
|
||||||
error.status = 400;
|
if (!userDel) {
|
||||||
return next(error);
|
let error = new Error("User not found");
|
||||||
}
|
error.status = 400;
|
||||||
else{
|
return next(error);
|
||||||
//pass res back to form to be set in local storage
|
}
|
||||||
console.log(Res);
|
*/
|
||||||
return res.json({
|
//destroy method call on seq object
|
||||||
message: "User login successfully",
|
req.token.destroy();
|
||||||
token: Res.token,
|
// DO NOT CALL THIS!!! IT WILL DESTROY USERMODEL SEQ OBJ
|
||||||
userId: Res.userid,
|
//req.user.destroy();
|
||||||
username: Res.username,
|
res.json({
|
||||||
});
|
message: "User logged out successfully",
|
||||||
|
});
|
||||||
|
|
||||||
|
}catch(error){
|
||||||
|
next(error);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
});
|
||||||
console.error(error);
|
|
||||||
next(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
//update
|
//update
|
||||||
//delete
|
//delete
|
||||||
//getbyid
|
|
||||||
|
|
||||||
module.exports = router;
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
curl localhost/api/v0/user/register -H "Content-Type: application/json" -X POST -d '{"username":
|
|
||||||
"testuser123", "password": "thisisthesystemuserpasswordnoob", "email": "testuser123@ecosaver.com", "address":
|
|
||||||
"Nanyang Polytechnic 180 Ang Mo Kio Avenue 8 Singapore 569830", "phone": "12345678"}'
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
const router = require('express').Router();
|
|
||||||
const {User} = require('../models/user');
|
|
||||||
|
|
||||||
router.get('/', async function(req, res, next){
|
|
||||||
try{
|
|
||||||
return res.json({
|
|
||||||
results: await User[req.query.detail ? "listDetail" : "list"]()
|
|
||||||
});
|
|
||||||
}catch(error){
|
|
||||||
next(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get('/me', async function(req, res, next){
|
|
||||||
try{
|
|
||||||
|
|
||||||
return res.json(await User.get({uid: req.user.uid}));
|
|
||||||
}catch(error){
|
|
||||||
next(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get('/:uid', async function(req, res, next){
|
|
||||||
try{
|
|
||||||
return res.json({
|
|
||||||
results: await User.get(req.params.uid),
|
|
||||||
});
|
|
||||||
}catch(error){
|
|
||||||
next(error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
160
consumerWebsite/views/api.ejs
Normal file
160
consumerWebsite/views/api.ejs
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
<!--
|
||||||
|
API Documentation HTML Template - 1.0.1
|
||||||
|
Copyright © 2016 Florian Nicolas
|
||||||
|
Licensed under the MIT license.
|
||||||
|
https://github.com/ticlekiwi/API-Documentation-HTML-Template
|
||||||
|
!-->
|
||||||
|
|
||||||
|
<%- include('top') %>
|
||||||
|
|
||||||
|
<body class="one-content-column-version">
|
||||||
|
<div class="left-menu">
|
||||||
|
<div class="content-logo">
|
||||||
|
<div class="logo">
|
||||||
|
<img alt="platform by Emily van den Heever from the Noun Project" title="platform by Emily van den Heever from the Noun Project" src="images/apilogo.png" height="32" />
|
||||||
|
<span>API Documentation</span>
|
||||||
|
</div>
|
||||||
|
<button class="burger-menu-icon" id="button-menu-mobile">
|
||||||
|
<svg width="34" height="34" viewBox="0 0 100 100"><path class="line line1" d="M 20,29.000046 H 80.000231 C 80.000231,29.000046 94.498839,28.817352 94.532987,66.711331 94.543142,77.980673 90.966081,81.670246 85.259173,81.668997 79.552261,81.667751 75.000211,74.999942 75.000211,74.999942 L 25.000021,25.000058"></path><path class="line line2" d="M 20,50 H 80"></path><path class="line line3" d="M 20,70.999954 H 80.000231 C 80.000231,70.999954 94.498839,71.182648 94.532987,33.288669 94.543142,22.019327 90.966081,18.329754 85.259173,18.331003 79.552261,18.332249 75.000211,25.000058 75.000211,25.000058 L 25.000021,74.999942"></path></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="mobile-menu-closer"></div>
|
||||||
|
<div class="content-menu">
|
||||||
|
<div class="content-infos">
|
||||||
|
<div class="info"><b>Version:</b> 1.0.5</div>
|
||||||
|
<div class="info"><b>Last Updated:</b> 15th Sep, 2021</div>
|
||||||
|
</div>
|
||||||
|
<ul>
|
||||||
|
<li class="scroll-to-link active" data-target="content-get-started">
|
||||||
|
<a>GET STARTED</a>
|
||||||
|
</li>
|
||||||
|
<li class="scroll-to-link" data-target="content-get-characters">
|
||||||
|
<a>Get Characters</a>
|
||||||
|
</li>
|
||||||
|
<li class="scroll-to-link" data-target="content-errors">
|
||||||
|
<a>Errors</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="content-page">
|
||||||
|
<div class="content">
|
||||||
|
<div class="overflow-hidden content-section" id="content-get-started">
|
||||||
|
<h1>Get started</h1>
|
||||||
|
<p>
|
||||||
|
The Westeros API provides programmatic access to read Game of Thrones data. Retrieve a character, provide an oauth connexion, retrieve a familly, filter them, etc.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
To use this API, you need an <strong>API key</strong>. Please contact us at <a href="mailto:jon.snow@nightswatch.wes">jon.snow@nightswatch.wes</a> to get your own API key.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="overflow-hidden content-section" id="content-get-characters">
|
||||||
|
<h2>get characters</h2>
|
||||||
|
<p>
|
||||||
|
To get characters you need to make a POST call to the following url :<br>
|
||||||
|
<code class="higlighted break-word">http://api.westeros.com/character/get</code>
|
||||||
|
</p>
|
||||||
|
<br>
|
||||||
|
<h4>QUERY PARAMETERS</h4>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Field</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>secret_key</td>
|
||||||
|
<td>String</td>
|
||||||
|
<td>Your API key.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>search</td>
|
||||||
|
<td>String</td>
|
||||||
|
<td>(optional) A search word to find character by name.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>house</td>
|
||||||
|
<td>String</td>
|
||||||
|
<td>
|
||||||
|
(optional) a string array of houses:
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>alive</td>
|
||||||
|
<td>Boolean</td>
|
||||||
|
<td>
|
||||||
|
(optional) a boolean to filter alived characters
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>gender</td>
|
||||||
|
<td>String</td>
|
||||||
|
<td>
|
||||||
|
(optional) a string to filter character by gender:<br> m: male<br> f: female
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>offset</td>
|
||||||
|
<td>Integer</td>
|
||||||
|
<td>(optional - default: 0) A cursor for use in pagination. Pagination starts offset the specified offset.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>limit</td>
|
||||||
|
<td>Integer</td>
|
||||||
|
<td>(optional - default: 10) A limit on the number of objects to be returned, between 1 and 100.</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="overflow-hidden content-section" id="content-errors">
|
||||||
|
<h2>Errors</h2>
|
||||||
|
<p>
|
||||||
|
The Westeros API uses the following error codes:
|
||||||
|
</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Error Code</th>
|
||||||
|
<th>Meaning</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>X000</td>
|
||||||
|
<td>
|
||||||
|
Some parameters are missing. This error appears when you don't pass every mandatory parameters.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>X001</td>
|
||||||
|
<td>
|
||||||
|
Unknown or unvalid <code class="higlighted">secret_key</code>. This error appears if you use an unknow API key or if your API key expired.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>X002</td>
|
||||||
|
<td>
|
||||||
|
Unvalid <code class="higlighted">secret_key</code> for this domain. This error appears if you use an API key non specified for your domain. Developper or Universal API keys doesn't have domain checker.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>X003</td>
|
||||||
|
<td>
|
||||||
|
Unknown or unvalid user <code class="higlighted">token</code>. This error appears if you use an unknow user <code class="higlighted">token</code> or if the user <code class="higlighted">token</code> expired.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
@ -88,4 +88,5 @@
|
|||||||
<script src="js/learnmore.js"></script>
|
<script src="js/learnmore.js"></script>
|
||||||
<script src="js/contact.js"></script>
|
<script src="js/contact.js"></script>
|
||||||
<script src="js/search.js"></script>
|
<script src="js/search.js"></script>
|
||||||
|
<script src="js/api.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<%- include('top') %>
|
<%- include('top') %>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<header class="slider-main">
|
<header class="slider-main">
|
||||||
<div id="carouselExampleIndicators" class="carousel slide carousel-fade" data-ride="carousel">
|
<div id="carouselExampleIndicators" class="carousel slide carousel-fade" data-ride="carousel">
|
||||||
<ol class="carousel-indicators">
|
<ol class="carousel-indicators">
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
<!-- Custom styles for this template -->
|
<!-- Custom styles for this template -->
|
||||||
<link rel="stylesheet" href="css/sp.css" />
|
<link rel="stylesheet" href="css/sp.css" />
|
||||||
<link rel="stylesheet" href="css/contact.css" />
|
|
||||||
|
|
||||||
<!-- jQuery library -->
|
<!-- jQuery library -->
|
||||||
<script src="https://code.jquery.com/jquery-3.7.1.min.js"
|
<script src="https://code.jquery.com/jquery-3.7.1.min.js"
|
||||||
@ -36,18 +36,23 @@
|
|||||||
<!-- wait for DOC to be ready -->
|
<!-- wait for DOC to be ready -->
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
//make document ready
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
//check if user is logged in
|
||||||
app.auth.isLoggedIn(function (error, data) {
|
app.auth.isLoggedIn(function (error, data) {
|
||||||
if (data) {
|
if (data) {
|
||||||
$('#cl-logout-button').show();
|
$('#cl-logout-button').show('fast');
|
||||||
$('#cl-profile-button').show();
|
$('#cl-profile-button').show('fast');
|
||||||
$('#cl-login-button').hide();
|
$('#cl-login-button').hide('fast');
|
||||||
} else {
|
} else {
|
||||||
$('#cl-login-button').show();
|
$('#cl-login-button').show('fast');
|
||||||
}
|
}
|
||||||
|
$('body').show('fast')
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-light top-nav fixed-top">
|
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-light top-nav fixed-top">
|
||||||
@ -70,6 +75,9 @@
|
|||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="/contact">Contact</a>
|
<a class="nav-link" href="/contact">Contact</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/api">API Doc</a>
|
||||||
|
</li>
|
||||||
<!-- profile button -->
|
<!-- profile button -->
|
||||||
<div class="form-inline mt-2 mt-md-0">
|
<div class="form-inline mt-2 mt-md-0">
|
||||||
<a id="cl-profile-button" class="btn btn-outline-danger my-2 my-sm-0" href="/profile"
|
<a id="cl-profile-button" class="btn btn-outline-danger my-2 my-sm-0" href="/profile"
|
||||||
@ -85,7 +93,7 @@
|
|||||||
<button id="cl-logout-button" class="btn btn-outline-danger my-2 my-sm-0"
|
<button id="cl-logout-button" class="btn btn-outline-danger my-2 my-sm-0"
|
||||||
onclick="app.auth.logOut(e => window.location.href='/')" style="display: none;">
|
onclick="app.auth.logOut(e => window.location.href='/')" style="display: none;">
|
||||||
<i class="fas fa-sign-out"></i>
|
<i class="fas fa-sign-out"></i>
|
||||||
Log Out
|
Logout
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -1,57 +1,64 @@
|
|||||||
<%- include('top') %>
|
<%- include('top') %>
|
||||||
|
<script type="text/javascript">
|
||||||
|
// Require login to see this page.
|
||||||
|
app.auth.forceLogin()
|
||||||
|
</script>
|
||||||
|
|
||||||
<div class="full-title">
|
<div class="full-title">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h1 class="mt-4 mb-3">Profile
|
<h1 class="mt-4 mb-3">Profile
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
<div class="centered-content">
|
<div class="centered-content">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-3 border-right">
|
<div class="col-md-3 border-right">
|
||||||
<div class="d-flex flex-column align-items-center text-center p-3 py-5"><img
|
<div class="d-flex flex-column align-items-center text-center p-3 py-5"><img
|
||||||
class="rounded-circle mt-5" width="150px"
|
class="rounded-circle mt-5" width="150px"
|
||||||
src="https://st3.depositphotos.com/15648834/17930/v/600/depositphotos_179308454-stock-illustration-unknown-person-silhouette-glasses-profile.jpg">
|
src="https://st3.depositphotos.com/15648834/17930/v/600/depositphotos_179308454-stock-illustration-unknown-person-silhouette-glasses-profile.jpg">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-5 border-right">
|
<div class="col-md-5 border-right">
|
||||||
<div class="p-3 py-5">
|
<div class="p-3 py-5">
|
||||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
<h4 class="text-right">Profile Settings</h4>
|
<h4 class="text-right">Profile Settings</h4>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mt-2">
|
<div class="row mt-2">
|
||||||
<div class="col-md-6"><label class="labels">Name</label><input type="text"
|
<div class="col-md-6"><label class="labels">Name</label><input type="text"
|
||||||
class="form-control" placeholder="first name" value=""></div>
|
class="form-control" placeholder="first name" value=""></div>
|
||||||
<div class="col-md-6"><label class="labels">Surname</label><input type="text"
|
<div class="col-md-6"><label class="labels">Surname</label><input type="text"
|
||||||
class="form-control" value="" placeholder="surname"></div>
|
class="form-control" value="" placeholder="surname"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mt-3">
|
<div class="row mt-3">
|
||||||
<div class="col-md-12"><label class="labels">Mobile Number</label><input type="text"
|
<div class="col-md-12"><label class="labels">Mobile Number</label><input type="text"
|
||||||
class="form-control" placeholder="enter phone number" value=""></div>
|
class="form-control" placeholder="enter phone number" value=""></div>
|
||||||
<div class="col-md-12"><label class="labels">Address</label><input type="text"
|
<div class="col-md-12"><label class="labels">Address</label><input type="text"
|
||||||
class="form-control" placeholder="enter address" value=""></div>
|
class="form-control" placeholder="enter address" value=""></div>
|
||||||
<div class="col-md-12"><label class="labels">Email</label><input type="text"
|
<div class="col-md-12"><label class="labels">Email</label><input type="text"
|
||||||
class="form-control" placeholder="enter email" value=""></div>
|
class="form-control" placeholder="enter email" value=""></div>
|
||||||
<div class="col-md-12"><label class="labels">Password</label><input type="text"
|
<div class="col-md-12"><label class="labels">Password</label><input type="text"
|
||||||
class="form-control" placeholder="enter password" value=""></div>
|
class="form-control" placeholder="enter password" value=""></div>
|
||||||
<div class="col-md-12"><label class="labels">Password</label><input type="text"
|
<div class="col-md-12"><label class="labels">Password</label><input type="text"
|
||||||
class="form-control" placeholder="re enter password" value=""></div>
|
class="form-control" placeholder="re enter password" value=""></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2 text-center">
|
<div class="mt-2 text-center">
|
||||||
<button class="btn btn-sm btn-secondary change-password-button" type="button">Change
|
<button class="btn btn-sm btn-secondary change-password-button" type="button">Change
|
||||||
Password</button>
|
Password</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-5 text-center"><button class="btn btn-primary profile-button" type="button">Save
|
<div class="mt-5 text-center"><button class="btn btn-primary profile-button" type="button">Save
|
||||||
Profile</button></div>
|
Profile</button></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
<%- include('bot') %>
|
<%- include('bot') %>
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
<%- include('logintop') %>
|
<%- include('logintop') %>
|
||||||
|
<script type="text/javascript">
|
||||||
|
app.auth.redirectIfLoggedIn();
|
||||||
|
</script>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<section class="wrapper">
|
<section class="wrapper">
|
||||||
@ -7,7 +10,9 @@
|
|||||||
<header>Signup</header>
|
<header>Signup</header>
|
||||||
<!-- localhost/api/v0/user/register -->
|
<!-- localhost/api/v0/user/register -->
|
||||||
<!-- evalAjax Fires when status 200 is returned -->
|
<!-- evalAjax Fires when status 200 is returned -->
|
||||||
<form action="user/register" onsubmit="formAJAX(this)" evalAJAX="app.auth.logInRedirect();">
|
<form action="auth/register" onsubmit="formAJAX(this)" evalAJAX="app.auth.logInRedirect();">
|
||||||
|
<input type="text" name="firstname" placeholder="First Name" required />
|
||||||
|
<input type="text" name="lastname" placeholder="Last Name" required />
|
||||||
<input type="text" name="username" placeholder="Username" required />
|
<input type="text" name="username" placeholder="Username" required />
|
||||||
<input type="text" name="email" placeholder="Email" required />
|
<input type="text" name="email" placeholder="Email" required />
|
||||||
<input type="text" name="address" placeholder="Address" required />
|
<input type="text" name="address" placeholder="Address" required />
|
||||||
@ -22,10 +27,10 @@
|
|||||||
<header>Login</header>
|
<header>Login</header>
|
||||||
<div class="card-header shadow actionMessage" style="display:none"></div>
|
<div class="card-header shadow actionMessage" style="display:none"></div>
|
||||||
<!-- evalAjax Fires when status 200 is returned -->
|
<!-- evalAjax Fires when status 200 is returned -->
|
||||||
<form action="user/login" onsubmit="formAJAX(this)"
|
<form action="auth/login" onsubmit="formAJAX(this)"
|
||||||
evalAJAX="app.auth.homeRedirect();
|
evalAJAX="app.auth.homeRedirect();
|
||||||
app.auth.setToken(data.token);
|
app.auth.setToken(data.token);
|
||||||
app.auth.setUserId(data.userId);
|
app.auth.setUserId(data.userid);
|
||||||
app.auth.setUsername(data.username);
|
app.auth.setUsername(data.username);
|
||||||
">
|
">
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<meta name="description" content="">
|
<meta name="description" content="">
|
||||||
<meta name="author" content="">
|
<meta name="author" content="">
|
||||||
|
<meta http-equiv="cleartype" content="on">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
|
||||||
<!-- Bootstrap core CSS -->
|
<!-- Bootstrap core CSS -->
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||||
@ -19,6 +21,12 @@
|
|||||||
<link href="css/contact.css" rel="stylesheet">
|
<link href="css/contact.css" rel="stylesheet">
|
||||||
|
|
||||||
|
|
||||||
|
<link href="css/contact.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="css/api.css" media="all">
|
||||||
|
<!-- weird api page cdn -->
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,300;0,400;0,500;1,300&family=Source+Code+Pro:wght@300&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
<!-- jQuery library -->
|
<!-- jQuery library -->
|
||||||
<script src="https://code.jquery.com/jquery-3.7.1.min.js"
|
<script src="https://code.jquery.com/jquery-3.7.1.min.js"
|
||||||
@ -27,31 +35,40 @@
|
|||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"
|
||||||
integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
|
integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
|
||||||
crossorigin="anonymous"></script>
|
crossorigin="anonymous"></script>
|
||||||
|
<!-- weird api page cdn -->
|
||||||
|
<!-- https://github.com/floriannicolas/API-Documentation-HTML-Template/tree/master -->
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.8.0/highlight.min.js"></script>
|
||||||
|
<!-- https://github.com/floriannicolas/API-Documentation-HTML-Template/tree/master -->
|
||||||
|
<script>
|
||||||
|
hljs.initHighlightingOnLoad();
|
||||||
|
</script>
|
||||||
<!-- jquery app.js -->
|
<!-- jquery app.js -->
|
||||||
<script src="js/app.js"></script>
|
<script src="js/app.js"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<!-- javascript function to check if user is auth -->
|
<!-- javascript function to check if user is auth -->
|
||||||
<!-- wait for DOC to be ready -->
|
|
||||||
<script>
|
<script>
|
||||||
|
//make document ready
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
//check if user is logged in
|
||||||
app.auth.isLoggedIn(function (error, data) {
|
app.auth.isLoggedIn(function (error, data) {
|
||||||
if (data) {
|
if (data) {
|
||||||
$('#cl-logout-button').show();
|
$('#cl-logout-button').show('fast');
|
||||||
$('#cl-profile-button').show();
|
$('#cl-profile-button').show('fast');
|
||||||
$('#cl-login-button').hide();
|
$('#cl-login-button').hide('fast');
|
||||||
} else {
|
} else {
|
||||||
$('#cl-login-button').show();
|
$('#cl-login-button').show('fast');
|
||||||
}
|
}
|
||||||
|
$('body').show('fast')
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<body>
|
||||||
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-light top-nav fixed-top">
|
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-light top-nav fixed-top">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<a class="navbar-brand" href="/">
|
<a class="navbar-brand" href="/">
|
||||||
@ -72,22 +89,24 @@
|
|||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="/contact">Contact</a>
|
<a class="nav-link" href="/contact">Contact</a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="/api">API Doc</a>
|
||||||
|
</li>
|
||||||
<!-- profile button -->
|
<!-- profile button -->
|
||||||
<div class="form-inline mt-2 mt-md-0">
|
<div class="form-inline mt-2 mt-md-0">
|
||||||
<a id="cl-profile-button" class="btn btn-outline-danger my-2 my-sm-0" href="/profile"
|
<!-- Profile Button -->
|
||||||
style="display: none;">
|
<a id="cl-profile-button" class="btn btn-outline-info btn-sm my-2 my-sm-0" href="/profile" style="display: none;">
|
||||||
<i class="fas fa-sign-out"></i>
|
<i class="fas fa-sign-out"></i> Profile
|
||||||
Profile
|
|
||||||
</a>
|
</a>
|
||||||
<a id="cl-login-button" class="btn btn-outline-danger my-2 my-sm-0"
|
|
||||||
onclick="app.auth.forceLogin()" style="display: none;">
|
<!-- Login Button -->
|
||||||
<i class="fas fa-sign-out"></i>
|
<a id="cl-login-button" class="btn btn-outline-danger btn-sm my-2 my-sm-0" onclick="app.auth.forceLogin()" style="display: none;">
|
||||||
Login
|
<i class="fas fa-sign-out"></i> Login
|
||||||
</a>
|
</a>
|
||||||
<button id="cl-logout-button" class="btn btn-outline-danger my-2 my-sm-0"
|
|
||||||
onclick="app.auth.logOut(e => window.location.href='/')" style="display: none;">
|
<!-- Logout Button -->
|
||||||
<i class="fas fa-sign-out"></i>
|
<button id="cl-logout-button" class="btn btn-outline-danger btn-sm my-2 my-sm-0" href="/" onclick="app.auth.logOut(e => window.location.href='/')" style="display: none;">
|
||||||
Log Out
|
<i class="fas fa-sign-out"></i> Logut
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
</ul>
|
||||||
@ -99,35 +118,3 @@
|
|||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
<!--
|
|
||||||
<ul class="navbar-nav ms-auto">
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link active" href="/">Home</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/news">News</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/contact">Contact</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="/profile">Profile</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<div class="form-inline mt-2 mt-md-0">
|
|
||||||
<a id="cl-login-button" class="btn btn-outline-danger my-2 my-sm-0"
|
|
||||||
onclick="app.auth.forceLogin()" style="display: none;">
|
|
||||||
<i class="fas fa-sign-out"></i>
|
|
||||||
Login
|
|
||||||
</a>
|
|
||||||
<button id="cl-logout-button" class="btn btn-outline-danger my-2 my-sm-0"
|
|
||||||
onclick="app.auth.logOut(e => window.location.href='/')" style="display: none;">
|
|
||||||
<i class="fas fa-sign-out"></i>
|
|
||||||
Log Out
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
-->
|
|
@ -1,4 +1,5 @@
|
|||||||
require('dotenv').config({ path: path.resolve(__dirname, '../../../.env') })
|
//import('dotenv').config({ path: path.resolve(__dirname, '../../../.env') })
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
@ -42,7 +42,7 @@ module.exports = { apikeyCheck };
|
|||||||
//web server microservice
|
//web server microservice
|
||||||
1) take user supplied rowid-apikey
|
1) take user supplied rowid-apikey
|
||||||
2) split the string by -
|
2) split the string by -
|
||||||
3) get the rowid
|
3) get the rowid or table id
|
||||||
4) get the apikey
|
4) get the apikey
|
||||||
5) compare the apikey with the one in database
|
5) compare the apikey with the one in database
|
||||||
6) if match, return true
|
6) if match, return true
|
||||||
|
Loading…
x
Reference in New Issue
Block a user