Skip to content

Commit

Permalink
Using DI of tsED and structure refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
devbenho committed Jun 13, 2024
1 parent 56b5329 commit d098202
Show file tree
Hide file tree
Showing 78 changed files with 734 additions and 368 deletions.
3 changes: 3 additions & 0 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"@tsed/schema": "^7.62.2",
"@tsed/swagger": "^7.62.2",
"@types/dotenv-defaults": "^2.0.4",
"argon2": "^0.40.3",
"bcrypt": "^5.1.1",
"compression": "^1.7.4",
"cookie-parser": "^1.4.6",
Expand All @@ -50,6 +51,7 @@
"inversify-express-utils": "^6.4.6",
"jsonwebtoken": "^9.0.2",
"knex": "^3.1.0",
"luxon": "^3.4.4",
"method-override": "^3.0.0",
"node-emoji": "^2.1.3",
"nodemon": "^3.0.3",
Expand All @@ -71,6 +73,7 @@
"@types/express": "^4.17.21",
"@types/figlet": "^1.5.8",
"@types/jsonwebtoken": "^9.0.6",
"@types/luxon": "^3.4.2",
"@types/method-override": "^0.0.35",
"@types/morgan": "^1.9.9",
"@types/node": "^20.11.28",
Expand Down
55 changes: 31 additions & 24 deletions server/src/application/auth/login/login.use-case.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,53 @@
import { AuthRequest, AuthResponseDto } from '@contracts/dtos/auth';
import { UnauthorizedError } from '@contracts/errors/unauthorized.error';
import { IHasherService } from '@contracts/services/IHasher';
import { IJwtService } from '@contracts/services/IJwt';
import { TYPES } from '@infrastructure/shared/ioc/types';
import { inject, injectable } from 'inversify';
import { BaseUseCase } from '@application/shared';
import { IUserRepository } from '@domain/repositories/user.repository';
import { BaseUseCase, UseCase } from '@application/shared';
import { UserRepository } from '@domain/entities/users';
import { HasherDomainService } from '@domain/shared/services';
import { TokenProviderDomainService } from '@domain/shared/services/token-provider.domain-service';
import { JwtPayload } from '@contracts/services/IJwt';

@injectable()
@UseCase()
class LoginUseCase extends BaseUseCase<AuthRequest, AuthResponseDto> {
private readonly _userRepository: UserRepository;
private readonly _jwtService: TokenProviderDomainService;

constructor(
@inject(TYPES.IUserRepository) private _userRepository: IUserRepository,
@inject(TYPES.IJwtService) private _jwtService: IJwtService,
@inject(TYPES.IHasherService) private _hasherService: IHasherService,
userRepository: UserRepository,
jwtService: TokenProviderDomainService,
) {
super();
this._userRepository = userRepository;
this._jwtService = jwtService;
}

public async performOperation(
request: AuthRequest,
): Promise<AuthResponseDto> {
const user =
(await this._userRepository.findByEmail(request.login)) ||
(await this._userRepository.findByUsername(request.login));
if (
!user ||
!(await this._hasherService.compare(request.password, user.password))
) {
throw new UnauthorizedError('Invalid credentials');
}
(await this._userRepository.findByUsername(request.login)) ||
(await this._userRepository.findByEmail(request.login));
if (!user) {
throw new UnauthorizedError('User not found');
throw new UnauthorizedError();
}
if (!(await HasherDomainService.compare(request.password, user.password))) {
throw new UnauthorizedError();
}
const token = this._jwtService.sign({ userId: user.id as string });

const payload: JwtPayload = {
email: { value: user.email },
roles: user.roles.map(role => ({ value: role })),
username: { value: user.username },
userUuid: { value: user.id as string },
};

const token = this._jwtService.createAccessToken(payload);
const result: AuthResponseDto = {
token,
tokenExpiration: new Date(Date.now() + 1000 * 60 * 60),
refreshToken: this._jwtService.sign({ userId: user.id as string }),
refreshTokenExpiration: new Date(Date.now() + 1000 * 60 * 60 * 24),
// tokenExpiration type is Date
tokenExpiration: new Date(),
userDetails: user,
};
return result;
}
}

export { LoginUseCase };
5 changes: 2 additions & 3 deletions server/src/application/auth/register/create-user.request.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { UseCaseRequest } from '@application/shared';
import { TriggeredBy, TriggeredByUser } from '@domain/shared/entities';
import { User } from '@domain/entities';
import { Role } from '@domain/eums/role.enum';

class CreateUserDto extends UseCaseRequest {
constructor(
Expand All @@ -12,7 +11,7 @@ class CreateUserDto extends UseCaseRequest {
public password: string,
public username: string,
public profilePicture?: string,
public role: Role = Role.USER,
public roles: string[] = ['user'],
) {
super(triggeredBy);
this.validate();
Expand Down Expand Up @@ -65,7 +64,7 @@ class CreateUserDto extends UseCaseRequest {
this.email,
this.username,
this.password,
this.role,
this.roles,
new Date(),
this.triggeredBy.who,
);
Expand Down
66 changes: 31 additions & 35 deletions server/src/application/auth/register/register.use-case.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,33 @@
import 'reflect-metadata';
import { AuthResponseDto } from '@contracts/dtos/auth';
import { CreateUserDto } from '@contracts/dtos/users';
import { IJwtService } from '@contracts/services/IJwt';
import { TYPES } from '@infrastructure/shared/ioc/types';
import { inject, injectable } from 'inversify';
import { BaseUseCase } from '@application/shared';
import { IUserRepository } from '@domain/repositories/user.repository';
import { log } from 'console';
// import 'reflect-metadata';
// import { AuthResponseDto } from '@contracts/dtos/auth';
// import { CreateUserDto } from '@contracts/dtos/users';
// import { TYPES } from '@infrastructure/shared/ioc/types';
// import { inject, injectable } from 'inversify';
// import { BaseUseCase } from '@application/shared';
// import { UserRepository } from '@domain/repositories/user.repository';
// import { log } from 'console';
// import { TokenProviderDomainService } from '@domain/shared/services/token-provider.domain-service';

@injectable()
class RegisterUsecase extends BaseUseCase<CreateUserDto, AuthResponseDto> {
constructor(
@inject(TYPES.IUserRepository) private _userRepository: IUserRepository,
@inject(TYPES.IJwtService) private _jwtService: IJwtService,
// @inject(TYPES.IUserMapper) private _mapper: Mapper<User, CreateUserDto>,
) {
super();
}
public async performOperation(
request: CreateUserDto,
): Promise<AuthResponseDto> {
const user = request.toEntity();
const createdUser = await this._userRepository.saveUser(user);
log('createdUser', createdUser);
const result: AuthResponseDto = {
token: this._jwtService.sign({ userId: createdUser.id as string }),
tokenExpiration: new Date(Date.now() + 1000 * 60 * 60),
refreshToken: this._jwtService.sign({ userId: createdUser.id as string }),
refreshTokenExpiration: new Date(Date.now() + 1000 * 60 * 60 * 24),
userDetails: createdUser,
};
return result;
}
}
// @injectable()
// class RegisterUsecase extends BaseUseCase<CreateUserDto, AuthResponseDto> {
// private _userRepository: UserRepository,
// private _jwtService: TokenProviderDomainService,

export { RegisterUsecase };
// public async performOperation(
// request: CreateUserDto,
// ): Promise<AuthResponseDto> {
// const user = request.toEntity();
// const createdUser = await this._userRepository.saveUser(user);
// log('createdUser', createdUser);
// const result: AuthResponseDto = {
// token: this._jwtService.({ userId: createdUser.id as string }),
// tokenExpiration: new Date(Date.now() + 1000 * 60 * 60),
// // refreshToken: this._jwtService.sign({ userId: createdUser.id as string }),
// // refreshTokenExpiration: new Date(Date.now() + 1000 * 60 * 60 * 24),
// userDetails: createdUser,
// };
// return result;
// }
// }

// export { RegisterUsecase };
7 changes: 3 additions & 4 deletions server/src/application/post/create/create-post.request.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { UseCaseRequest } from '@application/shared';
import { Post, User } from '@domain/entities';
import { POST_STATUS } from '@domain/eums/post-status.enum';
import { POST_STATUS } from '@domain/entities/posts/post-status.enum';
import { TriggeredBy } from '@domain/shared/entities/triggered-by';
import { UploadedFiles } from '@domain/shared/models';
import { InvalidParameterException } from '@domain/shared/exceptions';
Expand Down Expand Up @@ -42,10 +42,9 @@ class CreatePostRequest extends UseCaseRequest {
triggeredBy,
title,
content,
// authorId,
// author,
author,
attachments,
// status,
status,
);
}

Expand Down
9 changes: 4 additions & 5 deletions server/src/application/post/create/create-post.usecase.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import { BaseUseCase } from '@application/shared';
import { BaseUseCase, UseCase } from '@application/shared';
import { inject, injectable } from 'inversify';
import { TYPES } from '@infrastructure/shared/ioc/types';
import { IPostRepository } from '@domain/repositories/post.repository';
import { PostRepository } from '@domain/entities/posts/post.repository';
import { LOGGER } from '@/web/rest/logger';
import { PostDetailsResponseDto } from '@contracts/dtos/posts/post-details.response';
import { log } from 'console';
import { Post } from '@domain/entities';
import { CreatePostRequest } from './create-post.request';
import { Post } from '@domain/entities';

@injectable()
@UseCase()
class CreatePostUseCase extends BaseUseCase<
CreatePostRequest,
PostDetailsResponseDto
> {
constructor(
@inject(TYPES.IPostRepository) private _postRepository: IPostRepository,
@inject(TYPES.IPostRepository) private _postRepository: PostRepository,
) {
super();
}
Expand Down
4 changes: 2 additions & 2 deletions server/src/application/post/find-all/find-all-post.usecase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { BaseUseCase } from '@application/shared';
import { FindAllPostRequest } from './find-all-post.request';
import { PostResponseDto } from '@contracts/dtos/posts';
import { TYPES } from '@infrastructure/shared/ioc/types';
import { IPostRepository } from '@domain/repositories/post.repository';
import { PostRepository } from '@domain/entities/posts/post.repository';
import { inject } from 'inversify';
import { log } from 'console';

Expand All @@ -12,7 +12,7 @@ class FindAllPostUseCase extends BaseUseCase<
> {
constructor(
@inject(TYPES.IPostRepository)
private readonly _postRepository: IPostRepository,
private readonly _postRepository: PostRepository,
) {
super();
}
Expand Down
4 changes: 1 addition & 3 deletions server/src/contracts/dtos/auth/auth.response.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { User } from '@domain/entities';
import { User } from '@domain/entities/users';

class AuthResponseDto {
constructor(
public token: string,
public tokenExpiration: Date,
public refreshToken: string,
public refreshTokenExpiration: Date,
public userDetails: User,
) {}
}
Expand Down
1 change: 1 addition & 0 deletions server/src/contracts/dtos/users/user.response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export class UserResponseDto {
public username: string,
public email: string,
public pictureProfile?: string,
public roles?: string[],
) {}

public static fromEntity(entity: User): UserResponseDto {
Expand Down
12 changes: 5 additions & 7 deletions server/src/contracts/services/IJwt.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
interface IJwtService {
sign: (payload: JwtPayload) => string;
verify: (token: string) => JwtPayload;
}
import { Role } from "@domain/eums/role.enum";

export interface JwtPayload {
userId: string;
userUuid: { value: string };
username: { value: string };
email: { value: string };
roles: { value: string }[];
}

export { IJwtService };
File renamed without changes.
2 changes: 2 additions & 0 deletions server/src/domain/entities/chats/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './chat'
export * from './message'
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { AuditableBaseEntity } from '@domain/shared/auditable.entity';
import { User } from './user';
import { Post } from './posts';
import { Reply } from './reply';
import { LikeComment } from './like-comment';
import { Nullable } from '@domain/shared/types';
import { Post } from '../posts';
import { Reply, User } from '..';
import { LikeComment } from '../like-comments';

export class Comment extends AuditableBaseEntity {
constructor(
Expand Down
2 changes: 2 additions & 0 deletions server/src/domain/entities/comments/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './comment'
export * from './comment.repository'
17 changes: 8 additions & 9 deletions server/src/domain/entities/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
export * from './comment';
export * from './comments';
export * from './posts';
export * from "./user"
export * from './like-post';
export * from './like-reply';
export * from './message';
export * from './chat';
export * from './reply';
export * from './notification';

export * from './users';
export * from './like-posts';
export * from './like-replies';
export * from './like-comments';
export * from './chats/';
export * from './replies/';
export * from './notifications';
2 changes: 2 additions & 0 deletions server/src/domain/entities/like-comments/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './like-comment'
export * from './like-comment.repository'
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { LikeComment } from '@domain/entities/like-comment';
import { LikeComment } from ".";

interface ILikeCommentRepository {
createLikeComment(likeComment: LikeComment): Promise<LikeComment>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { AuditableBaseEntity } from '@domain/shared/auditable.entity';
import { Comment } from './comment';
import { User } from './user';
import { Nullable } from '@domain/shared/types';
import { User, Comment } from '..';

class LikeComment extends AuditableBaseEntity {
constructor(
Expand Down
2 changes: 2 additions & 0 deletions server/src/domain/entities/like-posts/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './like-post'
export * from './like-post.repository'
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Nullable } from '@domain/shared/types';
import { Post } from '@domain/entities/posts';
import { User } from '@domain/entities/user';
import { AuditableBaseEntity } from '@domain/shared/auditable.entity';
import { User } from '../users';

class LikePost extends AuditableBaseEntity {
constructor(
Expand Down
2 changes: 2 additions & 0 deletions server/src/domain/entities/like-replies/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './like-reply'
export * from './like-reply.repository'
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { AuditableBaseEntity } from '@domain/shared/auditable.entity';
import { Reply } from './reply';
import { User } from './user';
import { Nullable } from '@domain/shared/types';
import { Reply, User } from '..';

class LikeReply extends AuditableBaseEntity {
constructor(
Expand Down
1 change: 1 addition & 0 deletions server/src/domain/entities/notifications/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './notification'
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit d098202

Please sign in to comment.