mirror of
https://github.com/GithubOrgProjectPiza/server.git
synced 2026-09-04 08:36:10 +02:00
Merge pull request #3 from GithubOrgProjectPiza/feature-mailserver
Feature mailserver
This commit is contained in:
@@ -102,3 +102,6 @@ dist
|
|||||||
|
|
||||||
# TernJS port file
|
# TernJS port file
|
||||||
.tern-port
|
.tern-port
|
||||||
|
|
||||||
|
# Compiled mjml templates
|
||||||
|
.hbs
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
version: "3.4"
|
||||||
|
services:
|
||||||
|
mail:
|
||||||
|
image: boky/postfix
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
- ALLOWED_SENDER_DOMAINS=mail.${DOMAIN}
|
||||||
|
ports:
|
||||||
|
- "587:587"
|
||||||
|
container_name: "postfix"
|
||||||
|
volumes:
|
||||||
|
- ./host/keys/:/etc/opendkim/keys
|
||||||
|
postgres:
|
||||||
|
image: postgres
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
- POSTGRES_USER=server
|
||||||
|
- POSTGRES_PASSWORD=${DATABASE_PASSWORD}
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
redis:
|
||||||
|
image: redis
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "6379:6379"
|
||||||
Generated
-3745
File diff suppressed because it is too large
Load Diff
+16
-2
@@ -20,11 +20,25 @@
|
|||||||
"homepage": "https://github.com/GithubOrgProjectPiza/server#readme",
|
"homepage": "https://github.com/GithubOrgProjectPiza/server#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/client": "^3.10.0",
|
"@prisma/client": "^3.10.0",
|
||||||
|
"@types/argon2": "^0.15.0",
|
||||||
"@types/express": "^4.17.13",
|
"@types/express": "^4.17.13",
|
||||||
"axios": "^0.26.1",
|
"@types/handlebars": "^4.1.0",
|
||||||
|
"@types/jsonwebtoken": "^8.5.8",
|
||||||
|
"@types/mjml": "^4.7.0",
|
||||||
|
"@types/nodemailer": "^6.4.4",
|
||||||
|
"@types/redis": "^4.0.11",
|
||||||
|
"argon2": "^0.28.5",
|
||||||
|
"dotenv": "^16.0.0",
|
||||||
"express": "^4.17.3",
|
"express": "^4.17.3",
|
||||||
|
"handlebars": "^4.7.7",
|
||||||
|
"jsonwebtoken": "^8.5.1",
|
||||||
|
"mjml": "^4.12.0",
|
||||||
|
"nanoid": "^3.3.2",
|
||||||
|
"nodemailer": "^6.7.2",
|
||||||
|
"prisma": "^3.10.0",
|
||||||
|
"redis": "^4.0.4",
|
||||||
|
"axios": "^0.26.1",
|
||||||
"node-fetch": "^3.2.3",
|
"node-fetch": "^3.2.3",
|
||||||
"prisma": "^3.11.1",
|
|
||||||
"ts-node": "^10.5.0",
|
"ts-node": "^10.5.0",
|
||||||
"typescript": "^4.5.5"
|
"typescript": "^4.5.5"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ model User {
|
|||||||
passwordHash String
|
passwordHash String
|
||||||
passwordSalt String
|
passwordSalt String
|
||||||
role Role @default(USER)
|
role Role @default(USER)
|
||||||
|
status Status @default(UNVERIFIED)
|
||||||
organization Organization @relation(fields: [organizationId], references: [id])
|
organization Organization @relation(fields: [organizationId], references: [id])
|
||||||
organizationId Int
|
organizationId Int
|
||||||
orders Order[]
|
orders Order[]
|
||||||
@@ -63,3 +64,8 @@ enum Role {
|
|||||||
USER
|
USER
|
||||||
ADMIN
|
ADMIN
|
||||||
}
|
}
|
||||||
|
enum Status {
|
||||||
|
UNVERIFIED
|
||||||
|
VERIFIED
|
||||||
|
ENABLED
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<mjml>
|
||||||
|
<mj-body>
|
||||||
|
<mj-section>
|
||||||
|
<mj-column>
|
||||||
|
<mj-text font-size="20px" color="#6FB98F" font-family="helvetica" align="center">
|
||||||
|
πzza verification Email
|
||||||
|
</mj-text>
|
||||||
|
|
||||||
|
<mj-divider border-color="#6FB98F"></mj-divider>
|
||||||
|
|
||||||
|
<mj-text font-size="20px" color="#333" font-family="helvetica" align="center"
|
||||||
|
>Vielen Dank für deine Registrierung!<br />
|
||||||
|
Bitte klicke nun auf diesen Button,<br />
|
||||||
|
um den Konto zu bestätigen.</mj-text
|
||||||
|
>
|
||||||
|
|
||||||
|
<mj-button
|
||||||
|
background-color="#6FB98F"
|
||||||
|
font-family="helvetica"
|
||||||
|
font-size="20px"
|
||||||
|
border-radius="10px"
|
||||||
|
href="{{link}}"
|
||||||
|
>Hier Clicken</mj-button
|
||||||
|
>
|
||||||
|
|
||||||
|
<mj-text font-size="20px" color="#333" font-family="helvetica" align="center"
|
||||||
|
>Mit Freundlichen grüßen dein πzza Team</mj-text
|
||||||
|
>
|
||||||
|
</mj-column>
|
||||||
|
</mj-section>
|
||||||
|
</mj-body>
|
||||||
|
</mjml>
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
|
||||||
|
#load .env file
|
||||||
|
|
||||||
|
[[ -f .env ]] || { echo "`tput setaf 1`✗`tput sgr0` Could not find .env file are you in the correct directory (you should be in the server directory)"; exit 1;}
|
||||||
|
|
||||||
|
set -o allexport
|
||||||
|
[[ -f .env ]] && source .env
|
||||||
|
set +o allexport
|
||||||
|
|
||||||
|
#static variables
|
||||||
|
NC='tput sgr0' #No Color
|
||||||
|
GREEN='tput setaf 2'
|
||||||
|
RED='tput setaf 1'
|
||||||
|
|
||||||
|
|
||||||
|
#check dependencies
|
||||||
|
command -v opendkim-genkey >/dev/null 2>&1 || { echo >&2 "`$RED`✗`$NC` Opendkim not installed install with your favorite package manager (opendkim-tools | opendkim-utils)"; exit 1;}
|
||||||
|
|
||||||
|
#generate dkim keys
|
||||||
|
mkdir -p ./host/keys
|
||||||
|
echo "`$GREEN`✓`$NC` Created folder"
|
||||||
|
|
||||||
|
cd ./host/keys
|
||||||
|
opendkim-genkey -b 2048 -h rsa-sha256 -r -v --subdomains -s mail -d mail.$DOMAIN
|
||||||
|
sed -i 's/h=rsa-sha256/sha256/' mail.txt
|
||||||
|
mv mail.private mail.$DOMAIN.private
|
||||||
|
mv mail.txt mail.$DOMAIN.txt
|
||||||
|
|
||||||
|
echo "`$GREEN`✓`$NC` Generated dkim keys"
|
||||||
|
|
||||||
|
exit 0
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
import express from "express";
|
||||||
|
import { Request, Response } from "express";
|
||||||
|
import prisma from "../lib/prisma.lib";
|
||||||
|
import { Role, Status } from "@prisma/client";
|
||||||
|
import { createDefaultError, createDefaultSucces } from "../lib/standardResponse";
|
||||||
|
import argon2 from "argon2";
|
||||||
|
import jwt from "jsonwebtoken";
|
||||||
|
import { emailClient } from "../lib/redis.lib";
|
||||||
|
import { nanoid } from "nanoid";
|
||||||
|
import { verificationMail } from "../lib/mail";
|
||||||
|
|
||||||
|
const JWT_SECRET = process.env.jwtsecret || "secret";
|
||||||
|
|
||||||
|
interface registerBody {
|
||||||
|
name: string;
|
||||||
|
password: string;
|
||||||
|
role: string;
|
||||||
|
organization?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface authJwt {
|
||||||
|
id: number;
|
||||||
|
role: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ROLES: readonly string[] = [Role.ADMIN, Role.USER];
|
||||||
|
|
||||||
|
export const register = async (req: Request, res: Response) => {
|
||||||
|
const { name, password, role, organization } = req.body || {};
|
||||||
|
|
||||||
|
if (
|
||||||
|
!(
|
||||||
|
typeof name === "string" &&
|
||||||
|
typeof password === "string" &&
|
||||||
|
ROLES.includes(role) &&
|
||||||
|
typeof organization === "number"
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return res.status(400).json(
|
||||||
|
createDefaultError("Request body does not match required parameters", {
|
||||||
|
name: "string",
|
||||||
|
password: "string",
|
||||||
|
organization: "int",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const hash = await argon2.hash("salty" + password + "salty");
|
||||||
|
|
||||||
|
if (!(await prisma.organization.findUnique({ where: { id: organization } }))) {
|
||||||
|
return res.status(404).json(createDefaultError(`Could not find organization with id ${organization}`, {}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role ? ("USER" as Role) === Role.ADMIN : Role) {
|
||||||
|
if (req.auth?.role !== Role.ADMIN) {
|
||||||
|
return res.status(401).json(createDefaultError(`Unauthorized`, {}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = await prisma.user.create({
|
||||||
|
data: {
|
||||||
|
email: name,
|
||||||
|
passwordSalt: "salty",
|
||||||
|
passwordHash: hash,
|
||||||
|
role: role as Role,
|
||||||
|
status: role === Role.ADMIN ? Status.UNVERIFIED : Status.ENABLED,
|
||||||
|
organization: { connect: { id: organization } || undefined },
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
email: true,
|
||||||
|
role: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const usid = nanoid();
|
||||||
|
|
||||||
|
(await emailClient).set(usid, user.id);
|
||||||
|
|
||||||
|
verificationMail(name, usid);
|
||||||
|
|
||||||
|
res.status(201).json(createDefaultSucces("User created succesfully", user));
|
||||||
|
};
|
||||||
|
|
||||||
|
export const authenthicate = async (req: Request, res: Response) => {
|
||||||
|
const { name, password } = req.body || {};
|
||||||
|
|
||||||
|
if (!(typeof name === "string" && typeof password === "string")) {
|
||||||
|
return res.status(400).json(
|
||||||
|
createDefaultError("Request body does not match required parameters", {
|
||||||
|
name: "string",
|
||||||
|
password: "string",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const hash = await argon2.hash("salty" + password + "salty");
|
||||||
|
|
||||||
|
const user = await prisma.user.findUnique({ where: { email: name } });
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return res.status(403).json(createDefaultError("Username or Password wrong", {}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.passwordHash !== hash) {
|
||||||
|
return res.status(403).json(createDefaultError("Username or Password wrong", {}));
|
||||||
|
}
|
||||||
|
|
||||||
|
const userjwt: authJwt = {
|
||||||
|
id: user.id,
|
||||||
|
role: user.role,
|
||||||
|
};
|
||||||
|
|
||||||
|
req.headers.authorization = jwt.sign(userjwt, JWT_SECRET);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const verifyEmail = async (req: Request, res: Response) => {
|
||||||
|
const { code } = req.body || {};
|
||||||
|
|
||||||
|
if (!(typeof code === "string")) {
|
||||||
|
return res.status(400).json(
|
||||||
|
createDefaultError("Request body does not match required parameters", {
|
||||||
|
code: "string",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const acc: number | undefined = emailClient.get(code);
|
||||||
|
|
||||||
|
if (!acc) {
|
||||||
|
return res.status(404).json(createDefaultError("The code is invalid", {}));
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = prisma.user.update({
|
||||||
|
where: {
|
||||||
|
id: acc,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
status: Status.VERIFIED,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
import { authJwt } from "./controller/auth.controller";
|
||||||
|
|
||||||
|
declare module "express-serve-static-core" {
|
||||||
|
interface Request {
|
||||||
|
auth?: authJwt & { isAuthenthicated: boolean };
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
-10
@@ -1,24 +1,43 @@
|
|||||||
import express from "express";
|
import express, { NextFunction, Request, Response } from "express";
|
||||||
const app = express();
|
import dotenv from "dotenv";
|
||||||
|
|
||||||
|
import adminRoutes from "./routes/auth.route";
|
||||||
const testRoutes = require("./routes/testrouter.route");
|
const testRoutes = require("./routes/testrouter.route");
|
||||||
const ordersRoutes = require("./routes/orders.route");
|
const ordersRoutes = require("./routes/orders.route");
|
||||||
const organizationsRoutes = require("./routes/organisations.route");
|
const organizationsRoutes = require("./routes/organisations.route");
|
||||||
const pizzasRoutes = require("./routes/pizzas.route");
|
const pizzasRoutes = require("./routes/pizzas.route");
|
||||||
const restaurantsRoutes = require("./routes/restaurants.route");
|
const restaurantsRoutes = require("./routes/restaurants.route");
|
||||||
|
|
||||||
|
dotenv.config();
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
|
||||||
|
// Bodyparser and urlencoded to parse post request bodies
|
||||||
|
app.use(express.urlencoded({ extended: true }));
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
app.use("/tests", testRoutes);
|
|
||||||
app.use("/order", ordersRoutes);
|
app.use((err: any, req: Request, res: Response, next: NextFunction) => {
|
||||||
app.use("/organization", organizationsRoutes);
|
if (err) {
|
||||||
app.use("/pizza", pizzasRoutes);
|
res.status(400).send({
|
||||||
app.use("/restaurant", restaurantsRoutes);
|
type: "error",
|
||||||
|
payload: "The body of your request did not contain valid data",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
app.get("/", (req, res) => {
|
|
||||||
res.send("Hello World!");
|
|
||||||
});
|
|
||||||
|
|
||||||
|
app.use("/api/auth", adminRoutes);
|
||||||
|
app.use(express.json());
|
||||||
|
app.use("/tests", testRoutes);
|
||||||
|
app.use("/order", ordersRoutes);
|
||||||
|
app.use("/organization", organizationsRoutes);
|
||||||
|
app.use("/pizza", pizzasRoutes);
|
||||||
|
app.use("/restaurant", restaurantsRoutes);
|
||||||
|
|
||||||
app.listen(3000, () => {
|
app.listen(3000, () => {
|
||||||
console.log("Server is running on port 3000");
|
console.log("Server is running on port 3000");
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import Handlebars, { template } from "handlebars";
|
||||||
|
import nodemailer from "nodemailer";
|
||||||
|
import SMTPTransport from "nodemailer/lib/smtp-transport";
|
||||||
|
|
||||||
|
import mjml from "./mjml";
|
||||||
|
|
||||||
|
export let mailAccount = {
|
||||||
|
user: process.env.MAILUSER + "@mail." + process.env.DOMAIN,
|
||||||
|
pass: process.env.MAILPASSWORD || "password",
|
||||||
|
};
|
||||||
|
|
||||||
|
let transporter =
|
||||||
|
process.env.DEV == "true" || process.env.DOMAIN == undefined
|
||||||
|
? (async () => {
|
||||||
|
mailAccount = await nodemailer.createTestAccount();
|
||||||
|
//mailAccount = {
|
||||||
|
// user: "",
|
||||||
|
// pass: "",
|
||||||
|
//};
|
||||||
|
if (process.env.NODE_ENV != "test") {
|
||||||
|
console.log(mailAccount);
|
||||||
|
}
|
||||||
|
return nodemailer.createTransport({
|
||||||
|
host: "smtp.ethereal.email",
|
||||||
|
port: 587,
|
||||||
|
secure: false, // true for 465, false for other ports
|
||||||
|
auth: {
|
||||||
|
user: mailAccount.user, // generated ethereal user
|
||||||
|
pass: mailAccount.pass, // generated ethereal password
|
||||||
|
},
|
||||||
|
});
|
||||||
|
})()
|
||||||
|
: nodemailer.createTransport(
|
||||||
|
new SMTPTransport({
|
||||||
|
host: "localhost",
|
||||||
|
port: 587,
|
||||||
|
secure: false,
|
||||||
|
auth: {
|
||||||
|
user: mailAccount.user,
|
||||||
|
pass: mailAccount.pass,
|
||||||
|
},
|
||||||
|
tls: {
|
||||||
|
rejectUnauthorized: false,
|
||||||
|
secureProtocol: "TLSv1_method",
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const sendMail = async (from: string, to: string, subject: string, text?: string, html?: string) => {
|
||||||
|
return await (
|
||||||
|
await transporter
|
||||||
|
).sendMail({
|
||||||
|
from: from,
|
||||||
|
to: to,
|
||||||
|
subject: subject,
|
||||||
|
text: text,
|
||||||
|
html: html,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const verificationMail = async (to: string, id: string) => {
|
||||||
|
const raw = mjml.getTemplate("verify");
|
||||||
|
|
||||||
|
//TODO: Replace other handlebars with final values
|
||||||
|
const message = Handlebars.compile(raw);
|
||||||
|
|
||||||
|
const data = {};
|
||||||
|
const compiled = message(data);
|
||||||
|
|
||||||
|
sendMail(mailAccount.user, to, "Verify Email", undefined, compiled);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default { sendMail };
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import fs from "fs";
|
||||||
|
import path from "path";
|
||||||
|
import mjml from "mjml";
|
||||||
|
|
||||||
|
const template_folder = __dirname + "/../../resources/email/templates/";
|
||||||
|
|
||||||
|
const compileTemplates = () => {
|
||||||
|
console.log("Compiling templates: ");
|
||||||
|
|
||||||
|
fs.readdir(template_folder, (err, files) => {
|
||||||
|
if (err) console.log(err);
|
||||||
|
|
||||||
|
files.forEach((file) => {
|
||||||
|
if (path.extname(file) !== ".mjml") return;
|
||||||
|
|
||||||
|
let content = fs.readFileSync(template_folder + file);
|
||||||
|
let mjmlres = mjml(content.toString());
|
||||||
|
|
||||||
|
let hbs = template_folder + file.replace(".mjml", ".hbs");
|
||||||
|
fs.writeFileSync(hbs, mjmlres.html);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
compileTemplates(); // This will compile all templates when this file is first included
|
||||||
|
|
||||||
|
const getTemplate = (name: string): string => {
|
||||||
|
let file = "";
|
||||||
|
file = fs.readFileSync(path.join(template_folder, name + ".hbs")).toString();
|
||||||
|
return file;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default { getTemplate };
|
||||||
@@ -6,3 +6,4 @@ let prisma: PrismaClient;
|
|||||||
prisma = new PrismaClient();
|
prisma = new PrismaClient();
|
||||||
|
|
||||||
export default prisma;
|
export default prisma;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import redis, { createClient } from "redis";
|
||||||
|
import { promisify } from "util";
|
||||||
|
|
||||||
|
function createAsyncClient(client: redis.RedisClientType) {
|
||||||
|
return {
|
||||||
|
get: promisify(client.get).bind(client),
|
||||||
|
set: promisify(client.set).bind(client),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*----E-mail verify----*/
|
||||||
|
|
||||||
|
const email: redis.RedisClientType = createClient({
|
||||||
|
url: "redis://localhost:6379",
|
||||||
|
});
|
||||||
|
|
||||||
|
email.connect();
|
||||||
|
|
||||||
|
export const emailClient = createAsyncClient(email);
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
export const createDefaultError = (message: string, context: any) => ({
|
||||||
|
"type": "error",
|
||||||
|
"payload": {
|
||||||
|
"message": message,
|
||||||
|
"context": context,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export const createDefaultSucces = (message: string, context: any) => ({
|
||||||
|
"type": "success",
|
||||||
|
"payload": {
|
||||||
|
"message": message,
|
||||||
|
"context": context,
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
/// <reference path="../custom.d.ts" />
|
||||||
|
|
||||||
|
import { NextFunction, Request, Response } from "express";
|
||||||
|
import { createDefaultError } from "../lib/standardResponse";
|
||||||
|
import jwt, { JwtPayload } from "jsonwebtoken";
|
||||||
|
import { authJwt } from "../controller/auth.controller";
|
||||||
|
import prisma from "../lib/prisma.lib";
|
||||||
|
import { emailClient } from "../lib/redis.lib";
|
||||||
|
|
||||||
|
const verifyAuthorizationFormat = (authorization: string) => /^Bearer .+$/.test(authorization);
|
||||||
|
|
||||||
|
const getBearerToken = (authorization: string) => authorization.slice(7);
|
||||||
|
|
||||||
|
const JWT_SECRET = process.env.jwtsecret || "secret";
|
||||||
|
|
||||||
|
export const getAuthenthication = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
const { authorization } = req.headers;
|
||||||
|
|
||||||
|
if (!authorization) {
|
||||||
|
next();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!verifyAuthorizationFormat(authorization)) {
|
||||||
|
return res.status(400).json(createDefaultError("Malformed Bearer Token", { format: "Bearer <token>" }));
|
||||||
|
}
|
||||||
|
|
||||||
|
let payload_: string | JwtPayload;
|
||||||
|
|
||||||
|
try {
|
||||||
|
payload_ = jwt.verify(getBearerToken(authorization), JWT_SECRET);
|
||||||
|
} catch (e) {
|
||||||
|
return res.status(403).json(createDefaultError("The Token could not be verified, it might be expiered", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = payload_ as authJwt;
|
||||||
|
|
||||||
|
const { id } = payload;
|
||||||
|
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: { id },
|
||||||
|
select: {
|
||||||
|
role: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
req.auth = {
|
||||||
|
isAuthenthicated: true,
|
||||||
|
id,
|
||||||
|
role: user?.role || "user",
|
||||||
|
};
|
||||||
|
|
||||||
|
next();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const requireAuthentication = async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
const { authorization } = req.headers;
|
||||||
|
|
||||||
|
if (!authorization) {
|
||||||
|
return res.status(403).json(createDefaultError("The request did not contain a authorization header", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!verifyAuthorizationFormat(authorization)) {
|
||||||
|
return res.status(400).json(createDefaultError("Malformed Bearer Token", { format: "Bearer <token>" }));
|
||||||
|
}
|
||||||
|
|
||||||
|
let payload_: string | JwtPayload;
|
||||||
|
|
||||||
|
try {
|
||||||
|
payload_ = jwt.verify(getBearerToken(authorization), JWT_SECRET);
|
||||||
|
} catch (e) {
|
||||||
|
return res.status(403).json(createDefaultError("The Token could not be verified, it might be expiered", null));
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = payload_ as authJwt;
|
||||||
|
|
||||||
|
const { id } = payload;
|
||||||
|
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: { id },
|
||||||
|
select: {
|
||||||
|
role: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
req.auth = {
|
||||||
|
isAuthenthicated: true,
|
||||||
|
id,
|
||||||
|
role: user?.role || "USER",
|
||||||
|
};
|
||||||
|
|
||||||
|
next();
|
||||||
|
};
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { Router } from "express";
|
||||||
|
import { register } from "../controller/auth.controller";
|
||||||
|
import { getAuthenthication } from "../middleware/auth.middle";
|
||||||
|
|
||||||
|
const router = Router();
|
||||||
|
|
||||||
|
router.post("/register", getAuthenthication, register);
|
||||||
|
|
||||||
|
export default router;
|
||||||
Reference in New Issue
Block a user