@hedhog/admin 0.0.103 → 0.0.105

Sign up to get free protection for your applications and to get access to all the features.
Files changed (186) hide show
  1. package/README.md +141 -141
  2. package/dist/admin.module.js +7 -7
  3. package/dist/admin.module.js.map +1 -1
  4. package/dist/auth/auth.service.d.ts +1 -1
  5. package/dist/auth/auth.service.d.ts.map +1 -1
  6. package/dist/auth/auth.service.js +8 -8
  7. package/dist/auth/auth.service.js.map +1 -1
  8. package/dist/auth/auth.service.spec.js +16 -16
  9. package/dist/auth/auth.service.spec.js.map +1 -1
  10. package/dist/dto/with-locale.dto.d.ts +4 -0
  11. package/dist/dto/with-locale.dto.d.ts.map +1 -0
  12. package/dist/dto/{with-locales.dto.js → with-locale.dto.js} +5 -5
  13. package/dist/dto/with-locale.dto.js.map +1 -0
  14. package/dist/index.d.ts +2 -2
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +2 -2
  17. package/dist/index.js.map +1 -1
  18. package/dist/locale/locale.controller.js +1 -1
  19. package/dist/locale/locale.controller.js.map +1 -1
  20. package/dist/locale/locale.middleware.d.ts +1 -1
  21. package/dist/locale/locale.middleware.d.ts.map +1 -1
  22. package/dist/locale/locale.middleware.js +2 -2
  23. package/dist/locale/locale.middleware.js.map +1 -1
  24. package/dist/locale/locale.service.d.ts +6 -6
  25. package/dist/locale/locale.service.d.ts.map +1 -1
  26. package/dist/locale/locale.service.js +40 -40
  27. package/dist/locale/locale.service.js.map +1 -1
  28. package/dist/locale/locale.service.spec.js +14 -14
  29. package/dist/locale/locale.service.spec.js.map +1 -1
  30. package/dist/menu/menu.controller.js +3 -3
  31. package/dist/menu/menu.controller.js.map +1 -1
  32. package/dist/menu/menu.service.d.ts +3 -3
  33. package/dist/menu/menu.service.d.ts.map +1 -1
  34. package/dist/menu/menu.service.js +35 -35
  35. package/dist/menu/menu.service.js.map +1 -1
  36. package/dist/menu/menu.service.spec.js +33 -37
  37. package/dist/menu/menu.service.spec.js.map +1 -1
  38. package/dist/role/dto/create.dto.d.ts +2 -2
  39. package/dist/role/dto/create.dto.d.ts.map +1 -1
  40. package/dist/role/dto/create.dto.js +2 -2
  41. package/dist/role/dto/create.dto.js.map +1 -1
  42. package/dist/role/guards/role.guard.js +4 -4
  43. package/dist/role/guards/role.guard.js.map +1 -1
  44. package/dist/role/role.controller.js +7 -7
  45. package/dist/role/role.controller.js.map +1 -1
  46. package/dist/role/role.service.d.ts +2 -2
  47. package/dist/role/role.service.d.ts.map +1 -1
  48. package/dist/role/role.service.js +35 -35
  49. package/dist/role/role.service.js.map +1 -1
  50. package/dist/role/role.service.spec.d.ts +0 -1
  51. package/dist/role/role.service.spec.js +400 -340
  52. package/dist/role/role.service.spec.js.map +1 -1
  53. package/dist/route/route.controller.js +3 -3
  54. package/dist/route/route.controller.js.map +1 -1
  55. package/dist/route/route.service.d.ts +2 -2
  56. package/dist/route/route.service.d.ts.map +1 -1
  57. package/dist/route/route.service.js +18 -18
  58. package/dist/route/route.service.js.map +1 -1
  59. package/dist/route/route.service.spec.js +27 -27
  60. package/dist/route/route.service.spec.js.map +1 -1
  61. package/dist/screen/screen.controller.js +4 -4
  62. package/dist/screen/screen.controller.js.map +1 -1
  63. package/dist/screen/screen.service.d.ts +2 -2
  64. package/dist/screen/screen.service.d.ts.map +1 -1
  65. package/dist/screen/screen.service.js +16 -16
  66. package/dist/screen/screen.service.js.map +1 -1
  67. package/dist/screen/screen.service.spec.js +16 -16
  68. package/dist/screen/screen.service.spec.js.map +1 -1
  69. package/dist/setting/dto/setting.dto.d.ts +9 -0
  70. package/dist/setting/dto/setting.dto.d.ts.map +1 -0
  71. package/dist/setting/dto/{settings.dto.js → setting.dto.js} +6 -6
  72. package/dist/setting/dto/setting.dto.js.map +1 -0
  73. package/dist/setting/{settings.controller.d.ts → setting.controller.d.ts} +6 -6
  74. package/dist/setting/setting.controller.d.ts.map +1 -0
  75. package/dist/setting/{settings.controller.js → setting.controller.js} +20 -20
  76. package/dist/setting/setting.controller.js.map +1 -0
  77. package/dist/setting/setting.module.d.ts +3 -0
  78. package/dist/setting/setting.module.d.ts.map +1 -0
  79. package/dist/setting/{settings.module.js → setting.module.js} +6 -6
  80. package/dist/setting/setting.module.js.map +1 -0
  81. package/dist/setting/{settings.service.d.ts → setting.service.d.ts} +4 -4
  82. package/dist/setting/setting.service.d.ts.map +1 -0
  83. package/dist/setting/{settings.service.js → setting.service.js} +42 -42
  84. package/dist/setting/setting.service.js.map +1 -0
  85. package/dist/setting/setting.service.spec.d.ts +2 -0
  86. package/dist/setting/setting.service.spec.d.ts.map +1 -0
  87. package/dist/setting/{settings.service.spec.js → setting.service.spec.js} +17 -17
  88. package/dist/setting/setting.service.spec.js.map +1 -0
  89. package/dist/user/user.controller.js +3 -3
  90. package/dist/user/user.controller.js.map +1 -1
  91. package/dist/user/user.service.d.ts +2 -2
  92. package/dist/user/user.service.d.ts.map +1 -1
  93. package/dist/user/user.service.js +9 -9
  94. package/dist/user/user.service.js.map +1 -1
  95. package/dist/user/user.service.spec.js +24 -24
  96. package/dist/user/user.service.spec.js.map +1 -1
  97. package/package.json +2 -2
  98. package/src/admin.module.ts +36 -0
  99. package/src/auth/auth.controller.ts +48 -0
  100. package/src/auth/auth.module.ts +39 -0
  101. package/src/auth/auth.service.spec.ts +196 -0
  102. package/src/auth/auth.service.ts +175 -0
  103. package/src/auth/decorators/public.decorator.ts +4 -0
  104. package/src/auth/decorators/user.decorator.ts +17 -0
  105. package/src/auth/dto/forget.dto.ts +6 -0
  106. package/src/auth/dto/login.dto.ts +15 -0
  107. package/src/auth/dto/otp.dto.ts +11 -0
  108. package/src/auth/enums/multifactor-type.enum.ts +4 -0
  109. package/src/auth/guards/auth.guard.ts +50 -0
  110. package/src/auth/types/user.type.ts +8 -0
  111. package/src/dto/delete.dto.ts +8 -0
  112. package/src/dto/update-ids.dto.ts +9 -0
  113. package/src/dto/with-locale.dto.ts +8 -0
  114. package/src/index.ts +34 -0
  115. package/src/locale/dto/create.dto.ts +12 -0
  116. package/src/locale/dto/delete.dto.ts +8 -0
  117. package/src/locale/dto/set-enabled.dto.ts +9 -0
  118. package/src/locale/dto/update.dto.ts +15 -0
  119. package/src/locale/index.ts +4 -0
  120. package/src/locale/locale.controller.ts +79 -0
  121. package/src/locale/locale.decorator.ts +8 -0
  122. package/src/locale/locale.middleware.ts +34 -0
  123. package/src/locale/locale.module.ts +23 -0
  124. package/src/locale/locale.service.spec.ts +193 -0
  125. package/src/locale/locale.service.ts +366 -0
  126. package/src/menu/dto/create.dto.ts +25 -0
  127. package/src/menu/dto/order.dto.ts +8 -0
  128. package/src/menu/dto/update.dto.ts +19 -0
  129. package/src/menu/menu.controller.ts +106 -0
  130. package/src/menu/menu.module.ts +18 -0
  131. package/src/menu/menu.service.spec.ts +247 -0
  132. package/src/menu/menu.service.ts +263 -0
  133. package/src/role/decorators/role.decorator.ts +4 -0
  134. package/src/role/dto/create.dto.ts +7 -0
  135. package/src/role/dto/update.dto.ts +4 -0
  136. package/src/role/guards/role.guard.ts +122 -0
  137. package/src/role/role.controller.ts +126 -0
  138. package/src/role/role.module.ts +28 -0
  139. package/src/role/role.service.spec.ts +417 -0
  140. package/src/role/role.service.ts +302 -0
  141. package/src/route/dto/create.dto.ts +13 -0
  142. package/src/route/dto/update.dto.ts +15 -0
  143. package/src/route/route.controller.ts +91 -0
  144. package/src/route/route.module.ts +18 -0
  145. package/src/route/route.service.spec.ts +299 -0
  146. package/src/route/route.service.ts +164 -0
  147. package/src/screen/dto/create.dto.ts +19 -0
  148. package/src/screen/dto/update.dto.ts +19 -0
  149. package/src/screen/screen.controller.ts +93 -0
  150. package/src/screen/screen.module.ts +18 -0
  151. package/src/screen/screen.service.spec.ts +298 -0
  152. package/src/screen/screen.service.ts +181 -0
  153. package/src/setting/dto/create.dto.ts +1 -0
  154. package/src/setting/dto/setting-user.dto.ts +6 -0
  155. package/src/setting/dto/setting.dto.ts +17 -0
  156. package/src/setting/dto/update.dto.ts +3 -0
  157. package/src/setting/setting.controller.ts +100 -0
  158. package/src/setting/setting.module.ts +18 -0
  159. package/src/setting/setting.service.spec.ts +183 -0
  160. package/src/setting/setting.service.ts +346 -0
  161. package/src/types/http-method.ts +8 -0
  162. package/src/user/constants/user.constants.ts +1 -0
  163. package/src/user/dto/create.dto.ts +24 -0
  164. package/src/user/dto/update.dto.ts +41 -0
  165. package/src/user/user.controller.ts +75 -0
  166. package/src/user/user.module.ts +18 -0
  167. package/src/user/user.service.spec.ts +294 -0
  168. package/src/user/user.service.ts +129 -0
  169. package/tsconfig.lib.json +9 -0
  170. package/tsconfig.production.json +20 -0
  171. package/dist/dto/with-locales.dto.d.ts +0 -4
  172. package/dist/dto/with-locales.dto.d.ts.map +0 -1
  173. package/dist/dto/with-locales.dto.js.map +0 -1
  174. package/dist/setting/dto/settings.dto.d.ts +0 -9
  175. package/dist/setting/dto/settings.dto.d.ts.map +0 -1
  176. package/dist/setting/dto/settings.dto.js.map +0 -1
  177. package/dist/setting/settings.controller.d.ts.map +0 -1
  178. package/dist/setting/settings.controller.js.map +0 -1
  179. package/dist/setting/settings.module.d.ts +0 -3
  180. package/dist/setting/settings.module.d.ts.map +0 -1
  181. package/dist/setting/settings.module.js.map +0 -1
  182. package/dist/setting/settings.service.d.ts.map +0 -1
  183. package/dist/setting/settings.service.js.map +0 -1
  184. package/dist/setting/settings.service.spec.d.ts +0 -2
  185. package/dist/setting/settings.service.spec.d.ts.map +0 -1
  186. package/dist/setting/settings.service.spec.js.map +0 -1
@@ -0,0 +1,175 @@
1
+ import { MailService } from '@hedhog/mail';
2
+ import { PrismaService } from '@hedhog/prisma';
3
+ import {
4
+ forwardRef,
5
+ Inject,
6
+ Injectable,
7
+ NotFoundException,
8
+ } from '@nestjs/common';
9
+ import { JwtService } from '@nestjs/jwt';
10
+ import { compare } from 'bcrypt';
11
+ import { ForgetDTO } from './dto/forget.dto';
12
+ import { LoginDTO } from './dto/login.dto';
13
+ import { OtpDTO } from './dto/otp.dto';
14
+ import { MultifactorType } from './enums/multifactor-type.enum';
15
+
16
+ @Injectable()
17
+ export class AuthService {
18
+ constructor(
19
+ @Inject(forwardRef(() => PrismaService))
20
+ private readonly prisma: PrismaService,
21
+ @Inject(forwardRef(() => JwtService))
22
+ private readonly jwt: JwtService,
23
+ @Inject(forwardRef(() => MailService))
24
+ private readonly mail: MailService,
25
+ ) {}
26
+
27
+ async verifyToken(token: string) {
28
+ return this.jwt.verifyAsync(token, {
29
+ secret: String(process.env.JWT_SECRET),
30
+ });
31
+ }
32
+
33
+ generateRandomString(length: number): string {
34
+ const characters =
35
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
36
+ let result = '';
37
+ for (let i = 0; i < length; i++) {
38
+ const randomIndex = Math.floor(Math.random() * characters.length);
39
+ result += characters.charAt(randomIndex);
40
+ }
41
+ return result;
42
+ }
43
+
44
+ generateRandomNumber(): number {
45
+ const min = 100000;
46
+ const max = 999999;
47
+ return Math.floor(Math.random() * (max - min + 1)) + min;
48
+ }
49
+
50
+ async loginWithEmailAndPassword(email: string, password: string) {
51
+ const user = await this.prisma.user.findFirst({
52
+ where: {
53
+ email,
54
+ },
55
+ });
56
+ if (!user) {
57
+ throw new NotFoundException('User not found');
58
+ }
59
+
60
+ const isPasswordValid = await compare(password, user.password);
61
+
62
+ if (!isPasswordValid) {
63
+ throw new NotFoundException('Invalid password');
64
+ }
65
+
66
+ if (!user.multifactor_id) {
67
+ return this.getToken(user);
68
+ } else {
69
+ if (user.multifactor_id === MultifactorType.EMAIL) {
70
+ const code = this.generateRandomNumber();
71
+
72
+ await this.prisma.user.update({
73
+ where: {
74
+ id: user.id,
75
+ },
76
+ data: {
77
+ code: String(code),
78
+ },
79
+ });
80
+
81
+ await this.mail.send({
82
+ to: user.email,
83
+ subject: 'Login code',
84
+ body: `Your login code is ${code}`,
85
+ });
86
+ }
87
+
88
+ return {
89
+ token: this.jwt.sign({
90
+ id: user.id,
91
+ mfa: user.multifactor_id,
92
+ }),
93
+ mfa: true,
94
+ };
95
+ }
96
+ }
97
+
98
+ async getToken(user) {
99
+ delete user.password;
100
+
101
+ const payload = { user };
102
+
103
+ return {
104
+ token: this.jwt.sign(payload),
105
+ };
106
+ }
107
+
108
+ async forget({ email }: ForgetDTO) {
109
+ const user = await this.prisma.user.findFirst({
110
+ where: {
111
+ email,
112
+ },
113
+ select: {
114
+ id: true,
115
+ },
116
+ });
117
+
118
+ if (!user) {
119
+ throw new NotFoundException('User not found');
120
+ }
121
+
122
+ const code = this.generateRandomString(32);
123
+
124
+ await this.prisma.user.update({
125
+ where: {
126
+ id: user.id,
127
+ },
128
+ data: {
129
+ code,
130
+ },
131
+ });
132
+
133
+ await this.mail.send({
134
+ to: email,
135
+ subject: 'Reset password',
136
+ body: `Reset your password by clicking <a href="${process.env.FRONTEND_URL}/reset-password/${code}">here</a>`,
137
+ });
138
+
139
+ return true;
140
+ }
141
+
142
+ async otp({ token, code }: OtpDTO) {
143
+ const data = this.jwt.decode(token);
144
+
145
+ const user = await this.prisma.user.findFirst({
146
+ where: {
147
+ id: data['id'],
148
+ code: String(code),
149
+ },
150
+ });
151
+
152
+ if (!user) {
153
+ throw new NotFoundException('Invalid code');
154
+ }
155
+
156
+ await this.prisma.user.update({
157
+ where: {
158
+ id: user.id,
159
+ },
160
+ data: {
161
+ code: null,
162
+ },
163
+ });
164
+
165
+ return this.getToken(user);
166
+ }
167
+
168
+ login({ email, password }: LoginDTO) {
169
+ return this.loginWithEmailAndPassword(email, password);
170
+ }
171
+
172
+ verify(id: number) {
173
+ return this.prisma.user.findUnique({ where: { id } });
174
+ }
175
+ }
@@ -0,0 +1,4 @@
1
+ import { SetMetadata } from '@nestjs/common';
2
+
3
+ export const IS_PUBLIC_KEY = 'isPublic';
4
+ export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);
@@ -0,0 +1,17 @@
1
+ import {
2
+ createParamDecorator,
3
+ ExecutionContext,
4
+ UnauthorizedException,
5
+ } from '@nestjs/common';
6
+
7
+ export const User = createParamDecorator(
8
+ (field: string | null = null, ctx: ExecutionContext) => {
9
+ const request = ctx.switchToHttp().getRequest();
10
+
11
+ if (!request.auth || !request.auth.user) {
12
+ throw new UnauthorizedException(`User is not authenticated`);
13
+ }
14
+
15
+ return field ? request.auth.user[field] : request.auth.user;
16
+ },
17
+ );
@@ -0,0 +1,6 @@
1
+ import { IsEmail } from 'class-validator';
2
+
3
+ export class ForgetDTO {
4
+ @IsEmail()
5
+ email: string;
6
+ }
@@ -0,0 +1,15 @@
1
+ import { IsEmail, IsStrongPassword } from 'class-validator';
2
+
3
+ export class LoginDTO {
4
+ @IsEmail()
5
+ email: string;
6
+
7
+ @IsStrongPassword({
8
+ minLength: 6,
9
+ minLowercase: 1,
10
+ minUppercase: 0,
11
+ minNumbers: 0,
12
+ minSymbols: 0,
13
+ })
14
+ password: string;
15
+ }
@@ -0,0 +1,11 @@
1
+ import { IsInt, IsJWT, Max, Min } from 'class-validator';
2
+
3
+ export class OtpDTO {
4
+ @Min(0)
5
+ @Max(999999)
6
+ @IsInt()
7
+ code: number;
8
+
9
+ @IsJWT()
10
+ token: string;
11
+ }
@@ -0,0 +1,4 @@
1
+ export enum MultifactorType {
2
+ EMAIL = 1,
3
+ APP = 2,
4
+ }
@@ -0,0 +1,50 @@
1
+ import {
2
+ CanActivate,
3
+ ExecutionContext,
4
+ Injectable,
5
+ UnauthorizedException,
6
+ } from '@nestjs/common';
7
+ import { Reflector } from '@nestjs/core';
8
+ import { Request } from 'express';
9
+ import { AuthService } from '../auth.service';
10
+ import { IS_PUBLIC_KEY } from '../decorators/public.decorator';
11
+
12
+ @Injectable()
13
+ export class AuthGuard implements CanActivate {
14
+ constructor(
15
+ private auth: AuthService,
16
+ private reflector: Reflector,
17
+ ) {}
18
+
19
+ async canActivate(context: ExecutionContext): Promise<boolean> {
20
+ const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
21
+ context.getHandler(),
22
+ context.getClass(),
23
+ ]);
24
+
25
+ if (isPublic) {
26
+ return true;
27
+ }
28
+
29
+ const request = context.switchToHttp().getRequest();
30
+ const token = this.extractTokenFromHeader(request);
31
+
32
+ if (!token) {
33
+ throw new UnauthorizedException();
34
+ }
35
+ try {
36
+ const payload = await this.auth.verifyToken(token);
37
+
38
+ request['auth'] = payload;
39
+ } catch (error) {
40
+ throw new UnauthorizedException(error);
41
+ }
42
+ return true;
43
+ }
44
+
45
+ private extractTokenFromHeader(request: Request): string | undefined {
46
+ const [type, token] = request.headers.authorization?.split(' ') ?? [];
47
+
48
+ return type === 'Bearer' ? token : undefined;
49
+ }
50
+ }
@@ -0,0 +1,8 @@
1
+ export type User = {
2
+ id: number;
3
+ name: string;
4
+ email: string;
5
+ password: string;
6
+ created_at: string;
7
+ updated_at: string;
8
+ };
@@ -0,0 +1,8 @@
1
+ import { ArrayMinSize, IsArray, IsInt } from 'class-validator';
2
+
3
+ export class DeleteDTO {
4
+ @IsArray()
5
+ @ArrayMinSize(1)
6
+ @IsInt({ each: true })
7
+ ids: number[];
8
+ }
@@ -0,0 +1,9 @@
1
+ import { IsArray, IsInt } from 'class-validator';
2
+
3
+ export class UpdateIdsDTO {
4
+ @IsInt({
5
+ each: true,
6
+ })
7
+ @IsArray()
8
+ ids: number[];
9
+ }
@@ -0,0 +1,8 @@
1
+ import { IsObject, IsOptional, ValidateNested } from 'class-validator';
2
+
3
+ export class WithLocaleDTO {
4
+ @IsOptional()
5
+ @IsObject()
6
+ @ValidateNested({ each: true })
7
+ locale: Record<string, string>;
8
+ }
package/src/index.ts ADDED
@@ -0,0 +1,34 @@
1
+ // Admin Module
2
+ export * from './admin.module';
3
+
4
+ // Auth Module
5
+ export * from './auth/auth.service';
6
+ export * from './auth/decorators/public.decorator';
7
+ export * from './auth/decorators/user.decorator';
8
+ export * from './auth/guards/auth.guard';
9
+
10
+ // Menu Module
11
+ export * from './menu/menu.service';
12
+
13
+ // Permission Module
14
+ export * from './role/decorators/role.decorator';
15
+ export * from './role/guards/role.guard';
16
+ export * from './role/role.service';
17
+
18
+ // Screen Module
19
+ export * from './screen/screen.service';
20
+
21
+ // Screen Module
22
+ export * from './setting/setting.service';
23
+
24
+ // User Module
25
+ export * from './user/constants/user.constants';
26
+ export * from './user/user.service';
27
+
28
+ // Locale Module
29
+ export * from './locale/locale.decorator';
30
+ export * from './locale/locale.service';
31
+
32
+ export * from './dto/delete.dto';
33
+ export * from './dto/update-ids.dto';
34
+ export * from './dto/with-locale.dto';
@@ -0,0 +1,12 @@
1
+ import { IsString } from 'class-validator';
2
+
3
+ export class CreateDTO {
4
+ @IsString()
5
+ name: string;
6
+
7
+ @IsString()
8
+ code: string;
9
+
10
+ @IsString()
11
+ region: string;
12
+ }
@@ -0,0 +1,8 @@
1
+ import { ArrayMinSize, IsArray, IsInt } from 'class-validator';
2
+
3
+ export class DeleteDTO {
4
+ @IsArray()
5
+ @ArrayMinSize(1)
6
+ @IsInt({ each: true })
7
+ ids: number[];
8
+ }
@@ -0,0 +1,9 @@
1
+ import { IsString, IsArray } from 'class-validator';
2
+
3
+ export class SetEnabledDTO {
4
+ @IsArray()
5
+ @IsString({
6
+ each: true,
7
+ })
8
+ codes: string[];
9
+ }
@@ -0,0 +1,15 @@
1
+ import { IsOptional, IsString } from 'class-validator';
2
+
3
+ export class UpdateDTO {
4
+ @IsString()
5
+ @IsOptional()
6
+ name?: string;
7
+
8
+ @IsString()
9
+ @IsOptional()
10
+ code?: string;
11
+
12
+ @IsString()
13
+ @IsOptional()
14
+ region?: string;
15
+ }
@@ -0,0 +1,4 @@
1
+ export * from './locale.module';
2
+ export * from './locale.service';
3
+ export * from './locale.controller';
4
+ export * from './locale.decorator';
@@ -0,0 +1,79 @@
1
+ import { Pagination } from '@hedhog/pagination';
2
+ import {
3
+ Body,
4
+ Controller,
5
+ Delete,
6
+ forwardRef,
7
+ Get,
8
+ Inject,
9
+ Param,
10
+ ParseIntPipe,
11
+ Patch,
12
+ Post,
13
+ Put,
14
+ } from '@nestjs/common';
15
+ import { Public } from '../auth/decorators/public.decorator';
16
+ import { Role } from '../role/decorators/role.decorator';
17
+ import { CreateDTO } from './dto/create.dto';
18
+ import { DeleteDTO } from './dto/delete.dto';
19
+ import { SetEnabledDTO } from './dto/set-enabled.dto';
20
+ import { UpdateDTO } from './dto/update.dto';
21
+ import { Locale } from './locale.decorator';
22
+ import { LocaleService } from './locale.service';
23
+
24
+ @Role()
25
+ @Controller('locale')
26
+ export class LocaleController {
27
+ constructor(
28
+ @Inject(forwardRef(() => LocaleService))
29
+ private readonly localeService: LocaleService,
30
+ ) {}
31
+
32
+ @Public()
33
+ @Get('system/enables')
34
+ async getEnables(@Pagination() paginationParams, @Locale() locale: string) {
35
+ return this.localeService.getEnables(locale, paginationParams);
36
+ }
37
+
38
+ @Public()
39
+ @Get(':localeCode/:namespace')
40
+ async getTranslations(
41
+ @Param('localeCode') localeCode: string,
42
+ @Param('namespace') namespace: string,
43
+ ) {
44
+ return this.localeService.getTranslations(localeCode, namespace);
45
+ }
46
+
47
+ @Get()
48
+ async get(@Pagination() paginationParams, @Locale() locale: string) {
49
+ return this.localeService.get(locale, paginationParams);
50
+ }
51
+
52
+ @Get(':id')
53
+ async getById(@Param('id', ParseIntPipe) id: number) {
54
+ return this.localeService.getById(id);
55
+ }
56
+
57
+ @Post()
58
+ create(@Body() data: CreateDTO) {
59
+ return this.localeService.create(data);
60
+ }
61
+
62
+ @Put()
63
+ async setEnabled(@Body() { codes }: SetEnabledDTO) {
64
+ return this.localeService.setEnabled(codes);
65
+ }
66
+
67
+ @Patch(':id')
68
+ async update(@Param('id', ParseIntPipe) id: number, @Body() data: UpdateDTO) {
69
+ return this.localeService.update({
70
+ id,
71
+ data,
72
+ });
73
+ }
74
+
75
+ @Delete()
76
+ async delete(@Body() data: DeleteDTO) {
77
+ return this.localeService.delete(data);
78
+ }
79
+ }
@@ -0,0 +1,8 @@
1
+ import { createParamDecorator, ExecutionContext } from '@nestjs/common';
2
+
3
+ export const Locale = createParamDecorator(
4
+ (_data: unknown, ctx: ExecutionContext) => {
5
+ const request = ctx.switchToHttp().getRequest();
6
+ return request['locale'];
7
+ },
8
+ );
@@ -0,0 +1,34 @@
1
+ import { PrismaService } from '@hedhog/prisma';
2
+ import { Injectable, NestMiddleware } from '@nestjs/common';
3
+ import { NextFunction, Request, Response } from 'express';
4
+
5
+ @Injectable()
6
+ export class LocaleMiddleware implements NestMiddleware {
7
+ private languages = [];
8
+
9
+ constructor(private prisma: PrismaService) {}
10
+
11
+ async use(req: Request, _res: Response, next: NextFunction) {
12
+ const locale = req.headers['accept-language'] || 'en-US';
13
+ let code = locale.split(',')[0].split('-')[0];
14
+
15
+ if (!this.languages.length) {
16
+ const locale = await this.prisma.locale.findMany({
17
+ select: {
18
+ code: true,
19
+ },
20
+ });
21
+
22
+ for (const l of locale) {
23
+ this.languages.push(l.code);
24
+ }
25
+ }
26
+
27
+ if (!this.languages.includes(code)) {
28
+ code = 'en';
29
+ }
30
+
31
+ req['locale'] = code;
32
+ next();
33
+ }
34
+ }
@@ -0,0 +1,23 @@
1
+ import { PaginationModule } from '@hedhog/pagination';
2
+ import { PrismaModule } from '@hedhog/prisma';
3
+ import { forwardRef, MiddlewareConsumer, Module } from '@nestjs/common';
4
+ import { LocaleService } from './locale.service';
5
+ import { LocaleController } from './locale.controller';
6
+ import { LocaleMiddleware } from './locale.middleware';
7
+ import { AuthModule } from '../auth/auth.module';
8
+
9
+ @Module({
10
+ imports: [
11
+ forwardRef(() => AuthModule),
12
+ forwardRef(() => PrismaModule),
13
+ forwardRef(() => PaginationModule),
14
+ ],
15
+ controllers: [LocaleController],
16
+ providers: [LocaleService],
17
+ exports: [LocaleService],
18
+ })
19
+ export class LocaleModule {
20
+ configure(consumer: MiddlewareConsumer) {
21
+ consumer.apply(LocaleMiddleware).forRoutes('*');
22
+ }
23
+ }