create-craftjs 1.0.4 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +139 -137
- package/bin/index.js +158 -158
- package/package.json +24 -24
- package/template/Dockerfile +57 -12
- package/template/babel.config.json +3 -3
- package/template/craft/commands/build.js +16 -15
- package/template/craft/commands/db-fresh.js +22 -22
- package/template/craft/commands/db-generate.js +23 -23
- package/template/craft/commands/db-migrate.js +22 -22
- package/template/craft/commands/dev.js +16 -16
- package/template/craft/commands/key-generate.js +41 -41
- package/template/craft/commands/make-apidocs.js +121 -121
- package/template/craft/commands/make-command.js +38 -38
- package/template/craft/commands/make-controller.js +95 -95
- package/template/craft/commands/make-dto.js +39 -39
- package/template/craft/commands/make-middleware.js +46 -46
- package/template/craft/commands/make-repository.js +36 -36
- package/template/craft/commands/make-route.js +92 -92
- package/template/craft/commands/make-service.js +39 -39
- package/template/craft/commands/make-test.js +48 -48
- package/template/craft/commands/make-utils.js +30 -30
- package/template/craft/commands/make-validation.js +42 -42
- package/template/craft/commands/make-view.js +42 -42
- package/template/craft/commands/start.js +29 -29
- package/template/craft/commands/test.js +20 -20
- package/template/craft.js +256 -256
- package/template/docker-compose.yml +8 -0
- package/template/nodemon.json +6 -6
- package/template/package-lock.json +8877 -8877
- package/template/package.json +84 -84
- package/template/prisma/schema.prisma +22 -22
- package/template/prisma/seed.ts +29 -29
- package/template/src/apidocs/auth-docs.ts +314 -314
- package/template/src/apidocs/users-docs.ts +240 -240
- package/template/src/config/cloudinary.ts +21 -21
- package/template/src/config/database.ts +90 -90
- package/template/src/config/env.ts +67 -67
- package/template/src/config/logger.ts +139 -139
- package/template/src/config/nodemailer.ts +23 -23
- package/template/src/config/web.ts +47 -47
- package/template/src/controllers/auth-controller.ts +88 -88
- package/template/src/controllers/user-controller.ts +79 -79
- package/template/src/dtos/list-dto.ts +12 -12
- package/template/src/dtos/user-dto.ts +57 -57
- package/template/src/main.ts +28 -28
- package/template/src/middleware/auth-middleware.ts +44 -44
- package/template/src/middleware/error-middleware.ts +27 -27
- package/template/src/middleware/http-logger-middleware.ts +31 -31
- package/template/src/repositories/user-repository.ts +75 -75
- package/template/src/routes/auth-route.ts +20 -20
- package/template/src/routes/main-route.ts +25 -25
- package/template/src/routes/user-route.ts +35 -35
- package/template/src/services/auth-service.ts +162 -162
- package/template/src/services/user-service.ts +102 -102
- package/template/src/types/type-request.ts +6 -6
- package/template/src/utils/async-handler.ts +9 -9
- package/template/src/utils/response-error.ts +10 -10
- package/template/src/utils/response.ts +60 -60
- package/template/src/utils/swagger.ts +135 -135
- package/template/src/utils/validation.ts +7 -7
- package/template/src/validations/user-validation.ts +127 -127
- package/template/src/views/index.ejs +6 -6
- package/template/src/views/layouts/main.ejs +14 -14
- package/template/src/views/partials/header.ejs +3 -3
- package/template/test/user.test.ts +16 -16
- package/template/tsconfig.json +13 -13
- package/template/.dockerignore +0 -4
|
@@ -1,162 +1,162 @@
|
|
|
1
|
-
import {
|
|
2
|
-
toUserDetailResponse,
|
|
3
|
-
toUserResponse,
|
|
4
|
-
UserDetailResponse,
|
|
5
|
-
UserResponse,
|
|
6
|
-
loginRequest,
|
|
7
|
-
CreateUserRequest,
|
|
8
|
-
UpdateUserRequest,
|
|
9
|
-
} from "../dtos/user-dto";
|
|
10
|
-
import { ResponseError } from "../utils/response-error";
|
|
11
|
-
import { UserValidation } from "../validations/user-validation";
|
|
12
|
-
import { Validation } from "../utils/validation";
|
|
13
|
-
import * as argon2 from "argon2";
|
|
14
|
-
import { User } from "@prisma/client";
|
|
15
|
-
import jwt from "jsonwebtoken";
|
|
16
|
-
import { Request } from "express";
|
|
17
|
-
import { UserRepository } from "../repositories/user-repository";
|
|
18
|
-
import { UserRequest } from "../types/type-request";
|
|
19
|
-
import { prismaClient } from "../config/database";
|
|
20
|
-
import { env } from "../config/env";
|
|
21
|
-
|
|
22
|
-
export class AuthService {
|
|
23
|
-
static async register(request: CreateUserRequest): Promise<UserResponse> {
|
|
24
|
-
const data = Validation.validate(UserValidation.REGISTER, request);
|
|
25
|
-
const emailExits = await UserRepository.countByEmail(data.email);
|
|
26
|
-
|
|
27
|
-
if (emailExits != 0) {
|
|
28
|
-
throw new ResponseError(409, "Akun Sudah Terdaftar!");
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
data.password = await argon2.hash(data.password);
|
|
32
|
-
|
|
33
|
-
const response = await UserRepository.create({
|
|
34
|
-
fullName: data.fullName,
|
|
35
|
-
email: data.email,
|
|
36
|
-
password: data.password,
|
|
37
|
-
});
|
|
38
|
-
return toUserResponse(response);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
static async login(request: loginRequest) {
|
|
42
|
-
const data = Validation.validate(UserValidation.LOGIN, request);
|
|
43
|
-
const userExits = await UserRepository.findUserByEmail(data.email);
|
|
44
|
-
|
|
45
|
-
if (!userExits) {
|
|
46
|
-
throw new ResponseError(401, "Gagal Login! Detail login salah");
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const isPasswordValid = await argon2.verify(
|
|
50
|
-
userExits.password,
|
|
51
|
-
data.password
|
|
52
|
-
);
|
|
53
|
-
if (!isPasswordValid) {
|
|
54
|
-
throw new ResponseError(401, "Gagal Login! Detail login salah");
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const refreshToken = jwt.sign(
|
|
58
|
-
{
|
|
59
|
-
user_id: userExits.id,
|
|
60
|
-
user_fullName: userExits.fullName,
|
|
61
|
-
user_email: userExits.email,
|
|
62
|
-
},
|
|
63
|
-
env.JWT_SECRET as string,
|
|
64
|
-
{
|
|
65
|
-
expiresIn: "1d",
|
|
66
|
-
}
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
const accessToken = jwt.sign(
|
|
70
|
-
{
|
|
71
|
-
user_id: userExits.id,
|
|
72
|
-
user_fullName: userExits.fullName,
|
|
73
|
-
user_email: userExits.email,
|
|
74
|
-
},
|
|
75
|
-
env.JWT_SECRET as string,
|
|
76
|
-
{
|
|
77
|
-
expiresIn: "5m",
|
|
78
|
-
}
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
const user = toUserResponse(userExits);
|
|
82
|
-
return { user, refreshToken, accessToken };
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
static async me(user: User): Promise<UserDetailResponse> {
|
|
86
|
-
return toUserDetailResponse(user);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
static async updateProfile(
|
|
90
|
-
user: User,
|
|
91
|
-
request: UpdateUserRequest
|
|
92
|
-
): Promise<UserResponse> {
|
|
93
|
-
const data = Validation.validate(UserValidation.UPDATE, request);
|
|
94
|
-
if (data.fullName) {
|
|
95
|
-
user.fullName = data.fullName;
|
|
96
|
-
}
|
|
97
|
-
if (data.password) {
|
|
98
|
-
user.password = await argon2.hash(data.password);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (data.email && data.email !== user.email) {
|
|
102
|
-
const emailExists = await UserRepository.findemailExistsNotUserLoggedIn(
|
|
103
|
-
data.email,
|
|
104
|
-
user.id
|
|
105
|
-
);
|
|
106
|
-
if (emailExists != 0) {
|
|
107
|
-
throw new ResponseError(409, "Email Sudah Ada");
|
|
108
|
-
}
|
|
109
|
-
user.email = data.email;
|
|
110
|
-
}
|
|
111
|
-
const result = await UserRepository.updateUser(
|
|
112
|
-
{
|
|
113
|
-
fullName: user.fullName,
|
|
114
|
-
password: user.password,
|
|
115
|
-
email: user.email,
|
|
116
|
-
},
|
|
117
|
-
user.id
|
|
118
|
-
);
|
|
119
|
-
return toUserResponse(result);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
static async logout(req: UserRequest) {
|
|
123
|
-
const refreshToken = req.cookies.refresh_token;
|
|
124
|
-
if (!req.user) {
|
|
125
|
-
throw new ResponseError(401, "Unauthorized: Anda Belum Login.");
|
|
126
|
-
}
|
|
127
|
-
if (!refreshToken) {
|
|
128
|
-
throw new ResponseError(401, "Unauthorized: Anda Belum Login.");
|
|
129
|
-
}
|
|
130
|
-
return refreshToken;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
static async refreshToken(req: Request) {
|
|
134
|
-
const refreshToken = req.cookies.refresh_token;
|
|
135
|
-
if (!refreshToken) {
|
|
136
|
-
throw new ResponseError(401, "Unauthorized, Anda Belum Login");
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
try {
|
|
140
|
-
const decoded = jwt.verify(refreshToken, env.JWT_SECRET as string) as any;
|
|
141
|
-
|
|
142
|
-
const user = await prismaClient.user.findUnique({
|
|
143
|
-
where: { id: decoded.user_id },
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
if (!user) {
|
|
147
|
-
throw new ResponseError(401, "Unauthorized, Anda Belum Login.");
|
|
148
|
-
}
|
|
149
|
-
const payload = {
|
|
150
|
-
user_id: user.id,
|
|
151
|
-
user_fullName: user.fullName,
|
|
152
|
-
user_email: user.email,
|
|
153
|
-
};
|
|
154
|
-
const accessToken = jwt.sign(payload, env.JWT_SECRET as string, {
|
|
155
|
-
expiresIn: "6m",
|
|
156
|
-
});
|
|
157
|
-
return { accessToken, user: payload };
|
|
158
|
-
} catch (err) {
|
|
159
|
-
throw new ResponseError(401, "Token Tidak Valid Atau Kadaluarsa");
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
toUserDetailResponse,
|
|
3
|
+
toUserResponse,
|
|
4
|
+
UserDetailResponse,
|
|
5
|
+
UserResponse,
|
|
6
|
+
loginRequest,
|
|
7
|
+
CreateUserRequest,
|
|
8
|
+
UpdateUserRequest,
|
|
9
|
+
} from "../dtos/user-dto";
|
|
10
|
+
import { ResponseError } from "../utils/response-error";
|
|
11
|
+
import { UserValidation } from "../validations/user-validation";
|
|
12
|
+
import { Validation } from "../utils/validation";
|
|
13
|
+
import * as argon2 from "argon2";
|
|
14
|
+
import { User } from "@prisma/client";
|
|
15
|
+
import jwt from "jsonwebtoken";
|
|
16
|
+
import { Request } from "express";
|
|
17
|
+
import { UserRepository } from "../repositories/user-repository";
|
|
18
|
+
import { UserRequest } from "../types/type-request";
|
|
19
|
+
import { prismaClient } from "../config/database";
|
|
20
|
+
import { env } from "../config/env";
|
|
21
|
+
|
|
22
|
+
export class AuthService {
|
|
23
|
+
static async register(request: CreateUserRequest): Promise<UserResponse> {
|
|
24
|
+
const data = Validation.validate(UserValidation.REGISTER, request);
|
|
25
|
+
const emailExits = await UserRepository.countByEmail(data.email);
|
|
26
|
+
|
|
27
|
+
if (emailExits != 0) {
|
|
28
|
+
throw new ResponseError(409, "Akun Sudah Terdaftar!");
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
data.password = await argon2.hash(data.password);
|
|
32
|
+
|
|
33
|
+
const response = await UserRepository.create({
|
|
34
|
+
fullName: data.fullName,
|
|
35
|
+
email: data.email,
|
|
36
|
+
password: data.password,
|
|
37
|
+
});
|
|
38
|
+
return toUserResponse(response);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static async login(request: loginRequest) {
|
|
42
|
+
const data = Validation.validate(UserValidation.LOGIN, request);
|
|
43
|
+
const userExits = await UserRepository.findUserByEmail(data.email);
|
|
44
|
+
|
|
45
|
+
if (!userExits) {
|
|
46
|
+
throw new ResponseError(401, "Gagal Login! Detail login salah");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const isPasswordValid = await argon2.verify(
|
|
50
|
+
userExits.password,
|
|
51
|
+
data.password
|
|
52
|
+
);
|
|
53
|
+
if (!isPasswordValid) {
|
|
54
|
+
throw new ResponseError(401, "Gagal Login! Detail login salah");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const refreshToken = jwt.sign(
|
|
58
|
+
{
|
|
59
|
+
user_id: userExits.id,
|
|
60
|
+
user_fullName: userExits.fullName,
|
|
61
|
+
user_email: userExits.email,
|
|
62
|
+
},
|
|
63
|
+
env.JWT_SECRET as string,
|
|
64
|
+
{
|
|
65
|
+
expiresIn: "1d",
|
|
66
|
+
}
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
const accessToken = jwt.sign(
|
|
70
|
+
{
|
|
71
|
+
user_id: userExits.id,
|
|
72
|
+
user_fullName: userExits.fullName,
|
|
73
|
+
user_email: userExits.email,
|
|
74
|
+
},
|
|
75
|
+
env.JWT_SECRET as string,
|
|
76
|
+
{
|
|
77
|
+
expiresIn: "5m",
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
const user = toUserResponse(userExits);
|
|
82
|
+
return { user, refreshToken, accessToken };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
static async me(user: User): Promise<UserDetailResponse> {
|
|
86
|
+
return toUserDetailResponse(user);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
static async updateProfile(
|
|
90
|
+
user: User,
|
|
91
|
+
request: UpdateUserRequest
|
|
92
|
+
): Promise<UserResponse> {
|
|
93
|
+
const data = Validation.validate(UserValidation.UPDATE, request);
|
|
94
|
+
if (data.fullName) {
|
|
95
|
+
user.fullName = data.fullName;
|
|
96
|
+
}
|
|
97
|
+
if (data.password) {
|
|
98
|
+
user.password = await argon2.hash(data.password);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (data.email && data.email !== user.email) {
|
|
102
|
+
const emailExists = await UserRepository.findemailExistsNotUserLoggedIn(
|
|
103
|
+
data.email,
|
|
104
|
+
user.id
|
|
105
|
+
);
|
|
106
|
+
if (emailExists != 0) {
|
|
107
|
+
throw new ResponseError(409, "Email Sudah Ada");
|
|
108
|
+
}
|
|
109
|
+
user.email = data.email;
|
|
110
|
+
}
|
|
111
|
+
const result = await UserRepository.updateUser(
|
|
112
|
+
{
|
|
113
|
+
fullName: user.fullName,
|
|
114
|
+
password: user.password,
|
|
115
|
+
email: user.email,
|
|
116
|
+
},
|
|
117
|
+
user.id
|
|
118
|
+
);
|
|
119
|
+
return toUserResponse(result);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
static async logout(req: UserRequest) {
|
|
123
|
+
const refreshToken = req.cookies.refresh_token;
|
|
124
|
+
if (!req.user) {
|
|
125
|
+
throw new ResponseError(401, "Unauthorized: Anda Belum Login.");
|
|
126
|
+
}
|
|
127
|
+
if (!refreshToken) {
|
|
128
|
+
throw new ResponseError(401, "Unauthorized: Anda Belum Login.");
|
|
129
|
+
}
|
|
130
|
+
return refreshToken;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
static async refreshToken(req: Request) {
|
|
134
|
+
const refreshToken = req.cookies.refresh_token;
|
|
135
|
+
if (!refreshToken) {
|
|
136
|
+
throw new ResponseError(401, "Unauthorized, Anda Belum Login");
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
const decoded = jwt.verify(refreshToken, env.JWT_SECRET as string) as any;
|
|
141
|
+
|
|
142
|
+
const user = await prismaClient.user.findUnique({
|
|
143
|
+
where: { id: decoded.user_id },
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
if (!user) {
|
|
147
|
+
throw new ResponseError(401, "Unauthorized, Anda Belum Login.");
|
|
148
|
+
}
|
|
149
|
+
const payload = {
|
|
150
|
+
user_id: user.id,
|
|
151
|
+
user_fullName: user.fullName,
|
|
152
|
+
user_email: user.email,
|
|
153
|
+
};
|
|
154
|
+
const accessToken = jwt.sign(payload, env.JWT_SECRET as string, {
|
|
155
|
+
expiresIn: "6m",
|
|
156
|
+
});
|
|
157
|
+
return { accessToken, user: payload };
|
|
158
|
+
} catch (err) {
|
|
159
|
+
throw new ResponseError(401, "Token Tidak Valid Atau Kadaluarsa");
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
@@ -1,102 +1,102 @@
|
|
|
1
|
-
import {
|
|
2
|
-
CreateUserRequest,
|
|
3
|
-
ListUserRequest,
|
|
4
|
-
UpdateUserRequest,
|
|
5
|
-
toUserResponse,
|
|
6
|
-
UserResponse,
|
|
7
|
-
} from "../dtos/user-dto";
|
|
8
|
-
import { ResponseError } from "../utils/response-error";
|
|
9
|
-
import { UserValidation } from "../validations/user-validation";
|
|
10
|
-
import { Validation } from "../utils/validation";
|
|
11
|
-
import * as argon2 from "argon2";
|
|
12
|
-
import { listResponse, tolistResponse } from "../dtos/list-dto";
|
|
13
|
-
import { UserRepository } from "../repositories/user-repository";
|
|
14
|
-
import { env } from "../config/env";
|
|
15
|
-
export class UserService {
|
|
16
|
-
static async create(request: CreateUserRequest): Promise<UserResponse> {
|
|
17
|
-
const data = Validation.validate(UserValidation.CREATE, request);
|
|
18
|
-
const emailExits = await UserRepository.countByEmail(data.email);
|
|
19
|
-
if (emailExits != 0) {
|
|
20
|
-
throw new ResponseError(409, "Email Sudah Terdaftar");
|
|
21
|
-
}
|
|
22
|
-
data.password = await argon2.hash(data.password);
|
|
23
|
-
|
|
24
|
-
const response = await UserRepository.create({
|
|
25
|
-
fullName: data.fullName,
|
|
26
|
-
email: data.email,
|
|
27
|
-
password: data.password,
|
|
28
|
-
});
|
|
29
|
-
return toUserResponse(response);
|
|
30
|
-
}
|
|
31
|
-
static async getAll(request: ListUserRequest): Promise<listResponse> {
|
|
32
|
-
const requestList = Validation.validate(UserValidation.LIST, request);
|
|
33
|
-
const filters = [];
|
|
34
|
-
if (requestList.name) {
|
|
35
|
-
filters.push({
|
|
36
|
-
fullName: {
|
|
37
|
-
contains: requestList.name,
|
|
38
|
-
},
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
const data = await UserRepository.findMany(
|
|
42
|
-
filters,
|
|
43
|
-
requestList.skip,
|
|
44
|
-
requestList.take
|
|
45
|
-
);
|
|
46
|
-
const totalData = await UserRepository.count(filters);
|
|
47
|
-
const result = {
|
|
48
|
-
data,
|
|
49
|
-
total_data: totalData,
|
|
50
|
-
paging: {
|
|
51
|
-
current_page: requestList.page,
|
|
52
|
-
total_page: Math.ceil(totalData / requestList.take),
|
|
53
|
-
},
|
|
54
|
-
};
|
|
55
|
-
return tolistResponse(result);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
static async getOne(id: string): Promise<UserResponse> {
|
|
59
|
-
const data = await UserRepository.findById(id);
|
|
60
|
-
if (!data) {
|
|
61
|
-
throw new ResponseError(404, "Data Tidak Ditemukan");
|
|
62
|
-
}
|
|
63
|
-
return toUserResponse(data);
|
|
64
|
-
}
|
|
65
|
-
static async update(
|
|
66
|
-
id: string,
|
|
67
|
-
request: UpdateUserRequest
|
|
68
|
-
): Promise<UserResponse> {
|
|
69
|
-
const data = Validation.validate(UserValidation.UPDATE, request);
|
|
70
|
-
const user = await UserRepository.findById(id);
|
|
71
|
-
if (!user) {
|
|
72
|
-
throw new ResponseError(404, "Data Tidak Ditemukan");
|
|
73
|
-
}
|
|
74
|
-
if (data.fullName) {
|
|
75
|
-
user.fullName = data.fullName;
|
|
76
|
-
}
|
|
77
|
-
if (data.password) {
|
|
78
|
-
user.password = await argon2.hash(data.password);
|
|
79
|
-
}
|
|
80
|
-
if (data.email && data.email !== user.email) {
|
|
81
|
-
const emailExists = await UserRepository.countByEmail(data.email);
|
|
82
|
-
if (emailExists != 0) {
|
|
83
|
-
throw new ResponseError(409, "Email Sudah Ada");
|
|
84
|
-
}
|
|
85
|
-
user.email = data.email;
|
|
86
|
-
}
|
|
87
|
-
const result = await UserRepository.update(id, {
|
|
88
|
-
fullName: user.fullName,
|
|
89
|
-
password: user.password,
|
|
90
|
-
email: user.email,
|
|
91
|
-
});
|
|
92
|
-
return toUserResponse(result);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
static async delete(id: string) {
|
|
96
|
-
const data = await UserRepository.findById(id);
|
|
97
|
-
if (!data) {
|
|
98
|
-
throw new ResponseError(404, "Data Tidak Ditemukan");
|
|
99
|
-
}
|
|
100
|
-
await UserRepository.delete(id);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
CreateUserRequest,
|
|
3
|
+
ListUserRequest,
|
|
4
|
+
UpdateUserRequest,
|
|
5
|
+
toUserResponse,
|
|
6
|
+
UserResponse,
|
|
7
|
+
} from "../dtos/user-dto";
|
|
8
|
+
import { ResponseError } from "../utils/response-error";
|
|
9
|
+
import { UserValidation } from "../validations/user-validation";
|
|
10
|
+
import { Validation } from "../utils/validation";
|
|
11
|
+
import * as argon2 from "argon2";
|
|
12
|
+
import { listResponse, tolistResponse } from "../dtos/list-dto";
|
|
13
|
+
import { UserRepository } from "../repositories/user-repository";
|
|
14
|
+
import { env } from "../config/env";
|
|
15
|
+
export class UserService {
|
|
16
|
+
static async create(request: CreateUserRequest): Promise<UserResponse> {
|
|
17
|
+
const data = Validation.validate(UserValidation.CREATE, request);
|
|
18
|
+
const emailExits = await UserRepository.countByEmail(data.email);
|
|
19
|
+
if (emailExits != 0) {
|
|
20
|
+
throw new ResponseError(409, "Email Sudah Terdaftar");
|
|
21
|
+
}
|
|
22
|
+
data.password = await argon2.hash(data.password);
|
|
23
|
+
|
|
24
|
+
const response = await UserRepository.create({
|
|
25
|
+
fullName: data.fullName,
|
|
26
|
+
email: data.email,
|
|
27
|
+
password: data.password,
|
|
28
|
+
});
|
|
29
|
+
return toUserResponse(response);
|
|
30
|
+
}
|
|
31
|
+
static async getAll(request: ListUserRequest): Promise<listResponse> {
|
|
32
|
+
const requestList = Validation.validate(UserValidation.LIST, request);
|
|
33
|
+
const filters = [];
|
|
34
|
+
if (requestList.name) {
|
|
35
|
+
filters.push({
|
|
36
|
+
fullName: {
|
|
37
|
+
contains: requestList.name,
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
const data = await UserRepository.findMany(
|
|
42
|
+
filters,
|
|
43
|
+
requestList.skip,
|
|
44
|
+
requestList.take
|
|
45
|
+
);
|
|
46
|
+
const totalData = await UserRepository.count(filters);
|
|
47
|
+
const result = {
|
|
48
|
+
data,
|
|
49
|
+
total_data: totalData,
|
|
50
|
+
paging: {
|
|
51
|
+
current_page: requestList.page,
|
|
52
|
+
total_page: Math.ceil(totalData / requestList.take),
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
return tolistResponse(result);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
static async getOne(id: string): Promise<UserResponse> {
|
|
59
|
+
const data = await UserRepository.findById(id);
|
|
60
|
+
if (!data) {
|
|
61
|
+
throw new ResponseError(404, "Data Tidak Ditemukan");
|
|
62
|
+
}
|
|
63
|
+
return toUserResponse(data);
|
|
64
|
+
}
|
|
65
|
+
static async update(
|
|
66
|
+
id: string,
|
|
67
|
+
request: UpdateUserRequest
|
|
68
|
+
): Promise<UserResponse> {
|
|
69
|
+
const data = Validation.validate(UserValidation.UPDATE, request);
|
|
70
|
+
const user = await UserRepository.findById(id);
|
|
71
|
+
if (!user) {
|
|
72
|
+
throw new ResponseError(404, "Data Tidak Ditemukan");
|
|
73
|
+
}
|
|
74
|
+
if (data.fullName) {
|
|
75
|
+
user.fullName = data.fullName;
|
|
76
|
+
}
|
|
77
|
+
if (data.password) {
|
|
78
|
+
user.password = await argon2.hash(data.password);
|
|
79
|
+
}
|
|
80
|
+
if (data.email && data.email !== user.email) {
|
|
81
|
+
const emailExists = await UserRepository.countByEmail(data.email);
|
|
82
|
+
if (emailExists != 0) {
|
|
83
|
+
throw new ResponseError(409, "Email Sudah Ada");
|
|
84
|
+
}
|
|
85
|
+
user.email = data.email;
|
|
86
|
+
}
|
|
87
|
+
const result = await UserRepository.update(id, {
|
|
88
|
+
fullName: user.fullName,
|
|
89
|
+
password: user.password,
|
|
90
|
+
email: user.email,
|
|
91
|
+
});
|
|
92
|
+
return toUserResponse(result);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
static async delete(id: string) {
|
|
96
|
+
const data = await UserRepository.findById(id);
|
|
97
|
+
if (!data) {
|
|
98
|
+
throw new ResponseError(404, "Data Tidak Ditemukan");
|
|
99
|
+
}
|
|
100
|
+
await UserRepository.delete(id);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { User } from "@prisma/client";
|
|
2
|
-
import { Request } from "express";
|
|
3
|
-
|
|
4
|
-
export interface UserRequest extends Request {
|
|
5
|
-
user?: User;
|
|
6
|
-
}
|
|
1
|
+
import { User } from "@prisma/client";
|
|
2
|
+
import { Request } from "express";
|
|
3
|
+
|
|
4
|
+
export interface UserRequest extends Request {
|
|
5
|
+
user?: User;
|
|
6
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { NextFunction, Request, Response } from "express";
|
|
2
|
-
|
|
3
|
-
export const asyncHandler = (
|
|
4
|
-
fn: (req: Request, res: Response, next: NextFunction) => Promise<any>
|
|
5
|
-
) => {
|
|
6
|
-
return (req: Request, res: Response, next: NextFunction) => {
|
|
7
|
-
fn(req, res, next).catch(next);
|
|
8
|
-
};
|
|
9
|
-
};
|
|
1
|
+
import { NextFunction, Request, Response } from "express";
|
|
2
|
+
|
|
3
|
+
export const asyncHandler = (
|
|
4
|
+
fn: (req: Request, res: Response, next: NextFunction) => Promise<any>
|
|
5
|
+
) => {
|
|
6
|
+
return (req: Request, res: Response, next: NextFunction) => {
|
|
7
|
+
fn(req, res, next).catch(next);
|
|
8
|
+
};
|
|
9
|
+
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export class ResponseError extends Error {
|
|
2
|
-
public status: boolean;
|
|
3
|
-
constructor(
|
|
4
|
-
public status_code: number,
|
|
5
|
-
public message: string
|
|
6
|
-
) {
|
|
7
|
-
super(message);
|
|
8
|
-
this.status = false;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
1
|
+
export class ResponseError extends Error {
|
|
2
|
+
public status: boolean;
|
|
3
|
+
constructor(
|
|
4
|
+
public status_code: number,
|
|
5
|
+
public message: string
|
|
6
|
+
) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.status = false;
|
|
9
|
+
}
|
|
10
|
+
}
|