your session
parent
edfd6b08f3
commit
c8ba965329
|
@ -18,6 +18,7 @@
|
|||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"express-session": "^1.17.3",
|
||||
"express-useragent": "^1.0.15",
|
||||
"fs-extra": "^11.2.0",
|
||||
"mariadb": "^3.2.3",
|
||||
"passport": "^0.7.0",
|
||||
|
@ -36,6 +37,7 @@
|
|||
"@types/cors": "^2.8.17",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/express-session": "^1.17.10",
|
||||
"@types/express-useragent": "^1.0.5",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/passport-google-oauth20": "^2.0.14",
|
||||
"@types/swagger-jsdoc": "^6.0.4",
|
||||
|
@ -206,6 +208,15 @@
|
|||
"@types/express": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/express-useragent": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/express-useragent/-/express-useragent-1.0.5.tgz",
|
||||
"integrity": "sha512-G1zPW6jDj7oGJvMvB8UCIAWznCOafcksYzOg8LINfYmvrXlSGJ6nsJ7O7GlmYMjrgGYvobYaI8IhRCkAKslPJA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/express": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/fs-extra": {
|
||||
"version": "11.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz",
|
||||
|
@ -1068,6 +1079,14 @@
|
|||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/express-useragent": {
|
||||
"version": "1.0.15",
|
||||
"resolved": "https://registry.npmjs.org/express-useragent/-/express-useragent-1.0.15.tgz",
|
||||
"integrity": "sha512-eq5xMiYCYwFPoekffMjvEIk+NWdlQY9Y38OsTyl13IvA728vKT+q/CSERYWzcw93HGBJcIqMIsZC5CZGARPVdg==",
|
||||
"engines": {
|
||||
"node": ">=4.5"
|
||||
}
|
||||
},
|
||||
"node_modules/express/node_modules/body-parser": {
|
||||
"version": "1.20.1",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
"dotenv": "^16.3.1",
|
||||
"express": "^4.18.2",
|
||||
"express-session": "^1.17.3",
|
||||
"express-useragent": "^1.0.15",
|
||||
"fs-extra": "^11.2.0",
|
||||
"mariadb": "^3.2.3",
|
||||
"passport": "^0.7.0",
|
||||
|
@ -38,6 +39,7 @@
|
|||
"@types/cors": "^2.8.17",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/express-session": "^1.17.10",
|
||||
"@types/express-useragent": "^1.0.5",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/passport-google-oauth20": "^2.0.14",
|
||||
"@types/swagger-jsdoc": "^6.0.4",
|
||||
|
|
|
@ -6,6 +6,7 @@ import cors from "cors";
|
|||
import GoogleStrategy from "passport-google-oauth20";
|
||||
import cookieParser from "cookie-parser";
|
||||
import session from "express-session";
|
||||
import useragent from "express-useragent";
|
||||
|
||||
import calendarRoutes from "./src/routes/calendarRoutes";
|
||||
import storeRoutes from "./src/routes/storeRoutes";
|
||||
|
@ -51,8 +52,6 @@ const options = {
|
|||
apis: ["./src/routes/*.ts"],
|
||||
};
|
||||
|
||||
app.use(cookieParser());
|
||||
|
||||
app.use(
|
||||
session({
|
||||
secret: "keyboard cat",
|
||||
|
@ -108,6 +107,8 @@ passport.deserializeUser(function (user: User, cb) {
|
|||
|
||||
// TODO: setup cors
|
||||
app.use(cors());
|
||||
app.use(cookieParser());
|
||||
app.use(useragent.express());
|
||||
|
||||
app.use(bodyParser.json());
|
||||
app.use("/api/v1/calendar", calendarRoutes);
|
||||
|
|
|
@ -114,7 +114,7 @@ export async function SignUp(req: Request, res: Response) {
|
|||
);
|
||||
|
||||
// create session
|
||||
saveSession(res, user.user_id, user.username);
|
||||
saveSession(req, res, user.user_id, user.username);
|
||||
})
|
||||
.catch((err) => {
|
||||
logger.error(err);
|
||||
|
@ -181,7 +181,7 @@ export async function Login(req: Request, res: Response) {
|
|||
}
|
||||
|
||||
// create session
|
||||
saveSession(res, user.user_id, user.username);
|
||||
saveSession(req, res, user.user_id, user.username);
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
res.status(500).send({ err: "invalid request" });
|
||||
|
@ -272,6 +272,19 @@ export async function GetUser(req: Request, res: Response) {
|
|||
);
|
||||
}
|
||||
|
||||
// update user session last_used
|
||||
|
||||
Session.update(
|
||||
{
|
||||
last_used: new Date(),
|
||||
},
|
||||
{
|
||||
where: {
|
||||
session_id: session.session_id,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
res.status(200).send(respData);
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
|
@ -470,3 +483,73 @@ export async function UpdateUserProfilePassword(req: Request, res: Response) {
|
|||
res.status(500).send({ err: "invalid request" });
|
||||
}
|
||||
}
|
||||
|
||||
export async function GetUserProfileSessions(req: Request, res: Response) {
|
||||
try {
|
||||
const session = await getUserSession(req);
|
||||
|
||||
if (!session) {
|
||||
return res.status(401).send({ err: "unauthorized" });
|
||||
}
|
||||
|
||||
const sessions = await Session.findAll({
|
||||
where: {
|
||||
user_id: session.user_id,
|
||||
},
|
||||
attributes: ["session_id", "id", "browser", "os", "last_used"],
|
||||
});
|
||||
|
||||
// set last_used to now if session is the user's current session
|
||||
|
||||
let currentSession = sessions.find(
|
||||
(sess) => sess.session_id === session.session_id
|
||||
)?.id;
|
||||
|
||||
// remove session_id from sessions for security reasons
|
||||
|
||||
const sessionsList = sessions.map((sess) => {
|
||||
return {
|
||||
id: sess.id,
|
||||
browser: sess.browser,
|
||||
os: sess.os,
|
||||
last_used: sess.last_used,
|
||||
};
|
||||
});
|
||||
|
||||
res.status(200).json({
|
||||
sessions: sessionsList,
|
||||
currentSession: currentSession,
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
res.status(500).send({ err: "invalid request" });
|
||||
}
|
||||
}
|
||||
|
||||
export async function DeleteUserProfileSession(req: Request, res: Response) {
|
||||
try {
|
||||
const { id } = req.params;
|
||||
|
||||
if (!id) {
|
||||
return res.status(400).send({ err: "invalid request" });
|
||||
}
|
||||
|
||||
const session = await getUserSession(req);
|
||||
|
||||
if (!session) {
|
||||
return res.status(401).send({ err: "unauthorized" });
|
||||
}
|
||||
|
||||
await Session.destroy({
|
||||
where: {
|
||||
id: id,
|
||||
user_id: session.user_id,
|
||||
},
|
||||
});
|
||||
|
||||
res.status(200).send({ msg: "session deleted" });
|
||||
} catch (error) {
|
||||
logger.error(error);
|
||||
res.status(500).send({ err: "invalid request" });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,12 +4,21 @@ import sequelize from "../database/database";
|
|||
interface SessionAttributes {
|
||||
session_id: string;
|
||||
user_id: string;
|
||||
// needed in the ui to delete the session
|
||||
id: string;
|
||||
browser: string;
|
||||
os: string;
|
||||
last_used: Date;
|
||||
expires: Date;
|
||||
}
|
||||
|
||||
class Session extends Model<SessionAttributes> implements SessionAttributes {
|
||||
declare session_id: string;
|
||||
declare user_id: string;
|
||||
declare id: string;
|
||||
declare browser: string;
|
||||
declare os: string;
|
||||
declare last_used: Date;
|
||||
declare expires: Date;
|
||||
}
|
||||
|
||||
|
@ -25,6 +34,22 @@ Session.init(
|
|||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
id: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
browser: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
os: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false,
|
||||
},
|
||||
last_used: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
},
|
||||
expires: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false,
|
||||
|
|
|
@ -24,5 +24,15 @@ router.post(
|
|||
sessionProtection,
|
||||
userController.UpdateUserProfilePassword
|
||||
);
|
||||
router.get(
|
||||
"/profile/sessions",
|
||||
sessionProtection,
|
||||
userController.GetUserProfileSessions
|
||||
);
|
||||
router.delete(
|
||||
"/profile/sessions/:id",
|
||||
sessionProtection,
|
||||
userController.DeleteUserProfileSession
|
||||
);
|
||||
|
||||
export default router;
|
||||
|
|
|
@ -41,7 +41,12 @@ export function newUserSession() {
|
|||
return crypto.randomBytes(USER_SESSION_LENGTH).toString("hex");
|
||||
}
|
||||
|
||||
export function newSessionId() {
|
||||
return uuidv4();
|
||||
}
|
||||
|
||||
export async function saveSession(
|
||||
req: Request,
|
||||
res: Response,
|
||||
userId: string,
|
||||
username: string
|
||||
|
@ -52,6 +57,10 @@ export async function saveSession(
|
|||
await Session.create({
|
||||
user_id: userId,
|
||||
session_id: userSession,
|
||||
id: newSessionId(),
|
||||
browser: req.useragent?.browser as string,
|
||||
os: req.useragent?.os as string,
|
||||
last_used: new Date(),
|
||||
expires: new Date(Date.now() + DEFAULT_SESSION_EXPIRY),
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue