better basket and users table
Former-commit-id: cb7a9735df12510bc9d45b2bef984082799b0ab2
This commit is contained in:
@@ -11,6 +11,7 @@ let auth0 = null;
|
|||||||
async function CheckRedirect() {
|
async function CheckRedirect() {
|
||||||
const isAuthenticated = await auth0.isAuthenticated();
|
const isAuthenticated = await auth0.isAuthenticated();
|
||||||
if (isAuthenticated) {
|
if (isAuthenticated) {
|
||||||
|
localStorage.loggedIn = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,6 +22,7 @@ async function CheckRedirect() {
|
|||||||
await auth0.handleRedirectCallback();
|
await auth0.handleRedirectCallback();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
window.alert(e.message || 'authentication error, sorry');
|
window.alert(e.message || 'authentication error, sorry');
|
||||||
|
localStorage.loggedIn = false;
|
||||||
Signout();
|
Signout();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,6 +32,9 @@ async function CheckRedirect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function InitAuth0() {
|
export async function InitAuth0() {
|
||||||
|
localStorage.loggedIn = false;
|
||||||
|
localStorage.user = 'Guest';
|
||||||
|
|
||||||
auth0 = await window.createAuth0Client({
|
auth0 = await window.createAuth0Client({
|
||||||
domain: AUTH0CONFIG.domain,
|
domain: AUTH0CONFIG.domain,
|
||||||
client_id: AUTH0CONFIG.clientId,
|
client_id: AUTH0CONFIG.clientId,
|
||||||
@@ -41,7 +46,9 @@ export async function InitAuth0() {
|
|||||||
const isAuthenticated = await auth0.isAuthenticated();
|
const isAuthenticated = await auth0.isAuthenticated();
|
||||||
if (isAuthenticated) {
|
if (isAuthenticated) {
|
||||||
const user = await auth0.getUser();
|
const user = await auth0.getUser();
|
||||||
|
localStorage.user = user.given_name || user.nickname;
|
||||||
NotifyNavbar('login', user);
|
NotifyNavbar('login', user);
|
||||||
|
localStorage.loggedIn = true;
|
||||||
|
|
||||||
// tell the server about the logon, so that it can make the proper
|
// tell the server about the logon, so that it can make the proper
|
||||||
// entry in the database, if there is for example an address
|
// entry in the database, if there is for example an address
|
||||||
@@ -52,10 +59,11 @@ export async function InitAuth0() {
|
|||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: { Authorization: `Bearer ${token}` },
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
};
|
};
|
||||||
const res = await fetch('/api/auth/login', fetchOptions);
|
|
||||||
if (!res.ok) {
|
const res = await fetch('/api/auth/login', fetchOptions).then(res => res.json());
|
||||||
throw new Error('failed to login with the server');
|
console.log(res);
|
||||||
}
|
|
||||||
|
// do stuff
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,6 +88,8 @@ export async function LoginSignup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function Signout() {
|
export async function Signout() {
|
||||||
|
localStorage.loggedIn = false;
|
||||||
|
localStorage.user = 'Guest';
|
||||||
await auth0.logout({
|
await auth0.logout({
|
||||||
returnTo: window.location.origin,
|
returnTo: window.location.origin,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,6 +19,13 @@ let basketCallback = null;
|
|||||||
|
|
||||||
// TODO: Does the localstorage have a problem with mutual exclusion?
|
// TODO: Does the localstorage have a problem with mutual exclusion?
|
||||||
// TODO: Should the basket be persisted to the server?
|
// TODO: Should the basket be persisted to the server?
|
||||||
|
export function GetBasketItems() {
|
||||||
|
if (localStorage.getItem('basket') === null || !localStorage.getItem('basket')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return JSON.parse(localStorage.getItem('basket')).items;
|
||||||
|
}
|
||||||
|
|
||||||
export function AddProductToBasket(product, type, amount, brickModifier = 'none') {
|
export function AddProductToBasket(product, type, amount, brickModifier = 'none') {
|
||||||
if (localStorage.getItem('basket') === null || !localStorage.getItem('basket')) {
|
if (localStorage.getItem('basket') === null || !localStorage.getItem('basket')) {
|
||||||
localStorage.setItem('basket', JSON.stringify({
|
localStorage.setItem('basket', JSON.stringify({
|
||||||
@@ -61,46 +68,15 @@ export function RemoveProductFromBasket(product, type, amount, brickModifier = '
|
|||||||
product += '~' + brickModifier;
|
product += '~' + brickModifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (basket.items[product].quantity > amount) {
|
if (basket.items[product]) {
|
||||||
basket.items[product].quantity -= amount;
|
if (basket.items[product].quantity > amount) {
|
||||||
} else {
|
basket.items[product].quantity -= amount;
|
||||||
delete basket.items[product];
|
|
||||||
}
|
|
||||||
|
|
||||||
basket.total -= amount;
|
|
||||||
|
|
||||||
localStorage.setItem('basket', JSON.stringify(basket));
|
|
||||||
|
|
||||||
if (basketCallback) {
|
|
||||||
basketCallback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function SetProductInBasket(product, type, amount, brickModifier = 'none') {
|
|
||||||
if (localStorage.getItem('basket') === null || !localStorage.getItem('basket')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const basket = JSON.parse(localStorage.getItem('basket'));
|
|
||||||
|
|
||||||
if (type === 'brick') {
|
|
||||||
product += '~' + brickModifier;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (amount === 0) {
|
|
||||||
delete basket.items[product];
|
|
||||||
} else {
|
|
||||||
if (basket.items[product]) {
|
|
||||||
basket.total -= basket.items[product].quantity;
|
|
||||||
basket.items[product].quantity = amount;
|
|
||||||
} else {
|
} else {
|
||||||
basket.items[product] = {
|
delete basket.items[product];
|
||||||
quantity: amount,
|
|
||||||
type,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
basket.total += amount;
|
basket.total -= amount;
|
||||||
|
|
||||||
localStorage.setItem('basket', JSON.stringify(basket));
|
localStorage.setItem('basket', JSON.stringify(basket));
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { AddProductToBasket, SetProductInBasket, RemoveProductFromBasket, GetBasketTotal, GetBasketTotalPrice } from './basket-popout.mjs';
|
import { GetBasketItems, AddProductToBasket, RemoveProductFromBasket, GetBasketTotal, GetBasketTotalPrice } from './basket-popout.mjs';
|
||||||
import { RegisterComponent, Component } from './components.mjs';
|
import { RegisterComponent, Component } from './components.mjs';
|
||||||
|
|
||||||
class Basket extends Component {
|
class Basket extends Component {
|
||||||
@@ -39,7 +39,6 @@ class Basket extends Component {
|
|||||||
<div class="basket-items-list">
|
<div class="basket-items-list">
|
||||||
${Object.keys(this.state.items).map((key) => {
|
${Object.keys(this.state.items).map((key) => {
|
||||||
const item = this.state.items[key];
|
const item = this.state.items[key];
|
||||||
console.log(key, item);
|
|
||||||
const modifier = key.includes('~');
|
const modifier = key.includes('~');
|
||||||
return /* html */`
|
return /* html */`
|
||||||
<div class="basket-item">
|
<div class="basket-item">
|
||||||
@@ -49,13 +48,15 @@ class Basket extends Component {
|
|||||||
bigimage="true"
|
bigimage="true"
|
||||||
${modifier ? `modifier="${key.split('~')[1]}"` : ''}>
|
${modifier ? `modifier="${key.split('~')[1]}"` : ''}>
|
||||||
</super-compact-listing-component>
|
</super-compact-listing-component>
|
||||||
<div class="product-quantity-selector">
|
<div class="basket-item-content">
|
||||||
<button class="product-quantity-button reduce-quantity" type="button">-</button>
|
<div class="product-quantity-selector">
|
||||||
<input class="quantity-input" type="number" value="${item.quantity}" min="0" max="{item.stock}">
|
<button class="product-quantity-button reduce-quantity" type="button">-</button>
|
||||||
<button class="product-quantity-button increase-quantity" type="button">+</button>
|
<input class="quantity-input" type="number" value="${item.quantity}" min="0" max="{item.stock}">
|
||||||
<span class="product-quantity"> <span class="stock-number">0</span> in stock</span>
|
<button class="product-quantity-button increase-quantity" type="button">+</button>
|
||||||
</div>
|
<span class="product-quantity"> <span class="stock-number">0</span> in stock</span>
|
||||||
<button class="product-quantity-button remove-quantity" type="button">Remove</button>
|
</div>
|
||||||
|
<button class="product-quantity-button remove-quantity" type="button">Remove</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}).join('')}
|
}).join('')}
|
||||||
@@ -65,9 +66,11 @@ class Basket extends Component {
|
|||||||
<div class="basket-footer-subtotal">
|
<div class="basket-footer-subtotal">
|
||||||
Subtotal: £<span class="basket-subtotal">0.00</span>
|
Subtotal: £<span class="basket-subtotal">0.00</span>
|
||||||
</div>
|
</div>
|
||||||
<button class="basket-footer-button" type="button">Checkout</button>
|
<!-- checkout button -->
|
||||||
<button class="basket-footer-button" type="button">Checkout As Guest</button>
|
<div class="basket-footer-checkout">
|
||||||
</div>
|
<button class="basket-footer-button" type="button">Checkout as ${localStorage.user}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
`,
|
`,
|
||||||
style: `
|
style: `
|
||||||
.basket {
|
.basket {
|
||||||
@@ -88,15 +91,38 @@ class Basket extends Component {
|
|||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.basket-item-listing {
|
.basket-item-listing {
|
||||||
|
font-size: 1.3em;
|
||||||
|
flex-basis: 65%;
|
||||||
|
flex-grow: 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (pointer:none), (pointer:coarse), screen and (max-width: 900px) {
|
||||||
|
.basket-item {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.basket-item-listing {
|
||||||
|
font-size: 1.3em;
|
||||||
|
width: 100%;
|
||||||
|
flex-basis: 100%;
|
||||||
|
flex-grow: 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.basket-item-content {
|
||||||
|
flex-basis: 35%;
|
||||||
|
flex-grow: 1;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
font-size: 1.3em;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-around;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.product-quantity-selector {
|
.product-quantity-selector {
|
||||||
flex-basis: 40%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@@ -140,6 +166,44 @@ class Basket extends Component {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.basket-footer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 10px;
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.basket-footer-subtotal {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.basket-footer-checkout {
|
||||||
|
flex-basis: 70%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.basket-footer-button {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #222;
|
||||||
|
border: none;
|
||||||
|
color: #F5F6F6;
|
||||||
|
padding: 0.5em;
|
||||||
|
margin-left: 1em;
|
||||||
|
font-size: 1.4em;
|
||||||
|
transition: all 0.2s ease-in;
|
||||||
|
}
|
||||||
|
|
||||||
|
.basket-footer-button:hover {
|
||||||
|
background-color: #F5F6F6;
|
||||||
|
outline: 2px solid #222;
|
||||||
|
color: #222;
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -203,7 +267,6 @@ class Basket extends Component {
|
|||||||
const modifier = listing.getAttribute('modifier');
|
const modifier = listing.getAttribute('modifier');
|
||||||
const compositeId = id + (modifier ? `~${modifier}` : '');
|
const compositeId = id + (modifier ? `~${modifier}` : '');
|
||||||
const item = this.state.items[compositeId];
|
const item = this.state.items[compositeId];
|
||||||
console.log(id, modifier, item);
|
|
||||||
|
|
||||||
// update the quantity
|
// update the quantity
|
||||||
if (event.target.classList.contains('reduce-quantity')) {
|
if (event.target.classList.contains('reduce-quantity')) {
|
||||||
@@ -214,13 +277,12 @@ class Basket extends Component {
|
|||||||
if (item.quantity === 0) {
|
if (item.quantity === 0) {
|
||||||
RemoveProductFromBasket(id, item.type, item.quantity, modifier);
|
RemoveProductFromBasket(id, item.type, item.quantity, modifier);
|
||||||
this.UpdateSubtotal();
|
this.UpdateSubtotal();
|
||||||
delete this.state.items[compositeId];
|
|
||||||
|
|
||||||
return this.setState({
|
return this.setState({
|
||||||
...this.state,
|
...this.state,
|
||||||
total: GetBasketTotal(),
|
total: GetBasketTotal(),
|
||||||
items: {
|
items: {
|
||||||
...this.state.items,
|
...GetBasketItems(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -232,13 +294,12 @@ class Basket extends Component {
|
|||||||
} else if (event.target.classList.contains('remove-quantity')) {
|
} else if (event.target.classList.contains('remove-quantity')) {
|
||||||
RemoveProductFromBasket(id, item.type, item.quantity, modifier);
|
RemoveProductFromBasket(id, item.type, item.quantity, modifier);
|
||||||
this.UpdateSubtotal();
|
this.UpdateSubtotal();
|
||||||
delete this.state.items[compositeId];
|
|
||||||
|
|
||||||
return this.setState({
|
return this.setState({
|
||||||
...this.state,
|
...this.state,
|
||||||
total: GetBasketTotal(),
|
total: GetBasketTotal(),
|
||||||
items: {
|
items: {
|
||||||
...this.state.items,
|
...GetBasketItems(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -286,23 +347,30 @@ class Basket extends Component {
|
|||||||
if (event.target.value > item.stock) {
|
if (event.target.value > item.stock) {
|
||||||
event.target.value = item.stock;
|
event.target.value = item.stock;
|
||||||
}
|
}
|
||||||
item.quantity = parseInt(event.target.value);
|
|
||||||
|
|
||||||
SetProductInBasket(id, item.type, item.quantity, modifier);
|
if (parseInt(event.target.value) === 0) {
|
||||||
this.UpdateSubtotal();
|
RemoveProductFromBasket(id, item.type, item.quantity, modifier);
|
||||||
|
|
||||||
if (item.quantity === 0) {
|
|
||||||
delete this.state.items[compositeId];
|
|
||||||
|
|
||||||
return this.setState({
|
return this.setState({
|
||||||
...this.state,
|
...this.state,
|
||||||
total: GetBasketTotal(),
|
total: GetBasketTotal(),
|
||||||
items: {
|
items: {
|
||||||
...this.state.items,
|
...GetBasketItems(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if has gone up in quantity then add it
|
||||||
|
if (item.quantity < event.target.value) {
|
||||||
|
AddProductToBasket(id, item.type, event.target.value - item.quantity, modifier);
|
||||||
|
item.quantity = parseInt(event.target.value);
|
||||||
|
} else if (item.quantity > event.target.value) {
|
||||||
|
RemoveProductFromBasket(id, item.type, item.quantity - event.target.value, modifier);
|
||||||
|
item.quantity = parseInt(event.target.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.UpdateSubtotal();
|
||||||
|
|
||||||
// update the total
|
// update the total
|
||||||
this.setState({
|
this.setState({
|
||||||
...this.state,
|
...this.state,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { LoginSignup, Signout } from '../auth.mjs';
|
|||||||
let navbarCallback = null;
|
let navbarCallback = null;
|
||||||
export function NotifyNavbar(type, user) {
|
export function NotifyNavbar(type, user) {
|
||||||
if (navbarCallback && type === 'login') {
|
if (navbarCallback && type === 'login') {
|
||||||
navbarCallback.OnLogin(user);
|
navbarCallback.OnLogin();
|
||||||
}
|
}
|
||||||
if (navbarCallback && type === 'logout') {
|
if (navbarCallback && type === 'logout') {
|
||||||
navbarCallback.OnLogout();
|
navbarCallback.OnLogout();
|
||||||
@@ -39,12 +39,12 @@ class NavBar extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
OnLogin(user) {
|
OnLogin() {
|
||||||
const account = this.root.querySelector('.account-item');
|
const account = this.root.querySelector('.account-item');
|
||||||
|
|
||||||
// doing this with proper dom manipulation wasn't working
|
// doing this with proper dom manipulation wasn't working
|
||||||
account.innerHTML = `
|
account.innerHTML = `
|
||||||
<a class="nav-link" href="#">${user.name}▾</a>
|
<a class="nav-link" href="#">${localStorage.user}▾</a>
|
||||||
<ul class="sub-nav" >
|
<ul class="sub-nav" >
|
||||||
<li><a class="sub-nav-link" href="#">My Account</a></li>
|
<li><a class="sub-nav-link" href="#">My Account</a></li>
|
||||||
<li><a class="sub-nav-link logout-button" href="#">Log Out</a></li>
|
<li><a class="sub-nav-link logout-button" href="#">Log Out</a></li>
|
||||||
|
|||||||
@@ -16535,3 +16535,7 @@ INSERT INTO lego_set_tag (set_id, tag) VALUES ('1010', '1201');
|
|||||||
INSERT INTO lego_set_tag (set_id, tag) VALUES ('1010', '323');
|
INSERT INTO lego_set_tag (set_id, tag) VALUES ('1010', '323');
|
||||||
INSERT INTO set_descriptor (set_id, brick_id, amount) VALUES ('1010', '95228', '1000');
|
INSERT INTO set_descriptor (set_id, brick_id, amount) VALUES ('1010', '95228', '1000');
|
||||||
INSERT INTO lego_set_inventory (set_id, stock, price, new_price, last_updated) VALUES ('1010', '5', '1000.69', '50', now());
|
INSERT INTO lego_set_inventory (set_id, stock, price, new_price, last_updated) VALUES ('1010', '5', '1000.69', '50', now());
|
||||||
|
|
||||||
|
-- admin user
|
||||||
|
|
||||||
|
INSERT INTO users (id, email, admin, nickname, date_created, date_updated) VALUES ('62686cdead060b0068fe7d38', 'systemadmin@legolog.com', true, 'systemadmin', NOW(), NOW());
|
||||||
|
|||||||
@@ -79,11 +79,13 @@ CREATE TABLE IF NOT EXISTS lego_set_inventory (
|
|||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS users (
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
id VARCHAR (50) NOT NULL PRIMARY KEY,
|
id VARCHAR (50) NOT NULL PRIMARY KEY,
|
||||||
email text NOT NULL,
|
email TEXT NOT NULL,
|
||||||
first_name text NOT NULL,
|
admin BOOLEAN NOT NULL,
|
||||||
last_name text NOT NULL,
|
nickname TEXT NOT NULL,
|
||||||
address text NOT NULL,
|
first_name TEXT,
|
||||||
postcode text NOT NULL,
|
last_name TEXT,
|
||||||
|
address TEXT,
|
||||||
|
postcode TEXT,
|
||||||
date_created TIMESTAMP WITHOUT TIME ZONE NOT NULL,
|
date_created TIMESTAMP WITHOUT TIME ZONE NOT NULL,
|
||||||
date_updated TIMESTAMP WITHOUT TIME ZONE NOT NULL
|
date_updated TIMESTAMP WITHOUT TIME ZONE NOT NULL
|
||||||
);
|
);
|
||||||
|
|||||||
9920
package-lock.json
generated
9920
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,7 @@ async function Search(fuzzyStrings) {
|
|||||||
Logger.Error(dbres.error);
|
Logger.Error(dbres.error);
|
||||||
return dbres;
|
return dbres;
|
||||||
}
|
}
|
||||||
await Database.Query('COMMIT TRANSACTION;');
|
Database.Query('COMMIT TRANSACTION;');
|
||||||
|
|
||||||
// validate database response
|
// validate database response
|
||||||
if (dbres.rows.length === 0) {
|
if (dbres.rows.length === 0) {
|
||||||
@@ -89,7 +89,7 @@ async function SumPrices(bricksArr, quantityArray) {
|
|||||||
Logger.Error(dbres.error);
|
Logger.Error(dbres.error);
|
||||||
return dbres;
|
return dbres;
|
||||||
}
|
}
|
||||||
await Database.Query('COMMIT TRANSACTION;');
|
Database.Query('COMMIT TRANSACTION;');
|
||||||
|
|
||||||
// validate database response
|
// validate database response
|
||||||
if (dbres.rows.length === 0) {
|
if (dbres.rows.length === 0) {
|
||||||
@@ -126,7 +126,7 @@ async function GetBulkBricks(bricksArr) {
|
|||||||
Logger.Error(dbres.error);
|
Logger.Error(dbres.error);
|
||||||
return dbres;
|
return dbres;
|
||||||
}
|
}
|
||||||
await Database.Query('COMMIT TRANSACTION;');
|
Database.Query('COMMIT TRANSACTION;');
|
||||||
|
|
||||||
// validate database response
|
// validate database response
|
||||||
if (dbres.rows.length === 0) {
|
if (dbres.rows.length === 0) {
|
||||||
@@ -181,7 +181,7 @@ async function GetBrick(brickId) {
|
|||||||
return dbres || colDbres;
|
return dbres || colDbres;
|
||||||
}
|
}
|
||||||
|
|
||||||
await Database.Query('COMMIT TRANSACTION;');
|
Database.Query('COMMIT TRANSACTION;');
|
||||||
|
|
||||||
// validate database response
|
// validate database response
|
||||||
if (dbres.rows.length === 0) {
|
if (dbres.rows.length === 0) {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ async function Search(fuzzyStrings) {
|
|||||||
Logger.Error(dbres.error);
|
Logger.Error(dbres.error);
|
||||||
return dbres;
|
return dbres;
|
||||||
}
|
}
|
||||||
await Database.Query('COMMIT TRANSACTION;');
|
Database.Query('COMMIT TRANSACTION;');
|
||||||
|
|
||||||
// validate database response
|
// validate database response
|
||||||
if (dbres.rows.length === 0) {
|
if (dbres.rows.length === 0) {
|
||||||
@@ -99,7 +99,7 @@ async function SumPrices(setsArray, quantityArray) {
|
|||||||
Logger.Error(dbres.error);
|
Logger.Error(dbres.error);
|
||||||
return dbres;
|
return dbres;
|
||||||
}
|
}
|
||||||
await Database.Query('COMMIT TRANSACTION;');
|
Database.Query('COMMIT TRANSACTION;');
|
||||||
|
|
||||||
// validate database response
|
// validate database response
|
||||||
if (dbres.rows.length === 0) {
|
if (dbres.rows.length === 0) {
|
||||||
@@ -140,7 +140,7 @@ async function GetSet(setId) {
|
|||||||
Logger.Error(dbres.error);
|
Logger.Error(dbres.error);
|
||||||
return dbres;
|
return dbres;
|
||||||
}
|
}
|
||||||
await Database.Query('COMMIT TRANSACTION;');
|
Database.Query('COMMIT TRANSACTION;');
|
||||||
|
|
||||||
// validate database response
|
// validate database response
|
||||||
if (dbres.rows.length === 0) {
|
if (dbres.rows.length === 0) {
|
||||||
@@ -191,7 +191,7 @@ async function GetSets(page, resPerPage) {
|
|||||||
Logger.Error(dbres.error);
|
Logger.Error(dbres.error);
|
||||||
return dbres;
|
return dbres;
|
||||||
}
|
}
|
||||||
await Database.Query('COMMIT TRANSACTION;');
|
Database.Query('COMMIT TRANSACTION;');
|
||||||
|
|
||||||
const total = parseInt(countRes.rows[0].count);
|
const total = parseInt(countRes.rows[0].count);
|
||||||
|
|
||||||
|
|||||||
89
src/controllers/user-controller.js
Normal file
89
src/controllers/user-controller.js
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
const Database = require('../database/database.js');
|
||||||
|
const Logger = require('../logger.js');
|
||||||
|
|
||||||
|
// C
|
||||||
|
|
||||||
|
async function CreateUser(id, email, admin, nickname) {
|
||||||
|
await Database.Query('BEGIN TRANSACTION;');
|
||||||
|
const dbres = await Database.Query(`
|
||||||
|
INSERT INTO users (id, email, admin, nickname, date_created, date_updated)
|
||||||
|
VALUES ($1, $2, $3, $4, NOW(), NOW())
|
||||||
|
`, [id, email, admin, nickname]).catch(() => {
|
||||||
|
return {
|
||||||
|
error: 'Database error',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
if (dbres.error) {
|
||||||
|
Database.Query('ROLLBACK TRANSACTION;');
|
||||||
|
Logger.Error(dbres.error);
|
||||||
|
return {
|
||||||
|
error: 'Database error',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Database.Query('COMMIT TRANSACTION;');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// R
|
||||||
|
|
||||||
|
async function DoesUserExist(id) {
|
||||||
|
await Database.Query('BEGIN TRANSACTION;');
|
||||||
|
const dbres = await Database.Query(`
|
||||||
|
SELECT id
|
||||||
|
FROM users
|
||||||
|
WHERE id = $1
|
||||||
|
`, [id]).catch(() => {
|
||||||
|
return {
|
||||||
|
error: 'Database error',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
if (dbres.error) {
|
||||||
|
Logger.Error(dbres.error);
|
||||||
|
return {
|
||||||
|
error: 'Database error',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Database.Query('COMMIT TRANSACTION;');
|
||||||
|
|
||||||
|
return dbres.rows.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function GetUserByID(id) {
|
||||||
|
await Database.Query('BEGIN TRANSACTION;');
|
||||||
|
const dbres = await Database.Query(`
|
||||||
|
SELECT id, email, admin, nickname
|
||||||
|
FROM users
|
||||||
|
WHERE id = $1
|
||||||
|
`, [id]).catch(() => {
|
||||||
|
return {
|
||||||
|
error: 'Database error',
|
||||||
|
};
|
||||||
|
});
|
||||||
|
if (dbres.error) {
|
||||||
|
Logger.Error(dbres.error);
|
||||||
|
return {
|
||||||
|
error: 'Database error',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Database.Query('COMMIT TRANSACTION;');
|
||||||
|
|
||||||
|
if (dbres.rows.length === 0) {
|
||||||
|
return {
|
||||||
|
error: 'User not found',
|
||||||
|
long: 'The user you are looking for does not exist',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return dbres.rows[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// U
|
||||||
|
|
||||||
|
// D
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
CreateUser,
|
||||||
|
DoesUserExist,
|
||||||
|
GetUserByID,
|
||||||
|
};
|
||||||
@@ -32,18 +32,6 @@ function getFormatedTimeString() {
|
|||||||
// levelSource is the level that the source will log at ie, if levelSource is
|
// levelSource is the level that the source will log at ie, if levelSource is
|
||||||
// LEVEL_WARN, it will only log if the current level is at or above LEVEL_WARN.
|
// LEVEL_WARN, it will only log if the current level is at or above LEVEL_WARN.
|
||||||
function internalLog(type, message, cConsoleColour, levelSource) {
|
function internalLog(type, message, cConsoleColour, levelSource) {
|
||||||
message = [message].map(x => {
|
|
||||||
if (typeof x === 'object') {
|
|
||||||
return JSON.stringify(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(x)) {
|
|
||||||
return x.join(' ');
|
|
||||||
}
|
|
||||||
|
|
||||||
return x;
|
|
||||||
}).join(' ');
|
|
||||||
|
|
||||||
if (Options.logToConsole && (Options.logLevel <= levelSource)) {
|
if (Options.logToConsole && (Options.logLevel <= levelSource)) {
|
||||||
console.log(`${getFormatedTimeString()} [${cConsoleColour(type)}] ${message}`);
|
console.log(`${getFormatedTimeString()} [${cConsoleColour(type)}] ${message}`);
|
||||||
}
|
}
|
||||||
@@ -60,16 +48,15 @@ function internalLog(type, message, cConsoleColour, levelSource) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Info = (...messages) => internalLog('INFO', messages, clc.greenBright, LEVEL_INFO);
|
const Info = (...messages) => internalLog('INFO', messages.join(' '), clc.greenBright, LEVEL_INFO);
|
||||||
const Warn = (...messages) => internalLog('WARN', messages, clc.yellowBright, LEVEL_WARN);
|
const Warn = (...messages) => internalLog('WARN', messages.join(' '), clc.yellowBright, LEVEL_WARN);
|
||||||
const Error = (...messages) => internalLog('ERROR', messages, clc.redBright, LEVEL_STICK);
|
const Error = (...messages) => internalLog('ERROR', messages.join(' '), clc.redBright, LEVEL_STICK);
|
||||||
const Panic = (...messages) => internalLog('PANIC', messages, clc.bgRedBright, LEVEL_STICK);
|
const Panic = (...messages) => internalLog('PANIC', messages.join(' '), clc.bgRedBright, LEVEL_STICK);
|
||||||
const Debug = (...messages) => internalLog('DEBUG', messages, clc.cyanBright, LEVEL_DEBUG);
|
const Debug = (...messages) => internalLog('DEBUG', messages.join(' '), clc.cyanBright, LEVEL_DEBUG);
|
||||||
const Module = (module, ...messages) => internalLog(`MODULE [${module}]`, ` ${messages.join(' ')}`, clc.blue, LEVEL_INFO);
|
const Module = (module, ...messages) => internalLog(`MODULE [${module}]`, ` ${messages.join(' ')}`, clc.blue, LEVEL_INFO);
|
||||||
const Database = (...messages) => internalLog('PSQL', `[DB] ${messages.join(' ')}`, clc.blue, LEVEL_INFO);
|
const Database = (...messages) => internalLog('PSQL', `[DB] ${messages.join(' ')}`, clc.blue, LEVEL_INFO);
|
||||||
const ExpressLogger = (req, res, next) => {
|
const ExpressLogger = (req, res, next) => {
|
||||||
// don't spam the console with 1000000 bloody requests for thumbnails
|
if (req.originalUrl.startsWith('/api/cdn')) {
|
||||||
if (req.originalUrl.startsWith('/api/cdn/')) {
|
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
internalLog('HTTP', `[${req.method}] ${req.originalUrl} FROM ${req.headers['x-forwarded-for'] || req.socket.remoteAddress}`, clc.magenta, LEVEL_VERBOSE);
|
internalLog('HTTP', `[${req.method}] ${req.originalUrl} FROM ${req.headers['x-forwarded-for'] || req.socket.remoteAddress}`, clc.magenta, LEVEL_VERBOSE);
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// Loosely based on https://github.com/portsoc/auth0-example/blob/main/stages/6/server/auth0-helpers.js
|
// Loosely based on https://github.com/portsoc/auth0-example/blob/main/stages/6/server/auth0-helpers.js
|
||||||
|
// but better (obviously)
|
||||||
|
|
||||||
|
const Controller = require('../controllers/user-controller.js');
|
||||||
const Logger = require('../logger.js');
|
const Logger = require('../logger.js');
|
||||||
|
|
||||||
const Axios = require('axios');
|
const Axios = require('axios');
|
||||||
@@ -54,11 +56,37 @@ async function Auth0GetUser(req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function Login(req, res) {
|
async function Login(req, res) {
|
||||||
// tell the user all is well
|
|
||||||
res.send('Authenticated user: ' + req.auth.payload.sub);
|
|
||||||
|
|
||||||
// tell the database the user is new if they don't already exist
|
// tell the database the user is new if they don't already exist
|
||||||
const user = await Auth0GetUser(req);
|
const user = await Auth0GetUser(req);
|
||||||
|
|
||||||
|
const id = user.sub.split('|')[1];
|
||||||
|
|
||||||
|
const doesExist = await Controller.GetUserByID(id);
|
||||||
|
if (!doesExist.error) {
|
||||||
|
res.send({
|
||||||
|
user: {
|
||||||
|
id,
|
||||||
|
nickname: doesExist.nickname,
|
||||||
|
email: doesExist.email,
|
||||||
|
admin: doesExist.admin,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = user.nickname;
|
||||||
|
const email = user.email;
|
||||||
|
|
||||||
|
await Controller.CreateUser(id, email, false, name);
|
||||||
|
|
||||||
|
res.send({
|
||||||
|
user: {
|
||||||
|
id,
|
||||||
|
nickname: name,
|
||||||
|
email,
|
||||||
|
admin: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|||||||
@@ -38,15 +38,13 @@ async function CalculateBasketPrice(req, res) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Debug(`Set list: ${setList} Brick list: ${brickList}`);
|
let setSubtotal = setList.length > 0
|
||||||
let setSubtotal = setList > 0
|
|
||||||
? await SetController.SumPrices(setList, setQuantities)
|
? await SetController.SumPrices(setList, setQuantities)
|
||||||
: 0;
|
: 0;
|
||||||
let brickSubtotal = brickList > 0
|
let brickSubtotal = brickList.length > 0
|
||||||
? await BrickController.SumPrices(brickList, brickQuantities)
|
? await BrickController.SumPrices(brickList, brickQuantities)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
|
|
||||||
if (setSubtotal.error) setSubtotal = 0;
|
if (setSubtotal.error) setSubtotal = 0;
|
||||||
if (brickSubtotal.error) brickSubtotal = 0;
|
if (brickSubtotal.error) brickSubtotal = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ async function Get(req, res) {
|
|||||||
|
|
||||||
async function Featured(req, res) {
|
async function Featured(req, res) {
|
||||||
// query all sets and return all of them
|
// query all sets and return all of them
|
||||||
const { sets } = await Controller.GetSets(0, 10);
|
const { sets } = await Controller.GetSets(0, 9);
|
||||||
|
|
||||||
if (sets.error) {
|
if (sets.error) {
|
||||||
res.send(JSON.stringify(sets));
|
res.send(JSON.stringify(sets));
|
||||||
|
|||||||
Reference in New Issue
Block a user