This commit is contained in:
2024-10-28 16:16:53 +05:00
parent 77aabed207
commit d6809ff538
30 changed files with 1250 additions and 658 deletions
+11
View File
@@ -0,0 +1,11 @@
import { Router } from "express";
const router = Router();
router.get("/", (req, res) => {
res.json({ ok: 1 });
});
const checkRoute = router;
export default checkRoute;
+25 -19
View File
@@ -1,43 +1,49 @@
import { Router } from "express";
import jwt, { Secret } from "jsonwebtoken";
import bcrypt from "bcrypt";
import User from "../models/User.js";
import Token from "../models/Token.js";
import { decodeJwt, SignJWT } from "jose";
import { createSecretKey } from "crypto";
const router = Router();
router.post("/", async (req, res) => {
let { username, password } = req.body;
const { username, password } = req.body;
if (!username || !password) {
return res.json({
error: "You must pass the 'username' and 'password' parameters",
});
return res.json({ error: 1 });
}
username = username.toLowerCase();
const user = await User.findOne({ username });
const user = await User.findOne({ username }).lean();
if (!user) {
return res.json({ error: "A user with this name was not found" });
return res.json({ error: 2 });
}
if (!bcrypt.compareSync(password, user.password)) {
return res.json({ error: "Invalid username or password" });
if (!bcrypt.compareSync(password, user.password!)) {
return res.json({ error: 3 });
}
const accessToken = jwt.sign({ username }, process.env.JWT_SECRET as Secret, {
expiresIn: "365d",
});
const accessToken = await new SignJWT({ username })
.setProtectedHeader({ alg: "HS256" })
.setExpirationTime(process.env.JWT_ACCESS_EXP)
.sign(createSecretKey(process.env.JWT_SECRET, "utf8"));
const userId = user.id;
const refreshToken = await new SignJWT({ username })
.setProtectedHeader({ alg: "HS256" })
.setExpirationTime(process.env.JWT_REFRESH_EXP)
.sign(createSecretKey(process.env.JWT_SECRET, "utf8"));
await Token.create({ userId, accessToken });
await Token.create({ userId: user._id, accessToken, refreshToken });
res.json({ accessToken, user });
res
.cookie("refreshToken", refreshToken, {
httpOnly: true,
expires: new Date(decodeJwt(refreshToken).exp! * 1000),
})
.json({ accessToken, refreshToken, ...user });
});
const loginRouter = router;
const loginRoute = router;
export default loginRouter;
export default loginRoute;
+83
View File
@@ -0,0 +1,83 @@
import { createSecretKey } from "crypto";
import { Router } from "express";
import { jwtVerify, SignJWT } from "jose";
import Token from "../models/Token.js";
import User from "../models/User.js";
import IToken from "../types/IToken.js";
const router = Router();
router.post("/", async (req, res) => {
let _username;
if (req.cookies.refreshToken) {
try {
const {
payload: { username },
} = await jwtVerify(
req.cookies.refreshToken,
createSecretKey(process.env.JWT_SECRET!, "utf8")
);
_username = username;
} catch (error) {
return res.json({
error: `refreshToken jwtVerify - ${(error as Error).message}`,
});
}
const userWithTokens = await User.findOne({ username: _username }).populate(
{
path: "tokens",
}
);
if (!userWithTokens) {
return res.json({ error: "userWithTokens is null" });
}
if (!("tokens" in userWithTokens)) {
return res.json({ error: "tokens not found in userWithTokens" });
}
const foundRefreshToken = userWithTokens.tokens as IToken[];
if (
!foundRefreshToken.find(
(token) => token.refreshToken === req.cookies.refreshToken
)?.refreshToken
) {
console.log("refreshToken not found in DB");
return res.json({ error: "refreshToken not found in DB" });
}
const accessToken = await new SignJWT({ username: _username })
.setProtectedHeader({ alg: "HS256" })
.setExpirationTime(process.env.JWT_ACCESS_EXP)
.sign(createSecretKey(process.env.JWT_SECRET!, "utf8"));
await Token.findOneAndUpdate(
{ refreshToken: req.cookies.refreshToken },
{ accessToken }
);
return res.json({ accessToken });
}
// if (req.body.refreshToken) {
// try {
// jwtVerify(
// req.body.refreshToken,
// createSecretKey(process.env.JWT_SECRET!, "utf8")
// );
// } catch (error) {
// return res.json({ error: `refreshToken - ${(error as Error).message}` });
// }
// }
return res.json({ error: "refreshToken not found" });
});
const refreshRoute = router;
export default refreshRoute;
+22
View File
@@ -0,0 +1,22 @@
import bcrypt from "bcrypt";
import { Router } from "express";
import User from "../models/User.js";
const router = Router();
router.post("/", async (req, res) => {
const { username, password } = req.body;
try {
const passwordHash = bcrypt.hashSync(password, 12);
const result = await User.create({ username, password: passwordHash });
return res.json(result);
} catch (error) {
return res.json({ error: (error as Error).message });
}
});
const registerRoute = router;
export default registerRoute;
-40
View File
@@ -1,40 +0,0 @@
import { Router } from "express";
import jwt, { Secret } from "jsonwebtoken";
import bcrypt from "bcrypt";
import User from "../models/User.js";
import Token from "../models/Token.js";
const router = Router();
router.post("/", async (req, res) => {
const { username, password } = req.body;
if (!username || !password) {
return res.json({ error: 1 });
}
if (await User.exists({ username })) {
return res.json({ error: 2 });
}
const passwordHash = bcrypt.hashSync(password, 12);
if (!passwordHash) {
return res.json({ error: 3 });
}
const accessToken = jwt.sign({ username }, process.env.JWT_SECRET as Secret, {
expiresIn: "365d",
});
const user = await User.create({ username, password: passwordHash });
const userId = user.id;
await Token.create({ userId, accessToken });
res.json({ accessToken, user });
});
const registerRouter = router;
export default registerRouter;
+35 -95
View File
@@ -77,6 +77,8 @@ router.get("/:buildId", async (req, res) => {
router.post("/", async (req, res) => {
const { companyId, buildId, slot, startAt, client, duration } = req.body;
console.log("client", client);
if (!companyId || !buildId || !startAt || !slot) {
return res.json({
status: "error",
@@ -148,109 +150,47 @@ router.post("/", async (req, res) => {
startAt: startAtISO,
duration,
endAt: endAtISO,
client,
});
const url = `https://stream.graff.tech/scheduled/${scheduledSession.id}`;
// <-- Send an mail
if (client?.email) {
console.log("client?.email", client?.email);
// create reusable transporter object using the default SMTP transport
let transporter = createTransport({
host: "mail.netangels.ru",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: "stream@graff.tech", // generated ethereal user
pass: "zLUbt8Io7dh2F9KT", // generated ethereal password
},
});
// send mail with defined transport object
try {
await transporter.sendMail({
from: "stream@graff.tech", // sender address
to: client.email, // list of receivers
subject: "Приглашение на демонстрацию - stream.graff.tech", // Subject line
html: `<div>
Ссылка для подключения к демонстрации: <a href="${url}" target="_blank">${url}</a>
</div>`,
});
} catch (error) {
console.log("error", (error as Error).message);
}
}
return res.json({
status: "success",
scheduledSessionId: scheduledSession.id,
url: `https://stream.graff.tech/scheduled/${scheduledSession.id}`,
});
}
const schedule = await Schedule.findOne({
buildId,
startDate: { $lte: startAtISO },
// endDate: { $gte: startAtISO },
});
if (!schedule) {
return res.json({
status: "error",
message: "No matching schedule found", // Подходящего расписания не найдено
});
}
const scheduledSessions = await ScheduledSession.find({
buildId,
startAt: {
$gte: startOfDay(startAtISO),
$lte: endOfDay(startAtISO),
},
});
const endAtISO = addMinutes(startAtISO, schedule.sessionDuration);
if (scheduledSessions.length) {
const overlappingSessions = [];
for (const session of scheduledSessions) {
if (
areIntervalsOverlapping(
{
start: session.startAt,
end: addMinutes(session.endAt, schedule.sessionBreak),
},
{ start: startAtISO, end: endAtISO }
)
) {
overlappingSessions.push(session);
}
}
if (overlappingSessions.length >= build.sessionLimit) {
return res.json({
status: "error",
message:
"It is not possible to create a session because it overlaps with the time of another session", //Невозможно создать сеанс, поскольку он перекрывается со временем другого сеанса.
});
}
}
const scheduledSession = await ScheduledSession.create({
buildId,
client,
startAt: startAtISO,
endAt: endAtISO,
});
const url = `https://stream.graff.tech/scheduled/${scheduledSession.id}`;
// <-- Send an mail
if (client?.email) {
// create reusable transporter object using the default SMTP transport
let transporter = createTransport({
host: "mail.netangels.ru",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: "stream@graff.tech", // generated ethereal user
pass: "zLUbt8Io7dh2F9KT", // generated ethereal password
},
});
// send mail with defined transport object
try {
await transporter.sendMail({
from: "stream@graff.tech", // sender address
to: client.email, // list of receivers
subject: "Приглашение на демонстрацию - stream.graff.tech", // Subject line
html: `<div>
Ссылка для подключения к демонстрации: <a href="${url}" target="_blank">${url}</a>
</div>`,
});
} catch (error) {
console.log("error", (error as Error).message);
}
}
// Send an mail -->
res.json({
status: "success",
scheduledSessionId: scheduledSession.id,
url,
});
});
router.put("/:id", async (req, res) => {