@skroz/profile-api 1.0.9 → 1.0.11

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.
@@ -59,7 +59,7 @@ function createAuthResolver(deps) {
59
59
  ip: ctx.req.ip,
60
60
  userAgent: userAgent.slice(0, 500),
61
61
  });
62
- return { ok: true };
62
+ return user;
63
63
  });
64
64
  }
65
65
  login(input, ctx) {
@@ -120,7 +120,7 @@ function createAuthResolver(deps) {
120
120
  if (logTelegramBot) {
121
121
  yield logTelegramBot.sendError(`${user.email || user.urlSlug} подтвердил(а) email`);
122
122
  }
123
- return { ok: true };
123
+ return user;
124
124
  });
125
125
  }
126
126
  forgotPassword(input, ctx) {
@@ -168,7 +168,7 @@ function createAuthResolver(deps) {
168
168
  __decorate([
169
169
  (0, graphql_transformers_1.TransformArgs)(dto_1.registerTransformers, { arg: 'input' }),
170
170
  (0, graphql_validators_1.ValidateArgs)(dto_1.registerValidators, { arg: 'input', tKey: 'register' }),
171
- (0, type_graphql_1.Mutation)(() => graphql_utils_1.StatusPayload),
171
+ (0, type_graphql_1.Mutation)(() => userType),
172
172
  __param(0, (0, type_graphql_1.Arg)('input')),
173
173
  __param(1, (0, type_graphql_1.Ctx)()),
174
174
  __metadata("design:type", Function),
@@ -198,7 +198,7 @@ function createAuthResolver(deps) {
198
198
  arg: 'input',
199
199
  tKey: 'confirmEmail',
200
200
  }),
201
- (0, type_graphql_1.Mutation)(() => graphql_utils_1.StatusPayload),
201
+ (0, type_graphql_1.Mutation)(() => userType),
202
202
  __param(0, (0, type_graphql_1.Arg)('input')),
203
203
  __param(1, (0, type_graphql_1.Ctx)()),
204
204
  __metadata("design:type", Function),
@@ -47,7 +47,7 @@ function createProfileResolver(deps) {
47
47
  user.email = input.email;
48
48
  user.isEmailConfirmed = false;
49
49
  yield user.save();
50
- return { ok: true };
50
+ return user;
51
51
  });
52
52
  }
53
53
  updatePassword(input, ctx) {
@@ -62,7 +62,7 @@ function createProfileResolver(deps) {
62
62
  user.password = yield service.hashPassword(input.password);
63
63
  user.isTempPassword = false;
64
64
  yield user.save();
65
- return { ok: true };
65
+ return user;
66
66
  });
67
67
  }
68
68
  updateProfile(input, ctx) {
@@ -100,7 +100,7 @@ function createProfileResolver(deps) {
100
100
  (0, type_graphql_1.Authorized)(),
101
101
  (0, graphql_transformers_1.TransformArgs)(dto_1.updateEmailTransformers, { arg: 'input' }),
102
102
  (0, graphql_validators_1.ValidateArgs)(dto_1.updateEmailValidators, { arg: 'input', tKey: 'updateEmail' }),
103
- (0, type_graphql_1.Mutation)(() => graphql_utils_1.StatusPayload),
103
+ (0, type_graphql_1.Mutation)(() => userType),
104
104
  __param(0, (0, type_graphql_1.Arg)('input')),
105
105
  __param(1, (0, type_graphql_1.Ctx)()),
106
106
  __metadata("design:type", Function),
@@ -114,7 +114,7 @@ function createProfileResolver(deps) {
114
114
  arg: 'input',
115
115
  tKey: 'updatePassword',
116
116
  }),
117
- (0, type_graphql_1.Mutation)(() => graphql_utils_1.StatusPayload),
117
+ (0, type_graphql_1.Mutation)(() => userType),
118
118
  __param(0, (0, type_graphql_1.Arg)('input')),
119
119
  __param(1, (0, type_graphql_1.Ctx)()),
120
120
  __metadata("design:type", Function),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skroz/profile-api",
3
- "version": "1.0.9",
3
+ "version": "1.0.11",
4
4
  "license": "MIT",
5
5
  "repository": "git@gitlab.com:skroz/libs/utils.git",
6
6
  "main": "dist/index.js",
@@ -34,6 +34,8 @@
34
34
  "@types/pug": "2.0.6",
35
35
  "ioredis": "5.2.1",
36
36
  "rimraf": "3.0.2",
37
+ "type-graphql": "^1.1.1",
38
+ "typeorm": "^0.2.45",
37
39
  "typescript": "^5.0.0"
38
40
  },
39
41
  "peerDependencies": {
@@ -41,5 +43,5 @@
41
43
  "type-graphql": "^1.1.1",
42
44
  "typeorm": "^0.2.45"
43
45
  },
44
- "gitHead": "3208ed23610d456e63fddd636448fe4585adf401"
46
+ "gitHead": "7e51d709eca09ef48505153cb200ca3767859169"
45
47
  }
@@ -3,249 +3,249 @@ import { StatusPayload } from '@os-team/graphql-utils';
3
3
  import { TransformArgs } from '@os-team/graphql-transformers';
4
4
  import { ValidateArgs } from '@os-team/graphql-validators';
5
5
  import {
6
- ProfileAuthService,
7
- CONFIRMATION_REDIS_PREFIX,
8
- RECOVERY_REDIS_PREFIX,
6
+ ProfileAuthService,
7
+ CONFIRMATION_REDIS_PREFIX,
8
+ RECOVERY_REDIS_PREFIX,
9
9
  } from '../services/ProfileAuthService';
10
10
  import { ProfileContext } from '../types';
11
11
  import {
12
- RegisterInput,
13
- registerTransformers,
14
- registerValidators,
15
- LoginInput,
16
- loginTransformers,
17
- loginValidators,
18
- ConfirmEmailInput,
19
- ForgotPasswordInput,
20
- forgotPasswordTransformers,
21
- forgotPasswordValidators,
22
- RecoverPasswordInput,
23
- recoverPasswordTransformers,
24
- recoverPasswordValidators,
25
- SendTokenPayload,
26
- confirmEmailValidators,
12
+ RegisterInput,
13
+ registerTransformers,
14
+ registerValidators,
15
+ LoginInput,
16
+ loginTransformers,
17
+ loginValidators,
18
+ ConfirmEmailInput,
19
+ ForgotPasswordInput,
20
+ forgotPasswordTransformers,
21
+ forgotPasswordValidators,
22
+ RecoverPasswordInput,
23
+ recoverPasswordTransformers,
24
+ recoverPasswordValidators,
25
+ SendTokenPayload,
26
+ confirmEmailValidators,
27
27
  } from '../dto';
28
28
 
29
29
  export interface AuthResolverDependencies<
30
- TContext extends ProfileContext = ProfileContext
30
+ TContext extends ProfileContext = ProfileContext
31
31
  > {
32
- authService: ProfileAuthService | (() => ProfileAuthService);
33
- userType: any;
34
- onUserCreated?: (user: any, ctx: TContext) => Promise<void>;
35
- onLogin?: (user: any, ctx: TContext) => Promise<void>;
36
- onLogout?: (user: any, ctx: TContext) => Promise<void>;
37
- onEmailConfirmed?: (user: any, ctx: TContext) => Promise<void>;
38
- onPasswordRecovered?: (user: any, ctx: TContext) => Promise<void>;
39
- logTelegramBot?: { sendError: (msg: string) => Promise<any> };
32
+ authService: ProfileAuthService | (() => ProfileAuthService);
33
+ userType: any;
34
+ onUserCreated?: (user: any, ctx: TContext) => Promise<void>;
35
+ onLogin?: (user: any, ctx: TContext) => Promise<void>;
36
+ onLogout?: (user: any, ctx: TContext) => Promise<void>;
37
+ onEmailConfirmed?: (user: any, ctx: TContext) => Promise<void>;
38
+ onPasswordRecovered?: (user: any, ctx: TContext) => Promise<void>;
39
+ logTelegramBot?: { sendError: (msg: string) => Promise<any> };
40
40
  }
41
41
 
42
42
  export function createAuthResolver<
43
- TContext extends ProfileContext = ProfileContext
43
+ TContext extends ProfileContext = ProfileContext
44
44
  >(deps: AuthResolverDependencies<TContext>): any {
45
- const {
46
- authService,
47
- onUserCreated,
48
- onLogin,
49
- onLogout,
50
- onEmailConfirmed,
51
- onPasswordRecovered,
52
- logTelegramBot,
53
- userType,
54
- } = deps;
55
-
56
- const getAuthService = (): ProfileAuthService => {
57
- if (typeof authService === 'function') return authService();
58
- return authService;
59
- };
60
-
61
- @Resolver(() => userType)
62
- class AuthResolver {
63
- @TransformArgs(registerTransformers, { arg: 'input' })
64
- @ValidateArgs(registerValidators, { arg: 'input', tKey: 'register' })
65
- @Mutation(() => StatusPayload)
66
- async register(@Arg('input') input: RegisterInput, @Ctx() ctx: TContext) {
67
- const { t } = ctx;
68
- const service = getAuthService();
69
- if (await service.db.isEmailTaken(input.email)) {
70
- throw new Error(t('validation:auth.emailExists'));
71
- }
72
-
73
- const passwordHash = await service.hashPassword(input.password);
74
- const user = await service.db.createUser({
75
- email: input.email,
76
- passwordHash,
77
- });
78
-
79
- if (onUserCreated) await onUserCreated(user, ctx);
80
- if (logTelegramBot)
81
- await logTelegramBot.sendError(`Новый пользователь ${input.email}`);
82
-
83
- // Создаем сессию
84
- const userAgent = decodeURI(ctx.req.get('user-agent') || '');
85
- await ctx.req.session.create({
86
- userId: user.id,
87
- ip: ctx.req.ip,
88
- userAgent: userAgent.slice(0, 500),
89
- });
90
-
91
- return { ok: true };
92
- }
93
-
94
- @TransformArgs(loginTransformers, { arg: 'input' })
95
- @ValidateArgs(loginValidators, { arg: 'input', tKey: 'register' })
96
- @Mutation(() => StatusPayload)
97
- async login(@Arg('input') input: LoginInput, @Ctx() ctx: TContext) {
98
- const { t } = ctx;
99
- const service = getAuthService();
100
- const user = await service.db.findUserByEmail(input.email);
101
- if (!user) throw new Error(t('validation:user.notFound'));
102
-
103
- if (user.isBanned) throw new Error(t('validation:user.banned'));
104
-
105
- const isPasswordOk = await service.verifyPassword(
106
- user.password!,
107
- input.password
108
- );
109
- if (!isPasswordOk) throw new Error(t('validation:login.wrongPassword'));
110
-
111
- const userAgent = decodeURI(ctx.req.get('user-agent') || '');
112
- await ctx.req.session.create({
113
- userId: user.id,
114
- ip: ctx.req.ip,
115
- userAgent: userAgent.slice(0, 500),
116
- });
117
-
118
- if (onLogin) await onLogin(user, ctx);
119
- if (logTelegramBot) {
120
- await logTelegramBot.sendError(
121
- `${user.email || user.urlSlug} вошел(ла) на сайт`
122
- );
123
- }
124
-
125
- return { ok: true };
126
- }
127
-
128
- @Authorized()
129
- @Mutation(() => StatusPayload)
130
- async logout(@Ctx() ctx: TContext) {
131
- const { user } = ctx;
132
- if (onLogout) await onLogout(user, ctx);
133
- if (logTelegramBot) {
134
- await logTelegramBot.sendError(
135
- `${user && (user.email || user.urlSlug)} разлогинился(лась)`
136
- );
137
- }
138
- await ctx.req.session.destroy();
139
- return { ok: true };
140
- }
141
-
142
- @ValidateArgs(confirmEmailValidators, {
143
- arg: 'input',
144
- tKey: 'confirmEmail',
145
- })
146
- @Mutation(() => StatusPayload)
147
- async confirmEmail(
148
- @Arg('input') input: ConfirmEmailInput,
149
- @Ctx() ctx: TContext
150
- ) {
151
- const service = getAuthService();
152
- const user = await service.getUserByToken(
153
- CONFIRMATION_REDIS_PREFIX,
154
- input.token
155
- );
156
- if (!user) throw new Error(ctx.t('validation:error.wrongCode'));
157
-
158
- user.isEmailConfirmed = true;
159
- await user.save();
160
- await service.removeTokenFromRedis(
161
- CONFIRMATION_REDIS_PREFIX,
162
- user,
163
- input.token
164
- );
165
-
166
- const userAgent = decodeURI(ctx.req.get('user-agent') || '');
167
- await ctx.req.session.create({
168
- userId: user.id,
169
- ip: ctx.req.ip,
170
- userAgent: userAgent.slice(0, 500),
171
- });
172
-
173
- if (onEmailConfirmed) await onEmailConfirmed(user, ctx);
174
- if (logTelegramBot) {
175
- await logTelegramBot.sendError(
176
- `${user.email || user.urlSlug} подтвердил(а) email`
177
- );
178
- }
179
-
180
- return { ok: true };
181
- }
182
-
183
- @TransformArgs(forgotPasswordTransformers, { arg: 'input' })
184
- @ValidateArgs(forgotPasswordValidators, { arg: 'input', tKey: 'forgot' })
185
- @Mutation(() => SendTokenPayload)
186
- async forgotPassword(
187
- @Arg('input') input: ForgotPasswordInput,
188
- @Ctx() ctx: TContext
189
- ) {
190
- const { t } = ctx;
191
- const service = getAuthService();
192
- const user = await service.db.findUserByEmail(input.email);
193
- if (!user) throw new Error(t('validation:forgot.errors.notRegistered'));
194
-
195
- const res = await service.sendLink(user, 'recovery');
196
-
197
- if (logTelegramBot) {
198
- await logTelegramBot.sendError(
199
- `${user.email || user.urlSlug} запросил(а) восстановление пароля`
200
- );
201
- }
202
-
203
- return {
204
- recoveryLinkIsSent: res.ok,
205
- limitExpiresAt: res.limitExpiresAt,
206
- };
207
- }
208
-
209
- @TransformArgs(recoverPasswordTransformers, { arg: 'input' })
210
- @ValidateArgs(recoverPasswordValidators, { arg: 'input', tKey: 'recover' })
211
- @Mutation(() => StatusPayload)
212
- async recoverPassword(
213
- @Arg('input') input: RecoverPasswordInput,
214
- @Ctx() ctx: TContext
215
- ) {
216
- const service = getAuthService();
217
- const user = await service.getUserByToken(
218
- RECOVERY_REDIS_PREFIX,
219
- input.token
220
- );
221
- if (!user) throw new Error(ctx.t('validation:error.wrongCode'));
222
-
223
- user.password = await service.hashPassword(input.password);
224
- user.isTempPassword = false;
225
- await user.save();
226
- await service.removeTokenFromRedis(
227
- RECOVERY_REDIS_PREFIX,
228
- user,
229
- input.token
230
- );
231
-
232
- const userAgent = decodeURI(ctx.req.get('user-agent') || '');
233
- await ctx.req.session.create({
234
- userId: user.id,
235
- ip: ctx.req.ip,
236
- userAgent: userAgent.slice(0, 500),
237
- });
238
-
239
- if (onPasswordRecovered) await onPasswordRecovered(user, ctx);
240
- if (logTelegramBot) {
241
- await logTelegramBot.sendError(
242
- `${user.email || user.urlSlug} восстановил(а) пароль`
243
- );
244
- }
245
-
246
- return { ok: true };
247
- }
45
+ const {
46
+ authService,
47
+ onUserCreated,
48
+ onLogin,
49
+ onLogout,
50
+ onEmailConfirmed,
51
+ onPasswordRecovered,
52
+ logTelegramBot,
53
+ userType,
54
+ } = deps;
55
+
56
+ const getAuthService = (): ProfileAuthService => {
57
+ if (typeof authService === 'function') return authService();
58
+ return authService;
59
+ };
60
+
61
+ @Resolver(() => userType)
62
+ class AuthResolver {
63
+ @TransformArgs(registerTransformers, { arg: 'input' })
64
+ @ValidateArgs(registerValidators, { arg: 'input', tKey: 'register' })
65
+ @Mutation(() => userType)
66
+ async register(@Arg('input') input: RegisterInput, @Ctx() ctx: TContext) {
67
+ const { t } = ctx;
68
+ const service = getAuthService();
69
+ if (await service.db.isEmailTaken(input.email)) {
70
+ throw new Error(t('validation:auth.emailExists'));
71
+ }
72
+
73
+ const passwordHash = await service.hashPassword(input.password);
74
+ const user = await service.db.createUser({
75
+ email: input.email,
76
+ passwordHash,
77
+ });
78
+
79
+ if (onUserCreated) await onUserCreated(user, ctx);
80
+ if (logTelegramBot)
81
+ await logTelegramBot.sendError(`Новый пользователь ${input.email}`);
82
+
83
+ // Создаем сессию
84
+ const userAgent = decodeURI(ctx.req.get('user-agent') || '');
85
+ await ctx.req.session.create({
86
+ userId: user.id,
87
+ ip: ctx.req.ip,
88
+ userAgent: userAgent.slice(0, 500),
89
+ });
90
+
91
+ return user;
248
92
  }
249
93
 
250
- return AuthResolver;
94
+ @TransformArgs(loginTransformers, { arg: 'input' })
95
+ @ValidateArgs(loginValidators, { arg: 'input', tKey: 'register' })
96
+ @Mutation(() => StatusPayload)
97
+ async login(@Arg('input') input: LoginInput, @Ctx() ctx: TContext) {
98
+ const { t } = ctx;
99
+ const service = getAuthService();
100
+ const user = await service.db.findUserByEmail(input.email);
101
+ if (!user) throw new Error(t('validation:user.notFound'));
102
+
103
+ if (user.isBanned) throw new Error(t('validation:user.banned'));
104
+
105
+ const isPasswordOk = await service.verifyPassword(
106
+ user.password!,
107
+ input.password
108
+ );
109
+ if (!isPasswordOk) throw new Error(t('validation:login.wrongPassword'));
110
+
111
+ const userAgent = decodeURI(ctx.req.get('user-agent') || '');
112
+ await ctx.req.session.create({
113
+ userId: user.id,
114
+ ip: ctx.req.ip,
115
+ userAgent: userAgent.slice(0, 500),
116
+ });
117
+
118
+ if (onLogin) await onLogin(user, ctx);
119
+ if (logTelegramBot) {
120
+ await logTelegramBot.sendError(
121
+ `${user.email || user.urlSlug} вошел(ла) на сайт`
122
+ );
123
+ }
124
+
125
+ return { ok: true };
126
+ }
127
+
128
+ @Authorized()
129
+ @Mutation(() => StatusPayload)
130
+ async logout(@Ctx() ctx: TContext) {
131
+ const { user } = ctx;
132
+ if (onLogout) await onLogout(user, ctx);
133
+ if (logTelegramBot) {
134
+ await logTelegramBot.sendError(
135
+ `${user && (user.email || user.urlSlug)} разлогинился(лась)`
136
+ );
137
+ }
138
+ await ctx.req.session.destroy();
139
+ return { ok: true };
140
+ }
141
+
142
+ @ValidateArgs(confirmEmailValidators, {
143
+ arg: 'input',
144
+ tKey: 'confirmEmail',
145
+ })
146
+ @Mutation(() => userType)
147
+ async confirmEmail(
148
+ @Arg('input') input: ConfirmEmailInput,
149
+ @Ctx() ctx: TContext
150
+ ) {
151
+ const service = getAuthService();
152
+ const user = await service.getUserByToken(
153
+ CONFIRMATION_REDIS_PREFIX,
154
+ input.token
155
+ );
156
+ if (!user) throw new Error(ctx.t('validation:error.wrongCode'));
157
+
158
+ user.isEmailConfirmed = true;
159
+ await user.save();
160
+ await service.removeTokenFromRedis(
161
+ CONFIRMATION_REDIS_PREFIX,
162
+ user,
163
+ input.token
164
+ );
165
+
166
+ const userAgent = decodeURI(ctx.req.get('user-agent') || '');
167
+ await ctx.req.session.create({
168
+ userId: user.id,
169
+ ip: ctx.req.ip,
170
+ userAgent: userAgent.slice(0, 500),
171
+ });
172
+
173
+ if (onEmailConfirmed) await onEmailConfirmed(user, ctx);
174
+ if (logTelegramBot) {
175
+ await logTelegramBot.sendError(
176
+ `${user.email || user.urlSlug} подтвердил(а) email`
177
+ );
178
+ }
179
+
180
+ return user;
181
+ }
182
+
183
+ @TransformArgs(forgotPasswordTransformers, { arg: 'input' })
184
+ @ValidateArgs(forgotPasswordValidators, { arg: 'input', tKey: 'forgot' })
185
+ @Mutation(() => SendTokenPayload)
186
+ async forgotPassword(
187
+ @Arg('input') input: ForgotPasswordInput,
188
+ @Ctx() ctx: TContext
189
+ ) {
190
+ const { t } = ctx;
191
+ const service = getAuthService();
192
+ const user = await service.db.findUserByEmail(input.email);
193
+ if (!user) throw new Error(t('validation:forgot.errors.notRegistered'));
194
+
195
+ const res = await service.sendLink(user, 'recovery');
196
+
197
+ if (logTelegramBot) {
198
+ await logTelegramBot.sendError(
199
+ `${user.email || user.urlSlug} запросил(а) восстановление пароля`
200
+ );
201
+ }
202
+
203
+ return {
204
+ recoveryLinkIsSent: res.ok,
205
+ limitExpiresAt: res.limitExpiresAt,
206
+ };
207
+ }
208
+
209
+ @TransformArgs(recoverPasswordTransformers, { arg: 'input' })
210
+ @ValidateArgs(recoverPasswordValidators, { arg: 'input', tKey: 'recover' })
211
+ @Mutation(() => StatusPayload)
212
+ async recoverPassword(
213
+ @Arg('input') input: RecoverPasswordInput,
214
+ @Ctx() ctx: TContext
215
+ ) {
216
+ const service = getAuthService();
217
+ const user = await service.getUserByToken(
218
+ RECOVERY_REDIS_PREFIX,
219
+ input.token
220
+ );
221
+ if (!user) throw new Error(ctx.t('validation:error.wrongCode'));
222
+
223
+ user.password = await service.hashPassword(input.password);
224
+ user.isTempPassword = false;
225
+ await user.save();
226
+ await service.removeTokenFromRedis(
227
+ RECOVERY_REDIS_PREFIX,
228
+ user,
229
+ input.token
230
+ );
231
+
232
+ const userAgent = decodeURI(ctx.req.get('user-agent') || '');
233
+ await ctx.req.session.create({
234
+ userId: user.id,
235
+ ip: ctx.req.ip,
236
+ userAgent: userAgent.slice(0, 500),
237
+ });
238
+
239
+ if (onPasswordRecovered) await onPasswordRecovered(user, ctx);
240
+ if (logTelegramBot) {
241
+ await logTelegramBot.sendError(
242
+ `${user.email || user.urlSlug} восстановил(а) пароль`
243
+ );
244
+ }
245
+
246
+ return { ok: true };
247
+ }
248
+ }
249
+
250
+ return AuthResolver;
251
251
  }
@@ -43,7 +43,7 @@ export function createProfileResolver<
43
43
  @Authorized()
44
44
  @TransformArgs(updateEmailTransformers, { arg: 'input' })
45
45
  @ValidateArgs(updateEmailValidators, { arg: 'input', tKey: 'updateEmail' })
46
- @Mutation(() => StatusPayload)
46
+ @Mutation(() => userType)
47
47
  async updateEmail(
48
48
  @Arg('input') input: UpdateEmailInput,
49
49
  @Ctx() ctx: TContext
@@ -60,7 +60,7 @@ export function createProfileResolver<
60
60
  user.isEmailConfirmed = false;
61
61
  await user.save();
62
62
 
63
- return { ok: true };
63
+ return user;
64
64
  }
65
65
 
66
66
  @Authorized()
@@ -69,7 +69,7 @@ export function createProfileResolver<
69
69
  arg: 'input',
70
70
  tKey: 'updatePassword',
71
71
  })
72
- @Mutation(() => StatusPayload)
72
+ @Mutation(() => userType)
73
73
  async updatePassword(
74
74
  @Arg('input') input: UpdatePasswordInput,
75
75
  @Ctx() ctx: TContext
@@ -89,7 +89,7 @@ export function createProfileResolver<
89
89
  user.isTempPassword = false;
90
90
  await user.save();
91
91
 
92
- return { ok: true };
92
+ return user;
93
93
  }
94
94
 
95
95
  @Authorized()