diff --git a/src/domains/auth/AuthController.ts b/src/domains/auth/AuthController.ts index 35495df..2c704ae 100644 --- a/src/domains/auth/AuthController.ts +++ b/src/domains/auth/AuthController.ts @@ -24,7 +24,7 @@ import { PasswordResetPostDto } from "../../interfaces/dtos/auth/PasswordResetPo import { UserDeleteDto } from "../../interfaces/dtos/auth/UserDeleteDto" import { UserTokenPostDto } from "../../interfaces/dtos/auth/UserTokenPostDto" import { UsernamePutDto } from "../../interfaces/dtos/auth/UsernamePutDto" -import UserRepository from "../../repositories/UserRepository" +import { UserRepository } from "../../repositories/UserRepository" import { MyAuthRequest } from "../../utils/MyAuthRequest" import { $SaveUser } from "../user/use-cases/$SaveUser" import { AuthService } from "./AuthService" @@ -33,10 +33,10 @@ import { RegisterDto } from "./types/RegisterDto" @JsonController("/auth") export class AuthController { constructor( - private userRepo = UserRepository, - private preferenceRepo = dataSource.getRepository(UserPreference), - private authService = new AuthService(), - private $saveUser = new $SaveUser() + private readonly userRepo = new UserRepository(), + private readonly preferenceRepo = dataSource.getRepository(UserPreference), + private readonly authService = new AuthService(), + private readonly $saveUser = new $SaveUser() ) {} @Post("/register") @@ -122,7 +122,7 @@ export class AuthController { if (!passwordOk) throw new BadRequestError("Incorrect password.") if (passwordOk) { - await this.userRepo.delete({ id: requester.id }) + await this.userRepo.rawRepo.delete({ id: requester.id }) return true } @@ -135,7 +135,7 @@ export class AuthController { ) { const { newUsername } = body - const usernameExists = await this.userRepo.findOne({ + const usernameExists = await this.userRepo.rawRepo.findOne({ where: { username: newUsername, }, diff --git a/src/domains/auth/AuthService.ts b/src/domains/auth/AuthService.ts index 14c65e6..d61afe1 100644 --- a/src/domains/auth/AuthService.ts +++ b/src/domains/auth/AuthService.ts @@ -13,7 +13,7 @@ import { User } from "../../entities/User" import { AuthUserGetDto } from "../../interfaces/dtos/auth/AuthUserGetDto" import { PasswordResetPostDto } from "../../interfaces/dtos/auth/PasswordResetPostDto" import { UserTokenPostDto } from "../../interfaces/dtos/auth/UserTokenPostDto" -import UserRepository from "../../repositories/UserRepository" +import { UserRepository } from "../../repositories/UserRepository" import { myEnvs } from "../../utils/myEnvs" import { addMinutes } from "../../utils/time/addMinutes" import validateUserFields from "../../utils/validateUser" @@ -22,14 +22,14 @@ import { RegisterDto } from "./types/RegisterDto" export class AuthService { constructor( - private userRepo = UserRepository, - private tokenRepo = dataSource.getRepository(UserToken), - private $saveUser = new $SaveUser() + private readonly userRepo = new UserRepository(), + private readonly tokenRepo = dataSource.getRepository(UserToken), + private readonly $saveUser = new $SaveUser() ) {} async register(dto: RegisterDto) { // only creates an instance. Doesn't save on DB - const sentUser = this.userRepo.create(dto) + const sentUser = this.userRepo.rawRepo.create(dto) const userErrors = validateUserFields(sentUser) if (userErrors.length) { throw new BadRequestError(userErrors[0].message) @@ -39,7 +39,7 @@ export class AuthService { throw new BadRequestError("Passwords are different!") // Checking if email exists - let userExists = await this.userRepo.findOne({ + let userExists = await this.userRepo.rawRepo.findOne({ where: { email: sentUser.email, }, @@ -50,7 +50,7 @@ export class AuthService { } // Checking if username exists - userExists = await this.userRepo.findOne({ + userExists = await this.userRepo.rawRepo.findOne({ where: { username: sentUser.username, }, @@ -102,7 +102,7 @@ export class AuthService { } // username or email exists ? - const user = await this.userRepo.findOne({ + const user = await this.userRepo.rawRepo.findOne({ where: [{ email: sentUser.email }, { username: sentUser.email }], }) if (!user) { @@ -137,13 +137,13 @@ export class AuthService { } async keepTempUser(dto: RegisterDto, userId: number) { - const previousTempUser = await this.userRepo.findOne({ + const previousTempUser = await this.userRepo.rawRepo.findOne({ where: { id: userId }, }) if (!previousTempUser) throw new BadRequestError("User not found") // only creates an instance. Doesn't save on DB - const sentUser = this.userRepo.create(dto) + const sentUser = this.userRepo.rawRepo.create(dto) const userErrors = validateUserFields(sentUser) if (userErrors.length) { throw new BadRequestError(userErrors[0].message) @@ -153,7 +153,7 @@ export class AuthService { throw new BadRequestError("Passwords are different!") // Checking if email exists - let userExists = await this.userRepo.findOne({ + let userExists = await this.userRepo.rawRepo.findOne({ where: { email: sentUser.email, }, @@ -164,7 +164,7 @@ export class AuthService { } // Checking if username exists - userExists = await this.userRepo.findOne({ + userExists = await this.userRepo.rawRepo.findOne({ where: { username: sentUser.username, }, @@ -246,7 +246,7 @@ export class AuthService { // Same process as POST /auth/login - const user = await this.userRepo.findOne({ + const user = await this.userRepo.rawRepo.findOne({ where: { id: userId, }, @@ -295,7 +295,7 @@ export class AuthService { if (!tokenExists) throw new BadRequestError("Token does not exist or it is expired.") - const user = await this.userRepo.findOne({ + const user = await this.userRepo.rawRepo.findOne({ where: { id: userId, }, diff --git a/src/domains/feed/follow/FollowRepository.ts b/src/domains/feed/follow/FollowRepository.ts index de67caa..c387996 100644 --- a/src/domains/feed/follow/FollowRepository.ts +++ b/src/domains/feed/follow/FollowRepository.ts @@ -28,7 +28,6 @@ export class FollowRepository { } async findFolloweesByFollowerId(followerId: number) { - // PE 1/3 - todo: don't return all fields const follows = await this.db.getRepository(Follow).find({ where: { followerId, diff --git a/src/domains/feed/follow/FollowService.ts b/src/domains/feed/follow/FollowService.ts index 8478ed1..515d203 100644 --- a/src/domains/feed/follow/FollowService.ts +++ b/src/domains/feed/follow/FollowService.ts @@ -1,12 +1,12 @@ -import UserRepository from "../../../repositories/UserRepository" +import { UserRepository } from "../../../repositories/UserRepository" import { NotificationService } from "../../notification/NotificationService" import { FollowRepository } from "./FollowRepository" export class FollowService { constructor( - private followRepo = new FollowRepository(), - private userRepo = UserRepository, // private notificationService = new NotificationService() - private notificationService = new NotificationService() + private readonly followRepo = new FollowRepository(), + private readonly userRepo = new UserRepository(), + private readonly notificationService = new NotificationService() ) {} async toggleFollow(requesterId: number, followingUserId: number) { diff --git a/src/domains/monerate/category/CategoryController.ts b/src/domains/monerate/category/CategoryController.ts index 77e1881..e146148 100644 --- a/src/domains/monerate/category/CategoryController.ts +++ b/src/domains/monerate/category/CategoryController.ts @@ -2,10 +2,8 @@ import { BadRequestError, Body, CurrentUser, - Delete, Get, JsonController, - Param, Post, } from "routing-controllers" import { User } from "../../../entities/User" @@ -47,20 +45,4 @@ export class CategoryController { async getCategories(@CurrentUser({ required: true }) user: User) { return this.categoryRepo.getCategoriesFromUser(user) } - - // PE 1/3 - not being used? - @Delete("/:id") - async deleteCategory( - @CurrentUser({ required: true }) user: User, - @Param("id") categoryId: number - ) { - const result = await this.categoryRepo.delete({ - id: categoryId, - userId: user.id, - }) - if (!result.affected) - throw new BadRequestError("Category id not found, or user is not owner.") - - return this.categoryRepo.getCategoriesFromUser(user) - } } diff --git a/src/domains/notification/NotificationService.ts b/src/domains/notification/NotificationService.ts index c5e7c97..d33f84c 100644 --- a/src/domains/notification/NotificationService.ts +++ b/src/domains/notification/NotificationService.ts @@ -1,12 +1,12 @@ import { NotFoundError } from "routing-controllers" import { Follow } from "../../entities/feed/Follow" -import { UserRepositoryV2 } from "../user/UserRepositoryV2" +import { UserRepository } from "../../repositories/UserRepository" import { NotificationRepositoryV2 } from "./NotificationRepositoryV2" export class NotificationService { constructor( - private userRepo = new UserRepositoryV2(), - private notificationRepo = new NotificationRepositoryV2() + private readonly userRepo = new UserRepository(), + private readonly notificationRepo = new NotificationRepositoryV2() ) {} async createFollowNotification(follow: Follow) { diff --git a/src/domains/relearn/resource/use-cases/_SaveResource/_SaveResource.ts b/src/domains/relearn/resource/use-cases/_SaveResource/_SaveResource.ts index 1937527..97ebff4 100644 --- a/src/domains/relearn/resource/use-cases/_SaveResource/_SaveResource.ts +++ b/src/domains/relearn/resource/use-cases/_SaveResource/_SaveResource.ts @@ -12,8 +12,9 @@ export class _SaveResource { returnAll?: boolean }) { const { sentResource, user, returnAll = true } = params - if (sentResource.tag === null) + if (sentResource.tag === null) { throw new BadRequestError("Resource must have a tag.") + } if (sentResource.thumbnail === null) sentResource.thumbnail = "" @@ -38,22 +39,18 @@ export class _SaveResource { if ( previousResource.rating !== sentResource.rating && sentResource.rating > 0 - ) + ) { sentResource.completedAt = new Date().toISOString() + } - // PE 1/3 - Maybe it would be better to create a specific route for that... - // If adding a rating if (!previousResource.rating && sentResource.rating > 0) { - await this.resourceRepo.reducePosition( - sentResource.tag, + await this.resourceRepo.decrementResourcePositionsInTag({ + tag: sentResource.tag, user, - sentResource.position + 1 - ) + startingPosition: sentResource.position + 1, + }) sentResource.completedAt = new Date().toISOString() - // sentResource.position = null - - // TODO: reduce by 1 the others' positions } // If removing a rating else if (previousResource.rating > 0 && sentResource.rating === null) { @@ -70,11 +67,11 @@ export class _SaveResource { previousResource.tag?.id != sentResource.tag?.id) && // changing tag previousResource.position ) { - await this.resourceRepo.reducePosition( - previousResource.tag, + await this.resourceRepo.decrementResourcePositionsInTag({ + tag: previousResource.tag, user, - previousResource.position + 1 - ) + startingPosition: previousResource.position + 1, + }) sentResource.position = await this.resourceRepo.getLastPosition( sentResource.tag, diff --git a/src/domains/skillbase/learning/ProgressController.ts b/src/domains/skillbase/learning/ProgressController.ts deleted file mode 100644 index b160d1c..0000000 --- a/src/domains/skillbase/learning/ProgressController.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { - BadRequestError, - CurrentUser, - Delete, - Get, - JsonController, - Param, -} from "routing-controllers" -import { User } from "../../../entities/User" -import ProgressRepository from "../../../repositories/skillbase/ProgressRepository" - -// PE 1/3 - not being used. Delete? -@JsonController("/skillbase/progress") -export class ProgressController { - constructor(private progressRepo = ProgressRepository) {} - - @Get("/") - async findAllSkillsFromAuthUser( - @CurrentUser({ required: true }) - user: User - ) { - return this.progressRepo.getAllFromUser(user.id) - } - - @Delete("/:id") - async deleteProgress( - @CurrentUser({ required: true }) - user: User, - @Param("id") id: number - ) { - const result = await this.progressRepo.delete({ id, userId: user.id }) - if (!result.affected) - throw new BadRequestError("Progress not found, or user is not owner.") - - return this.progressRepo.getAllFromUser(user.id) - } -} diff --git a/src/domains/skillbase/skill/SkillController.ts b/src/domains/skillbase/skill/SkillController.ts index 449e835..9e06c7d 100644 --- a/src/domains/skillbase/skill/SkillController.ts +++ b/src/domains/skillbase/skill/SkillController.ts @@ -2,13 +2,10 @@ import { Body, CurrentUser, Delete, - ForbiddenError, Get, JsonController, NotFoundError, - Param, Post, - Put, UseBefore, } from "routing-controllers" import { dataSource } from "../../../dataSource" @@ -23,9 +20,13 @@ import SkillRepository from "../../../repositories/skillbase/SkillRepository" @JsonController() export class SkillController { constructor( - private skillRepo = SkillRepository, - private skillProgressRepo = dataSource.getRepository(SkillProgress), - private skillExpectationRepo = dataSource.getRepository(SkillExpectation) + private readonly skillRepo = SkillRepository, + private readonly skillProgressRepo = dataSource.getRepository( + SkillProgress + ), + private readonly skillExpectationRepo = dataSource.getRepository( + SkillExpectation + ) ) {} @Get("/skillbase/skill") @@ -88,31 +89,6 @@ export class SkillController { return savedSkill } - @Put("/skillbase/skill/:id") - async updateSkill( - @UseBefore(MyAuthMiddleware) - @CurrentUser({ required: true }) - user: User, - @Body() sentSkill: Skill, - @Param("id") skillId: number - ) { - const isOwner = await this.skillRepo.findOne({ - where: { - userId: user.id, - id: skillId, - }, - }) - if (!isOwner) - throw new ForbiddenError("User is not owner or skill doesn't exist") - - if (isOwner) { - sentSkill.id = skillId // PE 1/3 - why do we need this? - - const savedSkill = await this.skillRepo.save(sentSkill) - return savedSkill - } - } - @Delete("/skillbase/skill") async deleteSkill( @UseBefore(MyAuthMiddleware) diff --git a/src/domains/user/UserController.ts b/src/domains/user/UserController.ts index cd5c407..30a4f04 100644 --- a/src/domains/user/UserController.ts +++ b/src/domains/user/UserController.ts @@ -16,7 +16,7 @@ import { dataSource } from "../../dataSource" import { TagFollowPostDto } from "../../dtos/feed/TagFollowPostDto" import { User } from "../../entities/User" import { Profile } from "../../entities/feed/Profile" -import UserRepository from "../../repositories/UserRepository" +import { UserRepository } from "../../repositories/UserRepository" import FollowingTagRepository from "../../repositories/feed/FollowingTagRepository" import NotificationRepository from "../../repositories/feed/NotificationRepository" import ResourceRepository from "../../repositories/relearn/ResourceRepository" @@ -25,12 +25,12 @@ import { UserService } from "./UserService" @JsonController("/user") export class UserController { constructor( - private userRepo = UserRepository, - private resourceRepo = ResourceRepository, - private profileRepo = dataSource.getRepository(Profile), - private followingTagRepo = FollowingTagRepository, - private notificationRepo = NotificationRepository, - private userService = new UserService() + private readonly userRepo = new UserRepository(), + private readonly resourceRepo = ResourceRepository, + private readonly profileRepo = dataSource.getRepository(Profile), + private readonly followingTagRepo = FollowingTagRepository, + private readonly notificationRepo = NotificationRepository, + private readonly userService = new UserService() ) {} @Get("/:username/all") @@ -46,7 +46,7 @@ export class UserController { @CurrentUser({ required: true }) requester: User, @Param("username") username: string ) { - const user = await this.userRepo.findOne({ + const user = await this.userRepo.rawRepo.findOne({ where: { username, }, @@ -87,7 +87,7 @@ export class UserController { @Body() tagFollows: TagFollowPostDto[], @Param("username") username: string ) { - const foundOwner = await this.userRepo.findOne({ + const foundOwner = await this.userRepo.rawRepo.findOne({ where: { username, }, @@ -125,7 +125,7 @@ export class UserController { @CurrentUser({ required: true }) requester: User, @Param("username") username: string ) { - const user = await this.userRepo.findOne({ where: { username } }) + const user = await this.userRepo.rawRepo.findOne({ where: { username } }) if (!user) { throw new NotFoundError("User not found") } diff --git a/src/domains/user/UserRepositoryV2.ts b/src/domains/user/UserRepositoryV2.ts deleted file mode 100644 index 951b06d..0000000 --- a/src/domains/user/UserRepositoryV2.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { dataSource } from "../../dataSource" -import { User } from "../../entities/User" - -export class UserRepositoryV2 { - constructor(private db = dataSource) {} - - async findById(id: number) { - return this.db.getRepository(User).findOne({ - where: { - id, - }, - }) - } - - async findNewUsers() { - return this.db.getRepository(User).find({ - order: { - createdAt: "DESC", - }, - relations: ["profile"], - }) - } -} diff --git a/src/domains/user/UserService.ts b/src/domains/user/UserService.ts index 40ed120..51ff7db 100644 --- a/src/domains/user/UserService.ts +++ b/src/domains/user/UserService.ts @@ -2,30 +2,28 @@ import { NotFoundError } from "routing-controllers" import { dataSource } from "../../dataSource" import { newUserInfo } from "../../dtos/UserInfoDto" import { Profile } from "../../entities/feed/Profile" -import UserRepository from "../../repositories/UserRepository" import FollowingTagRepository from "../../repositories/feed/FollowingTagRepository" import TagRepository from "../../repositories/relearn/TagRepository" import SkillRepository from "../../repositories/skillbase/SkillRepository" +import { UserRepository } from "../../repositories/UserRepository" import { userToSimpleUserDto } from "../../utils/domain/user/userToSimpleUserDto" import { FeedRepository } from "../feed/feed/FeedRepository" -import { UserRepositoryV2 } from "./UserRepositoryV2" export class UserService { constructor( - private userRepo = UserRepository, - private profileRepo = dataSource.getRepository(Profile), - private tagRepo = TagRepository, - private followingTagRepo = FollowingTagRepository, - private skillRepo = SkillRepository, - private feedRepo = new FeedRepository(), - private userRepoV2 = new UserRepositoryV2() + private readonly userRepo = new UserRepository(), + private readonly profileRepo = dataSource.getRepository(Profile), + private readonly tagRepo = TagRepository, + private readonly followingTagRepo = FollowingTagRepository, + private readonly skillRepo = SkillRepository, + private readonly feedRepo = new FeedRepository() ) {} async getUserInfo(username: string, requesterId: number) { const userInfo = newUserInfo() // username exists? - const foundUser = await this.userRepo.findOne({ + const foundUser = await this.userRepo.rawRepo.findOne({ where: { username, }, @@ -85,7 +83,7 @@ export class UserService { } async findNewUsers() { - const users = await this.userRepoV2.findNewUsers() + const users = await this.userRepo.findNewUsers() return users.map((user) => userToSimpleUserDto(user)) } } diff --git a/src/domains/user/use-cases/$SaveUser.ts b/src/domains/user/use-cases/$SaveUser.ts index 7c10a0c..2d41de9 100644 --- a/src/domains/user/use-cases/$SaveUser.ts +++ b/src/domains/user/use-cases/$SaveUser.ts @@ -1,15 +1,15 @@ import { User } from "../../../entities/User" -import UserRepository from "../../../repositories/UserRepository" import TagRepository from "../../../repositories/relearn/TagRepository" +import { UserRepository } from "../../../repositories/UserRepository" export class $SaveUser { constructor( - private userRepo = UserRepository, - private tagRepo = TagRepository + private readonly userRepo = new UserRepository(), + private readonly tagRepo = TagRepository ) {} async exec(user: User) { - const previous = await this.userRepo.findOne({ + const previous = await this.userRepo.rawRepo.findOne({ where: { email: user.email }, }) const isCreated = !previous diff --git a/src/domains/utils/UtilsController.ts b/src/domains/utils/UtilsController.ts index 5a3a8ee..36d5738 100644 --- a/src/domains/utils/UtilsController.ts +++ b/src/domains/utils/UtilsController.ts @@ -13,7 +13,7 @@ import { EmailPostDto } from "../../interfaces/dtos/auth/EmailPostDto" import NotificationRepository from "../../repositories/feed/NotificationRepository" import ResourceRepository from "../../repositories/relearn/ResourceRepository" import SkillRepository from "../../repositories/skillbase/SkillRepository" -import UserRepository from "../../repositories/UserRepository" +import { UserRepository } from "../../repositories/UserRepository" import LinkPreviewService from "../../resolvers/utils/LinkPreview/LinkPreviewService" import { isValidEmail } from "../../utils/email/isValidEmail" import { sendPasswordResetEmail } from "../../utils/email/sendPasswordResetEmail" @@ -21,11 +21,11 @@ import { sendPasswordResetEmail } from "../../utils/email/sendPasswordResetEmail @JsonController() export class UtilsController { constructor( - private userRepo = UserRepository, - private notificationsRepo = NotificationRepository, - private skillRepo = SkillRepository, - private resourceRepo = ResourceRepository, - private linkPreviewService = new LinkPreviewService() + private readonly userRepo = new UserRepository(), + private readonly notificationsRepo = NotificationRepository, + private readonly skillRepo = SkillRepository, + private readonly resourceRepo = ResourceRepository, + private readonly linkPreviewService = new LinkPreviewService() ) {} @Post("/utils/passwordResetEmail") @@ -33,7 +33,7 @@ export class UtilsController { const { email } = body if (!isValidEmail(email)) throw new BadRequestError("Invalid email.") - const registeredUser = await this.userRepo.findOne({ + const registeredUser = await this.userRepo.rawRepo.findOne({ where: { email, }, diff --git a/src/middlewares/MyAuthMiddleware.ts b/src/middlewares/MyAuthMiddleware.ts index 06fdcf0..70ec19a 100644 --- a/src/middlewares/MyAuthMiddleware.ts +++ b/src/middlewares/MyAuthMiddleware.ts @@ -1,7 +1,8 @@ import { verify as validateJwt } from "jsonwebtoken" import { ExpressMiddlewareInterface } from "routing-controllers" -import UserRepository from "../repositories/UserRepository" +import { dataSource } from "../dataSource" +import { User } from "../entities/User" import { MyErrorsResponse } from "../utils/ErrorMessage" import { myEnvs } from "../utils/myEnvs" @@ -9,41 +10,39 @@ export class MyAuthMiddleware implements ExpressMiddlewareInterface { // interface implementation is optional use(req: any, res: any, next?: (err?: any) => any): any { - { - const authToken = req.header("x-auth-token") + const authToken = req.header("x-auth-token") - if (!authToken) - return res - .status(401) - .json( - new MyErrorsResponse( - "No token, authorization denied! Sign in and try again." - ) + if (!authToken) + return res + .status(401) + .json( + new MyErrorsResponse( + "No token, authorization denied! Sign in and try again." ) + ) - // Verify token - try { - validateJwt(authToken, myEnvs.JWT_SECRET, async (error, decodedObj) => { - //if userId is string, it means it is getting the token from another cookie.. - if (error || typeof decodedObj["userId"] === "string") { - return res - .status(401) - .json({ msg: "Token is not valid. Sign in and try again." }) - } else { - req.user = await UserRepository.findOne({ - where: { - id: decodedObj["userId"], - }, - }) + // Verify token + try { + validateJwt(authToken, myEnvs.JWT_SECRET, async (error, decodedObj) => { + //if userId is string, it means it is getting the token from another cookie.. + if (error || typeof decodedObj["userId"] === "string") { + return res + .status(401) + .json({ msg: "Token is not valid. Sign in and try again." }) + } else { + req.user = await dataSource.getRepository(User).findOne({ + where: { + id: decodedObj["userId"], + }, + }) - if (next) { - next() - } + if (next) { + next() } - }) - } catch (err) { - res.status(500).json(new MyErrorsResponse("Server Error")) - } + } + }) + } catch (err) { + res.status(500).json(new MyErrorsResponse("Server Error")) } } } diff --git a/src/middlewares/typegraphql/isAuth.ts b/src/middlewares/typegraphql/isAuth.ts index 5b8ac0c..d7b2d8b 100644 --- a/src/middlewares/typegraphql/isAuth.ts +++ b/src/middlewares/typegraphql/isAuth.ts @@ -1,7 +1,8 @@ import { verify as validateJwt } from "jsonwebtoken" import { MiddlewareFn } from "type-graphql" -import UserRepository from "../../repositories/UserRepository" +import { dataSource } from "../../dataSource" +import { User } from "../../entities/User" import { myEnvs } from "../../utils/myEnvs" import { MyContext } from "./MyContext" @@ -22,7 +23,7 @@ export const isAuth: MiddlewareFn = async ({ context }, next) => { throw new Error("Token is not valid. Sign in and try again.") } - const user = await UserRepository.findOne({ + const user = await dataSource.getRepository(User).findOne({ where: { id: decodedObj["userId"], }, diff --git a/src/repositories/UserRepository.ts b/src/repositories/UserRepository.ts index 12f6a71..ff4440b 100644 --- a/src/repositories/UserRepository.ts +++ b/src/repositories/UserRepository.ts @@ -1,10 +1,33 @@ -import { DeleteResult, In } from "typeorm" +import { DeleteResult, In, Repository } from "typeorm" import { dataSource } from "../dataSource" import { UserProfileDto } from "../dtos/feed/UserProfileDto" import { User } from "../entities/User" // PE 1/3 - transform in a proper Repository -const UserRepository = dataSource.getRepository(User).extend({ +export class UserRepository { + public readonly rawRepo: Repository + + constructor(private readonly db = dataSource) { + this.rawRepo = db.getRepository(User) + } + + async findById(id: number) { + return this.db.getRepository(User).findOne({ + where: { + id, + }, + }) + } + + async findNewUsers() { + return this.db.getRepository(User).find({ + order: { + createdAt: "DESC", + }, + relations: ["profile"], + }) + } + async getAvailableUsernameByEmail(email: string) { const emailArr = email.split("@") if (emailArr.length === 1) { @@ -12,7 +35,7 @@ const UserRepository = dataSource.getRepository(User).extend({ } const username = emailArr[0] - const user = await this.findOne({ + const user = await this.db.getRepository(User).findOne({ where: { username, }, @@ -21,29 +44,29 @@ const UserRepository = dataSource.getRepository(User).extend({ return username } - let foundAvailableUsername = false let i = 0 - while (!foundAvailableUsername) { + while (true) { const tryUsername = username + i - const tryUser = await this.findOne({ + const tryUser = await this.db.getRepository(User).findOne({ where: { username: tryUsername, }, }) if (!tryUser) { - foundAvailableUsername = true return tryUsername } i++ } - }, + } async getTemporaryUsers(): Promise { - return this.createQueryBuilder("user") + return this.db + .getRepository(User) + .createQueryBuilder("user") .where("user.expiresAt IS NOT NULL") .getMany() - }, + } async getAvailableTempUsername() { const tempUsers = await this.getTemporaryUsers() @@ -53,7 +76,7 @@ const UserRepository = dataSource.getRepository(User).extend({ while (!foundAvailable) { const tryUsername = "temp_user_" + i - const tryUser = await this.findOne({ + const tryUser = await this.db.getRepository(User).findOne({ where: { username: tryUsername, }, @@ -65,28 +88,30 @@ const UserRepository = dataSource.getRepository(User).extend({ } i++ } - }, + } // wow, this seems dangerous haha :D async deleteExpiredTempUsers(): Promise { - return this.createQueryBuilder("user") + return this.db + .getRepository(User) + .createQueryBuilder("user") .delete() .where('"expiresAt" < NOW()') .execute() - }, + } /** * * @deprecated use $Save instead */ async saveAndGetRelations(user: User) { - const savedUser = await this.save(user) - return this.findOneOrFail({ + const savedUser = await this.db.getRepository(User).save(user) + return this.db.getRepository(User).findOneOrFail({ where: { id: savedUser.id }, relations: ["preference"], }) - }, + } async getUsersByText(text: string): Promise { - return this.query(` + return this.db.getRepository(User).query(` select use."id" as "userId", use."email", pro."fullName", @@ -98,15 +123,15 @@ inner join profile pro on pro."userId" = use."id" where use."username" ilike '%${text}%' or use."email" ilike '%${text}%' or pro."fullName" ilike '%${text}%'`) - }, + } async createUserForUnitTests(username: string): Promise { - return this.save({ + return this.db.getRepository(User).save({ username, email: username + "@" + username, password: username, }) - }, + } async findByUserIds(userIds: number[]): Promise { return dataSource.getRepository(User).find({ @@ -114,7 +139,5 @@ inner join profile pro on pro."userId" = use."id" id: In(userIds), }, }) - }, -}) - -export default UserRepository + } +} diff --git a/src/repositories/feed/NotificationRepository.ts b/src/repositories/feed/NotificationRepository.ts index ce71606..4573972 100644 --- a/src/repositories/feed/NotificationRepository.ts +++ b/src/repositories/feed/NotificationRepository.ts @@ -5,7 +5,6 @@ import { NotificationDto } from "../../dtos/utils/NotificationDto" import { User } from "../../entities/User" import { Notification } from "../../entities/feed/Notification" import { Profile } from "../../entities/feed/Profile" -import UserRepository from "../UserRepository" import ResourceRepository from "../relearn/ResourceRepository" import TagRepository from "../relearn/TagRepository" @@ -67,7 +66,7 @@ const NotificationRepository = dataSource.getRepository(Notification).extend({ ): Promise { try { const resourceRepo = ResourceRepository - const userRepo = UserRepository + const userRepo = dataSource.getRepository(User) const resource = await resourceRepo.findOne({ where: { id: resourceId }, diff --git a/src/repositories/relearn/ResourceRepository.ts b/src/repositories/relearn/ResourceRepository.ts index d6521d1..9b2855f 100644 --- a/src/repositories/relearn/ResourceRepository.ts +++ b/src/repositories/relearn/ResourceRepository.ts @@ -72,12 +72,13 @@ const ResourceRepository = dataSource.getRepository(Resource).extend({ return 0 }, - // reduce by 1 - async reducePosition( - tag: Tag, - user: User, - startingPosition: Number - ): Promise { + async decrementResourcePositionsInTag(params: { + tag: Tag + user: User + startingPosition: number + }): Promise { + const { tag, user, startingPosition } = params + if (tag) { await dataSource.query( ` diff --git a/src/routines/executeEvery15Min.ts b/src/routines/executeEvery15Min.ts index 7327df7..1ad8af5 100644 --- a/src/routines/executeEvery15Min.ts +++ b/src/routines/executeEvery15Min.ts @@ -1,7 +1,7 @@ // Why did I import this for? import axios from "axios" import "reflect-metadata" -import UserRepository from "../repositories/UserRepository" +import { UserRepository } from "../repositories/UserRepository" import { myConsoleLoading } from "../utils/console/myConsoleLoading" import { myConsoleError } from "../utils/myConsoleError" import { myConsoleSuccess } from "../utils/myConsoleSuccess" @@ -45,7 +45,7 @@ const executeEvery15Min = async () => { .catch(() => myConsoleError("GET FAIL https://lolrates.vercel.app/")) try { - const userRepo = UserRepository + const userRepo = new UserRepository() const deleted = await userRepo.deleteExpiredTempUsers() myConsoleLoading("Deleting expired temp users") diff --git a/src/routines/executeEveryHour/saveSkillHistoryFromAllUsers/saveSkillHistoryFromAllUsers.ts b/src/routines/executeEveryHour/saveSkillHistoryFromAllUsers/saveSkillHistoryFromAllUsers.ts index 6ce1adf..54a67dc 100644 --- a/src/routines/executeEveryHour/saveSkillHistoryFromAllUsers/saveSkillHistoryFromAllUsers.ts +++ b/src/routines/executeEveryHour/saveSkillHistoryFromAllUsers/saveSkillHistoryFromAllUsers.ts @@ -1,31 +1,32 @@ -import UserRepository from "../../../repositories/UserRepository"; -import SkillHistoryService from "../../../services/SkillHistoryService"; -import { myConsoleSuccess } from "../../../utils/myConsoleSuccess"; +import { dataSource } from "../../../dataSource" +import { User } from "../../../entities/User" +import SkillHistoryService from "../../../services/SkillHistoryService" +import { myConsoleSuccess } from "../../../utils/myConsoleSuccess" const saveSkillHistoryFromAllUsers = async ( - userRepo = UserRepository, + userRepo = dataSource.getRepository(User), historyService = new SkillHistoryService() ) => { - const date = new Date(); - const year = date.getFullYear(); - const month = date.getMonth() + 1; + const date = new Date() + const year = date.getFullYear() + const month = date.getMonth() + 1 - const users = await userRepo.find(); + const users = await userRepo.find() for (const { id: userId } of users) { const thisMonthHistories = await historyService.findFromMonth({ userId, year, month, - }); + }) - const alreadySavedThisMonth = thisMonthHistories.length > 0; - if (alreadySavedThisMonth) return; + const alreadySavedThisMonth = thisMonthHistories.length > 0 + if (alreadySavedThisMonth) return - await historyService.saveCurrentSkillHistory(userId); + await historyService.saveCurrentSkillHistory(userId) } - myConsoleSuccess("Saved skill histories from all users."); -}; + myConsoleSuccess("Saved skill histories from all users.") +} -export default saveSkillHistoryFromAllUsers; +export default saveSkillHistoryFromAllUsers diff --git a/src/tests/DecisionTable/DecisionTableRepository.test.ts b/src/tests/DecisionTable/DecisionTableRepository.test.ts index 685d5bd..d3ceb30 100644 --- a/src/tests/DecisionTable/DecisionTableRepository.test.ts +++ b/src/tests/DecisionTable/DecisionTableRepository.test.ts @@ -1,7 +1,7 @@ import { dataSource } from "../../dataSource" import { DecisionTable } from "../../entities/BigDecisions/DecisionTable" import DecisionTableRepository from "../../repositories/BigDecisions/DecisionTableRepository" -import UserRepository from "../../repositories/UserRepository" +import { UserRepository } from "../../repositories/UserRepository" import createExampleDecision from "../../utils/domain/BigDecisions/createExampleDecision" import createOrmConn from "../../utils/typeOrm/createOrmConn" @@ -11,7 +11,8 @@ beforeEach(async () => { }) test("Normalize decision tables index", async () => { - const user = await UserRepository.createUserForUnitTests("test") + const userRepo = new UserRepository() + const user = await userRepo.createUserForUnitTests("test") const decision = await createExampleDecision(user, "decision") // automatically adds two tables on creation diff --git a/src/utils/domain/auth/validateJwt.ts b/src/utils/domain/auth/validateJwt.ts index 99ac70b..b54e44c 100644 --- a/src/utils/domain/auth/validateJwt.ts +++ b/src/utils/domain/auth/validateJwt.ts @@ -1,11 +1,12 @@ import { config } from "dotenv" import { verify } from "jsonwebtoken" import { UnauthorizedError } from "routing-controllers" +import { dataSource } from "../../../dataSource" import { User } from "../../../entities/User" -import UserRepository from "../../../repositories/UserRepository" config() export const validateJwt = (token: string) => { + const userRepo = dataSource.getRepository(User) return new Promise((res, rej) => { verify( token, @@ -15,7 +16,7 @@ export const validateJwt = (token: string) => { return rej(new UnauthorizedError("Token is not valid.")) } - const user = await UserRepository.findOne({ + const user = await userRepo.findOne({ where: { id: decodedObj["userId"], }, diff --git a/src/utils/passport-setup.ts b/src/utils/passport-setup.ts index 5b6a616..295ce56 100644 --- a/src/utils/passport-setup.ts +++ b/src/utils/passport-setup.ts @@ -1,6 +1,8 @@ import { genSalt, hash } from "bcryptjs" import { randomBytes } from "crypto" -import UserRepository from "../repositories/UserRepository" +import { dataSource } from "../dataSource" +import { User } from "../entities/User" +import { UserRepository } from "../repositories/UserRepository" const passport = require("passport") const GoogleStrategy = require("passport-google-oauth20").Strategy @@ -39,8 +41,9 @@ passport.use( */ // find current user - const userRepo = UserRepository - const currentUser = await userRepo.findOne({ + const userRepoRaw = dataSource.getRepository(User) + const userRepo = new UserRepository() + const currentUser = await userRepoRaw.findOne({ where: { googleId: profile.id, }, @@ -51,10 +54,10 @@ passport.use( // create new user if the database doesn't have this user if (!currentUser) { const email = profile.emails[0].value - const userWithEmail = await userRepo.findOne({ where: { email } }) + const userWithEmail = await userRepoRaw.findOne({ where: { email } }) if (userWithEmail) { userWithEmail.googleId = profile.id - await userRepo.save(userWithEmail) + await userRepoRaw.save(userWithEmail) return done(null, userWithEmail) } @@ -62,14 +65,14 @@ passport.use( const salt = await genSalt(10) const randomString = randomBytes(64).toString("hex") - const newUser = await userRepo.save({ + const newUser = await userRepoRaw.save({ googleId: profile.id, username, email, password: await hash(randomString, salt), }) - await userRepo.save(newUser) + await userRepoRaw.save(newUser) return done(null, newUser) } diff --git a/src/utils/user/createExampleUser.ts b/src/utils/user/createExampleUser.ts index 13d6115..afc56b1 100644 --- a/src/utils/user/createExampleUser.ts +++ b/src/utils/user/createExampleUser.ts @@ -1,5 +1,5 @@ +import { dataSource } from "../../dataSource" import { User } from "../../entities/User" -import UserRepository from "../../repositories/UserRepository" const createExampleUser = async (username: string) => { const newUser = new User() @@ -7,7 +7,7 @@ const createExampleUser = async (username: string) => { newUser.email = `${username}@${username}.com` newUser.password = username - const repo = UserRepository + const repo = dataSource.getRepository(User) return await repo.save(newUser) } diff --git a/src/utils/user/createPreferencesForAll.ts b/src/utils/user/createPreferencesForAll.ts index 928eded..96a9044 100644 --- a/src/utils/user/createPreferencesForAll.ts +++ b/src/utils/user/createPreferencesForAll.ts @@ -2,13 +2,12 @@ import { In, Not } from "typeorm" import { dataSource } from "../../dataSource" import { User } from "../../entities/User" import { UserPreference } from "../../entities/UserPreference" -import UserRepository from "../../repositories/UserRepository" import { myConsoleError } from "../myConsoleError" import { myConsoleSuccess } from "../myConsoleSuccess" export const createPreferencesForAll = async () => { try { - const userRepo = UserRepository + const userRepo = dataSource.getRepository(User) const preferenceRepo = dataSource.getRepository(UserPreference) const preferences = await preferenceRepo.find({ relations: ["user"] }) diff --git a/src/utils/user/createProfileForAll.ts b/src/utils/user/createProfileForAll.ts index a9539e0..e851cc3 100644 --- a/src/utils/user/createProfileForAll.ts +++ b/src/utils/user/createProfileForAll.ts @@ -2,13 +2,12 @@ import { In, Not } from "typeorm" import { dataSource } from "../../dataSource" import { Profile } from "../../entities/feed/Profile" import { User } from "../../entities/User" -import UserRepository from "../../repositories/UserRepository" import { myConsoleError } from "../myConsoleError" import { myConsoleSuccess } from "../myConsoleSuccess" export const createProfileForUsers = async () => { try { - const userRepo = UserRepository + const userRepo = dataSource.getRepository(User) const profile = dataSource.getRepository(Profile) const preferences = await profile.find({ relations: ["user"] })