@skroz/profile-api 1.0.7 → 1.0.8

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 (63) hide show
  1. package/dist/dto/ConfirmEmailInput.d.ts +1 -1
  2. package/dist/dto/ConfirmEmailInput.js +3 -3
  3. package/dist/dto/ForgotPasswordInput.d.ts +1 -1
  4. package/dist/dto/ForgotPasswordInput.js +3 -3
  5. package/dist/dto/LoginInput.d.ts +2 -2
  6. package/dist/dto/LoginInput.js +38 -5
  7. package/dist/dto/PasswordInput.d.ts +1 -1
  8. package/dist/dto/PasswordInput.js +3 -3
  9. package/dist/dto/RecoverPasswordInput.d.ts +2 -2
  10. package/dist/dto/RecoverPasswordInput.js +38 -5
  11. package/dist/dto/RegisterInput.d.ts +2 -2
  12. package/dist/dto/RegisterInput.js +38 -5
  13. package/dist/dto/SendTokenPayload.d.ts +2 -2
  14. package/dist/dto/SendTokenPayload.js +3 -4
  15. package/dist/dto/StatusPayload.d.ts +1 -1
  16. package/dist/dto/StatusPayload.js +2 -3
  17. package/dist/dto/UpdateEmailInput.d.ts +1 -1
  18. package/dist/dto/UpdateEmailInput.js +3 -3
  19. package/dist/dto/UpdatePasswordInput.d.ts +2 -2
  20. package/dist/dto/UpdatePasswordInput.js +38 -5
  21. package/dist/dto/UpdateProfileInput.d.ts +1 -1
  22. package/dist/dto/UpdateProfileInput.js +3 -3
  23. package/dist/dto/index.d.ts +11 -11
  24. package/dist/dto/index.js +42 -24
  25. package/dist/email-templates/base/content.pug +32 -0
  26. package/dist/email-templates/base/header.pug +28 -0
  27. package/dist/email-templates/base/layout.pug +34 -0
  28. package/dist/email-templates/base/mixins.pug +16 -0
  29. package/dist/email-templates/confirmEmail.pug +16 -0
  30. package/dist/email-templates/forgotPassword.pug +16 -0
  31. package/dist/email-templates/notification.pug +14 -0
  32. package/dist/email-templates/tempPassword.pug +14 -0
  33. package/dist/resolvers/AuthResolver.d.ts +1 -24
  34. package/dist/resolvers/AuthResolver.js +6 -3
  35. package/dist/resolvers/ProfileResolver.d.ts +1 -18
  36. package/dist/resolvers/ProfileResolver.js +8 -2
  37. package/dist/services/ProfileEmailService.js +2 -2
  38. package/dist/types/index.d.ts +1 -1
  39. package/package.json +3 -3
  40. package/src/dto/ConfirmEmailInput.ts +1 -1
  41. package/src/dto/ForgotPasswordInput.ts +1 -1
  42. package/src/dto/LoginInput.ts +2 -2
  43. package/src/dto/PasswordInput.ts +1 -1
  44. package/src/dto/RecoverPasswordInput.ts +2 -2
  45. package/src/dto/RegisterInput.ts +2 -2
  46. package/src/dto/SendTokenPayload.ts +2 -2
  47. package/src/dto/StatusPayload.ts +1 -1
  48. package/src/dto/UpdateEmailInput.ts +1 -1
  49. package/src/dto/UpdatePasswordInput.ts +2 -2
  50. package/src/dto/UpdateProfileInput.ts +1 -1
  51. package/src/dto/index.ts +11 -11
  52. package/src/email-templates/base/content.pug +32 -0
  53. package/src/email-templates/base/header.pug +28 -0
  54. package/src/email-templates/base/layout.pug +34 -0
  55. package/src/email-templates/base/mixins.pug +16 -0
  56. package/src/email-templates/confirmEmail.pug +16 -0
  57. package/src/email-templates/forgotPassword.pug +16 -0
  58. package/src/email-templates/notification.pug +14 -0
  59. package/src/email-templates/tempPassword.pug +14 -0
  60. package/src/resolvers/AuthResolver.ts +76 -30
  61. package/src/resolvers/ProfileResolver.ts +125 -98
  62. package/src/services/ProfileEmailService.ts +147 -147
  63. package/src/types/index.ts +1 -1
@@ -0,0 +1,14 @@
1
+ extends base/layout
2
+ include base/mixins
3
+
4
+ block content
5
+ +header(header)
6
+ p #{' ' + text}
7
+ if (link)
8
+ +link(link.href, link.label)
9
+ div(style='margin-top: 30px;')
10
+ strong #{mistakeHeader}
11
+ a(href=unsubscribeLink)
12
+ strong Отписаться
13
+ br
14
+ | #{mistakeText}
@@ -0,0 +1,14 @@
1
+ extends base/layout
2
+ include base/mixins
3
+
4
+ block content
5
+ +header(header)
6
+ p #{' ' + text}
7
+ if (link)
8
+ +link(link.href, link.label)
9
+ div(style='margin-top: 30px;')
10
+ strong #{mistakeHeader}
11
+ a(href=unsubscribeLink)
12
+ strong Отписаться
13
+ br
14
+ | #{mistakeText}
@@ -1,26 +1,34 @@
1
- import {
2
- Arg,
3
- Authorized,
4
- Ctx,
5
- Mutation,
6
- Resolver,
7
- } from 'type-graphql';
1
+ import { Arg, Authorized, Ctx, Mutation, Resolver } from 'type-graphql';
8
2
  import { StatusPayload } from '@os-team/graphql-utils';
9
3
  import { TransformArgs } from '@os-team/graphql-transformers';
10
4
  import { ValidateArgs } from '@os-team/graphql-validators';
11
- import { ProfileAuthService, CONFIRMATION_REDIS_PREFIX, RECOVERY_REDIS_PREFIX } from '../services/ProfileAuthService';
5
+ import {
6
+ ProfileAuthService,
7
+ CONFIRMATION_REDIS_PREFIX,
8
+ RECOVERY_REDIS_PREFIX,
9
+ } from '../services/ProfileAuthService';
12
10
  import { ProfileContext } from '../types';
13
11
  import {
14
- RegisterInput, registerTransformers, registerValidators,
15
- LoginInput, loginTransformers, loginValidators,
12
+ RegisterInput,
13
+ registerTransformers,
14
+ registerValidators,
15
+ LoginInput,
16
+ loginTransformers,
17
+ loginValidators,
16
18
  ConfirmEmailInput,
17
- ForgotPasswordInput, forgotPasswordTransformers, forgotPasswordValidators,
18
- RecoverPasswordInput, recoverPasswordTransformers, recoverPasswordValidators,
19
+ ForgotPasswordInput,
20
+ forgotPasswordTransformers,
21
+ forgotPasswordValidators,
22
+ RecoverPasswordInput,
23
+ recoverPasswordTransformers,
24
+ recoverPasswordValidators,
19
25
  SendTokenPayload,
20
- confirmEmailValidators
26
+ confirmEmailValidators,
21
27
  } from '../dto';
22
28
 
23
- export interface AuthResolverDependencies<TContext extends ProfileContext = ProfileContext> {
29
+ export interface AuthResolverDependencies<
30
+ TContext extends ProfileContext = ProfileContext
31
+ > {
24
32
  authService: ProfileAuthService | (() => ProfileAuthService);
25
33
  userType: any;
26
34
  onUserCreated?: (user: any, ctx: TContext) => Promise<void>;
@@ -31,7 +39,9 @@ export interface AuthResolverDependencies<TContext extends ProfileContext = Prof
31
39
  logTelegramBot?: { sendError: (msg: string) => Promise<any> };
32
40
  }
33
41
 
34
- export function createAuthResolver<TContext extends ProfileContext = ProfileContext>(deps: AuthResolverDependencies<TContext>) {
42
+ export function createAuthResolver<
43
+ TContext extends ProfileContext = ProfileContext
44
+ >(deps: AuthResolverDependencies<TContext>): any {
35
45
  const {
36
46
  authService,
37
47
  onUserCreated,
@@ -40,7 +50,7 @@ export function createAuthResolver<TContext extends ProfileContext = ProfileCont
40
50
  onEmailConfirmed,
41
51
  onPasswordRecovered,
42
52
  logTelegramBot,
43
- userType
53
+ userType,
44
54
  } = deps;
45
55
 
46
56
  const getAuthService = (): ProfileAuthService => {
@@ -67,7 +77,8 @@ export function createAuthResolver<TContext extends ProfileContext = ProfileCont
67
77
  });
68
78
 
69
79
  if (onUserCreated) await onUserCreated(user, ctx);
70
- if (logTelegramBot) await logTelegramBot.sendError(`Новый пользователь ${input.email}`);
80
+ if (logTelegramBot)
81
+ await logTelegramBot.sendError(`Новый пользователь ${input.email}`);
71
82
 
72
83
  // Создаем сессию
73
84
  const userAgent = decodeURI(ctx.req.get('user-agent') || '');
@@ -91,7 +102,10 @@ export function createAuthResolver<TContext extends ProfileContext = ProfileCont
91
102
 
92
103
  if (user.isBanned) throw new Error(t('validation:user.banned'));
93
104
 
94
- const isPasswordOk = await service.verifyPassword(user.password!, input.password);
105
+ const isPasswordOk = await service.verifyPassword(
106
+ user.password!,
107
+ input.password
108
+ );
95
109
  if (!isPasswordOk) throw new Error(t('validation:login.wrongPassword'));
96
110
 
97
111
  const userAgent = decodeURI(ctx.req.get('user-agent') || '');
@@ -125,16 +139,29 @@ export function createAuthResolver<TContext extends ProfileContext = ProfileCont
125
139
  return { ok: true };
126
140
  }
127
141
 
128
- @ValidateArgs(confirmEmailValidators, { arg: 'input', tKey: 'confirmEmail' })
142
+ @ValidateArgs(confirmEmailValidators, {
143
+ arg: 'input',
144
+ tKey: 'confirmEmail',
145
+ })
129
146
  @Mutation(() => StatusPayload)
130
- async confirmEmail(@Arg('input') input: ConfirmEmailInput, @Ctx() ctx: TContext) {
147
+ async confirmEmail(
148
+ @Arg('input') input: ConfirmEmailInput,
149
+ @Ctx() ctx: TContext
150
+ ) {
131
151
  const service = getAuthService();
132
- const user = await service.getUserByToken(CONFIRMATION_REDIS_PREFIX, input.token);
152
+ const user = await service.getUserByToken(
153
+ CONFIRMATION_REDIS_PREFIX,
154
+ input.token
155
+ );
133
156
  if (!user) throw new Error(ctx.t('validation:error.wrongCode'));
134
157
 
135
158
  user.isEmailConfirmed = true;
136
159
  await user.save();
137
- await service.removeTokenFromRedis(CONFIRMATION_REDIS_PREFIX, user, input.token);
160
+ await service.removeTokenFromRedis(
161
+ CONFIRMATION_REDIS_PREFIX,
162
+ user,
163
+ input.token
164
+ );
138
165
 
139
166
  const userAgent = decodeURI(ctx.req.get('user-agent') || '');
140
167
  await ctx.req.session.create({
@@ -145,7 +172,9 @@ export function createAuthResolver<TContext extends ProfileContext = ProfileCont
145
172
 
146
173
  if (onEmailConfirmed) await onEmailConfirmed(user, ctx);
147
174
  if (logTelegramBot) {
148
- await logTelegramBot.sendError(`${user.email || user.urlSlug} подтвердил(а) email`);
175
+ await logTelegramBot.sendError(
176
+ `${user.email || user.urlSlug} подтвердил(а) email`
177
+ );
149
178
  }
150
179
 
151
180
  return { ok: true };
@@ -154,7 +183,10 @@ export function createAuthResolver<TContext extends ProfileContext = ProfileCont
154
183
  @TransformArgs(forgotPasswordTransformers, { arg: 'input' })
155
184
  @ValidateArgs(forgotPasswordValidators, { arg: 'input', tKey: 'forgot' })
156
185
  @Mutation(() => SendTokenPayload)
157
- async forgotPassword(@Arg('input') input: ForgotPasswordInput, @Ctx() ctx: TContext) {
186
+ async forgotPassword(
187
+ @Arg('input') input: ForgotPasswordInput,
188
+ @Ctx() ctx: TContext
189
+ ) {
158
190
  const { t } = ctx;
159
191
  const service = getAuthService();
160
192
  const user = await service.db.findUserByEmail(input.email);
@@ -163,11 +195,13 @@ export function createAuthResolver<TContext extends ProfileContext = ProfileCont
163
195
  const res = await service.sendLink(user, 'recovery');
164
196
 
165
197
  if (logTelegramBot) {
166
- await logTelegramBot.sendError(`${user.email || user.urlSlug} запросил(а) восстановление пароля`);
198
+ await logTelegramBot.sendError(
199
+ `${user.email || user.urlSlug} запросил(а) восстановление пароля`
200
+ );
167
201
  }
168
202
 
169
203
  return {
170
- confirmationLinkIsSent: res.ok,
204
+ recoveryLinkIsSent: res.ok,
171
205
  limitExpiresAt: res.limitExpiresAt,
172
206
  };
173
207
  }
@@ -175,15 +209,25 @@ export function createAuthResolver<TContext extends ProfileContext = ProfileCont
175
209
  @TransformArgs(recoverPasswordTransformers, { arg: 'input' })
176
210
  @ValidateArgs(recoverPasswordValidators, { arg: 'input', tKey: 'recover' })
177
211
  @Mutation(() => StatusPayload)
178
- async recoverPassword(@Arg('input') input: RecoverPasswordInput, @Ctx() ctx: TContext) {
212
+ async recoverPassword(
213
+ @Arg('input') input: RecoverPasswordInput,
214
+ @Ctx() ctx: TContext
215
+ ) {
179
216
  const service = getAuthService();
180
- const user = await service.getUserByToken(RECOVERY_REDIS_PREFIX, input.token);
217
+ const user = await service.getUserByToken(
218
+ RECOVERY_REDIS_PREFIX,
219
+ input.token
220
+ );
181
221
  if (!user) throw new Error(ctx.t('validation:error.wrongCode'));
182
222
 
183
223
  user.password = await service.hashPassword(input.password);
184
224
  user.isTempPassword = false;
185
225
  await user.save();
186
- await service.removeTokenFromRedis(RECOVERY_REDIS_PREFIX, user, input.token);
226
+ await service.removeTokenFromRedis(
227
+ RECOVERY_REDIS_PREFIX,
228
+ user,
229
+ input.token
230
+ );
187
231
 
188
232
  const userAgent = decodeURI(ctx.req.get('user-agent') || '');
189
233
  await ctx.req.session.create({
@@ -194,7 +238,9 @@ export function createAuthResolver<TContext extends ProfileContext = ProfileCont
194
238
 
195
239
  if (onPasswordRecovered) await onPasswordRecovered(user, ctx);
196
240
  if (logTelegramBot) {
197
- await logTelegramBot.sendError(`${user.email || user.urlSlug} восстановил(а) пароль`);
241
+ await logTelegramBot.sendError(
242
+ `${user.email || user.urlSlug} восстановил(а) пароль`
243
+ );
198
244
  }
199
245
 
200
246
  return { ok: true };
@@ -1,10 +1,10 @@
1
1
  import {
2
- Arg,
3
- Authorized,
4
- Ctx,
5
- Mutation,
6
- Resolver,
7
- UnauthorizedError,
2
+ Arg,
3
+ Authorized,
4
+ Ctx,
5
+ Mutation,
6
+ Resolver,
7
+ UnauthorizedError,
8
8
  } from 'type-graphql';
9
9
  import { StatusPayload } from '@os-team/graphql-utils';
10
10
  import { TransformArgs } from '@os-team/graphql-transformers';
@@ -12,103 +12,130 @@ import { ValidateArgs } from '@os-team/graphql-validators';
12
12
  import { ProfileAuthService } from '../services/ProfileAuthService';
13
13
  import { ProfileContext } from '../types';
14
14
  import {
15
- UpdateEmailInput, updateEmailTransformers, updateEmailValidators,
16
- UpdatePasswordInput, updatePasswordTransformers, updatePasswordValidators,
17
- UpdateProfileInput, updateProfileTransformers, updateProfileValidators,
15
+ UpdateEmailInput,
16
+ updateEmailTransformers,
17
+ updateEmailValidators,
18
+ UpdatePasswordInput,
19
+ updatePasswordTransformers,
20
+ updatePasswordValidators,
21
+ UpdateProfileInput,
22
+ updateProfileTransformers,
23
+ updateProfileValidators,
18
24
  } from '../dto';
19
25
 
20
26
  export interface ProfileResolverDependencies {
21
- authService: ProfileAuthService | (() => ProfileAuthService);
22
- userType: any;
27
+ authService: ProfileAuthService | (() => ProfileAuthService);
28
+ userType: any;
23
29
  }
24
30
 
25
- export function createProfileResolver<TContext extends ProfileContext = ProfileContext>(deps: ProfileResolverDependencies) {
26
- const { authService, userType } = deps;
27
-
28
- const getAuthService = (): ProfileAuthService => {
29
- if (typeof authService === 'function') return authService();
30
- return authService;
31
- };
32
-
33
- @Resolver(() => userType)
34
- class ProfileResolver {
35
- @Authorized()
36
- @TransformArgs(updateEmailTransformers, { arg: 'input' })
37
- @ValidateArgs(updateEmailValidators, { arg: 'input', tKey: 'updateEmail' })
38
- @Mutation(() => StatusPayload)
39
- async updateEmail(@Arg('input') input: UpdateEmailInput, @Ctx() ctx: TContext) {
40
- const { user, t } = ctx;
41
- if (!user) throw new UnauthorizedError();
42
-
43
- const service = getAuthService();
44
- if (await service.db.isEmailTaken(input.email, user.id)) {
45
- throw new Error(t('validation:updateEmail.emailExists'));
46
- }
47
-
48
- user.email = input.email;
49
- user.isEmailConfirmed = false;
50
- await user.save();
51
-
52
- return { ok: true };
53
- }
54
-
55
- @Authorized()
56
- @TransformArgs(updatePasswordTransformers, { arg: 'input' })
57
- @ValidateArgs(updatePasswordValidators, { arg: 'input', tKey: 'updatePassword' })
58
- @Mutation(() => StatusPayload)
59
- async updatePassword(@Arg('input') input: UpdatePasswordInput, @Ctx() ctx: TContext) {
60
- const { user, t } = ctx;
61
- if (!user) throw new UnauthorizedError();
62
-
63
- const service = getAuthService();
64
- const isOldPasswordOk = await service.verifyPassword(user.password!, input.oldPassword);
65
- if (!isOldPasswordOk) throw new Error(t('validation:updatePassword.wrongPassword'));
66
-
67
- user.password = await service.hashPassword(input.password);
68
- user.isTempPassword = false;
69
- await user.save();
70
-
71
- return { ok: true };
72
- }
73
-
74
- @Authorized()
75
- @TransformArgs(updateProfileTransformers, { arg: 'input' })
76
- @ValidateArgs(updateProfileValidators, { arg: 'input', tKey: 'updateProfile' })
77
- @Mutation(() => userType)
78
- async updateProfile(@Arg('input') input: UpdateProfileInput, @Ctx() ctx: TContext) {
79
- const { user } = ctx;
80
- if (!user) throw new UnauthorizedError();
81
-
82
- user.name = input.name;
83
- await user.save();
84
-
85
- return user;
86
- }
87
-
88
- @Authorized()
89
- @Mutation(() => StatusPayload)
90
- async toggleEmailNotification(@Ctx() ctx: TContext) {
91
- const { user } = ctx;
92
- if (!user) throw new UnauthorizedError();
93
-
94
- user.isEmailNotificationEnabled = !user.isEmailNotificationEnabled;
95
- await user.save();
96
-
97
- return { ok: true };
98
- }
99
-
100
- @Authorized()
101
- @Mutation(() => StatusPayload)
102
- async toggleTelegramNotification(@Ctx() ctx: TContext) {
103
- const { user } = ctx;
104
- if (!user) throw new UnauthorizedError();
105
-
106
- user.isTelegramNotificationEnabled = !user.isTelegramNotificationEnabled;
107
- await user.save();
108
-
109
- return { ok: true };
110
- }
31
+ export function createProfileResolver<
32
+ TContext extends ProfileContext = ProfileContext
33
+ >(deps: ProfileResolverDependencies): any {
34
+ const { authService, userType } = deps;
35
+
36
+ const getAuthService = (): ProfileAuthService => {
37
+ if (typeof authService === 'function') return authService();
38
+ return authService;
39
+ };
40
+
41
+ @Resolver(() => userType)
42
+ class ProfileResolver {
43
+ @Authorized()
44
+ @TransformArgs(updateEmailTransformers, { arg: 'input' })
45
+ @ValidateArgs(updateEmailValidators, { arg: 'input', tKey: 'updateEmail' })
46
+ @Mutation(() => StatusPayload)
47
+ async updateEmail(
48
+ @Arg('input') input: UpdateEmailInput,
49
+ @Ctx() ctx: TContext
50
+ ) {
51
+ const { user, t } = ctx;
52
+ if (!user) throw new UnauthorizedError();
53
+
54
+ const service = getAuthService();
55
+ if (await service.db.isEmailTaken(input.email, user.id)) {
56
+ throw new Error(t('validation:updateEmail.emailExists'));
57
+ }
58
+
59
+ user.email = input.email;
60
+ user.isEmailConfirmed = false;
61
+ await user.save();
62
+
63
+ return { ok: true };
111
64
  }
112
65
 
113
- return ProfileResolver;
66
+ @Authorized()
67
+ @TransformArgs(updatePasswordTransformers, { arg: 'input' })
68
+ @ValidateArgs(updatePasswordValidators, {
69
+ arg: 'input',
70
+ tKey: 'updatePassword',
71
+ })
72
+ @Mutation(() => StatusPayload)
73
+ async updatePassword(
74
+ @Arg('input') input: UpdatePasswordInput,
75
+ @Ctx() ctx: TContext
76
+ ) {
77
+ const { user, t } = ctx;
78
+ if (!user) throw new UnauthorizedError();
79
+
80
+ const service = getAuthService();
81
+ const isOldPasswordOk = await service.verifyPassword(
82
+ user.password!,
83
+ input.oldPassword
84
+ );
85
+ if (!isOldPasswordOk)
86
+ throw new Error(t('validation:updatePassword.wrongPassword'));
87
+
88
+ user.password = await service.hashPassword(input.password);
89
+ user.isTempPassword = false;
90
+ await user.save();
91
+
92
+ return { ok: true };
93
+ }
94
+
95
+ @Authorized()
96
+ @TransformArgs(updateProfileTransformers, { arg: 'input' })
97
+ @ValidateArgs(updateProfileValidators, {
98
+ arg: 'input',
99
+ tKey: 'updateProfile',
100
+ })
101
+ @Mutation(() => userType)
102
+ async updateProfile(
103
+ @Arg('input') input: UpdateProfileInput,
104
+ @Ctx() ctx: TContext
105
+ ) {
106
+ const { user } = ctx;
107
+ if (!user) throw new UnauthorizedError();
108
+
109
+ user.name = input.name;
110
+ await user.save();
111
+
112
+ return user;
113
+ }
114
+
115
+ @Authorized()
116
+ @Mutation(() => StatusPayload)
117
+ async toggleEmailNotification(@Ctx() ctx: TContext) {
118
+ const { user } = ctx;
119
+ if (!user) throw new UnauthorizedError();
120
+
121
+ user.isEmailNotificationEnabled = !user.isEmailNotificationEnabled;
122
+ await user.save();
123
+
124
+ return { ok: true };
125
+ }
126
+
127
+ @Authorized()
128
+ @Mutation(() => StatusPayload)
129
+ async toggleTelegramNotification(@Ctx() ctx: TContext) {
130
+ const { user } = ctx;
131
+ if (!user) throw new UnauthorizedError();
132
+
133
+ user.isTelegramNotificationEnabled = !user.isTelegramNotificationEnabled;
134
+ await user.save();
135
+
136
+ return { ok: true };
137
+ }
138
+ }
139
+
140
+ return ProfileResolver;
114
141
  }