From a2c27b313afce1fabd98e43f3b772d30b3cfff16 Mon Sep 17 00:00:00 2001 From: rafiarrafif Date: Thu, 8 May 2025 15:21:05 +0700 Subject: [PATCH] add userSession module --- bun.lockb | Bin 50845 -> 60351 bytes package.json | 3 +- .../getUserHeaderInformation/index.ts | 26 +++++++++++++++ .../getUserHeaderInformation/types.ts | 6 ++++ .../createUserSession.controller.ts | 30 ++++++++++++++++++ src/modules/userSession/index.ts | 7 ++++ .../services/createUserSession.service.ts | 20 ++++++++++++ src/modules/userSession/userSession.model.ts | 3 ++ .../userSession/userSession.repository.ts | 25 +++++++++++++++ src/modules/userSession/userSession.schema.ts | 0 src/modules/userSession/userSession.types.ts | 6 ++++ 11 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 src/helpers/cookies/userHeader/getUserHeaderInformation/index.ts create mode 100644 src/helpers/cookies/userHeader/getUserHeaderInformation/types.ts create mode 100644 src/modules/userSession/controller/createUserSession.controller.ts create mode 100644 src/modules/userSession/index.ts create mode 100644 src/modules/userSession/services/createUserSession.service.ts create mode 100644 src/modules/userSession/userSession.model.ts create mode 100644 src/modules/userSession/userSession.repository.ts create mode 100644 src/modules/userSession/userSession.schema.ts create mode 100644 src/modules/userSession/userSession.types.ts diff --git a/bun.lockb b/bun.lockb index 9e8bf1e30db9ed230df71c4f40839e5d7dea4c35..4fb12fdec7e0bc45d1b6a04bb561951c9e8aaec9 100644 GIT binary patch delta 14356 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 BvDE+o delta 9010 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 mQAK0f(RQu}eAo|oUdWcfSt*tXLE diff --git a/package.json b/package.json index b677444..0942d5e 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "cookie": "^1.0.2", "elysia": "latest", "joi": "^17.13.3", - "jsonwebtoken": "^9.0.2" + "jsonwebtoken": "^9.0.2", + "ua-parser-js": "^2.0.3" }, "devDependencies": { "bun-types": "latest", diff --git a/src/helpers/cookies/userHeader/getUserHeaderInformation/index.ts b/src/helpers/cookies/userHeader/getUserHeaderInformation/index.ts new file mode 100644 index 0000000..b9dd853 --- /dev/null +++ b/src/helpers/cookies/userHeader/getUserHeaderInformation/index.ts @@ -0,0 +1,26 @@ +import { Context } from "elysia"; +import { UAParser } from "ua-parser-js"; +import { UserHeaderInformation } from "./types"; + +export const getUserHeaderInformation = ( + ctx: Context +): UserHeaderInformation => { + const headers = ctx.request.headers; + const userAgentHeader = headers.get("user-agent") || "desktop"; + const userAgent = new UAParser(userAgentHeader); + + const userIP = + headers.get("cf-connecting-ip") || + headers.get("x-real-ip") || + headers.get("x-forwarded-for")?.split(",")[0] || + "Unknown IP"; + + const userHeaderInformation = { + ip: userIP, + deviceType: userAgent.getDevice().type || "desktop", + deviceOS: userAgent.getOS().name + " " + userAgent.getOS().version, + browser: userAgent.getBrowser().name + " " + userAgent.getBrowser().version, + }; + + return userHeaderInformation; +}; diff --git a/src/helpers/cookies/userHeader/getUserHeaderInformation/types.ts b/src/helpers/cookies/userHeader/getUserHeaderInformation/types.ts new file mode 100644 index 0000000..f1a54d1 --- /dev/null +++ b/src/helpers/cookies/userHeader/getUserHeaderInformation/types.ts @@ -0,0 +1,6 @@ +export interface UserHeaderInformation { + ip: string; + deviceType: string; + deviceOS: string; + browser: string; +} diff --git a/src/modules/userSession/controller/createUserSession.controller.ts b/src/modules/userSession/controller/createUserSession.controller.ts new file mode 100644 index 0000000..c5a0ff3 --- /dev/null +++ b/src/modules/userSession/controller/createUserSession.controller.ts @@ -0,0 +1,30 @@ +import { Context } from "elysia"; +import { createUserSessionService } from "../services/createUserSession.service"; +import { getUserHeaderInformation } from "../../../helpers/cookies/userHeader/getUserHeaderInformation"; +import { handlePrismaError } from "../../../utils/databases/prisma/error/handler"; +import { + returnErrorResponse, + returnWriteResponse, +} from "../../../helpers/callback/httpResponse"; + +export const createUserSessionRole = async ( + ctx: Context & { body: { userId: string } } +) => { + const userHeaderData = getUserHeaderInformation(ctx); + + try { + const newUserSession = await createUserSessionService({ + userId: ctx.body.userId, + userHeaderInformation: userHeaderData, + }); + return returnWriteResponse( + ctx.set, + 201, + "User session created", + newUserSession + ); + } catch (error) { + const { status, message, details } = handlePrismaError(error); + return returnErrorResponse(ctx.set, status, message, details); + } +}; diff --git a/src/modules/userSession/index.ts b/src/modules/userSession/index.ts new file mode 100644 index 0000000..d4087c2 --- /dev/null +++ b/src/modules/userSession/index.ts @@ -0,0 +1,7 @@ +import Elysia from "elysia"; +import { createUserSessionRole } from "./controller/createUserSession.controller"; + +export const userSessionModule = new Elysia({ prefix: "/user-sessions" }).post( + "/", + createUserSessionRole +); diff --git a/src/modules/userSession/services/createUserSession.service.ts b/src/modules/userSession/services/createUserSession.service.ts new file mode 100644 index 0000000..c940e18 --- /dev/null +++ b/src/modules/userSession/services/createUserSession.service.ts @@ -0,0 +1,20 @@ +import { createUserSessionServiceParams } from "../userSession.types"; +import { createUserSessionRepo } from "../userSession.repository"; + +export const createUserSessionService = async ( + data: createUserSessionServiceParams +) => { + const sessionLifetime = Number(process.env.SESSION_EXPIRE!); + try { + const newUserSession = await createUserSessionRepo({ + userId: data.userId, + isAuthenticated: true, + deviceType: data.userHeaderInformation.deviceType, + deviceOs: data.userHeaderInformation.deviceOS, + deviceIp: data.userHeaderInformation.ip, + validUntil: new Date(new Date().getTime() + sessionLifetime * 1000), + }); + } catch (error) { + throw error; + } +}; diff --git a/src/modules/userSession/userSession.model.ts b/src/modules/userSession/userSession.model.ts new file mode 100644 index 0000000..6c993a4 --- /dev/null +++ b/src/modules/userSession/userSession.model.ts @@ -0,0 +1,3 @@ +import { prisma } from "../../utils/databases/prisma/connection"; + +export const userSessionModel = prisma.userSession; diff --git a/src/modules/userSession/userSession.repository.ts b/src/modules/userSession/userSession.repository.ts new file mode 100644 index 0000000..4f2f945 --- /dev/null +++ b/src/modules/userSession/userSession.repository.ts @@ -0,0 +1,25 @@ +import { Prisma } from "@prisma/client"; +import { userSessionModel } from "./userSession.model"; + +export const createUserSessionRepo = async ( + data: Prisma.UserSessionUncheckedCreateInput +) => { + try { + const newUserRole = await userSessionModel.create({ + data: data, + include: { + user: { + omit: { + password: true, + }, + include: { + roles: true, + }, + }, + }, + }); + return newUserRole; + } catch (error) { + throw error; + } +}; diff --git a/src/modules/userSession/userSession.schema.ts b/src/modules/userSession/userSession.schema.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/userSession/userSession.types.ts b/src/modules/userSession/userSession.types.ts new file mode 100644 index 0000000..c4bd913 --- /dev/null +++ b/src/modules/userSession/userSession.types.ts @@ -0,0 +1,6 @@ +import { UserHeaderInformation } from "../../helpers/cookies/userHeader/getUserHeaderInformation/types"; + +export interface createUserSessionServiceParams { + userId: string; + userHeaderInformation: UserHeaderInformation; +}