prototyping passport auth logic
This commit is contained in:
53
server/auth/index.ts
Normal file
53
server/auth/index.ts
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import { IUser, IUserAuth } from "../schemas";
|
||||||
|
import { User } from "../models/user";
|
||||||
|
import createError from "http-errors";
|
||||||
|
import bcrypt from "bcrypt";
|
||||||
|
import { QueryResult } from "pg";
|
||||||
|
|
||||||
|
const UserInstance = new User();
|
||||||
|
|
||||||
|
export default class AuthService {
|
||||||
|
// methods for local strategies
|
||||||
|
async register(data: IUser): Promise<Array<keyof IUser>> {
|
||||||
|
const { email, password } = data;
|
||||||
|
try {
|
||||||
|
const user = await UserInstance.getOneByEmail(email);
|
||||||
|
if (user) throw createError('409', 'Email already in use');
|
||||||
|
|
||||||
|
let createdUser: IUser | null = null;
|
||||||
|
|
||||||
|
bcrypt.genSalt((err, salt) => {
|
||||||
|
if (err) throw err;
|
||||||
|
bcrypt.hash(password, salt, (err, hash) => {
|
||||||
|
if (err) throw err;
|
||||||
|
|
||||||
|
createdUser = {
|
||||||
|
...data,
|
||||||
|
password: hash
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!createdUser) throw createError('400', 'Error creating user');
|
||||||
|
const result = await UserInstance.post(createdUser);
|
||||||
|
if (!result) throw createError('400', 'Error creating user');
|
||||||
|
return result;
|
||||||
|
} catch (e: any) {
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async login(data: IUserAuth): Promise<Array<keyof IUser>> {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// methods for Google OAuth
|
||||||
|
async googleRegister() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async googleLogin() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
13
server/db/sessionStore.ts
Normal file
13
server/db/sessionStore.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import connectPgSimple from 'connect-pg-simple';
|
||||||
|
import session from 'express-session';
|
||||||
|
import pool from ".";
|
||||||
|
|
||||||
|
export default function pgSessionStore(s: typeof session) {
|
||||||
|
const pgSession = connectPgSimple(s);
|
||||||
|
|
||||||
|
return new pgSession({
|
||||||
|
pool: pool,
|
||||||
|
tableName: "pgsessions",
|
||||||
|
createTableIfMissing: true
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import express from 'express';
|
import express from 'express';
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
import dotenv from 'dotenv';
|
import dotenv from 'dotenv';
|
||||||
dotenv.config({ path: './.env' });
|
dotenv.config();
|
||||||
|
|
||||||
import { loaders } from './loaders';
|
import { loaders } from './loaders';
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,27 @@
|
|||||||
import { Express } from 'express';
|
import { Express } from 'express';
|
||||||
import cors from 'cors';
|
|
||||||
import bodyParser from 'body-parser';
|
import bodyParser from 'body-parser';
|
||||||
|
import morgan from 'morgan';
|
||||||
|
import cors from 'cors';
|
||||||
|
import session from 'express-session';
|
||||||
|
import pgSessionStore from '../db/sessionStore';
|
||||||
|
|
||||||
export const expressLoader = (app: Express) => {
|
export const expressLoader = (app: Express) => {
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
app.use(bodyParser.urlencoded({ extended: true }));
|
app.use(bodyParser.urlencoded({ extended: true }));
|
||||||
|
|
||||||
// app.use(session({}))
|
app.use(morgan('tiny'));
|
||||||
|
|
||||||
|
app.use(session({
|
||||||
|
secret: process.env.SESSIONSECRET || "",
|
||||||
|
cookie: {
|
||||||
|
maxAge: 8 * 60 * 60 * 1000,
|
||||||
|
secure: false
|
||||||
|
},
|
||||||
|
resave: false,
|
||||||
|
saveUninitialized: false,
|
||||||
|
store: pgSessionStore(session)
|
||||||
|
}))
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
import { Strategy as LocalStrategy } from "passport-local";
|
||||||
|
import passport from "passport";
|
||||||
|
import { Express } from "express";
|
||||||
|
import AuthService from "../auth";
|
||||||
|
import { IUserAuth } from "../schemas";
|
||||||
|
const AuthInstance = new AuthService();
|
||||||
|
|
||||||
|
export const passportApp = (app: Express) => {
|
||||||
|
app.use(passport.initialize());
|
||||||
|
app.use(passport.session());
|
||||||
|
|
||||||
|
passport.serializeUser((user, done) => {
|
||||||
|
done(null, user);
|
||||||
|
})
|
||||||
|
|
||||||
|
passport.deserializeUser((user: IUserAuth, done) => {
|
||||||
|
process.nextTick(async () => {
|
||||||
|
const userData = await AuthInstance.login(user);
|
||||||
|
return userData ? done(null, userData) : done(null, false);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// sign in method with passport local strategy
|
||||||
|
passport.use(new LocalStrategy(async (email, password, done) => {
|
||||||
|
try {
|
||||||
|
const response = await AuthInstance.login({ email, password });
|
||||||
|
return done(null, response);
|
||||||
|
} catch (e: any) {
|
||||||
|
return done(e);
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
return passport;
|
||||||
|
}
|
||||||
@@ -28,6 +28,18 @@ export class User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getOneByEmail(email: string) {
|
||||||
|
try {
|
||||||
|
const statement = `SELECT * FROM recipin.appusers WHERE email = $1`;
|
||||||
|
const result = await pool.query(statement, [email]);
|
||||||
|
if (result.rows.length) return result.rows[0];
|
||||||
|
return null;
|
||||||
|
} catch (e: any) {
|
||||||
|
throw new Error(e);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async updateOneByID(id: string, data: IUser) {
|
async updateOneByID(id: string, data: IUser) {
|
||||||
try {
|
try {
|
||||||
const statement = `
|
const statement = `
|
||||||
@@ -55,13 +67,13 @@ export class User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async post(data: IUser) {
|
async post(data: IUser): Promise<Array<any> | null> {
|
||||||
const { firstname, lastname, handle, email, password, active } = data;
|
const { firstname, lastname, handle, email, password, active } = data;
|
||||||
try {
|
try {
|
||||||
const statement = `INSERT INTO recipin.appusers (firstname, lastname, handle, email, password, active) VALUES ($1, $2, $3, $4, $5, $6)`;
|
const statement = `INSERT INTO recipin.appusers (firstname, lastname, handle, email, password, active) VALUES ($1, $2, $3, $4, $5, $6)`;
|
||||||
const params = [firstname, lastname, handle, email, password, active];
|
const params = [firstname, lastname, handle, email, password, active];
|
||||||
const result = await pool.query(statement, params);
|
const result = await pool.query(statement, params);
|
||||||
if (result.rows.length) return result.rows;
|
if (result.rows.length) return result.rows as Array<keyof IUser>;
|
||||||
return null;
|
return null;
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
throw new Error(error);
|
throw new Error(error);
|
||||||
|
|||||||
810
server/package-lock.json
generated
810
server/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bcrypt": "^5.1.0",
|
"bcrypt": "^5.1.0",
|
||||||
"body-parser": "^1.20.1",
|
"body-parser": "^1.20.1",
|
||||||
|
"connect-pg-simple": "^8.0.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
@@ -23,6 +24,7 @@
|
|||||||
"helmet": "^6.0.0",
|
"helmet": "^6.0.0",
|
||||||
"http-errors": "^2.0.0",
|
"http-errors": "^2.0.0",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
|
"morgan": "^1.10.0",
|
||||||
"passport": "^0.6.0",
|
"passport": "^0.6.0",
|
||||||
"passport-local": "^1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
"pg": "^8.8.0",
|
"pg": "^8.8.0",
|
||||||
@@ -30,12 +32,18 @@
|
|||||||
"swagger-ui-express": "^4.6.0"
|
"swagger-ui-express": "^4.6.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/bcrypt": "^5.0.0",
|
||||||
|
"@types/connect-pg-simple": "^7.0.0",
|
||||||
"@types/cors": "^2.8.12",
|
"@types/cors": "^2.8.12",
|
||||||
"@types/dotenv": "^8.2.0",
|
"@types/dotenv": "^8.2.0",
|
||||||
"@types/express": "^4.17.14",
|
"@types/express": "^4.17.14",
|
||||||
|
"@types/express-session": "^1.17.5",
|
||||||
"@types/http-errors": "^2.0.1",
|
"@types/http-errors": "^2.0.1",
|
||||||
"@types/js-yaml": "^4.0.5",
|
"@types/js-yaml": "^4.0.5",
|
||||||
|
"@types/morgan": "^1.9.3",
|
||||||
"@types/node": "^18.11.9",
|
"@types/node": "^18.11.9",
|
||||||
|
"@types/passport": "^1.0.11",
|
||||||
|
"@types/passport-local": "^1.0.34",
|
||||||
"@types/pg": "^8.6.5",
|
"@types/pg": "^8.6.5",
|
||||||
"@types/pg-promise": "^5.4.3",
|
"@types/pg-promise": "^5.4.3",
|
||||||
"@types/swagger-ui-express": "^4.1.3",
|
"@types/swagger-ui-express": "^4.1.3",
|
||||||
|
|||||||
@@ -37,4 +37,9 @@ export interface IGroceryList {
|
|||||||
recipes?: IRecipe["id"][]
|
recipes?: IRecipe["id"][]
|
||||||
active: boolean
|
active: boolean
|
||||||
ownerid: IUser["id"]
|
ownerid: IUser["id"]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IUserAuth {
|
||||||
|
email: string
|
||||||
|
password: string
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
"strict": true,
|
"strict": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"baseUrl": ".",
|
"baseUrl": "./*",
|
||||||
"paths": {
|
"paths": {
|
||||||
"*": [
|
"*": [
|
||||||
"node_modules/*"
|
"node_modules/*"
|
||||||
|
|||||||
Reference in New Issue
Block a user