@hedhog/admin 0.0.103 → 0.0.105

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.
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
+ }