user registration connects to front end
This commit is contained in:
@@ -2,36 +2,37 @@ import { IUser, IUserAuth } from "../schemas";
|
||||
import { User } from "../models/user";
|
||||
import createError from "http-errors";
|
||||
import bcrypt from "bcrypt";
|
||||
import { QueryResult } from "pg";
|
||||
import now from "../util/now";
|
||||
|
||||
const UserInstance = new User();
|
||||
|
||||
export default class AuthService {
|
||||
// methods for local strategies
|
||||
async register(data: IUser): Promise<Array<keyof IUser>> {
|
||||
async register(data: IUser) {
|
||||
const { email, password } = data;
|
||||
|
||||
data.datecreated = now;
|
||||
data.datemodified = now;
|
||||
data.active = true;
|
||||
|
||||
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) => {
|
||||
bcrypt.genSalt(10, (err, salt) => {
|
||||
if (err) throw err;
|
||||
bcrypt.hash(password, salt, (err, hash) => {
|
||||
bcrypt.hash(password, salt, async (err, hash) => {
|
||||
if (err) throw err;
|
||||
|
||||
createdUser = {
|
||||
const newData = {
|
||||
...data,
|
||||
password: hash
|
||||
}
|
||||
|
||||
const result = await UserInstance.post(newData);
|
||||
if (result) console.log(result);
|
||||
return result;
|
||||
})
|
||||
})
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ export default async function populate() {
|
||||
|
||||
const populateUsers = `
|
||||
INSERT INTO recipin.appusers
|
||||
(firstname, lastname, handle, email, password, active, dateregistered, datelastactive)
|
||||
(firstname, lastname, handle, email, password, active, datecreated, datemodified)
|
||||
VALUES
|
||||
('Mikayla', 'Dobson', 'innocuoussymmetry', 'mikaylaherself@gmail.com', 'password1', true, $1, $1),
|
||||
('Emily', 'Dobson', 'emjdobson', 'emily@email.com', 'password2', true, $1, $1),
|
||||
@@ -68,9 +68,20 @@ export default async function populate() {
|
||||
;
|
||||
`
|
||||
|
||||
const populateComments = `
|
||||
INSERT INTO recipin.cmp_recipecomments
|
||||
(commentbody, datecreated, recipeid, authorid)
|
||||
VALUES
|
||||
('Very cool recipe!', $1, 2, 2),
|
||||
('I love making this one', $1, 1, 2),
|
||||
('Thanks for sharing this', $1, 1, 4)
|
||||
;
|
||||
`
|
||||
|
||||
const allStatements: Array<string> = [
|
||||
populateUsers, populateRecipes, populateCollection,
|
||||
populateIngredients, populateGroceryList, populateFriendships
|
||||
populateIngredients, populateGroceryList, populateFriendships,
|
||||
populateComments
|
||||
];
|
||||
|
||||
await pool.query(setup);
|
||||
|
||||
@@ -21,8 +21,8 @@ dotenv.config();
|
||||
email varchar NOT NULL UNIQUE,
|
||||
password varchar NOT NULL,
|
||||
active boolean NOT NULL,
|
||||
dateregistered varchar NOT NULL,
|
||||
datelastactive varchar NOT NULL
|
||||
datecreated varchar NOT NULL,
|
||||
datemodified varchar NOT NULL
|
||||
);
|
||||
`
|
||||
|
||||
@@ -76,7 +76,8 @@ dotenv.config();
|
||||
CREATE TABLE IF NOT EXISTS recipin.cmp_recipecomments (
|
||||
id INT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||
commentbody varchar NOT NULL,
|
||||
parentcommentid int,
|
||||
datecreated varchar NOT NULL,
|
||||
recipeid int REFERENCES recipin.recipe (id) NOT NULL,
|
||||
authorid int REFERENCES recipin.appusers (id) NOT NULL
|
||||
);
|
||||
`
|
||||
@@ -112,7 +113,7 @@ dotenv.config();
|
||||
`
|
||||
|
||||
const allStatements = [
|
||||
setRole, appusers, ingredient, collection, recipe,
|
||||
setRole, appusers, ingredient, collection, recipe, recipecomments,
|
||||
groceryList, recipeingredient, userscollections, userfriendships
|
||||
]
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { IUser } from "../schemas";
|
||||
import pgPromise from "pg-promise";
|
||||
import pool from '../db';
|
||||
import now from "../util/now";
|
||||
|
||||
const pgp = pgPromise({ capSQL: true });
|
||||
export class User {
|
||||
@@ -67,13 +68,22 @@ export class User {
|
||||
}
|
||||
|
||||
|
||||
async post(data: IUser): Promise<Array<any> | null> {
|
||||
async post(data: IUser) {
|
||||
const { firstname, lastname, handle, email, password, active } = data;
|
||||
const datecreated = now;
|
||||
const datemodified = now;
|
||||
|
||||
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 statement = `
|
||||
INSERT INTO recipin.appusers (
|
||||
firstname, lastname, handle, email, password,
|
||||
active, datecreated, datemodified)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
||||
RETURNING *;
|
||||
`;
|
||||
const params = [firstname, lastname, handle, email, password, active, datecreated, datemodified];
|
||||
const result = await pool.query(statement, params);
|
||||
if (result.rows.length) return result.rows as Array<keyof IUser>;
|
||||
if (result.rows.length) return result.rows;
|
||||
return null;
|
||||
} catch (error: any) {
|
||||
throw new Error(error);
|
||||
|
||||
@@ -23,6 +23,8 @@ export const authRoute = (app: Express, passport: PassportStatic) => {
|
||||
router.post('/register', async (req, res, next) => {
|
||||
try {
|
||||
const data: IUser = req.body;
|
||||
const now = new Intl.DateTimeFormat('en-US', {})
|
||||
|
||||
const response = await AuthInstance.register(data);
|
||||
res.status(200).send(response);
|
||||
} catch(e) {
|
||||
|
||||
@@ -1,45 +1,48 @@
|
||||
export interface IUser {
|
||||
interface HasHistory {
|
||||
datecreated?: string
|
||||
datemodified?: string
|
||||
}
|
||||
|
||||
interface CanDeactivate {
|
||||
active?: boolean
|
||||
}
|
||||
|
||||
interface DBEntity {
|
||||
id?: number
|
||||
}
|
||||
|
||||
export interface IUser extends DBEntity, HasHistory, CanDeactivate {
|
||||
firstname: string
|
||||
lastname: string
|
||||
handle: string
|
||||
email: string
|
||||
password: string
|
||||
active: boolean
|
||||
}
|
||||
|
||||
export interface IRecipe {
|
||||
id?: number
|
||||
name: string
|
||||
description?: string
|
||||
preptime: string
|
||||
removed: boolean
|
||||
authoruserid?: IUser["id"]
|
||||
}
|
||||
|
||||
export interface IIngredient {
|
||||
id?: number
|
||||
name: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
export interface ICollection {
|
||||
id?: number
|
||||
name: string
|
||||
active: string
|
||||
ismaincollection: boolean
|
||||
ownerid?: IUser["id"]
|
||||
}
|
||||
|
||||
export interface IGroceryList {
|
||||
id?: number
|
||||
name: string
|
||||
recipes?: IRecipe["id"][]
|
||||
active: boolean
|
||||
ownerid?: IUser["id"]
|
||||
}
|
||||
|
||||
export interface IUserAuth {
|
||||
email: string
|
||||
password: string
|
||||
}
|
||||
|
||||
export interface IRecipe extends DBEntity, HasHistory, CanDeactivate {
|
||||
name: string
|
||||
description?: string
|
||||
preptime: string
|
||||
authoruserid?: IUser["id"]
|
||||
}
|
||||
|
||||
export interface IIngredient extends DBEntity, HasHistory {
|
||||
name: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
export interface ICollection extends DBEntity, HasHistory, CanDeactivate {
|
||||
name: string
|
||||
ismaincollection: boolean
|
||||
ownerid?: IUser["id"]
|
||||
}
|
||||
|
||||
export interface IGroceryList extends DBEntity, HasHistory, CanDeactivate {
|
||||
name: string
|
||||
ownerid?: IUser["id"]
|
||||
}
|
||||
2
server/util/now.ts
Normal file
2
server/util/now.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
const now = new Intl.DateTimeFormat('en-US', { dateStyle: 'medium', timeStyle: 'long' }).format(Date.now())
|
||||
export default now;
|
||||
Reference in New Issue
Block a user