-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
채팅방 버그 이슈 및 프로필 사진 변경 모달 UI 수정 #139
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
/* eslint-disable no-underscore-dangle */ | ||
import Users, { IActivity } from '@models/users'; | ||
import Events from '@models/events'; | ||
import { activeUser } from '@src/sockets/user'; | ||
import { userNamespace } from '@src/sockets'; | ||
|
||
let instance: any = null; | ||
class UserService { | ||
constructor() { | ||
if (instance) return instance; | ||
instance = this; | ||
} | ||
|
||
Comment on lines
+6
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. activity 부분을 따로 서비스로직을 빼주셨군요! class 명을 ActivityService라고 해야할 것 같아요 |
||
async getActivityList(userDocumentId: string, count: number) { | ||
const user = await Users.findById(userDocumentId, ['activity']); | ||
const newActivityList = await Promise.all(user!.activity.slice(count, count + 10).map(async (activity: IActivity) => { | ||
const detailFrom = await this.findUserByDocumentId(activity.from); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
const newFrom = { userId: detailFrom!.userId, userName: detailFrom!.userName, profileUrl: detailFrom!.profileUrl }; | ||
return { ...activity, from: newFrom }; | ||
})); | ||
await Users.findByIdAndUpdate(userDocumentId, { activity: user!.activity.map((el) => ({ ...el, isChecked: true })) }); | ||
return newActivityList; | ||
} | ||
|
||
async isActivityChecked(userDocumentId: string) { | ||
try { | ||
const { activity } : any = await Users.findOne({ _id: userDocumentId }, ['activity']); | ||
if (!activity) return false; | ||
return activity.some((item: IActivity) => !item.isChecked); | ||
} catch (e) { | ||
return false; | ||
} | ||
} | ||
|
||
async addActivityTypeFollow(userDocumentId: string, targetUserDocumentId: string) { | ||
try { | ||
const newActivity = { | ||
type: 'follow', | ||
clickDocumentId: userDocumentId, | ||
from: userDocumentId, | ||
date: new Date(), | ||
isChecked: false, | ||
}; | ||
await Users.findByIdAndUpdate(targetUserDocumentId, { $push: { activity: { $each: [newActivity], $position: 0 } } }); | ||
this.emitToUserGetActivity(targetUserDocumentId); | ||
return true; | ||
} catch (e) { | ||
return false; | ||
} | ||
} | ||
|
||
async addActivityTypeRoom(userDocumentId: string, roomDocumentId: string) { | ||
try { | ||
const user = await Users.findById(userDocumentId, ['followers']); | ||
const newActivity = { | ||
type: 'room', | ||
clickDocumentId: String(roomDocumentId), | ||
from: userDocumentId, | ||
date: new Date(), | ||
isChecked: false, | ||
}; | ||
await Promise.all(user!.followers.map(async (userDocId: string) => { | ||
await Users.findByIdAndUpdate(userDocId, { $push: { activity: { $each: [newActivity], $position: 0 } } }); | ||
this.emitToUserGetActivity(userDocId); | ||
return true; | ||
})); | ||
return true; | ||
} catch (e) { | ||
return false; | ||
} | ||
} | ||
|
||
async addActivityTypeEvent(userDocumentId: string, eventDocumentId: string) { | ||
try { | ||
const event = await Events.findById(eventDocumentId, ['participants']); | ||
const newActivity = { | ||
type: 'event', | ||
clickDocumentId: String(eventDocumentId), | ||
from: userDocumentId, | ||
date: new Date(), | ||
isChecked: false, | ||
}; | ||
await Promise.all(event!.participants.map(async (userId: string) => { | ||
const user = await Users.findOneAndUpdate({ userId }, { $push: { activity: { $each: [newActivity], $position: 0 } } }); | ||
const userDocId = user!._id; | ||
this.emitToUserGetActivity(String(userDocId)); | ||
return true; | ||
})); | ||
return true; | ||
} catch (e) { | ||
return false; | ||
} | ||
} | ||
|
||
emitToUserGetActivity(userDocumentId: string) { | ||
const socketUser = activeUser.get(userDocumentId); | ||
if (socketUser) userNamespace.to(socketUser.socketId).emit('user:getActivity'); | ||
} | ||
} | ||
|
||
export default new UserService(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
/* eslint-disable no-underscore-dangle */ | ||
import jwt from 'jsonwebtoken'; | ||
|
||
import Users from '@models/users'; | ||
import RefreshTokens from '@models/refresh-token'; | ||
import jwtUtils from '@utils/jwt-util'; | ||
|
||
interface ISignupUserInfo { | ||
loginType: string, | ||
userId: string, | ||
password: string, | ||
userName: string, | ||
userEmail: string, | ||
} | ||
|
||
let instance: any = null; | ||
class AuthService { | ||
constructor() { | ||
if (instance) return instance; | ||
instance = this; | ||
} | ||
|
||
async signIn(email: string, password: string) { | ||
const user = await Users.findOne({ userEmail: email }); | ||
|
||
if (!user) { | ||
return { ok: false, msg: 'there is no user' }; | ||
} | ||
|
||
const isMatch = user.checkPassword(password); | ||
|
||
if (isMatch) { | ||
const accessToken = jwtUtils.sign(user._id, user.userEmail); | ||
const refreshToken = jwtUtils.refresh(); | ||
|
||
const existingRefreshToken = await RefreshTokens.findOneAndUpdate( | ||
{ userDocumentId: user._id }, | ||
{ token: refreshToken }, | ||
); | ||
|
||
if (!existingRefreshToken) { | ||
const usersRefreshTokens = new RefreshTokens({ | ||
userDocumentId: user._id, | ||
token: refreshToken, | ||
}); | ||
await usersRefreshTokens.save(); | ||
} | ||
|
||
return { | ||
accessToken, | ||
ok: true, | ||
msg: 'ok', | ||
}; | ||
} | ||
return { ok: false, msg: 'wrong password' }; | ||
} | ||
|
||
async signup(info: ISignupUserInfo) { | ||
try { | ||
await Users.insertMany([info]); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
} | ||
|
||
async verifyAccessToken(token: string) { | ||
const result = jwtUtils.verify(token); | ||
if (!result.ok) { | ||
const newToken = await this.tokenRefresh(token); | ||
return newToken; | ||
} | ||
return result; | ||
} | ||
|
||
async getRefreshTokens(userDocumentId: string) { | ||
const refreshToken = await RefreshTokens.findOne({ userDocumentId }); | ||
if (!refreshToken) { | ||
return null; | ||
} | ||
return refreshToken.token; | ||
} | ||
|
||
async tokenRefresh(accessToken: string) { | ||
const accessResult = jwtUtils.verify(accessToken); | ||
const decoded = jwt.decode(accessToken) as jwt.JwtPayload; | ||
|
||
if (decoded === null) { | ||
return { | ||
ok: false, | ||
msg: 'No authorized!', | ||
}; | ||
} | ||
|
||
const refreshToken = (await this.getRefreshTokens(decoded.id)) as string; | ||
const refreshResult = await jwtUtils.refreshVerify(refreshToken); | ||
|
||
if (accessResult.ok === false && accessResult.message === 'jwt expired') { | ||
if (refreshResult === false) { | ||
return { | ||
ok: false, | ||
msg: 'No authorized!', | ||
}; | ||
} | ||
const newAccessToken = jwtUtils.sign(decoded.id, decoded.email); | ||
|
||
return { | ||
ok: true, | ||
accessToken: newAccessToken, | ||
userDocumentId: decoded.id, | ||
}; | ||
} | ||
|
||
return { | ||
ok: true, | ||
msg: 'Acess token is not expired!', | ||
}; | ||
} | ||
} | ||
|
||
export default new AuthService(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
커스텀훅을 사용해서 view의 역할에 더 알맞게 코드가 바뀐 것 같아서 아주 좋네요!