@skroz/profile-api 1.0.6 → 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.
- package/dist/dto/ConfirmEmailInput.d.ts +1 -1
- package/dist/dto/ConfirmEmailInput.js +3 -3
- package/dist/dto/ForgotPasswordInput.d.ts +1 -1
- package/dist/dto/ForgotPasswordInput.js +3 -3
- package/dist/dto/LoginInput.d.ts +2 -2
- package/dist/dto/LoginInput.js +38 -5
- package/dist/dto/PasswordInput.d.ts +1 -1
- package/dist/dto/PasswordInput.js +3 -3
- package/dist/dto/RecoverPasswordInput.d.ts +2 -2
- package/dist/dto/RecoverPasswordInput.js +38 -5
- package/dist/dto/RegisterInput.d.ts +2 -2
- package/dist/dto/RegisterInput.js +38 -5
- package/dist/dto/SendTokenPayload.d.ts +2 -2
- package/dist/dto/SendTokenPayload.js +3 -4
- package/dist/dto/StatusPayload.d.ts +1 -1
- package/dist/dto/StatusPayload.js +2 -3
- package/dist/dto/UpdateEmailInput.d.ts +1 -1
- package/dist/dto/UpdateEmailInput.js +3 -3
- package/dist/dto/UpdatePasswordInput.d.ts +2 -2
- package/dist/dto/UpdatePasswordInput.js +38 -5
- package/dist/dto/UpdateProfileInput.d.ts +1 -1
- package/dist/dto/UpdateProfileInput.js +3 -3
- package/dist/dto/index.d.ts +11 -11
- package/dist/dto/index.js +42 -24
- package/dist/email-templates/base/content.pug +32 -0
- package/dist/email-templates/base/header.pug +28 -0
- package/dist/email-templates/base/layout.pug +34 -0
- package/dist/email-templates/base/mixins.pug +16 -0
- package/dist/email-templates/confirmEmail.pug +16 -0
- package/dist/email-templates/forgotPassword.pug +16 -0
- package/dist/email-templates/notification.pug +14 -0
- package/dist/email-templates/tempPassword.pug +14 -0
- package/dist/resolvers/AuthResolver.d.ts +2 -25
- package/dist/resolvers/AuthResolver.js +28 -15
- package/dist/resolvers/ProfileResolver.d.ts +2 -19
- package/dist/resolvers/ProfileResolver.js +18 -5
- package/dist/services/ProfileEmailService.js +2 -2
- package/dist/types/index.d.ts +1 -1
- package/package.json +3 -3
- package/src/dto/ConfirmEmailInput.ts +1 -1
- package/src/dto/ForgotPasswordInput.ts +1 -1
- package/src/dto/LoginInput.ts +2 -2
- package/src/dto/PasswordInput.ts +1 -1
- package/src/dto/RecoverPasswordInput.ts +2 -2
- package/src/dto/RegisterInput.ts +2 -2
- package/src/dto/SendTokenPayload.ts +2 -2
- package/src/dto/StatusPayload.ts +1 -1
- package/src/dto/UpdateEmailInput.ts +1 -1
- package/src/dto/UpdatePasswordInput.ts +2 -2
- package/src/dto/UpdateProfileInput.ts +1 -1
- package/src/dto/index.ts +11 -11
- package/src/email-templates/base/content.pug +32 -0
- package/src/email-templates/base/header.pug +28 -0
- package/src/email-templates/base/layout.pug +34 -0
- package/src/email-templates/base/mixins.pug +16 -0
- package/src/email-templates/confirmEmail.pug +16 -0
- package/src/email-templates/forgotPassword.pug +16 -0
- package/src/email-templates/notification.pug +14 -0
- package/src/email-templates/tempPassword.pug +14 -0
- package/src/resolvers/AuthResolver.ts +94 -38
- package/src/resolvers/ProfileResolver.ts +125 -91
- package/src/services/ProfileEmailService.ts +147 -147
- package/src/types/index.ts +1 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
table(
|
|
2
|
+
width='600px'
|
|
3
|
+
bgcolor='#f4f8fc'
|
|
4
|
+
border='0'
|
|
5
|
+
cellspacing='0'
|
|
6
|
+
cellpadding='0'
|
|
7
|
+
style={
|
|
8
|
+
'margin': '15px',
|
|
9
|
+
'width': 'inherit',
|
|
10
|
+
'max-width': '600px',
|
|
11
|
+
'min-width': '600px',
|
|
12
|
+
'border-radius': '25px',
|
|
13
|
+
'-webkit-border-radius': '25px',
|
|
14
|
+
'-moz-border-radius': '25px'
|
|
15
|
+
}
|
|
16
|
+
)
|
|
17
|
+
tr
|
|
18
|
+
td(valign='top')
|
|
19
|
+
include header
|
|
20
|
+
|
|
21
|
+
tr
|
|
22
|
+
td(
|
|
23
|
+
align='left'
|
|
24
|
+
valign='top'
|
|
25
|
+
style={
|
|
26
|
+
'padding-left': '25px',
|
|
27
|
+
'padding-right': '25px',
|
|
28
|
+
'padding-bottom': '35px',
|
|
29
|
+
'overflow-wrap': 'break-word'
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
block content
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
table(
|
|
2
|
+
width='100%'
|
|
3
|
+
bgcolor='#ff0066'
|
|
4
|
+
border='0'
|
|
5
|
+
cellspacing='0'
|
|
6
|
+
cellpadding='0'
|
|
7
|
+
style={
|
|
8
|
+
'border-radius': '25px 25px 0 0',
|
|
9
|
+
'-webkit-border-radius': '25px 25px 0 0',
|
|
10
|
+
'-moz-border-radius': '25px 25px 0 0'
|
|
11
|
+
}
|
|
12
|
+
)
|
|
13
|
+
tr
|
|
14
|
+
td(
|
|
15
|
+
align='center'
|
|
16
|
+
height='60px'
|
|
17
|
+
style={
|
|
18
|
+
'line-height': '1',
|
|
19
|
+
}
|
|
20
|
+
)
|
|
21
|
+
a(href=websiteUrl)
|
|
22
|
+
img(
|
|
23
|
+
src=logoUrl
|
|
24
|
+
height='26px'
|
|
25
|
+
style={
|
|
26
|
+
'margin-top': '2px',
|
|
27
|
+
}
|
|
28
|
+
)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
doctype html
|
|
2
|
+
html
|
|
3
|
+
head
|
|
4
|
+
meta(http-equiv='Content-Type' content='text/html; charset=utf-8')
|
|
5
|
+
meta(name='viewport' content='width=device-width, initial-scale=1.0')
|
|
6
|
+
|
|
7
|
+
body(
|
|
8
|
+
style={
|
|
9
|
+
'margin': '0',
|
|
10
|
+
'padding': '0',
|
|
11
|
+
'width': '100% !important',
|
|
12
|
+
'height': '100% !important',
|
|
13
|
+
'max-width': '100%',
|
|
14
|
+
'font-family': '"Helvetica Neue", Helvetica, Arial, sans-serif',
|
|
15
|
+
'font-size': '16px',
|
|
16
|
+
'line-height': '1.5',
|
|
17
|
+
'color': '#222',
|
|
18
|
+
'border-collapse': 'collapse',
|
|
19
|
+
'-webkit-font-smoothing': 'antialiased',
|
|
20
|
+
'-webkit-text-size-adjust': 'none',
|
|
21
|
+
'-ms-text-size-adjust': '100%',
|
|
22
|
+
'border-spacing': '0'
|
|
23
|
+
}
|
|
24
|
+
)
|
|
25
|
+
table(
|
|
26
|
+
width='100%'
|
|
27
|
+
align='center'
|
|
28
|
+
border='0'
|
|
29
|
+
cellspacing='0'
|
|
30
|
+
cellpadding='0'
|
|
31
|
+
)
|
|
32
|
+
tr
|
|
33
|
+
td(align='center' valign='top')
|
|
34
|
+
include content
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
mixin header(title)
|
|
2
|
+
h1(style={
|
|
3
|
+
'font-size': '26px',
|
|
4
|
+
'font-weight': '500',
|
|
5
|
+
'margin-top': '20px',
|
|
6
|
+
'margin-bottom': '15px',
|
|
7
|
+
})= title
|
|
8
|
+
|
|
9
|
+
mixin link(href, title)
|
|
10
|
+
if href
|
|
11
|
+
a(
|
|
12
|
+
href=href
|
|
13
|
+
style={
|
|
14
|
+
'color': '#1890ff'
|
|
15
|
+
}
|
|
16
|
+
)= title
|
|
@@ -0,0 +1,16 @@
|
|
|
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
|
+
// br
|
|
12
|
+
// | #{mistakeText}
|
|
13
|
+
div(style='margin-top: 30px; background-color: white; border-radius: 25px; padding: 20px; text-align: center; font-size: 30px ')
|
|
14
|
+
strong #{confirmationToken}
|
|
15
|
+
div(style='margin-top: 30px; text-align: center; font-size: 25px ')
|
|
16
|
+
p #{header}
|
|
@@ -0,0 +1,16 @@
|
|
|
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
|
+
// br
|
|
12
|
+
// | #{mistakeText}
|
|
13
|
+
div(style='margin-top: 30px; background-color: white; border-radius: 25px; padding: 20px; text-align: center; font-size: 30px ')
|
|
14
|
+
strong #{confirmationToken}
|
|
15
|
+
div(style='margin-top: 30px; text-align: center; font-size: 25px ')
|
|
16
|
+
p #{header}
|
|
@@ -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,8 +1,7 @@
|
|
|
1
1
|
import { ProfileAuthService } from '../services/ProfileAuthService';
|
|
2
2
|
import { ProfileContext } from '../types';
|
|
3
|
-
import { RegisterInput, LoginInput, ConfirmEmailInput, ForgotPasswordInput, RecoverPasswordInput } from '../dto';
|
|
4
3
|
export interface AuthResolverDependencies<TContext extends ProfileContext = ProfileContext> {
|
|
5
|
-
authService: ProfileAuthService;
|
|
4
|
+
authService: ProfileAuthService | (() => ProfileAuthService);
|
|
6
5
|
userType: any;
|
|
7
6
|
onUserCreated?: (user: any, ctx: TContext) => Promise<void>;
|
|
8
7
|
onLogin?: (user: any, ctx: TContext) => Promise<void>;
|
|
@@ -13,26 +12,4 @@ export interface AuthResolverDependencies<TContext extends ProfileContext = Prof
|
|
|
13
12
|
sendError: (msg: string) => Promise<any>;
|
|
14
13
|
};
|
|
15
14
|
}
|
|
16
|
-
export declare function createAuthResolver<TContext extends ProfileContext = ProfileContext>(deps: AuthResolverDependencies<TContext>):
|
|
17
|
-
new (): {
|
|
18
|
-
register(input: RegisterInput, ctx: TContext): Promise<{
|
|
19
|
-
ok: boolean;
|
|
20
|
-
}>;
|
|
21
|
-
login(input: LoginInput, ctx: TContext): Promise<{
|
|
22
|
-
ok: boolean;
|
|
23
|
-
}>;
|
|
24
|
-
logout(ctx: TContext): Promise<{
|
|
25
|
-
ok: boolean;
|
|
26
|
-
}>;
|
|
27
|
-
confirmEmail(input: ConfirmEmailInput, ctx: TContext): Promise<{
|
|
28
|
-
ok: boolean;
|
|
29
|
-
}>;
|
|
30
|
-
forgotPassword(input: ForgotPasswordInput, ctx: TContext): Promise<{
|
|
31
|
-
confirmationLinkIsSent: boolean;
|
|
32
|
-
limitExpiresAt: number;
|
|
33
|
-
}>;
|
|
34
|
-
recoverPassword(input: RecoverPasswordInput, ctx: TContext): Promise<{
|
|
35
|
-
ok: boolean;
|
|
36
|
-
}>;
|
|
37
|
-
};
|
|
38
|
-
};
|
|
15
|
+
export declare function createAuthResolver<TContext extends ProfileContext = ProfileContext>(deps: AuthResolverDependencies<TContext>): any;
|
|
@@ -29,16 +29,22 @@ const graphql_validators_1 = require("@os-team/graphql-validators");
|
|
|
29
29
|
const ProfileAuthService_1 = require("../services/ProfileAuthService");
|
|
30
30
|
const dto_1 = require("../dto");
|
|
31
31
|
function createAuthResolver(deps) {
|
|
32
|
-
const { authService, onUserCreated, onLogin, onLogout, onEmailConfirmed, onPasswordRecovered, logTelegramBot, userType } = deps;
|
|
32
|
+
const { authService, onUserCreated, onLogin, onLogout, onEmailConfirmed, onPasswordRecovered, logTelegramBot, userType, } = deps;
|
|
33
|
+
const getAuthService = () => {
|
|
34
|
+
if (typeof authService === 'function')
|
|
35
|
+
return authService();
|
|
36
|
+
return authService;
|
|
37
|
+
};
|
|
33
38
|
let AuthResolver = class AuthResolver {
|
|
34
39
|
register(input, ctx) {
|
|
35
40
|
return __awaiter(this, void 0, void 0, function* () {
|
|
36
41
|
const { t } = ctx;
|
|
37
|
-
|
|
42
|
+
const service = getAuthService();
|
|
43
|
+
if (yield service.db.isEmailTaken(input.email)) {
|
|
38
44
|
throw new Error(t('validation:auth.emailExists'));
|
|
39
45
|
}
|
|
40
|
-
const passwordHash = yield
|
|
41
|
-
const user = yield
|
|
46
|
+
const passwordHash = yield service.hashPassword(input.password);
|
|
47
|
+
const user = yield service.db.createUser({
|
|
42
48
|
email: input.email,
|
|
43
49
|
passwordHash,
|
|
44
50
|
});
|
|
@@ -59,12 +65,13 @@ function createAuthResolver(deps) {
|
|
|
59
65
|
login(input, ctx) {
|
|
60
66
|
return __awaiter(this, void 0, void 0, function* () {
|
|
61
67
|
const { t } = ctx;
|
|
62
|
-
const
|
|
68
|
+
const service = getAuthService();
|
|
69
|
+
const user = yield service.db.findUserByEmail(input.email);
|
|
63
70
|
if (!user)
|
|
64
71
|
throw new Error(t('validation:user.notFound'));
|
|
65
72
|
if (user.isBanned)
|
|
66
73
|
throw new Error(t('validation:user.banned'));
|
|
67
|
-
const isPasswordOk = yield
|
|
74
|
+
const isPasswordOk = yield service.verifyPassword(user.password, input.password);
|
|
68
75
|
if (!isPasswordOk)
|
|
69
76
|
throw new Error(t('validation:login.wrongPassword'));
|
|
70
77
|
const userAgent = decodeURI(ctx.req.get('user-agent') || '');
|
|
@@ -95,12 +102,13 @@ function createAuthResolver(deps) {
|
|
|
95
102
|
}
|
|
96
103
|
confirmEmail(input, ctx) {
|
|
97
104
|
return __awaiter(this, void 0, void 0, function* () {
|
|
98
|
-
const
|
|
105
|
+
const service = getAuthService();
|
|
106
|
+
const user = yield service.getUserByToken(ProfileAuthService_1.CONFIRMATION_REDIS_PREFIX, input.token);
|
|
99
107
|
if (!user)
|
|
100
108
|
throw new Error(ctx.t('validation:error.wrongCode'));
|
|
101
109
|
user.isEmailConfirmed = true;
|
|
102
110
|
yield user.save();
|
|
103
|
-
yield
|
|
111
|
+
yield service.removeTokenFromRedis(ProfileAuthService_1.CONFIRMATION_REDIS_PREFIX, user, input.token);
|
|
104
112
|
const userAgent = decodeURI(ctx.req.get('user-agent') || '');
|
|
105
113
|
yield ctx.req.session.create({
|
|
106
114
|
userId: user.id,
|
|
@@ -118,28 +126,30 @@ function createAuthResolver(deps) {
|
|
|
118
126
|
forgotPassword(input, ctx) {
|
|
119
127
|
return __awaiter(this, void 0, void 0, function* () {
|
|
120
128
|
const { t } = ctx;
|
|
121
|
-
const
|
|
129
|
+
const service = getAuthService();
|
|
130
|
+
const user = yield service.db.findUserByEmail(input.email);
|
|
122
131
|
if (!user)
|
|
123
132
|
throw new Error(t('validation:forgot.errors.notRegistered'));
|
|
124
|
-
const res = yield
|
|
133
|
+
const res = yield service.sendLink(user, 'recovery');
|
|
125
134
|
if (logTelegramBot) {
|
|
126
135
|
yield logTelegramBot.sendError(`${user.email || user.urlSlug} запросил(а) восстановление пароля`);
|
|
127
136
|
}
|
|
128
137
|
return {
|
|
129
|
-
|
|
138
|
+
recoveryLinkIsSent: res.ok,
|
|
130
139
|
limitExpiresAt: res.limitExpiresAt,
|
|
131
140
|
};
|
|
132
141
|
});
|
|
133
142
|
}
|
|
134
143
|
recoverPassword(input, ctx) {
|
|
135
144
|
return __awaiter(this, void 0, void 0, function* () {
|
|
136
|
-
const
|
|
145
|
+
const service = getAuthService();
|
|
146
|
+
const user = yield service.getUserByToken(ProfileAuthService_1.RECOVERY_REDIS_PREFIX, input.token);
|
|
137
147
|
if (!user)
|
|
138
148
|
throw new Error(ctx.t('validation:error.wrongCode'));
|
|
139
|
-
user.password = yield
|
|
149
|
+
user.password = yield service.hashPassword(input.password);
|
|
140
150
|
user.isTempPassword = false;
|
|
141
151
|
yield user.save();
|
|
142
|
-
yield
|
|
152
|
+
yield service.removeTokenFromRedis(ProfileAuthService_1.RECOVERY_REDIS_PREFIX, user, input.token);
|
|
143
153
|
const userAgent = decodeURI(ctx.req.get('user-agent') || '');
|
|
144
154
|
yield ctx.req.session.create({
|
|
145
155
|
userId: user.id,
|
|
@@ -184,7 +194,10 @@ function createAuthResolver(deps) {
|
|
|
184
194
|
__metadata("design:returntype", Promise)
|
|
185
195
|
], AuthResolver.prototype, "logout", null);
|
|
186
196
|
__decorate([
|
|
187
|
-
(0, graphql_validators_1.ValidateArgs)(dto_1.confirmEmailValidators, {
|
|
197
|
+
(0, graphql_validators_1.ValidateArgs)(dto_1.confirmEmailValidators, {
|
|
198
|
+
arg: 'input',
|
|
199
|
+
tKey: 'confirmEmail',
|
|
200
|
+
}),
|
|
188
201
|
(0, type_graphql_1.Mutation)(() => graphql_utils_1.StatusPayload),
|
|
189
202
|
__param(0, (0, type_graphql_1.Arg)('input')),
|
|
190
203
|
__param(1, (0, type_graphql_1.Ctx)()),
|
|
@@ -1,24 +1,7 @@
|
|
|
1
1
|
import { ProfileAuthService } from '../services/ProfileAuthService';
|
|
2
2
|
import { ProfileContext } from '../types';
|
|
3
|
-
import { UpdateEmailInput, UpdatePasswordInput, UpdateProfileInput } from '../dto';
|
|
4
3
|
export interface ProfileResolverDependencies {
|
|
5
|
-
authService: ProfileAuthService;
|
|
4
|
+
authService: ProfileAuthService | (() => ProfileAuthService);
|
|
6
5
|
userType: any;
|
|
7
6
|
}
|
|
8
|
-
export declare function createProfileResolver<TContext extends ProfileContext = ProfileContext>(deps: ProfileResolverDependencies):
|
|
9
|
-
new (): {
|
|
10
|
-
updateEmail(input: UpdateEmailInput, ctx: TContext): Promise<{
|
|
11
|
-
ok: boolean;
|
|
12
|
-
}>;
|
|
13
|
-
updatePassword(input: UpdatePasswordInput, ctx: TContext): Promise<{
|
|
14
|
-
ok: boolean;
|
|
15
|
-
}>;
|
|
16
|
-
updateProfile(input: UpdateProfileInput, ctx: TContext): Promise<import("../types").AuthUser>;
|
|
17
|
-
toggleEmailNotification(ctx: TContext): Promise<{
|
|
18
|
-
ok: boolean;
|
|
19
|
-
}>;
|
|
20
|
-
toggleTelegramNotification(ctx: TContext): Promise<{
|
|
21
|
-
ok: boolean;
|
|
22
|
-
}>;
|
|
23
|
-
};
|
|
24
|
-
};
|
|
7
|
+
export declare function createProfileResolver<TContext extends ProfileContext = ProfileContext>(deps: ProfileResolverDependencies): any;
|
|
@@ -29,13 +29,19 @@ const graphql_validators_1 = require("@os-team/graphql-validators");
|
|
|
29
29
|
const dto_1 = require("../dto");
|
|
30
30
|
function createProfileResolver(deps) {
|
|
31
31
|
const { authService, userType } = deps;
|
|
32
|
+
const getAuthService = () => {
|
|
33
|
+
if (typeof authService === 'function')
|
|
34
|
+
return authService();
|
|
35
|
+
return authService;
|
|
36
|
+
};
|
|
32
37
|
let ProfileResolver = class ProfileResolver {
|
|
33
38
|
updateEmail(input, ctx) {
|
|
34
39
|
return __awaiter(this, void 0, void 0, function* () {
|
|
35
40
|
const { user, t } = ctx;
|
|
36
41
|
if (!user)
|
|
37
42
|
throw new type_graphql_1.UnauthorizedError();
|
|
38
|
-
|
|
43
|
+
const service = getAuthService();
|
|
44
|
+
if (yield service.db.isEmailTaken(input.email, user.id)) {
|
|
39
45
|
throw new Error(t('validation:updateEmail.emailExists'));
|
|
40
46
|
}
|
|
41
47
|
user.email = input.email;
|
|
@@ -49,10 +55,11 @@ function createProfileResolver(deps) {
|
|
|
49
55
|
const { user, t } = ctx;
|
|
50
56
|
if (!user)
|
|
51
57
|
throw new type_graphql_1.UnauthorizedError();
|
|
52
|
-
const
|
|
58
|
+
const service = getAuthService();
|
|
59
|
+
const isOldPasswordOk = yield service.verifyPassword(user.password, input.oldPassword);
|
|
53
60
|
if (!isOldPasswordOk)
|
|
54
61
|
throw new Error(t('validation:updatePassword.wrongPassword'));
|
|
55
|
-
user.password = yield
|
|
62
|
+
user.password = yield service.hashPassword(input.password);
|
|
56
63
|
user.isTempPassword = false;
|
|
57
64
|
yield user.save();
|
|
58
65
|
return { ok: true };
|
|
@@ -103,7 +110,10 @@ function createProfileResolver(deps) {
|
|
|
103
110
|
__decorate([
|
|
104
111
|
(0, type_graphql_1.Authorized)(),
|
|
105
112
|
(0, graphql_transformers_1.TransformArgs)(dto_1.updatePasswordTransformers, { arg: 'input' }),
|
|
106
|
-
(0, graphql_validators_1.ValidateArgs)(dto_1.updatePasswordValidators, {
|
|
113
|
+
(0, graphql_validators_1.ValidateArgs)(dto_1.updatePasswordValidators, {
|
|
114
|
+
arg: 'input',
|
|
115
|
+
tKey: 'updatePassword',
|
|
116
|
+
}),
|
|
107
117
|
(0, type_graphql_1.Mutation)(() => graphql_utils_1.StatusPayload),
|
|
108
118
|
__param(0, (0, type_graphql_1.Arg)('input')),
|
|
109
119
|
__param(1, (0, type_graphql_1.Ctx)()),
|
|
@@ -114,7 +124,10 @@ function createProfileResolver(deps) {
|
|
|
114
124
|
__decorate([
|
|
115
125
|
(0, type_graphql_1.Authorized)(),
|
|
116
126
|
(0, graphql_transformers_1.TransformArgs)(dto_1.updateProfileTransformers, { arg: 'input' }),
|
|
117
|
-
(0, graphql_validators_1.ValidateArgs)(dto_1.updateProfileValidators, {
|
|
127
|
+
(0, graphql_validators_1.ValidateArgs)(dto_1.updateProfileValidators, {
|
|
128
|
+
arg: 'input',
|
|
129
|
+
tKey: 'updateProfile',
|
|
130
|
+
}),
|
|
118
131
|
(0, type_graphql_1.Mutation)(() => userType),
|
|
119
132
|
__param(0, (0, type_graphql_1.Arg)('input')),
|
|
120
133
|
__param(1, (0, type_graphql_1.Ctx)()),
|
|
@@ -27,8 +27,8 @@ class ProfileEmailService {
|
|
|
27
27
|
return this.config.websiteUrl || `https://${this.config.domain}`;
|
|
28
28
|
}
|
|
29
29
|
render(templateName, vars) {
|
|
30
|
-
const templatePath = path_1.default.resolve(this.config.templateDir, `${templateName}.pug`);
|
|
31
|
-
return pug_1.default.renderFile(templatePath, Object.assign({ domain: this.config.domain, websiteUrl: this.getWebsiteUrl(), primaryBrandColor: this.config.primaryBrandColor, logoUrl: this.config.logoUrl || '' }, vars));
|
|
30
|
+
const templatePath = path_1.default.resolve(this.config.templateDir || path_1.default.resolve(__dirname, '../email-templates'), `${templateName}.pug`);
|
|
31
|
+
return pug_1.default.renderFile(templatePath, Object.assign({ domain: this.config.domain, websiteUrl: this.getWebsiteUrl(), primaryBrandColor: this.config.primaryBrandColor, logoUrl: this.config.logoUrl || '', link: vars.linkHref ? { href: vars.linkHref, label: vars.linkTitle } : undefined }, vars));
|
|
32
32
|
}
|
|
33
33
|
getFrom(type) {
|
|
34
34
|
const { domain } = this.config;
|
package/dist/types/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skroz/profile-api",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": "git@gitlab.com:skroz/libs/utils.git",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
],
|
|
13
13
|
"scripts": {
|
|
14
14
|
"clean": "rimraf dist",
|
|
15
|
-
"build": "yarn clean && tsc --outDir dist",
|
|
15
|
+
"build": "yarn clean && tsc --outDir dist && cp -R src/email-templates dist/email-templates",
|
|
16
16
|
"ncu": "ncu -u"
|
|
17
17
|
},
|
|
18
18
|
"publishConfig": {
|
|
@@ -41,5 +41,5 @@
|
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"reflect-metadata": "0.1.13"
|
|
43
43
|
},
|
|
44
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "0c03e4bb82b77e9309550c90871cec3971972e6b"
|
|
45
45
|
}
|
package/src/dto/LoginInput.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Field, InputType } from 'type-graphql';
|
|
2
2
|
import { isEmail, isNotEmpty } from '@os-team/graphql-validators';
|
|
3
3
|
import { toLowerCase, trim } from '@os-team/graphql-transformers';
|
|
4
|
-
import
|
|
4
|
+
import PasswordInput, { passwordTransformers } from './PasswordInput';
|
|
5
5
|
|
|
6
6
|
@InputType()
|
|
7
|
-
export class LoginInput extends PasswordInput {
|
|
7
|
+
export default class LoginInput extends PasswordInput {
|
|
8
8
|
@Field()
|
|
9
9
|
email!: string;
|
|
10
10
|
}
|
package/src/dto/PasswordInput.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Field, InputType } from 'type-graphql';
|
|
2
2
|
import { isNotEmpty } from '@os-team/graphql-validators';
|
|
3
3
|
import { trim } from '@os-team/graphql-transformers';
|
|
4
|
-
import
|
|
4
|
+
import PasswordInput, { passwordTransformers, passwordValidators } from './PasswordInput';
|
|
5
5
|
|
|
6
6
|
@InputType()
|
|
7
|
-
export class RecoverPasswordInput extends PasswordInput {
|
|
7
|
+
export default class RecoverPasswordInput extends PasswordInput {
|
|
8
8
|
@Field()
|
|
9
9
|
token!: string;
|
|
10
10
|
}
|
package/src/dto/RegisterInput.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Field, InputType } from 'type-graphql';
|
|
2
2
|
import { isEmail } from '@os-team/graphql-validators';
|
|
3
3
|
import { toLowerCase, trim } from '@os-team/graphql-transformers';
|
|
4
|
-
import
|
|
4
|
+
import PasswordInput, { passwordTransformers, passwordValidators } from './PasswordInput';
|
|
5
5
|
import isTrue from '../validators/isTrue';
|
|
6
6
|
|
|
7
7
|
@InputType()
|
|
8
|
-
export class RegisterInput extends PasswordInput {
|
|
8
|
+
export default class RegisterInput extends PasswordInput {
|
|
9
9
|
@Field()
|
|
10
10
|
email!: string;
|
|
11
11
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Field, ObjectType } from 'type-graphql';
|
|
2
2
|
|
|
3
3
|
@ObjectType()
|
|
4
|
-
export class SendTokenPayload {
|
|
4
|
+
export default class SendTokenPayload {
|
|
5
5
|
@Field()
|
|
6
|
-
|
|
6
|
+
recoveryLinkIsSent!: boolean;
|
|
7
7
|
|
|
8
8
|
@Field(() => Number, { nullable: true })
|
|
9
9
|
limitExpiresAt?: number;
|
package/src/dto/StatusPayload.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { Field, InputType } from 'type-graphql';
|
|
2
2
|
import { isNotEmpty } from '@os-team/graphql-validators';
|
|
3
3
|
import { trim } from '@os-team/graphql-transformers';
|
|
4
|
-
import
|
|
4
|
+
import PasswordInput, { passwordTransformers, passwordValidators } from './PasswordInput';
|
|
5
5
|
|
|
6
6
|
@InputType()
|
|
7
|
-
export class UpdatePasswordInput extends PasswordInput {
|
|
7
|
+
export default class UpdatePasswordInput extends PasswordInput {
|
|
8
8
|
@Field()
|
|
9
9
|
oldPassword!: string;
|
|
10
10
|
}
|
package/src/dto/index.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
7
|
-
export
|
|
8
|
-
export
|
|
9
|
-
export
|
|
10
|
-
export
|
|
11
|
-
export
|
|
1
|
+
export { default as PasswordInput, passwordTransformers, passwordValidators } from './PasswordInput';
|
|
2
|
+
export { default as RegisterInput, registerTransformers, registerValidators } from './RegisterInput';
|
|
3
|
+
export { default as LoginInput, loginTransformers, loginValidators } from './LoginInput';
|
|
4
|
+
export { default as ForgotPasswordInput, forgotPasswordTransformers, forgotPasswordValidators } from './ForgotPasswordInput';
|
|
5
|
+
export { default as ConfirmEmailInput, confirmEmailValidators } from './ConfirmEmailInput';
|
|
6
|
+
export { default as StatusPayload } from './StatusPayload';
|
|
7
|
+
export { default as SendTokenPayload } from './SendTokenPayload';
|
|
8
|
+
export { default as UpdatePasswordInput, updatePasswordTransformers, updatePasswordValidators } from './UpdatePasswordInput';
|
|
9
|
+
export { default as UpdateEmailInput, updateEmailTransformers, updateEmailValidators } from './UpdateEmailInput';
|
|
10
|
+
export { default as UpdateProfileInput, updateProfileTransformers, updateProfileValidators } from './UpdateProfileInput';
|
|
11
|
+
export { default as RecoverPasswordInput, recoverPasswordTransformers, recoverPasswordValidators } from './RecoverPasswordInput';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
table(
|
|
2
|
+
width='600px'
|
|
3
|
+
bgcolor='#f4f8fc'
|
|
4
|
+
border='0'
|
|
5
|
+
cellspacing='0'
|
|
6
|
+
cellpadding='0'
|
|
7
|
+
style={
|
|
8
|
+
'margin': '15px',
|
|
9
|
+
'width': 'inherit',
|
|
10
|
+
'max-width': '600px',
|
|
11
|
+
'min-width': '600px',
|
|
12
|
+
'border-radius': '25px',
|
|
13
|
+
'-webkit-border-radius': '25px',
|
|
14
|
+
'-moz-border-radius': '25px'
|
|
15
|
+
}
|
|
16
|
+
)
|
|
17
|
+
tr
|
|
18
|
+
td(valign='top')
|
|
19
|
+
include header
|
|
20
|
+
|
|
21
|
+
tr
|
|
22
|
+
td(
|
|
23
|
+
align='left'
|
|
24
|
+
valign='top'
|
|
25
|
+
style={
|
|
26
|
+
'padding-left': '25px',
|
|
27
|
+
'padding-right': '25px',
|
|
28
|
+
'padding-bottom': '35px',
|
|
29
|
+
'overflow-wrap': 'break-word'
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
block content
|