@mindful-web/marko-web-identity-x 1.0.0
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/.eslintignore +1 -0
- package/LICENSE +21 -0
- package/README.md +200 -0
- package/api/fragment-types.json +1 -0
- package/api/fragments/active-user.js +108 -0
- package/api/mutations/add-external-user-id.js +24 -0
- package/api/mutations/create-app-user.js +11 -0
- package/api/mutations/delete-app-user-for-current-application.js +7 -0
- package/api/mutations/impersonate-app-user.js +12 -0
- package/api/mutations/logout-app-user.js +11 -0
- package/api/mutations/send-change-email-link.js +7 -0
- package/api/mutations/send-login-link.js +7 -0
- package/api/mutations/set-custom-attributes.js +15 -0
- package/api/queries/check-content-access.js +19 -0
- package/api/queries/get-active-context.js +45 -0
- package/api/queries/load-user-by-external-id.js +14 -0
- package/api/queries/load-user-by-id.js +11 -0
- package/api/queries/load-user.js +11 -0
- package/browser/.eslintrc.js +11 -0
- package/browser/access.vue +377 -0
- package/browser/authenticate.vue +278 -0
- package/browser/change-email-confirm.vue +120 -0
- package/browser/change-email-init.vue +179 -0
- package/browser/comments/create.vue +107 -0
- package/browser/comments/post.vue +151 -0
- package/browser/comments/stream.vue +319 -0
- package/browser/custom-column.vue +314 -0
- package/browser/dayjs.js +6 -0
- package/browser/download-related.vue +120 -0
- package/browser/download.vue +380 -0
- package/browser/errors/authentication.js +7 -0
- package/browser/errors/feature.js +7 -0
- package/browser/errors/form.js +7 -0
- package/browser/errors/logout.js +7 -0
- package/browser/form/address-block.vue +131 -0
- package/browser/form/common/checkbox-group.vue +140 -0
- package/browser/form/common/form-group.vue +24 -0
- package/browser/form/common/form-label.vue +17 -0
- package/browser/form/consent.vue +121 -0
- package/browser/form/fields/address-extra.vue +68 -0
- package/browser/form/fields/city.vue +68 -0
- package/browser/form/fields/comment-body.vue +63 -0
- package/browser/form/fields/country.vue +94 -0
- package/browser/form/fields/custom-boolean.vue +58 -0
- package/browser/form/fields/custom-select-group.vue +25 -0
- package/browser/form/fields/custom-select-multiple.vue +97 -0
- package/browser/form/fields/custom-select-write-in-inline.vue +39 -0
- package/browser/form/fields/custom-select-write-in.vue +66 -0
- package/browser/form/fields/custom-select.vue +191 -0
- package/browser/form/fields/custom-text.vue +62 -0
- package/browser/form/fields/display-name.vue +64 -0
- package/browser/form/fields/email.vue +62 -0
- package/browser/form/fields/family-name.vue +68 -0
- package/browser/form/fields/given-name.vue +68 -0
- package/browser/form/fields/organization-title.vue +68 -0
- package/browser/form/fields/organization.vue +68 -0
- package/browser/form/fields/phone-number.vue +68 -0
- package/browser/form/fields/postal-code.vue +68 -0
- package/browser/form/fields/receive-email.vue +58 -0
- package/browser/form/fields/region.vue +106 -0
- package/browser/form/fields/regional-policy.vue +59 -0
- package/browser/form/fields/street.vue +68 -0
- package/browser/graphql/create-client.js +65 -0
- package/browser/graphql/parse.js +1 -0
- package/browser/graphql/queries/download-related-content.js +38 -0
- package/browser/index.js +110 -0
- package/browser/login-fields.vue +214 -0
- package/browser/login.vue +331 -0
- package/browser/logout.vue +68 -0
- package/browser/mixins/global-auto-signup-event-emitter.js +18 -0
- package/browser/mixins/global-event-emitter.js +28 -0
- package/browser/profile.vue +688 -0
- package/browser/service.js +32 -0
- package/browser/utils/clean-path.js +1 -0
- package/browser/utils/cookies-enabled.js +10 -0
- package/browser/utils/get-as-array.js +6 -0
- package/browser/utils/get-referring-page.js +7 -0
- package/browser/utils/get.js +8 -0
- package/browser/utils/post.js +10 -0
- package/browser/utils/redirect.js +7 -0
- package/browser/utils/region-country-codes.js +1 -0
- package/components/access.marko +24 -0
- package/components/access.marko.js +61 -0
- package/components/comment-stream.marko +31 -0
- package/components/comment-stream.marko.js +71 -0
- package/components/context.marko +15 -0
- package/components/context.marko.js +52 -0
- package/components/form-access.marko +60 -0
- package/components/form-access.marko.js +111 -0
- package/components/form-authenticate.marko +32 -0
- package/components/form-authenticate.marko.js +73 -0
- package/components/form-change-email.marko +27 -0
- package/components/form-change-email.marko.js +68 -0
- package/components/form-login.marko +32 -0
- package/components/form-login.marko.js +72 -0
- package/components/form-logout.marko +7 -0
- package/components/form-logout.marko.js +36 -0
- package/components/form-profile.marko +38 -0
- package/components/form-profile.marko.js +78 -0
- package/components/form-register.marko +2 -0
- package/components/form-register.marko.js +32 -0
- package/components/identify.marko +17 -0
- package/components/identify.marko.js +59 -0
- package/components/marko.json +90 -0
- package/components/non-auth-identify.marko +15 -0
- package/components/non-auth-identify.marko.js +53 -0
- package/config.js +161 -0
- package/hooks.js +20 -0
- package/index.js +30 -0
- package/marko.json +6 -0
- package/middleware/content-access-state.js +31 -0
- package/middleware/content-download-state.js +27 -0
- package/middleware.js +32 -0
- package/package.json +40 -0
- package/routes/access.js +29 -0
- package/routes/authenticate.js +58 -0
- package/routes/change-email-confirm.js +60 -0
- package/routes/change-email-init.js +16 -0
- package/routes/comment-count.js +19 -0
- package/routes/comments.js +43 -0
- package/routes/countries.js +19 -0
- package/routes/create-comment.js +25 -0
- package/routes/download.js +29 -0
- package/routes/flag-comment.js +21 -0
- package/routes/index.js +40 -0
- package/routes/login-fields.js +35 -0
- package/routes/login.js +95 -0
- package/routes/logout.js +19 -0
- package/routes/profile.js +183 -0
- package/routes/regions.js +22 -0
- package/service.js +483 -0
- package/utils/call-hooks-for.js +28 -0
- package/utils/context-cookie.js +30 -0
- package/utils/create-client.js +48 -0
- package/utils/create-identity-builder.js +33 -0
- package/utils/get-as-array.js +6 -0
- package/utils/json-error-handler.js +41 -0
- package/utils/token-cookie.js +30 -0
package/routes/index.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const { Router } = require('express');
|
|
2
|
+
const { json } = require('body-parser');
|
|
3
|
+
const jsonErrorHandler = require('../utils/json-error-handler');
|
|
4
|
+
const access = require('./access');
|
|
5
|
+
const authenticate = require('./authenticate');
|
|
6
|
+
const changeEmailConfirm = require('./change-email-confirm');
|
|
7
|
+
const changeEmailInit = require('./change-email-init');
|
|
8
|
+
const commentCount = require('./comment-count');
|
|
9
|
+
const comments = require('./comments');
|
|
10
|
+
const countries = require('./countries');
|
|
11
|
+
const createComment = require('./create-comment');
|
|
12
|
+
const download = require('./download');
|
|
13
|
+
const flagComment = require('./flag-comment');
|
|
14
|
+
const login = require('./login');
|
|
15
|
+
const loginFields = require('./login-fields');
|
|
16
|
+
const logout = require('./logout');
|
|
17
|
+
const profile = require('./profile');
|
|
18
|
+
const regions = require('./regions');
|
|
19
|
+
|
|
20
|
+
const router = Router();
|
|
21
|
+
|
|
22
|
+
router.use(json());
|
|
23
|
+
router.get('/comment-count/:identifier', commentCount);
|
|
24
|
+
router.get('/comments/:identifier', comments);
|
|
25
|
+
router.get('/countries', countries);
|
|
26
|
+
router.get('/regions', regions);
|
|
27
|
+
router.post('/access', access);
|
|
28
|
+
router.post('/authenticate', authenticate);
|
|
29
|
+
router.post('/change-email/confirm', changeEmailConfirm);
|
|
30
|
+
router.post('/change-email/initiate', changeEmailInit);
|
|
31
|
+
router.post('/comment', createComment);
|
|
32
|
+
router.post('/comment/flag/:id', flagComment);
|
|
33
|
+
router.post('/download', download);
|
|
34
|
+
router.post('/login-fields', loginFields);
|
|
35
|
+
router.post('/login', login);
|
|
36
|
+
router.post('/logout', logout);
|
|
37
|
+
router.post('/profile', profile);
|
|
38
|
+
router.use(jsonErrorHandler());
|
|
39
|
+
|
|
40
|
+
module.exports = router;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const gql = require('graphql-tag');
|
|
2
|
+
const { asyncRoute } = require('@mindful-web/utils');
|
|
3
|
+
|
|
4
|
+
const { isArray } = Array;
|
|
5
|
+
|
|
6
|
+
const mutation = gql`
|
|
7
|
+
mutation SetPreLoginFields($input: SetAppUserUnverifiedDataMutationInput!) {
|
|
8
|
+
setAppUserUnverifiedData(input: $input) {
|
|
9
|
+
id
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
`;
|
|
13
|
+
|
|
14
|
+
module.exports = asyncRoute(async (req, res) => {
|
|
15
|
+
/** @type {import('../middleware').IdentityXRequest} */
|
|
16
|
+
const { identityX, body } = req;
|
|
17
|
+
const {
|
|
18
|
+
email,
|
|
19
|
+
values,
|
|
20
|
+
} = body;
|
|
21
|
+
|
|
22
|
+
const regionalConsentAnswers = isArray(values.regionalConsentAnswers)
|
|
23
|
+
? values.regionalConsentAnswers
|
|
24
|
+
: [];
|
|
25
|
+
|
|
26
|
+
const input = {
|
|
27
|
+
...values,
|
|
28
|
+
regionalConsentAnswers: regionalConsentAnswers
|
|
29
|
+
.map((answer) => ({ policyId: answer.id, given: answer.given })),
|
|
30
|
+
email,
|
|
31
|
+
};
|
|
32
|
+
await identityX.client.mutate({ mutation, variables: { input } });
|
|
33
|
+
const entity = await identityX.generateEntityId();
|
|
34
|
+
return res.json({ ok: true, entity });
|
|
35
|
+
});
|
package/routes/login.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
const gql = require('graphql-tag');
|
|
2
|
+
const { asyncRoute } = require('@mindful-web/utils');
|
|
3
|
+
|
|
4
|
+
const mutation = gql`
|
|
5
|
+
mutation SetPreLoginFields($input: SetAppUserUnverifiedDataMutationInput!) {
|
|
6
|
+
setAppUserUnverifiedData(input: $input) {
|
|
7
|
+
id
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
`;
|
|
11
|
+
|
|
12
|
+
const forceProfileReVerificationUser = gql`
|
|
13
|
+
mutation ForceRevalidateAppUser($input: ForceProfileReVerificationAppUserMutationInput!) {
|
|
14
|
+
forceProfileReVerificationAppUser(input: $input) {
|
|
15
|
+
id
|
|
16
|
+
forceProfileReVerification
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
module.exports = asyncRoute(async (req, res) => {
|
|
22
|
+
/** @type {import('../middleware').IdentityXRequest} */
|
|
23
|
+
const { identityX, body } = req;
|
|
24
|
+
const {
|
|
25
|
+
authUrl,
|
|
26
|
+
email,
|
|
27
|
+
source,
|
|
28
|
+
redirectTo,
|
|
29
|
+
additionalEventData = {},
|
|
30
|
+
} = body;
|
|
31
|
+
let appUser = await identityX.loadAppUserByEmail(email);
|
|
32
|
+
|
|
33
|
+
// Check for required creation fields
|
|
34
|
+
const required = identityX.config.getRequiredCreateFields();
|
|
35
|
+
if (required.length) {
|
|
36
|
+
// If we don't have a user, or the user is missing some of the required fields
|
|
37
|
+
if (!appUser || (appUser && !required.every((key) => appUser[key]))) {
|
|
38
|
+
additionalEventData.createdNewUser = true;
|
|
39
|
+
// And they weren't presented in the login request, require them.
|
|
40
|
+
if (!required.every((key) => body[key])) {
|
|
41
|
+
return res.status(400).json({ ok: false, requiresUserInput: true });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!appUser || (appUser && !required.every((key) => appUser[key]))) {
|
|
47
|
+
// Create the user.
|
|
48
|
+
appUser = await identityX.createAppUser({ email });
|
|
49
|
+
additionalEventData.createdNewUser = true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (additionalEventData.forceProfileReVerification) {
|
|
53
|
+
const { id } = appUser;
|
|
54
|
+
await identityX.client.mutate({
|
|
55
|
+
mutation: forceProfileReVerificationUser,
|
|
56
|
+
variables: { input: { id } },
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Set the fields as unverified app data and continue login.
|
|
61
|
+
if (required.length && additionalEventData.createdNewUser) {
|
|
62
|
+
const regionalConsentAnswers = Array.isArray(body.regionalConsentAnswers)
|
|
63
|
+
? body.regionalConsentAnswers
|
|
64
|
+
: [];
|
|
65
|
+
const input = {
|
|
66
|
+
...(required.reduce((obj, key) => ({ ...obj, [key]: body[key] }), {})),
|
|
67
|
+
regionalConsentAnswers: regionalConsentAnswers
|
|
68
|
+
.map((answer) => ({ policyId: answer.id, given: answer.given })),
|
|
69
|
+
email,
|
|
70
|
+
};
|
|
71
|
+
await identityX.client.mutate({ mutation, variables: { input } });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Refresh the user for verification/new field state
|
|
75
|
+
if (additionalEventData.forceProfileReVerification || additionalEventData.createdNewUser) {
|
|
76
|
+
appUser = await identityX.loadAppUserByEmail(email);
|
|
77
|
+
}
|
|
78
|
+
const entity = await identityX.generateEntityId({ userId: appUser.id });
|
|
79
|
+
|
|
80
|
+
// Send login link.
|
|
81
|
+
await identityX.sendLoginLink({
|
|
82
|
+
appUser,
|
|
83
|
+
authUrl,
|
|
84
|
+
source,
|
|
85
|
+
redirectTo,
|
|
86
|
+
additionalEventData,
|
|
87
|
+
});
|
|
88
|
+
const returnedAppUser = { id: appUser.id, email: appUser.email };
|
|
89
|
+
return res.json({
|
|
90
|
+
ok: true,
|
|
91
|
+
additionalEventData,
|
|
92
|
+
appUser: returnedAppUser,
|
|
93
|
+
entity,
|
|
94
|
+
});
|
|
95
|
+
});
|
package/routes/logout.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const { asyncRoute } = require('@mindful-web/utils');
|
|
2
|
+
const contextCookie = require('../utils/context-cookie');
|
|
3
|
+
const tokenCookie = require('../utils/token-cookie');
|
|
4
|
+
const callHooksFor = require('../utils/call-hooks-for');
|
|
5
|
+
|
|
6
|
+
module.exports = asyncRoute(async (req, res) => {
|
|
7
|
+
/** @type {import('../middleware').IdentityXRequest} */
|
|
8
|
+
const { identityX } = req;
|
|
9
|
+
contextCookie.removeFrom(res);
|
|
10
|
+
const token = tokenCookie.getFrom(req);
|
|
11
|
+
if (!token) {
|
|
12
|
+
await callHooksFor(identityX, 'onLogout', { req, res });
|
|
13
|
+
} else {
|
|
14
|
+
await identityX.logoutAppUser({ token });
|
|
15
|
+
}
|
|
16
|
+
res.json({
|
|
17
|
+
ok: true,
|
|
18
|
+
});
|
|
19
|
+
});
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
const gql = require('graphql-tag');
|
|
2
|
+
const { asyncRoute } = require('@mindful-web/utils');
|
|
3
|
+
const { getAsArray, getAsObject } = require('@mindful-web/object-path');
|
|
4
|
+
const userFragment = require('../api/fragments/active-user');
|
|
5
|
+
const callHooksFor = require('../utils/call-hooks-for');
|
|
6
|
+
|
|
7
|
+
const mutation = gql`
|
|
8
|
+
mutation UpdateUserProfile($input: UpdateOwnAppUserMutationInput!) {
|
|
9
|
+
updateOwnAppUser(input: $input) {
|
|
10
|
+
...ActiveUserFragment
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
${userFragment}
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
const consentAnswers = gql`
|
|
18
|
+
mutation SetAppUserRegionalConsent($input: SetAppUserRegionalConsentMutationInput!) {
|
|
19
|
+
setAppUserRegionalConsent(input: $input) {
|
|
20
|
+
id
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
`;
|
|
24
|
+
|
|
25
|
+
const customBooleanFieldsMutation = gql`
|
|
26
|
+
mutation SetAppUserCustomBooleanFields($input: UpdateOwnAppUserCustomBooleanAnswersMutationInput!) {
|
|
27
|
+
updateOwnAppUserCustomBooleanAnswers(input: $input) {
|
|
28
|
+
id
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
`;
|
|
32
|
+
|
|
33
|
+
const customSelectFieldsMutation = gql`
|
|
34
|
+
mutation SetAppUserCustomSelectFields($input: UpdateOwnAppUserCustomSelectAnswersMutationInput!) {
|
|
35
|
+
updateOwnAppUserCustomSelectAnswers(input: $input) {
|
|
36
|
+
id
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
`;
|
|
40
|
+
|
|
41
|
+
const customTextFieldsMutation = gql`
|
|
42
|
+
mutation SetAppUserCustomTextFields($input: UpdateOwnAppUserCustomTextAnswersMutationInput!) {
|
|
43
|
+
updateOwnAppUserCustomTextAnswers(input: $input) {
|
|
44
|
+
id
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
`;
|
|
48
|
+
|
|
49
|
+
module.exports = asyncRoute(async (req, res) => {
|
|
50
|
+
/** @type {import('../middleware').IdentityXRequest} */
|
|
51
|
+
const { identityX, body } = req;
|
|
52
|
+
const {
|
|
53
|
+
givenName,
|
|
54
|
+
familyName,
|
|
55
|
+
organization,
|
|
56
|
+
organizationTitle,
|
|
57
|
+
countryCode,
|
|
58
|
+
regionCode,
|
|
59
|
+
postalCode,
|
|
60
|
+
city,
|
|
61
|
+
street,
|
|
62
|
+
addressExtra,
|
|
63
|
+
mobileNumber,
|
|
64
|
+
phoneNumber,
|
|
65
|
+
receiveEmail,
|
|
66
|
+
regionalConsentAnswers,
|
|
67
|
+
customBooleanFieldAnswers,
|
|
68
|
+
customSelectFieldAnswers,
|
|
69
|
+
customTextFieldAnswers,
|
|
70
|
+
additionalEventData = {},
|
|
71
|
+
} = body;
|
|
72
|
+
const input = {
|
|
73
|
+
givenName,
|
|
74
|
+
familyName,
|
|
75
|
+
organization,
|
|
76
|
+
organizationTitle,
|
|
77
|
+
countryCode,
|
|
78
|
+
regionCode,
|
|
79
|
+
postalCode,
|
|
80
|
+
city,
|
|
81
|
+
street,
|
|
82
|
+
addressExtra,
|
|
83
|
+
mobileNumber,
|
|
84
|
+
phoneNumber,
|
|
85
|
+
receiveEmail,
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// get identity-x.forms custom-select question ids to append to ActiveCustomQuestionIds
|
|
89
|
+
const customFormFieldIds = Object.values(getAsObject(identityX, 'config.options.forms')).reduce((questions, form) => {
|
|
90
|
+
// loop over the fieldRows
|
|
91
|
+
getAsArray(form, 'fieldRows').forEach((row) => row.forEach((question) => {
|
|
92
|
+
// push the custom-select form being used with those forms to acceptable profile inputs
|
|
93
|
+
// @todo figure out if other types should also make it... custom-boolean specifically.
|
|
94
|
+
if (question.type === 'custom-select') questions.push(question.id);
|
|
95
|
+
}));
|
|
96
|
+
return questions;
|
|
97
|
+
}, []);
|
|
98
|
+
|
|
99
|
+
const customFieldIds = [
|
|
100
|
+
...new Set([
|
|
101
|
+
...getAsArray(identityX, 'config.options.activeCustomFieldIds'),
|
|
102
|
+
...customFormFieldIds,
|
|
103
|
+
]),
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
const answers = regionalConsentAnswers
|
|
107
|
+
.map((answer) => ({ policyId: answer.id, given: answer.given }));
|
|
108
|
+
|
|
109
|
+
if (answers.length) {
|
|
110
|
+
await identityX.client.mutate({ mutation: consentAnswers, variables: { input: { answers } } });
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (customBooleanFieldAnswers.length) {
|
|
114
|
+
// only update custom questions when there some :)
|
|
115
|
+
const customBooleanFieldsInput = customBooleanFieldAnswers.map((fieldAnswer) => ({
|
|
116
|
+
fieldId: fieldAnswer.field.id,
|
|
117
|
+
// can either be true, false or null. convert null to false.
|
|
118
|
+
// the form submit is effectively answers the question.
|
|
119
|
+
value: Boolean(fieldAnswer.answer),
|
|
120
|
+
})).filter(
|
|
121
|
+
customFieldIds.length > 0
|
|
122
|
+
? ({ fieldId }) => customFieldIds.includes(fieldId)
|
|
123
|
+
: () => true,
|
|
124
|
+
);
|
|
125
|
+
await identityX.client.mutate({
|
|
126
|
+
mutation: customBooleanFieldsMutation,
|
|
127
|
+
variables: { input: { answers: customBooleanFieldsInput } },
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (customSelectFieldAnswers.length) {
|
|
132
|
+
// only update custom questions when there some :)
|
|
133
|
+
const customSelectFieldsInput = customSelectFieldAnswers.map((fieldAnswer) => ({
|
|
134
|
+
fieldId: fieldAnswer.field.id,
|
|
135
|
+
optionIds: fieldAnswer.answers.map(({ id }) => id),
|
|
136
|
+
writeInValues: fieldAnswer.answers.reduce((arr, { id, writeInValue }) => ([
|
|
137
|
+
...arr,
|
|
138
|
+
...(writeInValue ? [{ optionId: id, value: writeInValue }] : []),
|
|
139
|
+
]), []),
|
|
140
|
+
})).filter(
|
|
141
|
+
customFieldIds.length > 0
|
|
142
|
+
? ({ fieldId }) => customFieldIds.includes(fieldId)
|
|
143
|
+
: () => true,
|
|
144
|
+
);
|
|
145
|
+
await identityX.client.mutate({
|
|
146
|
+
mutation: customSelectFieldsMutation,
|
|
147
|
+
variables: { input: { answers: customSelectFieldsInput } },
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (customTextFieldAnswers.length) {
|
|
152
|
+
// only update custom questions when there some :)
|
|
153
|
+
const customTextFieldsInput = customTextFieldAnswers.map((fieldAnswer) => ({
|
|
154
|
+
fieldId: fieldAnswer.field.id,
|
|
155
|
+
// the form submit is effectively answers the question.
|
|
156
|
+
value: fieldAnswer.value,
|
|
157
|
+
})).filter(
|
|
158
|
+
customFieldIds.length > 0
|
|
159
|
+
? ({ fieldId }) => customFieldIds.includes(fieldId)
|
|
160
|
+
: () => true,
|
|
161
|
+
);
|
|
162
|
+
await identityX.client.mutate({
|
|
163
|
+
mutation: customTextFieldsMutation,
|
|
164
|
+
variables: { input: { answers: customTextFieldsInput } },
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const { data } = await identityX.client.mutate({ mutation, variables: { input } });
|
|
169
|
+
const { updateOwnAppUser: user } = data;
|
|
170
|
+
await callHooksFor(identityX, 'onUserProfileUpdate', {
|
|
171
|
+
additionalEventData,
|
|
172
|
+
...(additionalEventData || {}),
|
|
173
|
+
req,
|
|
174
|
+
user,
|
|
175
|
+
});
|
|
176
|
+
const entity = await identityX.generateEntityId({ userId: user.id });
|
|
177
|
+
res.json({
|
|
178
|
+
ok: true,
|
|
179
|
+
user,
|
|
180
|
+
additionalEventData,
|
|
181
|
+
entity,
|
|
182
|
+
});
|
|
183
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const gql = require('graphql-tag');
|
|
2
|
+
const { asyncRoute } = require('@mindful-web/utils');
|
|
3
|
+
|
|
4
|
+
const localeRegions = gql`
|
|
5
|
+
query localeRegions {
|
|
6
|
+
localeRegions {
|
|
7
|
+
id
|
|
8
|
+
code
|
|
9
|
+
name
|
|
10
|
+
country {
|
|
11
|
+
id
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
16
|
+
|
|
17
|
+
module.exports = asyncRoute(async (req, res) => {
|
|
18
|
+
/** @type {import('../middleware').IdentityXRequest} */
|
|
19
|
+
const { identityX } = req;
|
|
20
|
+
const { data } = await identityX.client.query({ query: localeRegions });
|
|
21
|
+
res.json(data.localeRegions);
|
|
22
|
+
});
|