Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
a79e094
feature/ dashboardClient controller, service, model 생성, 회원가입기능(apikey…
nemo0824 Mar 10, 2025
7b7f726
feature: dashboardClient 로그인기능
nemo0824 Mar 10, 2025
ee18349
refactor: errorHandle 글로벌 에러핸들러 수정,
nemo0824 Mar 10, 2025
8af0afa
refactor: dashboardClientService(apikey를 bcrypt 에서 sha256으로 변경)
nemo0824 Mar 10, 2025
ccd0ef5
refactor: authenticate(SHA-256으로 hash한것으로 hahsedDomain끼리 조회 후 domain반환 )
nemo0824 Mar 10, 2025
fc53d20
refactor: dashboardClient service(타입단언 수정(get으로 일반객체로 불러오기, ) ), con…
nemo0824 Mar 10, 2025
67ab02d
refactor: dashboardClinet 에러메시지 변경
nemo0824 Mar 10, 2025
6ef8edb
refactor: sdkClientUser apiKeyservice(도메인 조회방법변경(raw 제거, 조회 후 일반객체로 …
nemo0824 Mar 11, 2025
b961fc4
refactor: dashboardClient(apikey 암호화 제거 및 필드에 암호화되지않은 apiKey로 변경)
nemo0824 Mar 11, 2025
0b85761
feature: dashboardClient(로그아웃 기능 추가)
nemo0824 Mar 11, 2025
ee4f480
refactor: dashboardController (도메인 session에서 사용), errorHanle(도메인 없을시 …
nemo0824 Mar 11, 2025
416f11e
refactor: hasDashboardDomain 미들웨어 생성 및 적용
nemo0824 Mar 11, 2025
e0b19b4
refactor: 미들웨어 ensureLogin추가(로그인 했는지 판별)
nemo0824 Mar 11, 2025
83c7f54
refactor: sessionType 추가 , Controller(Request타입 AuthenticatedRequest …
nemo0824 Mar 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"@types/cookie-parser": "^1.4.8",
"@types/cors": "^2.8.17",
"@types/express": "^5.0.0",
"@types/express-session": "^1.18.1",
"@types/node": "^22.13.5",
"eslint": "^9.21.0",
"eslint-config-prettier": "^10.0.1",
Expand All @@ -28,6 +29,7 @@
"typescript-eslint": "^8.25.0"
},
"dependencies": {
"bcryptjs": "^3.0.2",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
"dotenv": "^16.4.7",
Expand Down
128 changes: 113 additions & 15 deletions src/controllers/dashboardController.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { NextFunction, Request, Response } from 'express';
import { dashboardClientService } from '../services/dashboardClientService';
import { userActionService } from '../services/userActionService';
import { userConnectionService } from '../services/userConnectionService';
import { userDeviceService } from '../services/userDeviceService';
Expand All @@ -8,7 +9,11 @@ import { userPageInfoService } from '../services/userPageInfoService';
export const dashboardController = {
getOnlineUsersCount: async (req: Request, res: Response, next: NextFunction) => {
try {
const { domain } = req.params;
const domain = req.session.client?.domain;
if (!domain) {
next(new Error('로그인 필요'));
return;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 코드 중복이 엄청 많은데 미들웨어로 처리해보세요.
별개로 domain이 있는지 없는지를 보고 로그인 여부를 판단하는 것도 어색합니다.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵 중복된코드 미들웨어 활용해서 처리했습니다.
domain이있는지 없는지로 로그인 여부 판단하는게 어색하다고하셨는데 1차원적으로 "도메인이 없다" 라고 표현하는게 더 자연스러울까요?

const onlineUsersCount = await userConnectionService.getOnlineUsersCount(domain);
res.status(200).json({ onlineUsersCount });
} catch (err) {
Expand All @@ -18,7 +23,11 @@ export const dashboardController = {

getPerPageAverageScrollDepth: async (req: Request, res: Response, next: NextFunction) => {
try {
const { domain } = req.params;
const domain = req.session.client?.domain;
if (!domain) {
next(new Error('로그인 필요'));
return;
}
const perPageAverageScrollDepth =
await userActionService.getPerPageAverageScrollDepth(domain);
res.status(200).json(perPageAverageScrollDepth);
Expand All @@ -29,7 +38,11 @@ export const dashboardController = {

getPerPageBounceRate: async (req: Request, res: Response, next: NextFunction) => {
try {
const { domain } = req.params;
const domain = req.session.client?.domain;
if (!domain) {
next(new Error('로그인 필요'));
return;
}
const bounceRate = await userActionService.getPerPageBounceRate(domain);
res.status(200).json(bounceRate);
} catch (err) {
Expand All @@ -39,7 +52,11 @@ export const dashboardController = {

getBrowserStats: async (req: Request, res: Response, next: NextFunction) => {
try {
const { domain } = req.params;
const domain = req.session.client?.domain;
if (!domain) {
next(new Error('로그인 필요'));
return;
}
const userBrowserStats = await userDeviceService.getBrowserStats(domain);
res.status(200).json(userBrowserStats);
} catch (err) {
Expand All @@ -49,7 +66,11 @@ export const dashboardController = {

getOsStats: async (req: Request, res: Response, next: NextFunction) => {
try {
const { domain } = req.params;
const domain = req.session.client?.domain;
if (!domain) {
next(new Error('로그인 필요'));
return;
}
const userOsStats = await userDeviceService.getOsStats(domain);
res.status(200).json(userOsStats);
} catch (err) {
Expand All @@ -59,7 +80,11 @@ export const dashboardController = {

getDeviceStats: async (req: Request, res: Response, next: NextFunction) => {
try {
const { domain } = req.params;
const domain = req.session.client?.domain;
if (!domain) {
next(new Error('로그인 필요'));
return;
}
const userDeviceStats = await userDeviceService.getDeviceStats(domain);
res.status(200).json(userDeviceStats);
} catch (err) {
Expand All @@ -69,7 +94,11 @@ export const dashboardController = {

getResolutionStats: async (req: Request, res: Response, next: NextFunction) => {
try {
const { domain } = req.params;
const domain = req.session.client?.domain;
if (!domain) {
next(new Error('로그인 필요'));
return;
}
const userResolutionStats = await userDeviceService.getResolutionStats(domain);
res.status(200).json(userResolutionStats);
} catch (err) {
Expand All @@ -79,7 +108,11 @@ export const dashboardController = {

getLanguageStats: async (req: Request, res: Response, next: NextFunction) => {
try {
const { domain } = req.params;
const domain = req.session.client?.domain;
if (!domain) {
next(new Error('로그인 필요'));
return;
}
const languageStats = await userInfoService.getLanguageStats(domain);
res.status(200).json(languageStats);
} catch (err) {
Expand All @@ -89,7 +122,11 @@ export const dashboardController = {

getCountryStats: async (req: Request, res: Response, next: NextFunction) => {
try {
const { domain } = req.params;
const domain = req.session.client?.domain;
if (!domain) {
next(new Error('로그인 필요'));
return;
}
const countryStats = await userInfoService.getCountryStats(domain);
res.status(200).json(countryStats);
} catch (err) {
Expand All @@ -99,7 +136,11 @@ export const dashboardController = {

getVisitedUsersRate: async (req: Request, res: Response, next: NextFunction) => {
try {
const { domain } = req.params;
const domain = req.session.client?.domain;
if (!domain) {
next(new Error('로그인 필요'));
return;
}
const getVisitedUsersRate = await userInfoService.getVisitedUsersRate(domain);
res.status(200).json(getVisitedUsersRate);
} catch (err) {
Expand All @@ -109,7 +150,11 @@ export const dashboardController = {

getReferrerStats: async (req: Request, res: Response, next: NextFunction) => {
try {
const { domain } = req.params;
const domain = req.session.client?.domain;
if (!domain) {
next(new Error('로그인 필요'));
return;
}
const referrerStatus = await userPageInfoService.getReferrerStats(domain);
res.status(200).json(referrerStatus);
} catch (err) {
Expand All @@ -119,7 +164,11 @@ export const dashboardController = {

getAveragePageLoadTime: async (req: Request, res: Response, next: NextFunction) => {
try {
const { domain } = req.params;
const domain = req.session.client?.domain;
if (!domain) {
next(new Error('로그인 필요'));
return;
}
const avgLoadTime = await userPageInfoService.getAveragePageLoadTime(domain);
res.status(200).json(avgLoadTime);
} catch (err) {
Expand All @@ -129,7 +178,11 @@ export const dashboardController = {

getPageViewCount: async (req: Request, res: Response, next: NextFunction) => {
try {
const { domain } = req.params;
const domain = req.session.client?.domain;
if (!domain) {
next(new Error('로그인 필요'));
return;
}
const { startDate, endDate } = req.query;
if (typeof startDate !== 'string' || typeof endDate !== 'string') {
res.status(400).json({ message: '시작 날짜와 종료날짜 올바르게 입력하세요' });
Expand All @@ -148,7 +201,11 @@ export const dashboardController = {

getVisitorsByPeriod: async (req: Request, res: Response, next: NextFunction) => {
try {
const { domain } = req.params;
const domain = req.session.client?.domain;
if (!domain) {
next(new Error('로그인 필요'));
return;
}
const { startDate, endDate } = req.query;
if (typeof startDate !== 'string' || typeof endDate !== 'string') {
res.status(400).json({ message: 'startDate와 endDate는 필수입니다.' });
Expand All @@ -167,11 +224,52 @@ export const dashboardController = {

getTotalVisitors: async (req: Request, res: Response, next: NextFunction) => {
try {
const { domain } = req.params;
const domain = req.session.client?.domain;
if (!domain) {
next(new Error('로그인 필요'));
return;
}
const totalVisitorsData = await userPageInfoService.getTotalVisitors(domain);
res.status(200).json(totalVisitorsData);
} catch (err) {
next(err);
}
},

enrollClient: async (req: Request, res: Response, next: NextFunction) => {
try {
const { email, password } = req.body;
const domain = req.session.client?.domain;
if (!domain) {
next(new Error('로그인 필요'));
return;
}
const apiKey = await dashboardClientService.enrollClient(email, password, domain);
res.status(201).json({ message: '회원가입성공', apiKey });
} catch (err) {
next(err);
}
},

loginClient: async (req: Request, res: Response, next: NextFunction) => {
try {
const { email, password } = req.body;
const domain = await dashboardClientService.loginClient(email, password);
req.session.client = { email, domain };
res.status(200).json({ message: '로그인 성공' });
} catch (err) {
next(err);
}
},

logoutClient: (req: Request, res: Response, next: NextFunction) => {
if (!req.session.client) {
next(new Error('이미 로그아웃'));
return;
}
req.session.destroy(() => {
res.clearCookie('connect.sid');
res.json({ message: '로그아웃 성공' });
});
},
};
Loading
Loading