Skip to content
This repository has been archived by the owner on May 6, 2022. It is now read-only.

Commit

Permalink
Merge pull request #41 from Tolfix/dev
Browse files Browse the repository at this point in the history
v0.3
  • Loading branch information
Tolfx authored Dec 3, 2021
2 parents 2045b29 + 04ab283 commit ab89e72
Show file tree
Hide file tree
Showing 20 changed files with 263 additions and 114 deletions.
2 changes: 0 additions & 2 deletions src/Cache/CacheAdmin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ export const CacheAdmin = new Map<IAdministrator["uid"], IAdministrator>();
export function getAdminByUsername(username: IAdministrator["username"])
{
for (const [key, value] of CacheAdmin.entries())
{
if(value.username === username)
return key;
}

return null;
}
2 changes: 1 addition & 1 deletion src/Cache/reCache.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import AdminModel from "../Database/Schemas/Administrators";
import CategoryModel from "../Database/Schemas/Category";
import CustomerModel from "../Database/Schemas/Customer";
import CustomerModel from "../Database/Schemas/Customers/Customer";
import ImageModel from "../Database/Schemas/Images";
import OrderModel from "../Database/Schemas/Orders";
import ProductModel from "../Database/Schemas/Products";
Expand Down
2 changes: 1 addition & 1 deletion src/Cron/CronInvoices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { CronJob } from "cron";
import InvoiceModel from "../Database/Schemas/Invoices";
import Logger from "../Lib/Logger";
import dateFormat from "date-and-time";
import CustomerModel from "../Database/Schemas/Customer";
import CustomerModel from "../Database/Schemas/Customers/Customer";
import { d_Days } from "../Config";
import { sendInvoiceEmail, sendLateInvoiceEmail } from "../Lib/Invoices/SendEmail";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import mongoose, { Document, model, Schema } from "mongoose"
import increment from "mongoose-auto-increment";
import { MongoDB_URI } from "../../Config";
import { ICustomer } from "../../Interfaces/Customer";
import { MongoDB_URI } from "../../../Config";
import { ICustomer } from "../../../Interfaces/Customer";

const CustomerSchema = new Schema
(
Expand Down
27 changes: 27 additions & 0 deletions src/Database/Schemas/Customers/PasswordReset.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { model, Schema } from "mongoose"

const PasswordResetSchema = new Schema
(
{

token: {
type: String,
required: true,
},

email: {
type: String,
required: true,
},

used: {
type: Boolean,
default: false,
}

}
);

const PasswordResetModel = model("password_reset", PasswordResetSchema);

export default PasswordResetModel;
2 changes: 1 addition & 1 deletion src/Interfaces/Events/MainOnEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ export interface MainOnEvents
invoice_notified: IInvoice;
order_created: IOrder;
order_updated: IOrder;
order_deleted: IOrder;
order_deleted: IOrder;
}
2 changes: 1 addition & 1 deletion src/Lib/Invoices/CreatePDFInvoice.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import CustomerModel from "../../Database/Schemas/Customer";
import CustomerModel from "../../Database/Schemas/Customers/Customer";
import { IInvoice } from "../../Interfaces/Invoice";
import easyinvoice from 'easyinvoice';
import { createSwishQRCode } from "../../Payments/Swish";
Expand Down
2 changes: 1 addition & 1 deletion src/Payments/Stripe.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import stripe from "stripe";
import { Company_Currency, DebugMode, Stripe_SK_Live, Stripe_SK_Test } from "../Config";
import CustomerModel from "../Database/Schemas/Customer";
import CustomerModel from "../Database/Schemas/Customers/Customer";
import TransactionsModel from "../Database/Schemas/Transactions";
import { IInvoice } from "../Interfaces/Invoice";
import { idTransicitons } from "../Lib/Generator";
Expand Down
2 changes: 1 addition & 1 deletion src/Plugins/PluginHandler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Application } from "express";
import CategoryModel from "../Database/Schemas/Category";
import CustomerModel from "../Database/Schemas/Customer";
import CustomerModel from "../Database/Schemas/Customers/Customer";
import ImageModel from "../Database/Schemas/Images";
import InvoiceModel from "../Database/Schemas/Invoices";
import OrderModel from "../Database/Schemas/Orders";
Expand Down
24 changes: 9 additions & 15 deletions src/Routes/v2/Categories/Categories.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,17 @@ function getByUid(req: Request, res: Response)

function list(req: Request, res: Response)
{
let limit = parseInt(req.query.limit as string)
&& parseInt(req.query.limit as string) <= 100 ?
parseInt(req.query.limit as string)
:
10;
let page = 0;
let limit = parseInt(req.query._end as string)
&& parseInt(req.query._end as string) <= 100 ?
parseInt(req.query._end as string)
:
25;
let start = 0;
if(req.query)
{
if(req.query.page)
{
let p = parseInt(req.query.page as string);
page = Number.isInteger(p) ? p : 0;
}
}
if(req.query._start)
start = Number.isInteger(parseInt(req.query._start as string)) ? parseInt(req.query._start as string) : 0;

//@ts-ignore
API_CategoryModel.findAll(limit, page).then((result: any) => {
API_CategoryModel.findAll(limit, start).then((result: any) => {
APISuccess(result)(res)
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,13 @@ function list(req: Request, res: Response)
{
let limit = parseInt(req.query._end as string)
&& parseInt(req.query._end as string) <= 100 ?
parseInt(req.query._end as string)
:
25;
parseInt(req.query._end as string)
:
25;
let start = 0;
if(req.query)
{
if(req.query._start)
{
let p = parseInt(req.query._start as string);
start = Number.isInteger(p) ? p : 0;
}
}
start = Number.isInteger(parseInt(req.query._start as string)) ? parseInt(req.query._start as string) : 0;

API.findAll(limit, start).then((result: any) => {
APISuccess(result)(res)
Expand Down
143 changes: 141 additions & 2 deletions src/Routes/v2/Customers/Customers.config.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { Application, Router } from "express";
import EnsureAdmin from "../../../Middlewares/EnsureAdmin";
import CustomerController from "./Customers.controller";
import { JWT_Access_Token } from "../../../Config";
import { Full_Domain, JWT_Access_Token } from "../../../Config";
import jwt from "jsonwebtoken";
import bcrypt from "bcryptjs";
import { APIError, APISuccess } from "../../../Lib/Response";
import CustomerModel from "../../../Database/Schemas/Customer";
import CustomerModel from "../../../Database/Schemas/Customers/Customer";
import Logger from "../../../Lib/Logger";
import EnsureAuth from "../../../Middlewares/EnsureAuth";
import crypto from "crypto";
import PasswordResetModel from "../../../Database/Schemas/Customers/PasswordReset";
import { SendEmail } from "../../../Email/Send";
import Footer from "../../../Email/Templates/General/Footer";

export default class CustomerRouter
{
Expand All @@ -28,6 +32,141 @@ export default class CustomerRouter
EnsureAuth(),
CustomerController.getMyProfile
]);

this.router.post("/my/reset-password", async (req, res) => {
const email = req.body.email;
const customer = await CustomerModel.findOne({ "personal.email": email });
if(!customer)
return APIError(`Unable to find user with email ${email}`)(res);

const randomToken = crypto.randomBytes(20).toString("hex");
const token = crypto.createHash("sha256").update(randomToken).digest("hex");

new PasswordResetModel({
email: customer.personal.email,
token: token
}).save();

SendEmail(customer.personal.email, "Reset Password", {
isHTML: true,
body: `
Hello ${customer.personal.first_name} <br />
Here is your reset password link: <a href="${Full_Domain}/${version}/customers/my/reset-password/${token}">Reset password</a>
`
});

return APISuccess(`Succesfully created a reset password email`)(res);
});

this.router.get("/my/reset-password/:token", async (req, res) => {
const token = req.params.token;
const passwordReset = await PasswordResetModel.findOne({ token: token }) as any;
if(!passwordReset)
return APIError(`Unable to find password reset token`)(res);

if(!passwordReset.token)
return APIError(`Unable to find password reset token`)(res);

if(passwordReset.used)
return APIError(`This password reset token has already been used`)(res);

const customer = await CustomerModel.findOne({ "personal.email": passwordReset.email });
if(!customer)
return APIError(`Unable to find user with email ${passwordReset.email}`)(res);

return res.send(`
<!-- Style it in the middle -->
<style>
.container {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
/* Style input forms */
.form-container {
flex-direction: column;
margin: 0 auto;
}
.form-container input {
width: 20%;
height: 40px;
border: 1px solid #ccc;
border-radius: 5px;
padding: 5px;
margin-bottom: 10px;
}
.form-container button {
width: 20%;
height: 40px;
border: 1px solid #ccc;
border-radius: 5px;
padding: 5px;
margin-bottom: 10px;
}
</style>
<html>
<body>
<form class="container form-container" action="/${version}/customers/my/new-password?token=${token}" method="POST">
<input type="password" name="password" placeholder="New Password" />
<input type="password" name="password_confirmation" placeholder="Confirm Password" />
<button type="submit" value="Submit">Reset password</button>
</form>
${Footer}
</body>
</html>
`);
});

this.router.post("/my/new-password", async (req, res) => {
const token = req.query.token;
const password = req.body.password;

if(!password)
return APIError(`Password is required`)(res);

const passwordReset = await PasswordResetModel.findOne({ token: token }) as any;
if(!passwordReset)
return APIError(`Unable to find password reset token`)(res);

if(!passwordReset.token)
return APIError(`Unable to find password reset token`)(res);

if(passwordReset.used)
return APIError(`This password reset token has already been used`)(res);

const customer = await CustomerModel.findOne({ "personal.email": passwordReset.email });
if(!customer)
return APIError(`Unable to find user with email ${passwordReset.email}`)(res);

const genSalt = await bcrypt.genSalt(10);
customer.password = bcrypt.hashSync(password, genSalt);
await customer.save();
passwordReset.used = true;
await passwordReset.save();
res.send(`
<style>
.container {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
</style>
<html>
<body class="container">
<h1>Password reset successful</h1>
<div>
<p>You can now login with your new password</p>
</div>
${Footer}
</body>
</html>
`);
});

this.router.get("/:uid", [
EnsureAdmin,
Expand Down
43 changes: 28 additions & 15 deletions src/Routes/v2/Customers/Customers.controller.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { Request, Response } from "express";
import bcrypt from "bcryptjs";
import CustomerModel from "../../../Database/Schemas/Customer";
import CustomerModel from "../../../Database/Schemas/Customers/Customer";
import { ICustomer } from "../../../Interfaces/Customer";
import { idCustomer } from "../../../Lib/Generator";
import { APIError, APISuccess } from "../../../Lib/Response";
import BaseModelAPI from "../../../Models/BaseModelAPI";
import Logger from "../../../Lib/Logger";
import { SendEmail } from "../../../Email/Send";
import { Company_Name } from "../../../Config";
import Footer from "../../../Email/Templates/General/Footer";
import getFullName from "../../../Lib/Customers/getFullName";

const API_CustomerModel = new BaseModelAPI<ICustomer>(idCustomer, CustomerModel);

Expand All @@ -28,6 +32,20 @@ function insert(req: Request, res: Response)

API_CustomerModel.create(req.body)
.then((result) => {

// Send email to customer
SendEmail(result.personal.email, `Welcome to ${Company_Name}`, {
isHTML: true,
body: `
Welcome ${getFullName(result)} to ${Company_Name}! <br>
<br>
Your account has been created. <br>
With email: ${result.personal.email} <br>
<br>
<br />
${Footer}`
});

APISuccess({
uid: result.uid
})(res);
Expand All @@ -45,22 +63,17 @@ function getByUid(req: Request, res: Response)

function list(req: Request, res: Response)
{
let limit = parseInt(req.query.limit as string)
&& parseInt(req.query.limit as string) <= 100 ?
parseInt(req.query.limit as string)
:
10;
let page = 0;
let limit = parseInt(req.query._end as string)
&& parseInt(req.query._end as string) <= 100 ?
parseInt(req.query._end as string)
:
25;
let start = 0;
if(req.query)
{
if(req.query.page)
{
let p = parseInt(req.query.page as string);
page = Number.isInteger(p) ? p : 0;
}
}
if(req.query._start)
start = Number.isInteger(parseInt(req.query._start as string)) ? parseInt(req.query._start as string) : 0;

API_CustomerModel.findAll(limit, page).then((result: any) => {
API_CustomerModel.findAll(limit, start).then((result: any) => {
APISuccess(result)(res)
});
}
Expand Down
Loading

0 comments on commit ab89e72

Please sign in to comment.