116 lines
3.7 KiB
JavaScript
116 lines
3.7 KiB
JavaScript
import dotenv from 'dotenv';
|
|
import jwt from 'jsonwebtoken';
|
|
import argon2 from 'argon2';
|
|
|
|
dotenv.config();
|
|
|
|
export default class AuthHandler {
|
|
ips = new Map()
|
|
#secret
|
|
|
|
constructor() {
|
|
this.#secret = process.env.JWT_SECRET;
|
|
}
|
|
|
|
isLoggedInUser(req, res) {
|
|
const token = req.cookies.auth_token;
|
|
|
|
if (!token) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
const decoded = jwt.verify(token, process.env.JWT_SECRET);
|
|
req.user = decoded;
|
|
return true;
|
|
} catch (err) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
getRequestEmail(req, res) {
|
|
const token = req.cookies?.auth_token;
|
|
if (!token) return res.status(401).send({ error: "No auth token" });
|
|
|
|
try {
|
|
const payload = jwt.verify(token, process.env.JWT_SECRET);
|
|
const email = payload.email;
|
|
return email
|
|
} catch (e) {
|
|
console.error("Error getting profile: ", e)
|
|
throw new Error("Error getting email: invalid auth token")
|
|
}
|
|
}
|
|
|
|
async getProfile(req, res) {
|
|
try {
|
|
let email = global.auth.getRequestEmail(req, res)
|
|
|
|
const user = await db.members.getByEmail(email);
|
|
const connections = await db.MEMBER_IN_NETWORK.getByMember(user.id);
|
|
|
|
const userOrgs = await Promise.all(connections.map(async (c) => {
|
|
const network = await db.networks.get(c.network_id);
|
|
delete network.stripe_account_id;
|
|
delete network.stripe_access_token;
|
|
return network;
|
|
}));
|
|
|
|
res.send({
|
|
id: user.id,
|
|
email: user.email,
|
|
first_name: user.first_name,
|
|
last_name: user.last_name,
|
|
networks: userOrgs,
|
|
apps: user.apps
|
|
});
|
|
} catch (e) {
|
|
console.error("Error getting profile: ", e)
|
|
res.status(401).send({ error: "Invalid token" });
|
|
}
|
|
}
|
|
|
|
async login(req, res) {
|
|
const { email, password } = req.body;
|
|
let foundUser = await global.db.members.getByEmail(email)
|
|
if(!foundUser) {
|
|
res.status(400).json({ error: 'Incorrect email.' });
|
|
return;
|
|
}
|
|
const storedHash = foundUser.password
|
|
const valid = await argon2.verify(storedHash, password);
|
|
if (!valid) {
|
|
res.status(400).json({ error: 'Incorrect password.' });
|
|
} else {
|
|
const payload = { email: foundUser.email };
|
|
console.log("login: ", payload)
|
|
const secret = process.env.JWT_SECRET;
|
|
const options = { expiresIn: "2h" };
|
|
const token = jwt.sign(payload, secret, options);
|
|
|
|
res.cookie("auth_token", token, {
|
|
httpOnly: true, // cannot be accessed by JS
|
|
secure: process.env.ENV === "production", // only over HTTPS
|
|
sameSite: "lax", // like SameSiteLaxMode
|
|
maxAge: 60 * 24 * 60 * 60 * 1000, // 60 days
|
|
path: "/", // available on entire site
|
|
domain: process.env.ENV === "production" ? "." + process.env.BASE_URL : undefined
|
|
});
|
|
|
|
res.redirect("/")
|
|
}
|
|
}
|
|
|
|
logout(req, res) {
|
|
res.cookie('auth_token', '', {
|
|
httpOnly: true,
|
|
secure: process.env.NODE_ENV === 'production',
|
|
sameSite: 'lax',
|
|
maxAge: 0, // expire immediately
|
|
path: '/',
|
|
domain: process.env.ENV === "production" ? "." + process.env.BASE_URL : undefined
|
|
});
|
|
|
|
res.redirect("/")
|
|
}
|
|
} |