setting up auth system
This commit is contained in:
91
server/controllers/AuthController.js
Normal file
91
server/controllers/AuthController.js
Normal file
@@ -0,0 +1,91 @@
|
||||
const bcrypt = require('bcrypt');
|
||||
|
||||
const ControllerResponse = require('./ControllerResponse');
|
||||
const User = require('../models/User');
|
||||
|
||||
module.exports = class AuthController {
|
||||
static async getOne(id) {
|
||||
const user = await User.getOne(id);
|
||||
|
||||
const ok = user !== null;
|
||||
const data = ok ? user : ("No user found with id " + id);
|
||||
const code = ok ? 200 : 404;
|
||||
|
||||
return new ControllerResponse(ok, data, code);
|
||||
}
|
||||
|
||||
static async getOneByEmail(email) {
|
||||
const user = await User.getOneByEmail(email);
|
||||
|
||||
const ok = user !== null;
|
||||
const data = ok ? user : ("No user found with email" + email);
|
||||
const code = ok ? 200 : 404;
|
||||
|
||||
return new ControllerResponse(ok, data, code);
|
||||
}
|
||||
|
||||
static async getAll() {
|
||||
const list = await User.getAll();
|
||||
|
||||
const ok = list.length > 0;
|
||||
const data = ok ? list : "No user data found";
|
||||
const code = ok ? 200 : 404;
|
||||
|
||||
return new ControllerResponse(ok, data, code);
|
||||
}
|
||||
|
||||
static async create() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {{ email: string, password: string }} userData - data to compare against encrypted DB entry
|
||||
* @returns { ControllerResponse | null } controller response, or null failing all else
|
||||
*/
|
||||
static async login(userData) {
|
||||
try {
|
||||
const potentialUser = await AuthController.getOneByEmail(userData.email);
|
||||
|
||||
if (potentialUser.ok) {
|
||||
const match = await bcrypt.compare(userData.password, potentialUser.data.password);
|
||||
return new ControllerResponse(match, (match ? potentialUser : "Invalid credentials"), (match ? 200 : 403));
|
||||
} else {
|
||||
return new ControllerResponse(false, "No user found with these credentials", 404);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static async logout() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* ## Register method
|
||||
*
|
||||
* @param {{ username: string, password: string, email: string }} data - provided user data
|
||||
* @returns { ControllerResponse } controller response including status codes
|
||||
*/
|
||||
static async register(userData) {
|
||||
try {
|
||||
const potentialUser = await AuthController.getOneByEmail(userData.email);
|
||||
if (potentialUser.ok) {
|
||||
return new ControllerResponse(false, ("User already registered with email " + userData.email), 401);
|
||||
}
|
||||
|
||||
const salt = await bcrypt.genSalt(12);
|
||||
const hash = await bcrypt.hash(userData.password, salt);
|
||||
|
||||
const newUser = new User(userData.username, userData.email, hash);
|
||||
const result = await User.create(newUser);
|
||||
|
||||
return new ControllerResponse(result.rows.length > 0, result, (result.rows.length > 0 ? 201 : 400));
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
server/controllers/ControllerResponse.js
Normal file
11
server/controllers/ControllerResponse.js
Normal file
@@ -0,0 +1,11 @@
|
||||
module.exports = class ControllerResponse {
|
||||
ok;
|
||||
data;
|
||||
code;
|
||||
|
||||
constructor(ok, data, code) {
|
||||
this.ok = ok;
|
||||
this.data = data;
|
||||
this.code = code;
|
||||
}
|
||||
}
|
||||
24
server/controllers/ItemController.js
Normal file
24
server/controllers/ItemController.js
Normal file
@@ -0,0 +1,24 @@
|
||||
const Item = require('../models/Item');
|
||||
const ControllerResponse = require('./ControllerResponse');
|
||||
|
||||
module.exports = class ItemController {
|
||||
static async getAll() {
|
||||
const result = await Item.getAll();
|
||||
|
||||
const ok = result !== null;
|
||||
const code = ok ? 200 : 404;
|
||||
const data = ok ? result : "No items found";
|
||||
|
||||
return new ControllerResponse(ok, data, code);
|
||||
}
|
||||
|
||||
static async getOne(id) {
|
||||
const result = await Item.getOne(id);
|
||||
|
||||
const ok = result !== null;
|
||||
const code = ok ? 200 : 404;
|
||||
const data = ok ? result : ("No item found with ID " + id);
|
||||
|
||||
return new ControllerResponse(ok, data, code);
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,9 @@ const root = path.resolve(__dirname);
|
||||
async function seed() {
|
||||
console.clear();
|
||||
|
||||
await pool.query(`DROP TABLE IF EXISTS item`);
|
||||
await pool.query(`DROP TABLE IF EXISTS appuser`);
|
||||
|
||||
const createUserTable = fs.readFileSync(root + "/sql/create/createUserTable.sql").toString();
|
||||
const createItemTable = fs.readFileSync(root + "/sql/create/createItemTable.sql").toString();
|
||||
const populateItemTable = fs.readFileSync(root + "/sql/populate/populateItemTable.sql").toString();
|
||||
|
||||
@@ -3,6 +3,6 @@ CREATE TABLE IF NOT EXISTS appuser (
|
||||
username VARCHAR NOT NULL,
|
||||
email VARCHAR UNIQUE,
|
||||
password VARCHAR NOT NULL,
|
||||
created VARCHAR NOT NULL,
|
||||
modified VARCHAR NOT NULL
|
||||
created TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
modified TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
@@ -1,5 +1,6 @@
|
||||
const passport = require('passport');
|
||||
const { Strategy } = require('passport-local');
|
||||
const AuthController = require('../controllers/authController');
|
||||
|
||||
async function passportLoader(app) {
|
||||
app.use(passport.initialize());
|
||||
@@ -13,13 +14,20 @@ async function passportLoader(app) {
|
||||
done(null, user);
|
||||
})
|
||||
|
||||
passport.use(new Strategy(async (email, password, done) => {
|
||||
passport.use(new Strategy({ usernameField: "email", passwordField: "password" }, async (email, password, done) => {
|
||||
try {
|
||||
console.log(email, password);
|
||||
const response = await AuthController.login({ email: email, password: password });
|
||||
if (response && response.ok) {
|
||||
return done(null, response.data.data);
|
||||
} else {
|
||||
return done(null, false);
|
||||
}
|
||||
} catch (error) {
|
||||
return done(error);
|
||||
}
|
||||
}))
|
||||
|
||||
return passport;
|
||||
}
|
||||
|
||||
module.exports = passportLoader;
|
||||
@@ -1,4 +1,6 @@
|
||||
class Item {
|
||||
const pool = require('../db');
|
||||
|
||||
module.exports = class Item {
|
||||
name;
|
||||
description;
|
||||
created;
|
||||
@@ -12,7 +14,23 @@ class Item {
|
||||
this.modified = new Date(Date.now()).toDateString();
|
||||
}
|
||||
|
||||
async getAll() {
|
||||
static async getAll() {
|
||||
const query = `SELECT * FROM item;`
|
||||
const result = await pool.query(query);
|
||||
if (result.rows.length) {
|
||||
return result.rows;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static async getOne(id) {
|
||||
const query = `SELECT * FROM item WHERE id = $1`;
|
||||
const result = await pool.query(query, [id]);
|
||||
if (result.rows.length) {
|
||||
return result.rows[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
const pool = require('../db');
|
||||
|
||||
module.exports = class User {
|
||||
username;
|
||||
email;
|
||||
@@ -12,4 +14,64 @@ module.exports = class User {
|
||||
this.created = new Date(Date.now()).toDateString();
|
||||
this.modified = new Date(Date.now()).toDateString();
|
||||
}
|
||||
|
||||
presentAsArray() {
|
||||
return [this.username, this.email, this.password];
|
||||
}
|
||||
|
||||
static async getOne(id) {
|
||||
const query = `SELECT * FROM appuser WHERE id = $1`;
|
||||
const result = await pool.query(query, [id]);
|
||||
if (result.rows.length) {
|
||||
return result.rows[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static async getOneByEmail(email) {
|
||||
const query = `SELECT * FROM appuser WHERE email = $1`;
|
||||
const result = await pool.query(query, [email]);
|
||||
if (result.rows.length) {
|
||||
return result.rows[0];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static async getAll() {
|
||||
const query = `SELECT * FROM appuser;`;
|
||||
const result = await pool.query(query);
|
||||
if (result.rows.length) {
|
||||
return result.rows;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static async create(data) {
|
||||
let result;
|
||||
const query = `INSERT INTO appuser (username, email, password) VALUES ($1, $2, $3) RETURNING *`;
|
||||
|
||||
if (!data instanceof User) {
|
||||
const newUser = new User(data.username, data.email, data.password);
|
||||
result = await pool.query(query, newUser.presentAsArray());
|
||||
} else {
|
||||
result = await pool.query(query, data.presentAsArray());
|
||||
}
|
||||
|
||||
return result.rows;
|
||||
}
|
||||
|
||||
static async login() {
|
||||
|
||||
}
|
||||
|
||||
static async logout() {
|
||||
|
||||
}
|
||||
|
||||
static async register() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@
|
||||
"dotenv": "^16.0.3",
|
||||
"express": "^4.18.2",
|
||||
"express-session": "^1.17.3",
|
||||
"passport": "^0.6.0",
|
||||
"passport": "^0.4.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"pg": "^8.9.0"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,55 @@
|
||||
function authRoute(app, passport) {
|
||||
const AuthController = require('../controllers/authController');
|
||||
|
||||
const router = require('express').Router();
|
||||
|
||||
async function authRoute(app, passport) {
|
||||
router.post('/register', async (req, res) => {
|
||||
try {
|
||||
const data = req.body;
|
||||
const response = await AuthController.register(data);
|
||||
|
||||
res.status(response.code).send(response.data);
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
})
|
||||
|
||||
router.post('/login', async (req, res, next) => {
|
||||
try {
|
||||
const data = req.body;
|
||||
const response = await AuthController.login(data);
|
||||
|
||||
if (!response || !response.ok) {
|
||||
res.status(response.code || 400).send(response.data || "Something went wrong");
|
||||
} else {
|
||||
req.session.user = response.data;
|
||||
req.session.save((err) => {
|
||||
return next(err);
|
||||
})
|
||||
|
||||
res.send(response.data);
|
||||
}
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
})
|
||||
|
||||
router.delete('/logout', async (req, res, next) => {
|
||||
try {
|
||||
req.session.destroy((err) => {
|
||||
if (err) throw err;
|
||||
req.logout((err) => {
|
||||
if (err) return next(err);
|
||||
})
|
||||
})
|
||||
|
||||
res.status(204).send({ ok: true });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
})
|
||||
|
||||
return router;
|
||||
}
|
||||
|
||||
module.exports = authRoute;
|
||||
@@ -1,5 +1,16 @@
|
||||
async function routesLoader(app, passport) {
|
||||
const authRoute = require("./auth");
|
||||
const itemRoute = require("./item");
|
||||
|
||||
async function routesLoader(app, passport) {
|
||||
const authRouter = await authRoute(app, passport);
|
||||
const itemRouter = await itemRoute(app, passport);
|
||||
|
||||
app.get('/', (req, res) => {
|
||||
res.send(req.session);
|
||||
})
|
||||
|
||||
app.use('/auth', authRouter);
|
||||
app.use('/app', passport.authenticate('local'), itemRouter);
|
||||
}
|
||||
|
||||
module.exports = routesLoader;
|
||||
@@ -1,9 +1,20 @@
|
||||
const router = require('express').Router();
|
||||
const ItemController = require('../controllers/ItemController');
|
||||
|
||||
function itemRoute(app, passport) {
|
||||
app.use('/app/items', router);
|
||||
|
||||
router.get('/', (req, res) => {
|
||||
res.status(200).send('items');
|
||||
router.get('/item', async (req, res) => {
|
||||
const response = await ItemController.getAll();
|
||||
const { data, code } = response;
|
||||
res.status(code).send(data);
|
||||
})
|
||||
}
|
||||
|
||||
router.get('/item/:id', async (req, res) => {
|
||||
const { id } = req.params;
|
||||
const { data, code } = await ItemController.getOne(id);
|
||||
res.status(code).send(data);
|
||||
})
|
||||
|
||||
return router;
|
||||
}
|
||||
|
||||
module.exports = itemRoute;
|
||||
Reference in New Issue
Block a user