Add session management
This commit is contained in:
64
src/auth/auth.route.ts
Normal file
64
src/auth/auth.route.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { FastifyInstance, FastifyReply, FastifyRequest } from "fastify";
|
||||
import { getUserByEmail, updateUser } from "../user/user.service";
|
||||
import { createSession, getSession } from "./auth.service";
|
||||
|
||||
export async function authRoutes(fastify: FastifyInstance) {
|
||||
fastify.get(
|
||||
"/microsoft/token",
|
||||
{},
|
||||
async (req: FastifyRequest, res: FastifyReply) => {
|
||||
try {
|
||||
const { token } =
|
||||
await fastify.microsoftOauth.getAccessTokenFromAuthorizationCodeFlow(
|
||||
req
|
||||
);
|
||||
|
||||
const user = (await fastify.microsoftOauth.userinfo(token)) as {
|
||||
givenname: string;
|
||||
familyname: string;
|
||||
email: string;
|
||||
picture: string;
|
||||
};
|
||||
|
||||
const userInDb = await getUserByEmail(user.email);
|
||||
if (userInDb == null)
|
||||
return res.code(401).send({ error: "not_allowed" });
|
||||
|
||||
await updateUser(userInDb.pid, {
|
||||
firstName: user.givenname,
|
||||
lastName: user.familyname,
|
||||
email: user.email,
|
||||
avatar: user.picture,
|
||||
});
|
||||
|
||||
const session = await createSession(
|
||||
userInDb.id,
|
||||
req.ip,
|
||||
req.headers["user-agent"]
|
||||
);
|
||||
|
||||
return res.code(201).send({ session_token: session.sid });
|
||||
} catch (err) {
|
||||
//@ts-ignore
|
||||
if (err.data) {
|
||||
//@ts-ignore
|
||||
fastify.log.warn(err.data.payload);
|
||||
return res.code(400).send();
|
||||
} else {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
fastify.delete("/logout", {}, async (req, res) => {
|
||||
if (!req.headers.authorization) return res.code(200).send();
|
||||
|
||||
const auth = req.headers.authorization.split(" ")[1];
|
||||
const sessionInDb = await getSession(auth);
|
||||
if (sessionInDb === null) return res.code(200).send();
|
||||
|
||||
await sessionInDb.deleteOne();
|
||||
return res.code(200).send();
|
||||
});
|
||||
}
|
||||
20
src/auth/auth.schema.ts
Normal file
20
src/auth/auth.schema.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import mongoose from "mongoose";
|
||||
|
||||
export const sessionModel = mongoose.model(
|
||||
"session",
|
||||
new mongoose.Schema({
|
||||
sid: {
|
||||
type: String,
|
||||
unique: true,
|
||||
required: true,
|
||||
},
|
||||
user: { type: mongoose.Types.ObjectId, ref: "user" },
|
||||
ip: String,
|
||||
userAgent: String,
|
||||
createdAt: Date,
|
||||
expiresAt: {
|
||||
type: Date,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
);
|
||||
24
src/auth/auth.service.ts
Normal file
24
src/auth/auth.service.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { generateToken } from "../utils/id";
|
||||
import { sessionModel } from "./auth.schema";
|
||||
|
||||
export async function createSession(userId: string, ip?: string, ua?: string) {
|
||||
const allUserSessions = await sessionModel.find({ user: userId });
|
||||
for (const session of allUserSessions) {
|
||||
await session.deleteOne();
|
||||
}
|
||||
|
||||
const newSession = await sessionModel.create({
|
||||
sid: await generateToken(),
|
||||
user: userId,
|
||||
ip: ip,
|
||||
userAgent: ua,
|
||||
createdAt: new Date(),
|
||||
expiresAt: new Date(Date.now() + 3600 * 24 * 30 * 1000),
|
||||
});
|
||||
|
||||
return newSession;
|
||||
}
|
||||
|
||||
export async function getSession(sessionId: string) {
|
||||
return await sessionModel.findOne({ sid: sessionId }).populate("user");
|
||||
}
|
||||
Reference in New Issue
Block a user