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 cors from 'cors';
|
||||
import dotenv from 'dotenv';
|
||||
dotenv.config({ path: './.env' });
|
||||
dotenv.config();
|
||||
|
||||
import { loaders } from './loaders';
|
||||
|
||||
|
||||
@@ -1,13 +1,27 @@
|
||||
import { Express } from 'express';
|
||||
import cors from 'cors';
|
||||
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) => {
|
||||
app.use(cors());
|
||||
app.use(bodyParser.json());
|
||||
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;
|
||||
}
|
||||
@@ -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) {
|
||||
try {
|
||||
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;
|
||||
try {
|
||||
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 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;
|
||||
} catch (error: any) {
|
||||
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": {
|
||||
"bcrypt": "^5.1.0",
|
||||
"body-parser": "^1.20.1",
|
||||
"connect-pg-simple": "^8.0.0",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.0.3",
|
||||
"express": "^4.18.2",
|
||||
@@ -23,6 +24,7 @@
|
||||
"helmet": "^6.0.0",
|
||||
"http-errors": "^2.0.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"morgan": "^1.10.0",
|
||||
"passport": "^0.6.0",
|
||||
"passport-local": "^1.0.0",
|
||||
"pg": "^8.8.0",
|
||||
@@ -30,12 +32,18 @@
|
||||
"swagger-ui-express": "^4.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bcrypt": "^5.0.0",
|
||||
"@types/connect-pg-simple": "^7.0.0",
|
||||
"@types/cors": "^2.8.12",
|
||||
"@types/dotenv": "^8.2.0",
|
||||
"@types/express": "^4.17.14",
|
||||
"@types/express-session": "^1.17.5",
|
||||
"@types/http-errors": "^2.0.1",
|
||||
"@types/js-yaml": "^4.0.5",
|
||||
"@types/morgan": "^1.9.3",
|
||||
"@types/node": "^18.11.9",
|
||||
"@types/passport": "^1.0.11",
|
||||
"@types/passport-local": "^1.0.34",
|
||||
"@types/pg": "^8.6.5",
|
||||
"@types/pg-promise": "^5.4.3",
|
||||
"@types/swagger-ui-express": "^4.1.3",
|
||||
|
||||
@@ -37,4 +37,9 @@ export interface IGroceryList {
|
||||
recipes?: IRecipe["id"][]
|
||||
active: boolean
|
||||
ownerid: IUser["id"]
|
||||
}
|
||||
|
||||
export interface IUserAuth {
|
||||
email: string
|
||||
password: string
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"outDir": "dist",
|
||||
"baseUrl": ".",
|
||||
"baseUrl": "./*",
|
||||
"paths": {
|
||||
"*": [
|
||||
"node_modules/*"
|
||||
|
||||
Reference in New Issue
Block a user