@webresto/graphql 1.3.6 → 1.3.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/.gitattributes +2 -0
- package/.gitlab-ci.yml +18 -0
- package/.vscode/extensions.json +5 -0
- package/docs/actions.md +25 -0
- package/docs/authorization.md +215 -0
- package/docs/captcha.md +71 -0
- package/docs/device-id.md +30 -0
- package/docs/messages.md +10 -0
- package/docs/user.md +54 -0
- package/index.d.ts +0 -1
- package/index.js +6 -2
- package/index.ts +2 -2
- package/lib/afterHook.js +8 -0
- package/lib/afterHook.ts +9 -0
- package/lib/bindTranslations.d.ts +1 -0
- package/lib/bindTranslations.js +40 -0
- package/lib/bindTranslations.ts +39 -0
- package/lib/defaults.d.ts +1 -0
- package/lib/defaults.js +49 -10
- package/lib/defaults.ts +55 -0
- package/lib/eventHelper.d.ts +14 -5
- package/lib/eventHelper.js +28 -9
- package/lib/eventHelper.ts +41 -8
- package/lib/getRecomended.d.ts +1 -0
- package/lib/getRecomended.js +29 -0
- package/lib/getRecomended.ts +31 -0
- package/lib/graphqlHelper.d.ts +3 -4
- package/lib/graphqlHelper.js +184 -73
- package/lib/graphqlHelper.ts +329 -186
- package/lib/jwt.d.ts +10 -0
- package/lib/jwt.js +43 -0
- package/lib/jwt.ts +61 -0
- package/package.json +13 -6
- package/src/additionalResolvers.d.ts +72 -9
- package/src/additionalResolvers.js +93 -24
- package/src/additionalResolvers.ts +105 -34
- package/src/graphql.d.ts +5 -3
- package/src/graphql.js +170 -37
- package/src/graphql.ts +210 -60
- package/src/resolvers/bonusProgram.d.ts +32 -0
- package/src/resolvers/bonusProgram.js +65 -0
- package/src/resolvers/bonusProgram.ts +79 -0
- package/src/resolvers/captcha.d.ts +11 -0
- package/src/resolvers/captcha.js +19 -0
- package/src/resolvers/captcha.ts +16 -0
- package/src/resolvers/checkout.d.ts +43 -14
- package/src/resolvers/checkout.js +172 -122
- package/src/resolvers/checkout.ts +218 -142
- package/src/resolvers/dishAndModifier.js +8 -4
- package/src/resolvers/dishAndModifier.ts +4 -0
- package/src/resolvers/error.d.ts +9 -0
- package/src/resolvers/error.js +21 -0
- package/src/resolvers/error.ts +21 -0
- package/src/resolvers/menu.d.ts +9 -0
- package/src/resolvers/menu.js +12 -0
- package/src/resolvers/menu.ts +10 -0
- package/src/resolvers/order.d.ts +527 -0
- package/src/resolvers/order.js +349 -0
- package/src/resolvers/order.ts +435 -0
- package/src/resolvers/paymentMethod.js +7 -3
- package/src/resolvers/paymentMethod.ts +9 -5
- package/src/resolvers/pickupPoint.d.ts +1 -0
- package/src/resolvers/pickupPoint.js +24 -0
- package/src/resolvers/pickupPoint.ts +23 -0
- package/src/resolvers/recomended.d.ts +13 -0
- package/src/resolvers/recomended.js +80 -0
- package/src/resolvers/recomended.ts +86 -0
- package/src/resolvers/restrictions.d.ts +37 -1
- package/src/resolvers/restrictions.js +100 -15
- package/src/resolvers/restrictions.ts +106 -14
- package/src/resolvers/streets.d.ts +1 -1
- package/src/resolvers/streets.js +1 -4
- package/src/resolvers/streets.ts +1 -3
- package/src/resolvers/subscriptions.d.ts +4 -4
- package/src/resolvers/subscriptions.js +49 -12
- package/src/resolvers/subscriptions.ts +59 -14
- package/src/resolvers/telemetry.d.ts +14 -0
- package/src/resolvers/telemetry.js +25 -0
- package/src/resolvers/telemetry.ts +24 -0
- package/src/resolvers/user.d.ts +82 -0
- package/src/resolvers/user.js +416 -0
- package/src/resolvers/user.ts +621 -0
- package/src/resolvers/userLocation.d.ts +53 -0
- package/src/resolvers/userLocation.js +74 -0
- package/src/resolvers/userLocation.ts +125 -0
- package/src/resolvers/userOTPrequest.d.ts +21 -0
- package/src/resolvers/userOTPrequest.js +57 -0
- package/src/resolvers/userOTPrequest.ts +75 -0
- package/test/e2e_helper.js +157 -0
- package/test/e2e_helper.ts +212 -0
- package/test/fixture/config/i18n.js +7 -20
- package/test/fixture/config/locales/de.json +1 -0
- package/test/fixture/config/locales/en.json +10 -0
- package/test/fixture/config/locales/es.json +3 -0
- package/test/fixture/config/locales/fr.json +1 -0
- package/test/fixture/config/log.js +1 -1
- package/test/fixture/package.json +5 -6
- package/test/fixture/patches/rttc+10.0.1.patch +17 -0
- package/test/integration/captcha.test.js +20 -0
- package/test/integration/captcha.test.ts +25 -0
- package/test/integration/dish.test.js +35 -0
- package/test/integration/dish.test.ts +43 -0
- package/test/integration/graphql.test.js +5 -2
- package/test/integration/graphql.test.ts +2 -4
- package/test/integration/images.test.js +35 -0
- package/test/integration/images.test.ts +40 -0
- package/test/integration/locale.test.js +26 -0
- package/test/integration/locale.test.ts +32 -0
- package/test/integration/order.test.js +56 -43
- package/test/integration/order.test.ts +59 -59
- package/test/integration/subscriptions.test.js +136 -0
- package/test/integration/subscriptions.test.ts +162 -0
- package/test/integration/user.test.js +249 -0
- package/test/integration/user.test.ts +299 -0
- package/test/unit/first.test.js +4 -2
- package/test/unit/first.test.ts +1 -1
- package/test/unit/get-recomended.test.js +56 -0
- package/test/unit/get-recomended.test.ts +63 -0
- package/translations/de.json +2 -0
- package/translations/en.json +3 -0
- package/translations/es.json +3 -0
- package/translations/fr.json +2 -0
- package/translations/ru.json +36 -0
- package/tsconfig.json +20 -5
- package/types/global.d.ts +30 -0
- package/types/global.js +2 -0
- package/types/global.ts +31 -0
- package/types/primitives.d.ts +19 -0
- package/types/references.d.ts +1 -0
- package/types/restoGraphQLConfig.d.ts +13 -0
- package/lib/afterHook.ts___graphql-transport-ws +0 -138
- package/lib/afterHook.ts___graphql-ws +0 -133
- package/lib/errorWrapper.d.ts +0 -4
- package/lib/errorWrapper.js +0 -13
- package/lib/errorWrapper.ts +0 -12
- package/notes.md +0 -1976
- package/src/resolvers/cart.d.ts +0 -343
- package/src/resolvers/cart.js +0 -196
- package/src/resolvers/cart.ts +0 -277
- package/test/fixture/config/connections.js +0 -9
- package/test/integration/sails_not_crash.test.js +0 -3
- package/test/integration/sails_not_crash.test.ts +0 -3
|
@@ -0,0 +1,621 @@
|
|
|
1
|
+
// const userAuth = sails.config.restographql.authService;
|
|
2
|
+
import { JWTAuth } from "../../lib/jwt";
|
|
3
|
+
import { Phone } from "@webresto/core/models/User";
|
|
4
|
+
import User from "@webresto/core/models/User";
|
|
5
|
+
import { Captcha } from "@webresto/core/adapters";
|
|
6
|
+
import { ResolvedCaptcha } from "@webresto/core/adapters/captcha/CaptchaAdapter";
|
|
7
|
+
import { Message, Action, Response } from "../../types/primitives";
|
|
8
|
+
let captchaAdapter = Captcha.getAdapter();
|
|
9
|
+
|
|
10
|
+
import graphqlHelper from "../../lib/graphqlHelper";
|
|
11
|
+
|
|
12
|
+
// define UserResponse
|
|
13
|
+
interface UserResponse extends Response {
|
|
14
|
+
user: User | undefined;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
interface InputUser {
|
|
19
|
+
firstName: string
|
|
20
|
+
lastName: string
|
|
21
|
+
birthday: string
|
|
22
|
+
customData: {
|
|
23
|
+
[key: string]: string | boolean | number;
|
|
24
|
+
}
|
|
25
|
+
customFields: {
|
|
26
|
+
[key: string]: string | boolean | number;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
graphqlHelper.addType(`#graphql
|
|
31
|
+
type UserResponse {
|
|
32
|
+
user: User
|
|
33
|
+
message: Message
|
|
34
|
+
action: Action
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
input InputUser {
|
|
38
|
+
firstName: String
|
|
39
|
+
lastName: String
|
|
40
|
+
birthday: String
|
|
41
|
+
customData: Json
|
|
42
|
+
customFields: Json
|
|
43
|
+
}
|
|
44
|
+
`);
|
|
45
|
+
|
|
46
|
+
type RegistrationPayload = {
|
|
47
|
+
login: string;
|
|
48
|
+
phone: Phone;
|
|
49
|
+
password: string;
|
|
50
|
+
otp: string;
|
|
51
|
+
firstName: string;
|
|
52
|
+
lastName: string;
|
|
53
|
+
customFields: {
|
|
54
|
+
[key: string]: string | boolean | number;
|
|
55
|
+
};
|
|
56
|
+
captcha: ResolvedCaptcha;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export default {
|
|
60
|
+
Mutation: {
|
|
61
|
+
login: {
|
|
62
|
+
def: `#graphql
|
|
63
|
+
""" login method """
|
|
64
|
+
login(
|
|
65
|
+
login: String!,
|
|
66
|
+
|
|
67
|
+
"(required when login field is phone)"
|
|
68
|
+
phone: InputPhone,
|
|
69
|
+
|
|
70
|
+
"(only when passwordPolicy is required )"
|
|
71
|
+
password: String,
|
|
72
|
+
|
|
73
|
+
"(from otpRequest)"
|
|
74
|
+
otp: String,
|
|
75
|
+
|
|
76
|
+
"(solved captcha for label 'quickAccessByOTP:%login%')"
|
|
77
|
+
captcha: Captcha!
|
|
78
|
+
): UserResponse`,
|
|
79
|
+
fn: async (
|
|
80
|
+
parent: any,
|
|
81
|
+
payload: any,
|
|
82
|
+
context: any,
|
|
83
|
+
info: any
|
|
84
|
+
): Promise<UserResponse> => {
|
|
85
|
+
// TODO: this is copied from restrictions need make it from one place
|
|
86
|
+
if (
|
|
87
|
+
!(await captchaAdapter).check(
|
|
88
|
+
payload.captcha,
|
|
89
|
+
`login:${payload.login}`
|
|
90
|
+
)
|
|
91
|
+
)
|
|
92
|
+
throw `bad captcha`;
|
|
93
|
+
|
|
94
|
+
// Define password policy
|
|
95
|
+
let passwordPolicy = (await Settings.get("PASSWORD_POLICY")) as
|
|
96
|
+
| "required"
|
|
97
|
+
| "from_otp"
|
|
98
|
+
| "disabled";
|
|
99
|
+
if (!passwordPolicy) passwordPolicy = "from_otp";
|
|
100
|
+
|
|
101
|
+
let loginOTPRequired = await Settings.get("LOGIN_OTP_REQUIRED");
|
|
102
|
+
if (!loginOTPRequired) loginOTPRequired = false;
|
|
103
|
+
|
|
104
|
+
let loginField = await Settings.get("LOGIN_FIELD");
|
|
105
|
+
if (!loginField) loginField = "phone";
|
|
106
|
+
|
|
107
|
+
if (passwordPolicy === "required" && !payload.password) {
|
|
108
|
+
throw `password is required`;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (loginOTPRequired && !payload.otp) {
|
|
112
|
+
throw `OTP is required`;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// It shoul have or Password or OTP at one time
|
|
116
|
+
if (!payload.otp && !payload.password) {
|
|
117
|
+
throw `or Password or OTP required`;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (!context.connectionParams.deviceId) {
|
|
121
|
+
throw `Missed deviceId`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Check phone TODO: move in User
|
|
125
|
+
if (
|
|
126
|
+
(await Settings.get("LOGIN_FIELD")) === undefined ||
|
|
127
|
+
(await Settings.get("LOGIN_FIELD")) === "phone"
|
|
128
|
+
) {
|
|
129
|
+
if (!payload.phone) {
|
|
130
|
+
throw `Phone is required, when login field is phone`;
|
|
131
|
+
} else {
|
|
132
|
+
let genLogin = (
|
|
133
|
+
payload.phone.code +
|
|
134
|
+
payload.phone.number +
|
|
135
|
+
payload.phone.additionalNumber
|
|
136
|
+
).replace(/\D/g, "");
|
|
137
|
+
if (genLogin !== payload.login) {
|
|
138
|
+
throw `Login is: js (payload.phone.code+payload.phone.number+payload.phone.additionalNumber).replace(/\D/g, '')`;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
let userDevice = await User.login(
|
|
144
|
+
payload.login,
|
|
145
|
+
payload.phone,
|
|
146
|
+
context.connectionParams.deviceId,
|
|
147
|
+
"DEVICE NAME",
|
|
148
|
+
payload.password,
|
|
149
|
+
payload.otp,
|
|
150
|
+
context.connectionParams["user-agent"],
|
|
151
|
+
"IP_"
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
let authData = {
|
|
155
|
+
userId: userDevice.user as string,
|
|
156
|
+
deviceId: userDevice.id as string,
|
|
157
|
+
sessionId: userDevice.sessionId as string,
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const JWTtoken = await JWTAuth.sign(authData);
|
|
161
|
+
let message: Message = {
|
|
162
|
+
deviceId: context.connectionParams.deviceId,
|
|
163
|
+
title: context.i18n.__("Success"),
|
|
164
|
+
type: "info",
|
|
165
|
+
message: context.i18n.__("Authorization"),
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
let user = await User.findOne({ id: userDevice.user as string });
|
|
171
|
+
context.connectionParams.authorization = JWTtoken;
|
|
172
|
+
let action: Action = {
|
|
173
|
+
deviceId: context.connectionParams.deviceId,
|
|
174
|
+
type: "Authorization",
|
|
175
|
+
data: {
|
|
176
|
+
token: JWTtoken,
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
// Here should be Emmiter for midificate Action And Message
|
|
181
|
+
|
|
182
|
+
return {
|
|
183
|
+
user: user,
|
|
184
|
+
message: message,
|
|
185
|
+
action: action,
|
|
186
|
+
};
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
restorePassword: {
|
|
190
|
+
def: `#graphql
|
|
191
|
+
""" Password restore method """
|
|
192
|
+
restorePassword(
|
|
193
|
+
login: String!,
|
|
194
|
+
|
|
195
|
+
"(required when login field is phone)"
|
|
196
|
+
phone: InputPhone,
|
|
197
|
+
|
|
198
|
+
password: String!,
|
|
199
|
+
|
|
200
|
+
"(from otpRequest)"
|
|
201
|
+
otp: String!,
|
|
202
|
+
|
|
203
|
+
"(solved captcha for label 'quickAccessByOTP:%login%')"
|
|
204
|
+
captcha: Captcha!
|
|
205
|
+
): UserResponse`,
|
|
206
|
+
|
|
207
|
+
fn: async (
|
|
208
|
+
parent: any,
|
|
209
|
+
payload: any,
|
|
210
|
+
context: any
|
|
211
|
+
): Promise<UserResponse> => {
|
|
212
|
+
|
|
213
|
+
if (!context.connectionParams.deviceId) {
|
|
214
|
+
throw `Missed deviceId`
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Check password policy
|
|
218
|
+
let passwordPolicy = (await Settings.get("PASSWORD_POLICY")) as
|
|
219
|
+
| "required"
|
|
220
|
+
| "from_otp"
|
|
221
|
+
| "disabled";
|
|
222
|
+
if (!passwordPolicy) passwordPolicy = "from_otp";
|
|
223
|
+
|
|
224
|
+
// It shoul have or Password or OTP at one time
|
|
225
|
+
if (!payload.otp || !payload.password) {
|
|
226
|
+
throw `Password and OTP required`;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
let userDevice;
|
|
230
|
+
let user = await User.findOne({ login: payload.login });
|
|
231
|
+
if (user && user.verified) {
|
|
232
|
+
userDevice = await User.login(
|
|
233
|
+
payload.login,
|
|
234
|
+
payload.phone,
|
|
235
|
+
context.connectionParams.deviceId,
|
|
236
|
+
"DEVICE NAME",
|
|
237
|
+
null,
|
|
238
|
+
payload.otp,
|
|
239
|
+
context.connectionParams["user-agent"],
|
|
240
|
+
"0.0.0.0"
|
|
241
|
+
);
|
|
242
|
+
await User.setPassword(user.id, payload.password, null, true, null);
|
|
243
|
+
} else {
|
|
244
|
+
return {
|
|
245
|
+
user: null,
|
|
246
|
+
message: {
|
|
247
|
+
deviceId: context.connectionParams.deviceId,
|
|
248
|
+
title: context.i18n.__("User not found"),
|
|
249
|
+
type: "error",
|
|
250
|
+
message: context.i18n.__("Check login please"),
|
|
251
|
+
},
|
|
252
|
+
action: null,
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
let authData = {
|
|
257
|
+
userId: userDevice.user as string,
|
|
258
|
+
deviceId: userDevice.id as string,
|
|
259
|
+
sessionId: userDevice.sessionId as string,
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
const JWTtoken = await JWTAuth.sign(authData);
|
|
263
|
+
|
|
264
|
+
let message: Message = {
|
|
265
|
+
deviceId: context.connectionParams.deviceId,
|
|
266
|
+
title: context.i18n.__("Success"),
|
|
267
|
+
type: "info",
|
|
268
|
+
message: context.i18n.__("Password was cahanged"),
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
let action: Action = {
|
|
272
|
+
deviceId: context.connectionParams.deviceId,
|
|
273
|
+
type: "Authorization",
|
|
274
|
+
data: {
|
|
275
|
+
token: JWTtoken,
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
// Here should be Emmiter for midificate Action And Message
|
|
280
|
+
|
|
281
|
+
return {
|
|
282
|
+
user: user,
|
|
283
|
+
message: message,
|
|
284
|
+
action: action,
|
|
285
|
+
};
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
|
|
289
|
+
registration: {
|
|
290
|
+
def: `#graphql
|
|
291
|
+
registration(
|
|
292
|
+
|
|
293
|
+
"loginField from UserRestrictions, When (UserRestrictions.loginField=phone) you must send concatenate [otp+number] (only digits)"
|
|
294
|
+
login: String!,
|
|
295
|
+
|
|
296
|
+
"required when loginField=phone, it will checks with login field"
|
|
297
|
+
phone: InputPhone
|
|
298
|
+
|
|
299
|
+
password: String,
|
|
300
|
+
|
|
301
|
+
"otp from otpRequest"
|
|
302
|
+
otp: String!
|
|
303
|
+
|
|
304
|
+
firstName: String,
|
|
305
|
+
lastName: String,
|
|
306
|
+
|
|
307
|
+
"Is object {} with all required fields from UserRestrictions.customFields. Is required if custom required fields was defined"
|
|
308
|
+
customFields: Json,
|
|
309
|
+
|
|
310
|
+
"Solved captcha for label 'registration:%login%'"
|
|
311
|
+
captcha: Captcha!
|
|
312
|
+
): UserResponse`,
|
|
313
|
+
|
|
314
|
+
fn: async (
|
|
315
|
+
parent: any,
|
|
316
|
+
payload: RegistrationPayload,
|
|
317
|
+
context: any,
|
|
318
|
+
info: any
|
|
319
|
+
): Promise<UserResponse> => {
|
|
320
|
+
if (!context.connectionParams.deviceId) {
|
|
321
|
+
throw `Missed deviceId`
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
try {
|
|
325
|
+
if (
|
|
326
|
+
!(await captchaAdapter).check(
|
|
327
|
+
payload.captcha,
|
|
328
|
+
`registration:${payload.login}`
|
|
329
|
+
)
|
|
330
|
+
)
|
|
331
|
+
throw `bad captcha`;
|
|
332
|
+
|
|
333
|
+
if (!payload.password && !payload.otp) {
|
|
334
|
+
throw `(password || otp) is required`;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Define password policy
|
|
338
|
+
let passwordPolicy = (await Settings.get("PASSWORD_POLICY")) as
|
|
339
|
+
| "required"
|
|
340
|
+
| "from_otp"
|
|
341
|
+
| "disabled";
|
|
342
|
+
if (!passwordPolicy) passwordPolicy = "from_otp";
|
|
343
|
+
|
|
344
|
+
if (
|
|
345
|
+
(await Settings.get("FIRSTNAME_REQUIRED")) &&
|
|
346
|
+
!payload.firstName
|
|
347
|
+
) {
|
|
348
|
+
throw `firstName is required`;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
if (passwordPolicy === "required" && !payload.password) {
|
|
352
|
+
throw `password is required`;
|
|
353
|
+
} else if (
|
|
354
|
+
passwordPolicy === "disabled" &&
|
|
355
|
+
payload.password
|
|
356
|
+
) {
|
|
357
|
+
throw `Found password but passwordPolicy is: disabled`;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (
|
|
361
|
+
(await Settings.get("LOGIN_FIELD")) === undefined ||
|
|
362
|
+
(await Settings.get("LOGIN_FIELD")) === "phone"
|
|
363
|
+
) {
|
|
364
|
+
if (!payload.phone) {
|
|
365
|
+
throw `Phone is required, when login field is phone`;
|
|
366
|
+
} else {
|
|
367
|
+
let genLogin = (
|
|
368
|
+
payload.phone.code +
|
|
369
|
+
payload.phone.number +
|
|
370
|
+
payload.phone.additionalNumber
|
|
371
|
+
).replace(/\D/g, "");
|
|
372
|
+
if (genLogin !== payload.login) {
|
|
373
|
+
throw `Login is: js (payload.phone.code+payload.phone.number+payload.phone.additionalNumber).replace(/\D/g, '')`;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (
|
|
379
|
+
payload.otp &&
|
|
380
|
+
!(await OneTimePassword.check(payload.login, payload.otp))
|
|
381
|
+
) {
|
|
382
|
+
throw "OTP check failed";
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
let newUser = await User.create({
|
|
386
|
+
phone: payload.phone,
|
|
387
|
+
login: payload.login,
|
|
388
|
+
firstName: payload.firstName,
|
|
389
|
+
}).fetch();
|
|
390
|
+
|
|
391
|
+
if (passwordPolicy === "required") {
|
|
392
|
+
newUser = await User.setPassword(
|
|
393
|
+
newUser.id,
|
|
394
|
+
payload.password,
|
|
395
|
+
null,
|
|
396
|
+
true
|
|
397
|
+
);
|
|
398
|
+
} else if (passwordPolicy === "from_otp") {
|
|
399
|
+
newUser = await User.setPassword(
|
|
400
|
+
newUser.id,
|
|
401
|
+
payload.otp,
|
|
402
|
+
null,
|
|
403
|
+
true
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
let message: Message = {
|
|
408
|
+
deviceId: context.connectionParams.deviceId,
|
|
409
|
+
title: context.i18n.__("Success"),
|
|
410
|
+
type: "info",
|
|
411
|
+
message: context.i18n.__("New user created"),
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
// let action: Action = {
|
|
415
|
+
// type: "GoTo",
|
|
416
|
+
// data: {
|
|
417
|
+
// "section": "login",
|
|
418
|
+
// "delaySeconds": 5
|
|
419
|
+
// }
|
|
420
|
+
// }
|
|
421
|
+
|
|
422
|
+
return {
|
|
423
|
+
user: newUser,
|
|
424
|
+
message: message,
|
|
425
|
+
action: null,
|
|
426
|
+
};
|
|
427
|
+
} catch (error) {
|
|
428
|
+
sails.log.error(error);
|
|
429
|
+
throw new Error(error);
|
|
430
|
+
}
|
|
431
|
+
},
|
|
432
|
+
},
|
|
433
|
+
|
|
434
|
+
// Authentication required
|
|
435
|
+
logout: {
|
|
436
|
+
def: `#graphql
|
|
437
|
+
logout(
|
|
438
|
+
"Optional field if not pass logout from current device",
|
|
439
|
+
deviceId: String
|
|
440
|
+
): Response`,
|
|
441
|
+
fn: async (
|
|
442
|
+
parent: any,
|
|
443
|
+
payload: { deviceId: any },
|
|
444
|
+
context: { connectionParams: { authorization: string }, i18n: any }
|
|
445
|
+
): Promise<Response> => {
|
|
446
|
+
|
|
447
|
+
const auth = await JWTAuth.verify(
|
|
448
|
+
context.connectionParams.authorization
|
|
449
|
+
);
|
|
450
|
+
let deviceId: string;
|
|
451
|
+
if (!payload.deviceId) {
|
|
452
|
+
deviceId = auth.deviceId;
|
|
453
|
+
} else {
|
|
454
|
+
let ud = await UserDevice.findOne({ name: payload.deviceId });
|
|
455
|
+
deviceId = ud.id;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
if (
|
|
459
|
+
!(await UserDevice.checkSession(auth.sessionId, auth.userId, {
|
|
460
|
+
lastIP: "IP",
|
|
461
|
+
userAgent: context.connectionParams["user-agent"],
|
|
462
|
+
}))
|
|
463
|
+
) {
|
|
464
|
+
throw `Authentication failed`;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
await UserDevice.update({ id: deviceId }, { isLogined: false });
|
|
468
|
+
|
|
469
|
+
let message: Message = {
|
|
470
|
+
deviceId: deviceId,
|
|
471
|
+
title: context.i18n.__("Success"),
|
|
472
|
+
type: "info",
|
|
473
|
+
message: context.i18n.__("Logout"),
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
let action: Action = undefined;
|
|
477
|
+
|
|
478
|
+
// Here should be Emmiter for midificate Action And Message
|
|
479
|
+
|
|
480
|
+
return {
|
|
481
|
+
message: message,
|
|
482
|
+
action: action,
|
|
483
|
+
};
|
|
484
|
+
},
|
|
485
|
+
},
|
|
486
|
+
|
|
487
|
+
logoutFromAllDevices: {
|
|
488
|
+
def: `logoutFromAllDevices: Response`,
|
|
489
|
+
fn: async (
|
|
490
|
+
parent: any,
|
|
491
|
+
payload: any,
|
|
492
|
+
context: any
|
|
493
|
+
): Promise<Response> => {
|
|
494
|
+
const auth = await JWTAuth.verify(
|
|
495
|
+
context.connectionParams.authorization
|
|
496
|
+
);
|
|
497
|
+
|
|
498
|
+
if (
|
|
499
|
+
!(await UserDevice.checkSession(auth.sessionId, auth.userId, {
|
|
500
|
+
lastIP: "IP",
|
|
501
|
+
userAgent: context.connectionParams["user-agent"],
|
|
502
|
+
}))
|
|
503
|
+
) {
|
|
504
|
+
throw `Authentication failed`;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
UserDevice.update({ user: auth.userId }, { isLogined: false });
|
|
508
|
+
|
|
509
|
+
let message: Message = {
|
|
510
|
+
deviceId: null,
|
|
511
|
+
title: context.i18n.__("Success"),
|
|
512
|
+
type: "info",
|
|
513
|
+
message: context.i18n.__("Logout from all devices"),
|
|
514
|
+
};
|
|
515
|
+
|
|
516
|
+
let action: Action = undefined;
|
|
517
|
+
|
|
518
|
+
// Here should be Emmiter for midificate Action And Message
|
|
519
|
+
|
|
520
|
+
return {
|
|
521
|
+
message: message,
|
|
522
|
+
action: action,
|
|
523
|
+
};
|
|
524
|
+
},
|
|
525
|
+
},
|
|
526
|
+
|
|
527
|
+
// Authentication required
|
|
528
|
+
favoriteDish: {
|
|
529
|
+
def: `#graphql
|
|
530
|
+
favoriteDish(
|
|
531
|
+
dishId: String!
|
|
532
|
+
): Boolean`,
|
|
533
|
+
fn: async (
|
|
534
|
+
parent: any,
|
|
535
|
+
payload: { dishId: string },
|
|
536
|
+
context: { connectionParams: { authorization: string } }
|
|
537
|
+
): Promise<boolean> => {
|
|
538
|
+
|
|
539
|
+
const auth = await JWTAuth.verify(
|
|
540
|
+
context.connectionParams.authorization
|
|
541
|
+
);
|
|
542
|
+
|
|
543
|
+
await User.handleFavoriteDish(auth.userId, payload.dishId)
|
|
544
|
+
return true
|
|
545
|
+
},
|
|
546
|
+
},
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
// Authentication required
|
|
551
|
+
userUpdate: {
|
|
552
|
+
def: `#graphql
|
|
553
|
+
userUpdate(
|
|
554
|
+
user: InputUser!
|
|
555
|
+
): UserResponse`,
|
|
556
|
+
fn: async (
|
|
557
|
+
parent: any,
|
|
558
|
+
payload: { user: InputUser },
|
|
559
|
+
context: any
|
|
560
|
+
): Promise<UserResponse> => {
|
|
561
|
+
const auth = await JWTAuth.verify(
|
|
562
|
+
context.connectionParams.authorization
|
|
563
|
+
);
|
|
564
|
+
|
|
565
|
+
let user = await User.updateOne({id: auth.userId}, payload.user)
|
|
566
|
+
|
|
567
|
+
let message: Message = {
|
|
568
|
+
deviceId: null,
|
|
569
|
+
title: context.i18n.__("Success"),
|
|
570
|
+
type: "info",
|
|
571
|
+
message: context.i18n.__("User was updated"),
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
// Here should be Emmiter for midificate Action And Message
|
|
575
|
+
|
|
576
|
+
return {
|
|
577
|
+
user: user,
|
|
578
|
+
message: message,
|
|
579
|
+
action: null,
|
|
580
|
+
};
|
|
581
|
+
},
|
|
582
|
+
},
|
|
583
|
+
userDelete: {
|
|
584
|
+
def: `#graphql
|
|
585
|
+
"""User delete method """
|
|
586
|
+
userDelete(
|
|
587
|
+
|
|
588
|
+
"(from otpRequest userDelete:%login%)"
|
|
589
|
+
otp: String!,
|
|
590
|
+
): Response`,
|
|
591
|
+
fn: async (
|
|
592
|
+
parent: any,
|
|
593
|
+
payload: any,
|
|
594
|
+
context: any,
|
|
595
|
+
info: any
|
|
596
|
+
): Promise<Response> => {
|
|
597
|
+
|
|
598
|
+
const auth = await JWTAuth.verify(
|
|
599
|
+
context.connectionParams.authorization
|
|
600
|
+
);
|
|
601
|
+
|
|
602
|
+
await User.delete(auth.userId, payload.otp);
|
|
603
|
+
|
|
604
|
+
let message: Message = {
|
|
605
|
+
deviceId: null,
|
|
606
|
+
title: context.i18n.__("Success"),
|
|
607
|
+
type: "info",
|
|
608
|
+
message: context.i18n.__("The user will be deleted"),
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
let action: Action = null
|
|
612
|
+
// Here should be Emmiter for midificate Action And Message
|
|
613
|
+
|
|
614
|
+
return {
|
|
615
|
+
message: message,
|
|
616
|
+
action: action,
|
|
617
|
+
};
|
|
618
|
+
},
|
|
619
|
+
},
|
|
620
|
+
},
|
|
621
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
interface InputLocation {
|
|
2
|
+
street: string;
|
|
3
|
+
streetId: string;
|
|
4
|
+
home: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
city?: string;
|
|
7
|
+
housing?: string;
|
|
8
|
+
isDefault?: boolean;
|
|
9
|
+
index?: string;
|
|
10
|
+
entrance?: string;
|
|
11
|
+
floor?: string;
|
|
12
|
+
apartment?: string;
|
|
13
|
+
doorphone?: string;
|
|
14
|
+
comment?: string;
|
|
15
|
+
customData?: {
|
|
16
|
+
[key: string]: string | boolean | number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
declare const _default: {
|
|
20
|
+
Mutation: {
|
|
21
|
+
locationCreate: {
|
|
22
|
+
def: string;
|
|
23
|
+
fn: (parent: any, payload: {
|
|
24
|
+
location: InputLocation;
|
|
25
|
+
}, context: {
|
|
26
|
+
connectionParams: {
|
|
27
|
+
authorization: string;
|
|
28
|
+
};
|
|
29
|
+
}) => Promise<boolean>;
|
|
30
|
+
};
|
|
31
|
+
locationSetIsDefault: {
|
|
32
|
+
def: string;
|
|
33
|
+
fn: (parent: any, payload: {
|
|
34
|
+
locationId: string;
|
|
35
|
+
}, context: {
|
|
36
|
+
connectionParams: {
|
|
37
|
+
authorization: string;
|
|
38
|
+
};
|
|
39
|
+
}) => Promise<boolean>;
|
|
40
|
+
};
|
|
41
|
+
locationDelete: {
|
|
42
|
+
def: string;
|
|
43
|
+
fn: (parent: any, payload: {
|
|
44
|
+
locationId: string;
|
|
45
|
+
}, context: {
|
|
46
|
+
connectionParams: {
|
|
47
|
+
authorization: string;
|
|
48
|
+
};
|
|
49
|
+
}) => Promise<boolean>;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
export default _default;
|