default values for env and critic check for values

This commit is contained in:
Julian Krauser 2024-08-25 18:07:34 +02:00
parent b3d1c2d729
commit d889f92643
8 changed files with 92 additions and 27 deletions

View file

@ -1,5 +1,6 @@
import { dataSource } from "../data-source";
import { refresh } from "../entity/refresh";
import { REFRESH_EXPIRATION } from "../env.defaults";
import InternalException from "../exceptions/internalException";
import { JWTHelper } from "../helpers/jwtHelper";
import { StringHelper } from "../helpers/stringHelper";
@ -28,7 +29,7 @@ export default abstract class RefreshCommandHandler {
.values({
token: refreshToken,
user: await UserService.getById(createRefresh.userId),
expiry: new Date(Date.now() + ms(process.env.REFRESH_EXPIRATION)),
expiry: new Date(Date.now() + ms(REFRESH_EXPIRATION)),
})
.execute()
.then((result) => {

View file

@ -15,6 +15,7 @@ import MailHelper from "../helpers/mailHelper";
import InviteService from "../service/inviteService";
import UserService from "../service/userService";
import CustomRequestException from "../exceptions/customRequestException";
import { CLUB_NAME } from "../env.defaults";
/**
* @description start first user
@ -43,7 +44,7 @@ export async function inviteUser(req: Request, res: Response): Promise<any> {
throw new CustomRequestException(409, "Username and Mail are already in use");
}
var secret = speakeasy.generateSecret({ length: 20, name: `Mitgliederverwaltung ${process.env.CLUB_NAME}` });
var secret = speakeasy.generateSecret({ length: 20, name: `Mitgliederverwaltung ${CLUB_NAME}` });
let createInvite: CreateInviteCommand = {
username: username,
@ -58,7 +59,7 @@ export async function inviteUser(req: Request, res: Response): Promise<any> {
let mailhelper = new MailHelper();
await mailhelper.sendMail(
mail,
`Email Bestätigung für Mitglieder Admin-Portal von ${process.env.CLUB_NAME}`,
`Email Bestätigung für Mitglieder Admin-Portal von ${CLUB_NAME}`,
`Öffne folgenden Link: ${origin}/setup/verify?mail=${mail}&token=${token}`
);
@ -77,11 +78,14 @@ export async function verifyInvite(req: Request, res: Response): Promise<any> {
let { secret } = await InviteService.getByMailAndToken(mail, token);
const url = `otpauth://totp/Mitgliederverwaltung ${process.env.CLUB_NAME}?secret=${secret}`;
const url = `otpauth://totp/Mitgliederverwaltung ${CLUB_NAME}?secret=${secret}`;
QRCode.toDataURL(url)
.then((result) => {
res.send(result);
res.json({
dataUrl: result,
otp: secret,
});
})
.catch((err) => {
throw new InternalException("QRCode not created");

View file

@ -9,14 +9,15 @@ import { invite } from "./entity/invite";
import { Initial1724317398939 } from "./migrations/1724317398939-initial";
import { RefreshPrimaryChange1724573307851 } from "./migrations/1724573307851-refreshPrimaryChange";
import { Invite1724579024939 } from "./migrations/1724579024939-invite";
import { DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME } from "./env.defaults";
const dataSource = new DataSource({
type: "mysql",
host: process.env.NODE_ENV || process.env.DBMODE ? "localhost" : process.env.DB_HOST,
host: process.env.NODE_ENV || process.env.DBMODE ? "localhost" : DB_HOST,
port: 3306,
username: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
username: DB_USERNAME,
password: DB_PASSWORD,
database: DB_NAME,
synchronize: false,
logging: process.env.NODE_ENV ? true : ["schema", "error", "warn", "log", "migration"],
bigNumberStrings: false,

51
src/env.defaults.ts Normal file
View file

@ -0,0 +1,51 @@
import "dotenv/config";
import ms from "ms";
export const DB_HOST = process.env.DB_HOST ?? "";
export const DB_NAME = process.env.DB_NAME ?? "";
export const DB_USERNAME = process.env.DB_USERNAME ?? "";
export const DB_PASSWORD = process.env.DB_PASSWORD ?? "";
export const SERVER_PORT = Number(process.env.SERVER_PORT ?? 5000);
export const JWT_SECRET = process.env.JWT_SECRET ?? "my_jwt_secret_string_ilughfnadiuhgq§$IUZGFVRweiouarbt1oub3h5q4a";
export const JWT_EXPIRATION = process.env.JWT_EXPIRATION ?? "15m";
export const REFRESH_EXPIRATION = process.env.REFRESH_EXPIRATION ?? "1d";
export const MAIL_USERNAME = process.env.MAIL_USERNAME ?? "";
export const MAIL_PASSWORD = process.env.MAIL_PASSWORD ?? "";
export const MAIL_HOST = process.env.MAIL_HOST ?? "";
export const MAIL_PORT = Number(process.env.MAIL_PORT ?? "587");
export const MAIL_SECURE = process.env.MAIL_SECURE ?? "false";
export const CLUB_NAME = process.env.CLUB_NAME ?? "";
export function configCheck() {
if (DB_HOST == "" ?? typeof DB_HOST != "string") throw new Error("set valid value to DB_HOST");
if (DB_NAME == "" ?? typeof DB_NAME != "string") throw new Error("set valid value to DB_NAME");
if (DB_USERNAME == "" ?? typeof DB_USERNAME != "string") throw new Error("set valid value to DB_USERNAME");
if (DB_PASSWORD == "" ?? typeof DB_PASSWORD != "string") throw new Error("set valid value to DB_PASSWORD");
if (typeof SERVER_PORT != "number") throw new Error("set valid numeric value to SERVER_PORT");
if (JWT_SECRET == "" ?? typeof JWT_SECRET != "string") throw new Error("set valid value to JWT_SECRET");
checkMS(JWT_EXPIRATION, "JWT_EXPIRATION");
checkMS(REFRESH_EXPIRATION, "REFRESH_EXPIRATION");
if (MAIL_USERNAME == "" ?? typeof MAIL_USERNAME != "string") throw new Error("set valid value to MAIL_USERNAME");
if (MAIL_PASSWORD == "" ?? typeof MAIL_PASSWORD != "string") throw new Error("set valid value to MAIL_PASSWORD");
if (MAIL_HOST == "" ?? typeof MAIL_HOST != "string") throw new Error("set valid value to MAIL_HOST");
if (typeof MAIL_PORT != "number") throw new Error("set valid numeric value to MAIL_PORT");
if (MAIL_SECURE != "true" && MAIL_SECURE != "false") throw new Error("set 'true' or 'false' to MAIL_SECURE");
}
function checkMS(input: string, origin: string) {
try {
const result = ms(input);
if (result === undefined) {
throw new Error(`set valid ms value to ${origin}`);
}
} catch (e) {
throw new Error(`set valid ms value to ${origin}`);
}
}

View file

@ -1,10 +1,11 @@
import jwt from "jsonwebtoken";
import { JWTData } from "../type/jwtTypes";
import { JWT_SECRET, JWT_EXPIRATION } from "../env.defaults";
export abstract class JWTHelper {
static validate(token: string): Promise<string | jwt.JwtPayload> {
return new Promise<string | jwt.JwtPayload>((resolve, reject) => {
jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
jwt.verify(token, JWT_SECRET, (err, decoded) => {
if (err) reject(err.message);
else resolve(decoded);
});
@ -15,9 +16,9 @@ export abstract class JWTHelper {
return new Promise<string>((resolve, reject) => {
jwt.sign(
data,
process.env.JWT_SECRET,
JWT_SECRET,
{
expiresIn: process.env.JWT_EXPIRATION,
expiresIn: JWT_EXPIRATION,
},
(err, token) => {
if (err) reject(err.message);

View file

@ -1,16 +1,17 @@
import { Transporter, createTransport, TransportOptions } from "nodemailer";
import { CLUB_NAME, MAIL_HOST, MAIL_PASSWORD, MAIL_PORT, MAIL_SECURE, MAIL_USERNAME } from "../env.defaults";
export default class MailHelper {
private readonly transporter: Transporter;
constructor() {
this.transporter = createTransport({
host: process.env.MAIL_HOST,
port: Number(process.env.MAIL_PORT),
secure: (process.env.MAIL_SECURE as "true" | "false") == "true",
host: MAIL_HOST,
port: MAIL_PORT,
secure: (MAIL_SECURE as "true" | "false") == "true",
auth: {
user: process.env.MAIL_USERNAME,
pass: process.env.MAIL_PASSWORD,
user: MAIL_USERNAME,
pass: MAIL_PASSWORD,
},
} as TransportOptions);
}
@ -26,7 +27,7 @@ export default class MailHelper {
return new Promise((resolve, reject) => {
this.transporter
.sendMail({
from: `"${process.env.CLUB_NAME}" <${process.env.MAIL_USERNAME}>`,
from: `"${CLUB_NAME}" <${MAIL_USERNAME}>`,
to: target,
subject,
text: content,

View file

@ -1,11 +1,14 @@
import crypto from "crypto";
export abstract class StringHelper {
static random(len: number, charSet?: string): string {
charSet = charSet || "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var randomString = "";
for (var i = 0; i < len; i++) {
var randomPoz = Math.floor(Math.random() * charSet.length);
randomString += charSet.substring(randomPoz, randomPoz + 1);
}
return randomString;
// charSet = charSet || "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
// var randomString = "";
// for (var i = 0; i < len; i++) {
// var randomPoz = Math.floor(Math.random() * charSet.length);
// randomString += charSet.substring(randomPoz, randomPoz + 1);
// }
// return randomString;
return crypto.randomBytes(len).toString("base64");
}
}

View file

@ -1,6 +1,9 @@
import "dotenv/config";
import express from "express";
import { configCheck, SERVER_PORT } from "./env.defaults";
configCheck();
declare global {
namespace Express {
export interface Request {
@ -18,6 +21,6 @@ dataSource.initialize();
const app = express();
import router from "./routes/index";
router(app);
app.listen(process.env.SERVER_PORT, () => {
console.log(`listening on *:${process.env.SERVER_PORT}`);
app.listen(SERVER_PORT, () => {
console.log(`listening on *:${SERVER_PORT}`);
});