|
@@ -1,43 +1,61 @@
|
|
|
-import { differenceInMinutes, addMinutes, subMinutes } from "date-fns";
|
|
|
|
|
-import { Handler } from "express";
|
|
|
|
|
-import passport from "passport";
|
|
|
|
|
-import bcrypt from "bcryptjs";
|
|
|
|
|
-import nanoid from "nanoid";
|
|
|
|
|
-import { v4 as uuid } from "uuid";
|
|
|
|
|
-import axios from "axios";
|
|
|
|
|
-
|
|
|
|
|
-import { CustomError } from "../utils";
|
|
|
|
|
-import * as utils from "../utils";
|
|
|
|
|
-import * as redis from "../redis";
|
|
|
|
|
-import * as mail from "../mail";
|
|
|
|
|
-import query from "../queries";
|
|
|
|
|
-import env from "../env";
|
|
|
|
|
-
|
|
|
|
|
-const authenticate = (
|
|
|
|
|
- type: "jwt" | "local" | "localapikey",
|
|
|
|
|
- error: string,
|
|
|
|
|
- isStrict = true
|
|
|
|
|
-) =>
|
|
|
|
|
- async function auth(req, res, next) {
|
|
|
|
|
|
|
+const { differenceInMinutes, addMinutes, subMinutes } = require("date-fns");
|
|
|
|
|
+const passport = require("passport");
|
|
|
|
|
+const { v4: uuid } = require("uuid");
|
|
|
|
|
+const bcrypt = require("bcryptjs");
|
|
|
|
|
+const nanoid = require("nanoid");
|
|
|
|
|
+const axios = require("axios");
|
|
|
|
|
+
|
|
|
|
|
+const { CustomError } = require("../utils");
|
|
|
|
|
+const query = require("../queries");
|
|
|
|
|
+const utils = require("../utils");
|
|
|
|
|
+const redis = require("../redis");
|
|
|
|
|
+const mail = require("../mail");
|
|
|
|
|
+const env = require("../env");
|
|
|
|
|
+
|
|
|
|
|
+function authenticate(type, error, isStrict) {
|
|
|
|
|
+ return function auth(req, res, next) {
|
|
|
if (req.user) return next();
|
|
if (req.user) return next();
|
|
|
|
|
|
|
|
passport.authenticate(type, (err, user) => {
|
|
passport.authenticate(type, (err, user) => {
|
|
|
if (err) return next(err);
|
|
if (err) return next(err);
|
|
|
|
|
+ const accepts = req.accepts(["json", "html"]);
|
|
|
|
|
|
|
|
if (!user && isStrict) {
|
|
if (!user && isStrict) {
|
|
|
- throw new CustomError(error, 401);
|
|
|
|
|
|
|
+ if (accepts === "html") {
|
|
|
|
|
+ return utils.sleep(2000).then(() => {
|
|
|
|
|
+ return res.render("partials/login_signup", {
|
|
|
|
|
+ layout: null,
|
|
|
|
|
+ error
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+ } else {
|
|
|
|
|
+ throw new CustomError(error, 401);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (user && isStrict && !user.verified) {
|
|
if (user && isStrict && !user.verified) {
|
|
|
- throw new CustomError(
|
|
|
|
|
- "Your email address is not verified. " +
|
|
|
|
|
- "Click on signup to get the verification link again.",
|
|
|
|
|
- 400
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ const errorMessage = "Your email address is not verified. " +
|
|
|
|
|
+ "Sign up to get the verification link again."
|
|
|
|
|
+ if (accepts === "html") {
|
|
|
|
|
+ return res.render("partials/login_signup", {
|
|
|
|
|
+ layout: null,
|
|
|
|
|
+ error: errorMessage
|
|
|
|
|
+ });
|
|
|
|
|
+ } else {
|
|
|
|
|
+ throw new CustomError(errorMessage, 400);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (user && user.banned) {
|
|
if (user && user.banned) {
|
|
|
- throw new CustomError("You're banned from using this website.", 403);
|
|
|
|
|
|
|
+ const errorMessage = "You're banned from using this website.";
|
|
|
|
|
+ if (accepts === "html") {
|
|
|
|
|
+ return res.render("partials/login_signup", {
|
|
|
|
|
+ layout: null,
|
|
|
|
|
+ error: errorMessage
|
|
|
|
|
+ });
|
|
|
|
|
+ } else {
|
|
|
|
|
+ throw new CustomError(errorMessage, 403);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (user) {
|
|
if (user) {
|
|
@@ -49,27 +67,27 @@ const authenticate = (
|
|
|
}
|
|
}
|
|
|
return next();
|
|
return next();
|
|
|
})(req, res, next);
|
|
})(req, res, next);
|
|
|
- };
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
-export const local = authenticate("local", "Login credentials are wrong.");
|
|
|
|
|
-export const jwt = authenticate("jwt", "Unauthorized.");
|
|
|
|
|
-export const jwtLoose = authenticate("jwt", "Unauthorized.", false);
|
|
|
|
|
-export const apikey = authenticate(
|
|
|
|
|
- "localapikey",
|
|
|
|
|
- "API key is not correct.",
|
|
|
|
|
- false
|
|
|
|
|
-);
|
|
|
|
|
|
|
+const local = authenticate("local", "Login credentials are wrong.", true);
|
|
|
|
|
+const jwt = authenticate("jwt", "Unauthorized.", true);
|
|
|
|
|
+const jwtLoose = authenticate("jwt", "Unauthorized.", false);
|
|
|
|
|
+const apikey = authenticate("localapikey", "API key is not correct.", false);
|
|
|
|
|
|
|
|
-export const cooldown: Handler = async (req, res, next) => {
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * @type {import("express").Handler}
|
|
|
|
|
+ */
|
|
|
|
|
+async function cooldown(req, res, next) {
|
|
|
if (env.DISALLOW_ANONYMOUS_LINKS) return next();
|
|
if (env.DISALLOW_ANONYMOUS_LINKS) return next();
|
|
|
const cooldownConfig = env.NON_USER_COOLDOWN;
|
|
const cooldownConfig = env.NON_USER_COOLDOWN;
|
|
|
if (req.user || !cooldownConfig) return next();
|
|
if (req.user || !cooldownConfig) return next();
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
const ip = await query.ip.find({
|
|
const ip = await query.ip.find({
|
|
|
ip: req.realIP.toLowerCase(),
|
|
ip: req.realIP.toLowerCase(),
|
|
|
created_at: [">", subMinutes(new Date(), cooldownConfig).toISOString()]
|
|
created_at: [">", subMinutes(new Date(), cooldownConfig).toISOString()]
|
|
|
});
|
|
});
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (ip) {
|
|
if (ip) {
|
|
|
const timeToWait =
|
|
const timeToWait =
|
|
|
cooldownConfig - differenceInMinutes(new Date(), new Date(ip.created_at));
|
|
cooldownConfig - differenceInMinutes(new Date(), new Date(ip.created_at));
|
|
@@ -79,60 +97,66 @@ export const cooldown: Handler = async (req, res, next) => {
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
next();
|
|
next();
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-export const recaptcha: Handler = async (req, res, next) => {
|
|
|
|
|
- if (env.isDev || req.user) return next();
|
|
|
|
|
- if (env.DISALLOW_ANONYMOUS_LINKS) return next();
|
|
|
|
|
- if (!env.RECAPTCHA_SECRET_KEY) return next();
|
|
|
|
|
-
|
|
|
|
|
- const isReCaptchaValid = await axios({
|
|
|
|
|
- method: "post",
|
|
|
|
|
- url: "https://www.google.com/recaptcha/api/siteverify",
|
|
|
|
|
- headers: {
|
|
|
|
|
- "Content-type": "application/x-www-form-urlencoded"
|
|
|
|
|
- },
|
|
|
|
|
- params: {
|
|
|
|
|
- secret: env.RECAPTCHA_SECRET_KEY,
|
|
|
|
|
- response: req.body.reCaptchaToken,
|
|
|
|
|
- remoteip: req.realIP
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
-
|
|
|
|
|
- if (!isReCaptchaValid.data.success) {
|
|
|
|
|
- throw new CustomError("reCAPTCHA is not valid. Try again.", 401);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- return next();
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-export const admin: Handler = async (req, res, next) => {
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * @type {import("express").Handler}
|
|
|
|
|
+ */
|
|
|
|
|
+function admin(req, res, next) {
|
|
|
|
|
+ // FIXME: attaching to req is risky, find another way
|
|
|
if (req.user.admin) return next();
|
|
if (req.user.admin) return next();
|
|
|
throw new CustomError("Unauthorized", 401);
|
|
throw new CustomError("Unauthorized", 401);
|
|
|
-};
|
|
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
-export const signup: Handler = async (req, res) => {
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * @type {import("express").Handler}
|
|
|
|
|
+ */
|
|
|
|
|
+async function signup(req, res) {
|
|
|
const salt = await bcrypt.genSalt(12);
|
|
const salt = await bcrypt.genSalt(12);
|
|
|
const password = await bcrypt.hash(req.body.password, salt);
|
|
const password = await bcrypt.hash(req.body.password, salt);
|
|
|
|
|
|
|
|
|
|
+ const accepts = req.accepts(["json", "html"]);
|
|
|
|
|
+
|
|
|
const user = await query.user.add(
|
|
const user = await query.user.add(
|
|
|
{ email: req.body.email, password },
|
|
{ email: req.body.email, password },
|
|
|
req.user
|
|
req.user
|
|
|
);
|
|
);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
await mail.verification(user);
|
|
await mail.verification(user);
|
|
|
|
|
|
|
|
- return res.status(201).send({ message: "Verification email has been sent." });
|
|
|
|
|
-};
|
|
|
|
|
-
|
|
|
|
|
-export const token: Handler = async (req, res) => {
|
|
|
|
|
|
|
+ if (accepts === "html") {
|
|
|
|
|
+ return res.render("partials/signup_verify_email", { layout: null });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return res.status(201).send({ message: "A verification email has been sent." });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * @type {import("express").Handler}
|
|
|
|
|
+ */
|
|
|
|
|
+function login(req, res) {
|
|
|
const token = utils.signToken(req.user);
|
|
const token = utils.signToken(req.user);
|
|
|
|
|
+
|
|
|
|
|
+ const accepts = req.accepts(["json", "html"]);
|
|
|
|
|
+
|
|
|
|
|
+ if (accepts === "html") {
|
|
|
|
|
+ res.cookie("token", token, {
|
|
|
|
|
+ maxAge: 1000 * 60 * 15, // expire after seven days
|
|
|
|
|
+ httpOnly: true,
|
|
|
|
|
+ secure: env.isProd
|
|
|
|
|
+ });
|
|
|
|
|
+ return res.render("partials/login_welcome", { layout: false });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return res.status(200).send({ token });
|
|
return res.status(200).send({ token });
|
|
|
-};
|
|
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
-export const verify: Handler = async (req, res, next) => {
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * @type {import("express").Handler}
|
|
|
|
|
+ */
|
|
|
|
|
+async function verify(req, res, next) {
|
|
|
if (!req.params.verificationToken) return next();
|
|
if (!req.params.verificationToken) return next();
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
const [user] = await query.user.update(
|
|
const [user] = await query.user.update(
|
|
|
{
|
|
{
|
|
|
verification_token: req.params.verificationToken,
|
|
verification_token: req.params.verificationToken,
|
|
@@ -144,45 +168,54 @@ export const verify: Handler = async (req, res, next) => {
|
|
|
verification_expires: null
|
|
verification_expires: null
|
|
|
}
|
|
}
|
|
|
);
|
|
);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (user) {
|
|
if (user) {
|
|
|
const token = utils.signToken(user);
|
|
const token = utils.signToken(user);
|
|
|
req.token = token;
|
|
req.token = token;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return next();
|
|
return next();
|
|
|
-};
|
|
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
-export const changePassword: Handler = async (req, res) => {
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * @type {import("express").Handler}
|
|
|
|
|
+ */
|
|
|
|
|
+async function changePassword(req, res) {
|
|
|
const salt = await bcrypt.genSalt(12);
|
|
const salt = await bcrypt.genSalt(12);
|
|
|
const password = await bcrypt.hash(req.body.password, salt);
|
|
const password = await bcrypt.hash(req.body.password, salt);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
const [user] = await query.user.update({ id: req.user.id }, { password });
|
|
const [user] = await query.user.update({ id: req.user.id }, { password });
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (!user) {
|
|
if (!user) {
|
|
|
throw new CustomError("Couldn't change the password. Try again later.");
|
|
throw new CustomError("Couldn't change the password. Try again later.");
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return res
|
|
return res
|
|
|
.status(200)
|
|
.status(200)
|
|
|
.send({ message: "Your password has been changed successfully." });
|
|
.send({ message: "Your password has been changed successfully." });
|
|
|
-};
|
|
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
-export const generateApiKey: Handler = async (req, res) => {
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * @type {import("express").Handler}
|
|
|
|
|
+ */
|
|
|
|
|
+async function generateApiKey(req, res) {
|
|
|
const apikey = nanoid(40);
|
|
const apikey = nanoid(40);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
redis.remove.user(req.user);
|
|
redis.remove.user(req.user);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
const [user] = await query.user.update({ id: req.user.id }, { apikey });
|
|
const [user] = await query.user.update({ id: req.user.id }, { apikey });
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (!user) {
|
|
if (!user) {
|
|
|
throw new CustomError("Couldn't generate API key. Please try again later.");
|
|
throw new CustomError("Couldn't generate API key. Please try again later.");
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return res.status(201).send({ apikey });
|
|
return res.status(201).send({ apikey });
|
|
|
-};
|
|
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
-export const resetPasswordRequest: Handler = async (req, res) => {
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * @type {import("express").Handler}
|
|
|
|
|
+ */
|
|
|
|
|
+async function resetPasswordRequest(req, res) {
|
|
|
const [user] = await query.user.update(
|
|
const [user] = await query.user.update(
|
|
|
{ email: req.body.email },
|
|
{ email: req.body.email },
|
|
|
{
|
|
{
|
|
@@ -190,19 +223,22 @@ export const resetPasswordRequest: Handler = async (req, res) => {
|
|
|
reset_password_expires: addMinutes(new Date(), 30).toISOString()
|
|
reset_password_expires: addMinutes(new Date(), 30).toISOString()
|
|
|
}
|
|
}
|
|
|
);
|
|
);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (user) {
|
|
if (user) {
|
|
|
await mail.resetPasswordToken(user);
|
|
await mail.resetPasswordToken(user);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return res.status(200).send({
|
|
return res.status(200).send({
|
|
|
message: "If email address exists, a reset password email has been sent."
|
|
message: "If email address exists, a reset password email has been sent."
|
|
|
});
|
|
});
|
|
|
-};
|
|
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
-export const resetPassword: Handler = async (req, res, next) => {
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * @type {import("express").Handler}
|
|
|
|
|
+ */
|
|
|
|
|
+async function resetPassword(req, res, next) {
|
|
|
const { resetPasswordToken } = req.params;
|
|
const { resetPasswordToken } = req.params;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (resetPasswordToken) {
|
|
if (resetPasswordToken) {
|
|
|
const [user] = await query.user.update(
|
|
const [user] = await query.user.update(
|
|
|
{
|
|
{
|
|
@@ -211,35 +247,41 @@ export const resetPassword: Handler = async (req, res, next) => {
|
|
|
},
|
|
},
|
|
|
{ reset_password_expires: null, reset_password_token: null }
|
|
{ reset_password_expires: null, reset_password_token: null }
|
|
|
);
|
|
);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (user) {
|
|
if (user) {
|
|
|
- const token = utils.signToken(user as UserJoined);
|
|
|
|
|
|
|
+ const token = utils.signToken(user);
|
|
|
req.token = token;
|
|
req.token = token;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
return next();
|
|
return next();
|
|
|
-};
|
|
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
-export const signupAccess: Handler = (req, res, next) => {
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * @type {import("express").Handler}
|
|
|
|
|
+ */
|
|
|
|
|
+function signupAccess(req, res, next) {
|
|
|
if (!env.DISALLOW_REGISTRATION) return next();
|
|
if (!env.DISALLOW_REGISTRATION) return next();
|
|
|
return res.status(403).send({ message: "Registration is not allowed." });
|
|
return res.status(403).send({ message: "Registration is not allowed." });
|
|
|
-};
|
|
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
-export const changeEmailRequest: Handler = async (req, res) => {
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * @type {import("express").Handler}
|
|
|
|
|
+ */
|
|
|
|
|
+async function changeEmailRequest(req, res) {
|
|
|
const { email, password } = req.body;
|
|
const { email, password } = req.body;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
const isMatch = await bcrypt.compare(password, req.user.password);
|
|
const isMatch = await bcrypt.compare(password, req.user.password);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (!isMatch) {
|
|
if (!isMatch) {
|
|
|
throw new CustomError("Password is wrong.", 400);
|
|
throw new CustomError("Password is wrong.", 400);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
const currentUser = await query.user.find({ email });
|
|
const currentUser = await query.user.find({ email });
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (currentUser) {
|
|
if (currentUser) {
|
|
|
throw new CustomError("Can't use this email address.", 400);
|
|
throw new CustomError("Can't use this email address.", 400);
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
const [updatedUser] = await query.user.update(
|
|
const [updatedUser] = await query.user.update(
|
|
|
{ id: req.user.id },
|
|
{ id: req.user.id },
|
|
|
{
|
|
{
|
|
@@ -248,30 +290,33 @@ export const changeEmailRequest: Handler = async (req, res) => {
|
|
|
change_email_expires: addMinutes(new Date(), 30).toISOString()
|
|
change_email_expires: addMinutes(new Date(), 30).toISOString()
|
|
|
}
|
|
}
|
|
|
);
|
|
);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
redis.remove.user(updatedUser);
|
|
redis.remove.user(updatedUser);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (updatedUser) {
|
|
if (updatedUser) {
|
|
|
await mail.changeEmail({ ...updatedUser, email });
|
|
await mail.changeEmail({ ...updatedUser, email });
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return res.status(200).send({
|
|
return res.status(200).send({
|
|
|
message:
|
|
message:
|
|
|
"If email address exists, an email " +
|
|
"If email address exists, an email " +
|
|
|
"with a verification link has been sent."
|
|
"with a verification link has been sent."
|
|
|
});
|
|
});
|
|
|
-};
|
|
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
-export const changeEmail: Handler = async (req, res, next) => {
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * @type {import("express").Handler}
|
|
|
|
|
+ */
|
|
|
|
|
+async function changeEmail(req, res, next) {
|
|
|
const { changeEmailToken } = req.params;
|
|
const { changeEmailToken } = req.params;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (changeEmailToken) {
|
|
if (changeEmailToken) {
|
|
|
const foundUser = await query.user.find({
|
|
const foundUser = await query.user.find({
|
|
|
change_email_token: changeEmailToken
|
|
change_email_token: changeEmailToken
|
|
|
});
|
|
});
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (!foundUser) return next();
|
|
if (!foundUser) return next();
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
const [user] = await query.user.update(
|
|
const [user] = await query.user.update(
|
|
|
{
|
|
{
|
|
|
change_email_token: changeEmailToken,
|
|
change_email_token: changeEmailToken,
|
|
@@ -284,13 +329,32 @@ export const changeEmail: Handler = async (req, res, next) => {
|
|
|
email: foundUser.change_email_address
|
|
email: foundUser.change_email_address
|
|
|
}
|
|
}
|
|
|
);
|
|
);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
redis.remove.user(foundUser);
|
|
redis.remove.user(foundUser);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (user) {
|
|
if (user) {
|
|
|
- const token = utils.signToken(user as UserJoined);
|
|
|
|
|
|
|
+ const token = utils.signToken(user);
|
|
|
req.token = token;
|
|
req.token = token;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
return next();
|
|
return next();
|
|
|
-};
|
|
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+module.exports = {
|
|
|
|
|
+ admin,
|
|
|
|
|
+ apikey,
|
|
|
|
|
+ changeEmail,
|
|
|
|
|
+ changeEmailRequest,
|
|
|
|
|
+ changePassword,
|
|
|
|
|
+ cooldown,
|
|
|
|
|
+ generateApiKey,
|
|
|
|
|
+ jwt,
|
|
|
|
|
+ jwtLoose,
|
|
|
|
|
+ local,
|
|
|
|
|
+ login,
|
|
|
|
|
+ resetPassword,
|
|
|
|
|
+ resetPasswordRequest,
|
|
|
|
|
+ signup,
|
|
|
|
|
+ signupAccess,
|
|
|
|
|
+ verify,
|
|
|
|
|
+}
|