From 218a25daeef4898d776cf9688b36e0672674742f Mon Sep 17 00:00:00 2001 From: chreamy Date: Tue, 5 Mar 2024 01:27:53 -0600 Subject: [PATCH] feat: user sessions history & fix ts --- packages/analytics/src/controllers/index.ts | 4 +- packages/analytics/src/controllers/quests.ts | 3 +- .../analytics/src/controllers/sessions.ts | 6 +- packages/analytics/src/controllers/users.ts | 19 ++---- packages/analytics/src/interface.ts | 61 +++++++++++++++++++ packages/analytics/src/models/sessions.ts | 27 ++++---- packages/analytics/src/models/users.ts | 18 +++--- 7 files changed, 95 insertions(+), 43 deletions(-) create mode 100644 packages/analytics/src/interface.ts diff --git a/packages/analytics/src/controllers/index.ts b/packages/analytics/src/controllers/index.ts index 002d09c..688aa1d 100644 --- a/packages/analytics/src/controllers/index.ts +++ b/packages/analytics/src/controllers/index.ts @@ -1,8 +1,8 @@ import { userCount } from '../models/users.js' import { questList } from '../models/quests.ts' - +import { Request, Response } from 'express' // eslint-disable-next-line import/prefer-default-export -export async function homeController(req: any, res: any) { +export async function homeController(req: Request, res: Response) { const quests = await questList() const [totalQuests, totalCompleted] = quests.reduce( ([total, completed], quest) => [ diff --git a/packages/analytics/src/controllers/quests.ts b/packages/analytics/src/controllers/quests.ts index 047f3ce..06136f2 100644 --- a/packages/analytics/src/controllers/quests.ts +++ b/packages/analytics/src/controllers/quests.ts @@ -1,6 +1,7 @@ import { questList } from '../models/quests.js' +import { Request, Response } from 'express' // eslint-disable-next-line import/prefer-default-export -export async function questListController(req: any, res: any) { +export async function questListController(req: Request, res: Response) { const quests = await questList() quests.forEach((quest) => { quest.failed = quest.started - quest.completed diff --git a/packages/analytics/src/controllers/sessions.ts b/packages/analytics/src/controllers/sessions.ts index bf01f21..9948cc0 100644 --- a/packages/analytics/src/controllers/sessions.ts +++ b/packages/analytics/src/controllers/sessions.ts @@ -1,8 +1,8 @@ import Pagination from '../models/pagination.ts' import { sessionList, sessionDetail } from '../models/sessions.ts' import { Request, Response } from 'express' -export async function sessionListController(req: any, res: any) { - const { nextKey, order } = req.query +export async function sessionListController(req: Request, res: Response) { + const { nextKey, order } = req.query as { nextKey: string; order: string } const itemsPerPage = 50 try { @@ -21,7 +21,7 @@ export async function sessionListController(req: any, res: any) { } } -export async function sessionDetailController(req: any, res: any) { +export async function sessionDetailController(req: Request, res: Response) { const { id } = req.params const session = await sessionDetail(id) res.render('sessionDetail', { session }) diff --git a/packages/analytics/src/controllers/users.ts b/packages/analytics/src/controllers/users.ts index d651488..4be4a57 100644 --- a/packages/analytics/src/controllers/users.ts +++ b/packages/analytics/src/controllers/users.ts @@ -1,13 +1,9 @@ -<<<<<<< HEAD +import mongoose from 'mongoose' import Pagination from '../models/pagination.ts' import { userList, userDetail, idToUser } from '../models/users.js' -======= -import Pagination from '../models/pagination.js' -import { userList } from '../models/users.js' ->>>>>>> bb4a11b20c8fdad8459ac3b7a0fdb8d9d9221e31 - -export async function userListController(req: any, res: any) { - const { nextKey, order } = req.query +import { Request, Response } from 'express' +export async function userListController(req: Request, res: Response) { + const { nextKey, order } = req.query as { nextKey: string; order: string } const itemsPerPage = 50 try { @@ -25,9 +21,8 @@ export async function userListController(req: any, res: any) { res.status(500).send('Error fetching user data') } } -<<<<<<< HEAD -export async function userDetailController(req: any, res: any) { - const { id } = req.params +export async function userDetailController(req: Request, res: Response) { + const id = new mongoose.Types.ObjectId(req.params.id) const sessions = await userDetail(id) try { const user = await idToUser(id) @@ -37,5 +32,3 @@ export async function userDetailController(req: any, res: any) { res.status(500).send('Error fetching user data') } } -======= ->>>>>>> bb4a11b20c8fdad8459ac3b7a0fdb8d9d9221e31 diff --git a/packages/analytics/src/interface.ts b/packages/analytics/src/interface.ts new file mode 100644 index 0000000..ba7c48c --- /dev/null +++ b/packages/analytics/src/interface.ts @@ -0,0 +1,61 @@ +import { Types } from 'mongoose' + +export interface User { + username: string +} +export interface SessionDocument { + _id: Types.ObjectId + user: User + quest: string + status: string + createdAt: Date + finishedAt: Date +} +export interface CommandObject { + command: string + pwd: string + stage: string | null | undefined + output: string | undefined + error: string | undefined + createdAt: string +} +export interface SessionObject { + _id: Types.ObjectId + user: string + quest: string + status: string + createdAt: string + finishedAt: string + lastActivityAt: string + usedTime: string + commandCount: number + commands: CommandObject[] +} +export interface SessionDetail { + _id: Types.ObjectId + user: string + quest: string + status: string + createdAt: string + finishedAt: string + usedTime: string + commands: CommandObject[] +} +export interface IUser extends Document { + hashedPassword?: string + socialLogins?: Record< + string, + { + id: string + provider: string + displayName?: string | null | undefined + } + > +} +export interface UserSessionDetail { + _id: Types.ObjectId + quest: string + status: string + createdAt: string + usedTime: string +} diff --git a/packages/analytics/src/models/sessions.ts b/packages/analytics/src/models/sessions.ts index ab9cd1d..345bfe2 100644 --- a/packages/analytics/src/models/sessions.ts +++ b/packages/analytics/src/models/sessions.ts @@ -1,6 +1,11 @@ import { Command, Session } from '@linux-odyssey/models' import Pagination from './pagination.ts' -import { Types } from 'mongoose' +import { + CommandObject, + SessionDetail, + SessionDocument, + SessionObject, +} from '../interface.ts' function formatTime(time: number) { const seconds = Math.floor(time / 1000) @@ -9,7 +14,9 @@ function formatTime(time: number) { return `${hours}h ${minutes % 60}m ${seconds % 60}s` } -export async function sessionList(pagination: Pagination): Promise { +export async function sessionList( + pagination: Pagination +): Promise { const sessions = await Session.aggregate([ pagination.match('_id'), { @@ -57,26 +64,16 @@ export async function sessionList(pagination: Pagination): Promise { ? formatTime(lastActivityAt.getTime() - createdAt.getTime()) : 'N/A', // Ensure both dates are present commandCount: commands?.length || 0, + commands, } }) } -interface User { - username: string -} -interface SessionDocument { - _id: Types.ObjectId - user: User - quest: string - status: string - createdAt: Date - finishedAt: Date -} -export async function sessionDetail(id: string): Promise { +export async function sessionDetail(id: string): Promise { const session = (await Session.findById(id) .populate('user') .exec()) as unknown as SessionDocument - const commands = (await Command.find({ session: id })).map( + const commands: CommandObject[] = (await Command.find({ session: id })).map( ({ command, pwd, output, error, createdAt, stage }) => ({ command: command?.slice(0, 20), pwd, diff --git a/packages/analytics/src/models/users.ts b/packages/analytics/src/models/users.ts index fa7b16b..b236d4c 100644 --- a/packages/analytics/src/models/users.ts +++ b/packages/analytics/src/models/users.ts @@ -1,11 +1,7 @@ import { Session, User } from '@linux-odyssey/models' import Pagination from './pagination.ts' -import { ObjectId, Model } from 'mongoose' - -interface IUser extends Document { - hashedPassword?: string - socialLogins?: Record -} +import { Types } from 'mongoose' +import { IUser, UserSessionDetail } from '../interface.ts' function loginMethods(user: IUser): string[] { const methods: string[] = [] @@ -62,12 +58,15 @@ export async function userList(pagination: Pagination) { } }) } -export async function userDetail(id: ObjectId): Promise { + +export async function userDetail( + id: Types.ObjectId +): Promise { const sessions = await Session.find({ user: id, }) return sessions.map((session) => { - const { _id, user, quest, status, createdAt, lastActivityAt } = session + const { _id, quest, status, createdAt, lastActivityAt } = session return { _id, quest, @@ -81,7 +80,8 @@ export async function userDetail(id: ObjectId): Promise { } }) } -export async function idToUser(id: ObjectId): Promise { + +export async function idToUser(id: Types.ObjectId): Promise { const user = await User.findOne({ _id: id, })