parse-server 2.8.4 → 8.6.2
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/LICENSE +167 -25
- package/NOTICE +10 -0
- package/README.md +929 -278
- package/lib/AccountLockout.js +47 -30
- package/lib/Adapters/AdapterLoader.js +21 -6
- package/lib/Adapters/Analytics/AnalyticsAdapter.js +15 -12
- package/lib/Adapters/Auth/AuthAdapter.js +116 -13
- package/lib/Adapters/Auth/BaseCodeAuthAdapter.js +99 -0
- package/lib/Adapters/Auth/OAuth1Client.js +27 -46
- package/lib/Adapters/Auth/apple.js +123 -0
- package/lib/Adapters/Auth/facebook.js +162 -35
- package/lib/Adapters/Auth/gcenter.js +217 -0
- package/lib/Adapters/Auth/github.js +118 -48
- package/lib/Adapters/Auth/google.js +160 -51
- package/lib/Adapters/Auth/gpgames.js +125 -0
- package/lib/Adapters/Auth/httpsRequest.js +6 -7
- package/lib/Adapters/Auth/index.js +170 -62
- package/lib/Adapters/Auth/instagram.js +114 -40
- package/lib/Adapters/Auth/janraincapture.js +52 -23
- package/lib/Adapters/Auth/janrainengage.js +19 -36
- package/lib/Adapters/Auth/keycloak.js +148 -0
- package/lib/Adapters/Auth/ldap.js +167 -0
- package/lib/Adapters/Auth/line.js +125 -0
- package/lib/Adapters/Auth/linkedin.js +111 -55
- package/lib/Adapters/Auth/meetup.js +24 -34
- package/lib/Adapters/Auth/mfa.js +324 -0
- package/lib/Adapters/Auth/microsoft.js +111 -0
- package/lib/Adapters/Auth/oauth2.js +97 -162
- package/lib/Adapters/Auth/phantauth.js +53 -0
- package/lib/Adapters/Auth/qq.js +108 -49
- package/lib/Adapters/Auth/spotify.js +107 -55
- package/lib/Adapters/Auth/twitter.js +188 -48
- package/lib/Adapters/Auth/utils.js +28 -0
- package/lib/Adapters/Auth/vkontakte.js +26 -39
- package/lib/Adapters/Auth/wechat.js +106 -44
- package/lib/Adapters/Auth/weibo.js +132 -58
- package/lib/Adapters/Cache/CacheAdapter.js +13 -8
- package/lib/Adapters/Cache/InMemoryCache.js +3 -13
- package/lib/Adapters/Cache/InMemoryCacheAdapter.js +5 -13
- package/lib/Adapters/Cache/LRUCache.js +13 -27
- package/lib/Adapters/Cache/NullCacheAdapter.js +3 -8
- package/lib/Adapters/Cache/RedisCacheAdapter.js +85 -76
- package/lib/Adapters/Cache/SchemaCache.js +25 -0
- package/lib/Adapters/Email/MailAdapter.js +10 -8
- package/lib/Adapters/Files/FilesAdapter.js +83 -25
- package/lib/Adapters/Files/GridFSBucketAdapter.js +231 -0
- package/lib/Adapters/Files/GridStoreAdapter.js +4 -91
- package/lib/Adapters/Logger/LoggerAdapter.js +18 -14
- package/lib/Adapters/Logger/WinstonLogger.js +69 -88
- package/lib/Adapters/Logger/WinstonLoggerAdapter.js +7 -16
- package/lib/Adapters/MessageQueue/EventEmitterMQ.js +8 -26
- package/lib/Adapters/PubSub/EventEmitterPubSub.js +12 -25
- package/lib/Adapters/PubSub/PubSubAdapter.js +34 -0
- package/lib/Adapters/PubSub/RedisPubSub.js +42 -19
- package/lib/Adapters/Push/PushAdapter.js +14 -7
- package/lib/Adapters/Storage/Mongo/MongoCollection.js +137 -45
- package/lib/Adapters/Storage/Mongo/MongoSchemaCollection.js +158 -63
- package/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js +320 -168
- package/lib/Adapters/Storage/Mongo/MongoTransform.js +279 -306
- package/lib/Adapters/Storage/Postgres/PostgresClient.js +14 -10
- package/lib/Adapters/Storage/Postgres/PostgresConfigParser.js +47 -21
- package/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js +854 -468
- package/lib/Adapters/Storage/Postgres/sql/index.js +4 -6
- package/lib/Adapters/Storage/StorageAdapter.js +1 -1
- package/lib/Adapters/WebSocketServer/WSAdapter.js +35 -0
- package/lib/Adapters/WebSocketServer/WSSAdapter.js +66 -0
- package/lib/Auth.js +488 -125
- package/lib/ClientSDK.js +2 -6
- package/lib/Config.js +525 -94
- package/lib/Controllers/AdaptableController.js +5 -25
- package/lib/Controllers/AnalyticsController.js +22 -23
- package/lib/Controllers/CacheController.js +10 -31
- package/lib/Controllers/DatabaseController.js +767 -313
- package/lib/Controllers/FilesController.js +49 -54
- package/lib/Controllers/HooksController.js +80 -84
- package/lib/Controllers/LiveQueryController.js +35 -22
- package/lib/Controllers/LoggerController.js +22 -58
- package/lib/Controllers/ParseGraphQLController.js +293 -0
- package/lib/Controllers/PushController.js +58 -49
- package/lib/Controllers/SchemaController.js +916 -422
- package/lib/Controllers/UserController.js +265 -180
- package/lib/Controllers/index.js +90 -125
- package/lib/Controllers/types.js +1 -1
- package/lib/Deprecator/Deprecations.js +30 -0
- package/lib/Deprecator/Deprecator.js +127 -0
- package/lib/Error.js +48 -0
- package/lib/GraphQL/ParseGraphQLSchema.js +375 -0
- package/lib/GraphQL/ParseGraphQLServer.js +214 -0
- package/lib/GraphQL/helpers/objectsMutations.js +30 -0
- package/lib/GraphQL/helpers/objectsQueries.js +246 -0
- package/lib/GraphQL/loaders/configMutations.js +87 -0
- package/lib/GraphQL/loaders/configQueries.js +79 -0
- package/lib/GraphQL/loaders/defaultGraphQLMutations.js +21 -0
- package/lib/GraphQL/loaders/defaultGraphQLQueries.js +23 -0
- package/lib/GraphQL/loaders/defaultGraphQLTypes.js +1098 -0
- package/lib/GraphQL/loaders/defaultRelaySchema.js +53 -0
- package/lib/GraphQL/loaders/filesMutations.js +107 -0
- package/lib/GraphQL/loaders/functionsMutations.js +78 -0
- package/lib/GraphQL/loaders/parseClassMutations.js +268 -0
- package/lib/GraphQL/loaders/parseClassQueries.js +127 -0
- package/lib/GraphQL/loaders/parseClassTypes.js +493 -0
- package/lib/GraphQL/loaders/schemaDirectives.js +62 -0
- package/lib/GraphQL/loaders/schemaMutations.js +162 -0
- package/lib/GraphQL/loaders/schemaQueries.js +81 -0
- package/lib/GraphQL/loaders/schemaTypes.js +341 -0
- package/lib/GraphQL/loaders/usersMutations.js +433 -0
- package/lib/GraphQL/loaders/usersQueries.js +90 -0
- package/lib/GraphQL/parseGraphQLUtils.js +63 -0
- package/lib/GraphQL/transformers/className.js +14 -0
- package/lib/GraphQL/transformers/constraintType.js +53 -0
- package/lib/GraphQL/transformers/inputType.js +51 -0
- package/lib/GraphQL/transformers/mutation.js +274 -0
- package/lib/GraphQL/transformers/outputType.js +51 -0
- package/lib/GraphQL/transformers/query.js +237 -0
- package/lib/GraphQL/transformers/schemaFields.js +99 -0
- package/lib/KeyPromiseQueue.js +48 -0
- package/lib/LiveQuery/Client.js +25 -33
- package/lib/LiveQuery/Id.js +2 -5
- package/lib/LiveQuery/ParseCloudCodePublisher.js +26 -23
- package/lib/LiveQuery/ParseLiveQueryServer.js +560 -285
- package/lib/LiveQuery/ParsePubSub.js +7 -16
- package/lib/LiveQuery/ParseWebSocketServer.js +42 -39
- package/lib/LiveQuery/QueryTools.js +76 -15
- package/lib/LiveQuery/RequestSchema.js +111 -97
- package/lib/LiveQuery/SessionTokenCache.js +23 -36
- package/lib/LiveQuery/Subscription.js +8 -17
- package/lib/LiveQuery/equalObjects.js +2 -3
- package/lib/Options/Definitions.js +1355 -382
- package/lib/Options/docs.js +301 -62
- package/lib/Options/index.js +11 -1
- package/lib/Options/parsers.js +14 -10
- package/lib/Page.js +44 -0
- package/lib/ParseMessageQueue.js +6 -13
- package/lib/ParseServer.js +474 -235
- package/lib/ParseServerRESTController.js +102 -40
- package/lib/PromiseRouter.js +39 -50
- package/lib/Push/PushQueue.js +24 -30
- package/lib/Push/PushWorker.js +32 -56
- package/lib/Push/utils.js +22 -35
- package/lib/RestQuery.js +361 -139
- package/lib/RestWrite.js +713 -344
- package/lib/Routers/AggregateRouter.js +97 -71
- package/lib/Routers/AnalyticsRouter.js +8 -14
- package/lib/Routers/AudiencesRouter.js +16 -35
- package/lib/Routers/ClassesRouter.js +86 -72
- package/lib/Routers/CloudCodeRouter.js +28 -37
- package/lib/Routers/FeaturesRouter.js +22 -25
- package/lib/Routers/FilesRouter.js +266 -171
- package/lib/Routers/FunctionsRouter.js +87 -103
- package/lib/Routers/GlobalConfigRouter.js +94 -33
- package/lib/Routers/GraphQLRouter.js +41 -0
- package/lib/Routers/HooksRouter.js +43 -47
- package/lib/Routers/IAPValidationRouter.js +57 -70
- package/lib/Routers/InstallationsRouter.js +17 -25
- package/lib/Routers/LogsRouter.js +10 -25
- package/lib/Routers/PagesRouter.js +647 -0
- package/lib/Routers/PublicAPIRouter.js +104 -112
- package/lib/Routers/PurgeRouter.js +19 -29
- package/lib/Routers/PushRouter.js +14 -28
- package/lib/Routers/RolesRouter.js +7 -14
- package/lib/Routers/SchemasRouter.js +63 -42
- package/lib/Routers/SecurityRouter.js +34 -0
- package/lib/Routers/SessionsRouter.js +25 -38
- package/lib/Routers/UsersRouter.js +463 -190
- package/lib/SchemaMigrations/DefinedSchemas.js +379 -0
- package/lib/SchemaMigrations/Migrations.js +30 -0
- package/lib/Security/Check.js +109 -0
- package/lib/Security/CheckGroup.js +44 -0
- package/lib/Security/CheckGroups/CheckGroupDatabase.js +44 -0
- package/lib/Security/CheckGroups/CheckGroupServerConfig.js +96 -0
- package/lib/Security/CheckGroups/CheckGroups.js +21 -0
- package/lib/Security/CheckRunner.js +213 -0
- package/lib/SharedRest.js +29 -0
- package/lib/StatusHandler.js +96 -93
- package/lib/TestUtils.js +70 -14
- package/lib/Utils.js +468 -0
- package/lib/batch.js +74 -40
- package/lib/cache.js +8 -8
- package/lib/cli/definitions/parse-live-query-server.js +4 -3
- package/lib/cli/definitions/parse-server.js +4 -3
- package/lib/cli/parse-live-query-server.js +9 -17
- package/lib/cli/parse-server.js +49 -47
- package/lib/cli/utils/commander.js +20 -29
- package/lib/cli/utils/runner.js +31 -32
- package/lib/cloud-code/Parse.Cloud.js +711 -36
- package/lib/cloud-code/Parse.Server.js +21 -0
- package/lib/cryptoUtils.js +6 -11
- package/lib/defaults.js +21 -15
- package/lib/deprecated.js +1 -1
- package/lib/index.js +78 -67
- package/lib/logger.js +12 -20
- package/lib/middlewares.js +484 -160
- package/lib/password.js +10 -6
- package/lib/request.js +175 -0
- package/lib/requiredParameter.js +4 -3
- package/lib/rest.js +157 -82
- package/lib/triggers.js +627 -185
- package/lib/vendor/README.md +3 -3
- package/lib/vendor/mongodbUrl.js +224 -137
- package/package.json +135 -57
- package/postinstall.js +38 -50
- package/public_html/invalid_verification_link.html +3 -3
- package/types/@types/@parse/fs-files-adapter/index.d.ts +5 -0
- package/types/@types/deepcopy/index.d.ts +5 -0
- package/types/LiveQuery/ParseLiveQueryServer.d.ts +40 -0
- package/types/Options/index.d.ts +301 -0
- package/types/ParseServer.d.ts +65 -0
- package/types/eslint.config.mjs +30 -0
- package/types/index.d.ts +21 -0
- package/types/logger.d.ts +2 -0
- package/types/tests.ts +44 -0
- package/types/tsconfig.json +24 -0
- package/CHANGELOG.md +0 -1246
- package/PATENTS +0 -37
- package/bin/dev +0 -37
- package/lib/.DS_Store +0 -0
- package/lib/Adapters/Auth/common.js +0 -2
- package/lib/Adapters/Auth/facebookaccountkit.js +0 -69
- package/lib/Controllers/SchemaCache.js +0 -97
- package/lib/LiveQuery/.DS_Store +0 -0
- package/lib/cli/utils/parsers.js +0 -77
- package/lib/cloud-code/.DS_Store +0 -0
- package/lib/cloud-code/HTTPResponse.js +0 -57
- package/lib/cloud-code/Untitled-1 +0 -123
- package/lib/cloud-code/httpRequest.js +0 -102
- package/lib/cloud-code/team.html +0 -123
- package/lib/graphql/ParseClass.js +0 -234
- package/lib/graphql/Schema.js +0 -197
- package/lib/graphql/index.js +0 -1
- package/lib/graphql/types/ACL.js +0 -35
- package/lib/graphql/types/Date.js +0 -25
- package/lib/graphql/types/File.js +0 -24
- package/lib/graphql/types/GeoPoint.js +0 -35
- package/lib/graphql/types/JSONObject.js +0 -30
- package/lib/graphql/types/NumberInput.js +0 -43
- package/lib/graphql/types/NumberQuery.js +0 -42
- package/lib/graphql/types/Pointer.js +0 -35
- package/lib/graphql/types/QueryConstraint.js +0 -61
- package/lib/graphql/types/StringQuery.js +0 -39
- package/lib/graphql/types/index.js +0 -110
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _otpauth = require("otpauth");
|
|
8
|
+
var _cryptoUtils = require("../../cryptoUtils");
|
|
9
|
+
var _AuthAdapter = _interopRequireDefault(require("./AuthAdapter"));
|
|
10
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
+
/**
|
|
12
|
+
* Parse Server authentication adapter for Multi-Factor Authentication (MFA).
|
|
13
|
+
*
|
|
14
|
+
* @class MFAAdapter
|
|
15
|
+
* @param {Object} options - The adapter options.
|
|
16
|
+
* @param {Array<String>} options.options - Supported MFA methods. Must include `"SMS"` or `"TOTP"`.
|
|
17
|
+
* @param {Number} [options.digits=6] - The number of digits for the one-time password (OTP). Must be between 4 and 10.
|
|
18
|
+
* @param {Number} [options.period=30] - The validity period of the OTP in seconds. Must be greater than 10.
|
|
19
|
+
* @param {String} [options.algorithm="SHA1"] - The algorithm used for TOTP generation. Defaults to `"SHA1"`.
|
|
20
|
+
* @param {Function} [options.sendSMS] - A callback function for sending SMS OTPs. Required if `"SMS"` is included in `options`.
|
|
21
|
+
*
|
|
22
|
+
* @description
|
|
23
|
+
* ## Parse Server Configuration
|
|
24
|
+
* To configure Parse Server for MFA, use the following structure:
|
|
25
|
+
* ```javascript
|
|
26
|
+
* {
|
|
27
|
+
* auth: {
|
|
28
|
+
* mfa: {
|
|
29
|
+
* options: ["SMS", "TOTP"],
|
|
30
|
+
* digits: 6,
|
|
31
|
+
* period: 30,
|
|
32
|
+
* algorithm: "SHA1",
|
|
33
|
+
* sendSMS: (token, mobile) => {
|
|
34
|
+
* // Send the SMS using your preferred SMS provider.
|
|
35
|
+
* console.log(`Sending SMS to ${mobile} with token: ${token}`);
|
|
36
|
+
* }
|
|
37
|
+
* }
|
|
38
|
+
* }
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* ## MFA Methods
|
|
43
|
+
* - **SMS**:
|
|
44
|
+
* - Requires a valid mobile number.
|
|
45
|
+
* - Sends a one-time password (OTP) via SMS for login or verification.
|
|
46
|
+
* - Uses the `sendSMS` callback for sending the OTP.
|
|
47
|
+
*
|
|
48
|
+
* - **TOTP**:
|
|
49
|
+
* - Requires a secret key for setup.
|
|
50
|
+
* - Validates the user's OTP against a time-based one-time password (TOTP) generated using the secret key.
|
|
51
|
+
* - Supports configurable digits, period, and algorithm for TOTP generation.
|
|
52
|
+
*
|
|
53
|
+
* ## MFA Payload
|
|
54
|
+
* The adapter requires the following `authData` fields:
|
|
55
|
+
* - **For SMS-based MFA**:
|
|
56
|
+
* - `mobile`: The user's mobile number (required for setup).
|
|
57
|
+
* - `token`: The OTP provided by the user for login or verification.
|
|
58
|
+
* - **For TOTP-based MFA**:
|
|
59
|
+
* - `secret`: The TOTP secret key for the user (required for setup).
|
|
60
|
+
* - `token`: The OTP provided by the user for login or verification.
|
|
61
|
+
*
|
|
62
|
+
* ## Example Payloads
|
|
63
|
+
* ### SMS Setup Payload
|
|
64
|
+
* ```json
|
|
65
|
+
* {
|
|
66
|
+
* "mobile": "+1234567890"
|
|
67
|
+
* }
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* ### TOTP Setup Payload
|
|
71
|
+
* ```json
|
|
72
|
+
* {
|
|
73
|
+
* "secret": "BASE32ENCODEDSECRET",
|
|
74
|
+
* "token": "123456"
|
|
75
|
+
* }
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* ### Login Payload
|
|
79
|
+
* ```json
|
|
80
|
+
* {
|
|
81
|
+
* "token": "123456"
|
|
82
|
+
* }
|
|
83
|
+
* ```
|
|
84
|
+
*
|
|
85
|
+
* @see {@link https://en.wikipedia.org/wiki/Time-based_One-Time_Password_algorithm Time-based One-Time Password Algorithm (TOTP)}
|
|
86
|
+
* @see {@link https://tools.ietf.org/html/rfc6238 RFC 6238: TOTP: Time-Based One-Time Password Algorithm}
|
|
87
|
+
*/
|
|
88
|
+
|
|
89
|
+
class MFAAdapter extends _AuthAdapter.default {
|
|
90
|
+
validateOptions(opts) {
|
|
91
|
+
const validOptions = opts.options;
|
|
92
|
+
if (!Array.isArray(validOptions)) {
|
|
93
|
+
throw 'mfa.options must be an array';
|
|
94
|
+
}
|
|
95
|
+
this.sms = validOptions.includes('SMS');
|
|
96
|
+
this.totp = validOptions.includes('TOTP');
|
|
97
|
+
if (!this.sms && !this.totp) {
|
|
98
|
+
throw 'mfa.options must include SMS or TOTP';
|
|
99
|
+
}
|
|
100
|
+
const digits = opts.digits || 6;
|
|
101
|
+
const period = opts.period || 30;
|
|
102
|
+
if (typeof digits !== 'number') {
|
|
103
|
+
throw 'mfa.digits must be a number';
|
|
104
|
+
}
|
|
105
|
+
if (typeof period !== 'number') {
|
|
106
|
+
throw 'mfa.period must be a number';
|
|
107
|
+
}
|
|
108
|
+
if (digits < 4 || digits > 10) {
|
|
109
|
+
throw 'mfa.digits must be between 4 and 10';
|
|
110
|
+
}
|
|
111
|
+
if (period < 10) {
|
|
112
|
+
throw 'mfa.period must be greater than 10';
|
|
113
|
+
}
|
|
114
|
+
const sendSMS = opts.sendSMS;
|
|
115
|
+
if (this.sms && typeof sendSMS !== 'function') {
|
|
116
|
+
throw 'mfa.sendSMS callback must be defined when using SMS OTPs';
|
|
117
|
+
}
|
|
118
|
+
this.smsCallback = sendSMS;
|
|
119
|
+
this.digits = digits;
|
|
120
|
+
this.period = period;
|
|
121
|
+
this.algorithm = opts.algorithm || 'SHA1';
|
|
122
|
+
}
|
|
123
|
+
validateSetUp(mfaData) {
|
|
124
|
+
if (mfaData.mobile && this.sms) {
|
|
125
|
+
return this.setupMobileOTP(mfaData.mobile);
|
|
126
|
+
}
|
|
127
|
+
if (this.totp) {
|
|
128
|
+
return this.setupTOTP(mfaData);
|
|
129
|
+
}
|
|
130
|
+
throw 'Invalid MFA data';
|
|
131
|
+
}
|
|
132
|
+
async validateLogin(loginData, _, req) {
|
|
133
|
+
const saveResponse = {
|
|
134
|
+
doNotSave: true
|
|
135
|
+
};
|
|
136
|
+
const token = loginData.token;
|
|
137
|
+
const auth = req.original.get('authData') || {};
|
|
138
|
+
const {
|
|
139
|
+
secret,
|
|
140
|
+
recovery,
|
|
141
|
+
mobile,
|
|
142
|
+
token: saved,
|
|
143
|
+
expiry
|
|
144
|
+
} = auth.mfa || {};
|
|
145
|
+
if (this.sms && mobile) {
|
|
146
|
+
if (token === 'request') {
|
|
147
|
+
const {
|
|
148
|
+
token: sendToken,
|
|
149
|
+
expiry
|
|
150
|
+
} = await this.sendSMS(mobile);
|
|
151
|
+
auth.mfa.token = sendToken;
|
|
152
|
+
auth.mfa.expiry = expiry;
|
|
153
|
+
req.object.set('authData', auth);
|
|
154
|
+
await req.object.save(null, {
|
|
155
|
+
useMasterKey: true
|
|
156
|
+
});
|
|
157
|
+
throw 'Please enter the token';
|
|
158
|
+
}
|
|
159
|
+
if (!saved || token !== saved) {
|
|
160
|
+
throw 'Invalid MFA token 1';
|
|
161
|
+
}
|
|
162
|
+
if (new Date() > expiry) {
|
|
163
|
+
throw 'Invalid MFA token 2';
|
|
164
|
+
}
|
|
165
|
+
delete auth.mfa.token;
|
|
166
|
+
delete auth.mfa.expiry;
|
|
167
|
+
return {
|
|
168
|
+
save: auth.mfa
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
if (this.totp) {
|
|
172
|
+
if (typeof token !== 'string') {
|
|
173
|
+
throw 'Invalid MFA token';
|
|
174
|
+
}
|
|
175
|
+
if (!secret) {
|
|
176
|
+
return saveResponse;
|
|
177
|
+
}
|
|
178
|
+
if (recovery[0] === token || recovery[1] === token) {
|
|
179
|
+
return saveResponse;
|
|
180
|
+
}
|
|
181
|
+
const totp = new _otpauth.TOTP({
|
|
182
|
+
algorithm: this.algorithm,
|
|
183
|
+
digits: this.digits,
|
|
184
|
+
period: this.period,
|
|
185
|
+
secret: _otpauth.Secret.fromBase32(secret)
|
|
186
|
+
});
|
|
187
|
+
const valid = totp.validate({
|
|
188
|
+
token
|
|
189
|
+
});
|
|
190
|
+
if (valid === null) {
|
|
191
|
+
throw 'Invalid MFA token';
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return saveResponse;
|
|
195
|
+
}
|
|
196
|
+
async validateUpdate(authData, _, req) {
|
|
197
|
+
if (req.master) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (authData.mobile && this.sms) {
|
|
201
|
+
if (!authData.token) {
|
|
202
|
+
throw 'MFA is already set up on this account';
|
|
203
|
+
}
|
|
204
|
+
return this.confirmSMSOTP(authData, req.original.get('authData')?.mfa || {});
|
|
205
|
+
}
|
|
206
|
+
if (this.totp) {
|
|
207
|
+
await this.validateLogin({
|
|
208
|
+
token: authData.old
|
|
209
|
+
}, null, req);
|
|
210
|
+
return this.validateSetUp(authData);
|
|
211
|
+
}
|
|
212
|
+
throw 'Invalid MFA data';
|
|
213
|
+
}
|
|
214
|
+
afterFind(authData, options, req) {
|
|
215
|
+
if (req.master) {
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
if (this.totp && authData.secret) {
|
|
219
|
+
return {
|
|
220
|
+
status: 'enabled'
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
if (this.sms && authData.mobile) {
|
|
224
|
+
return {
|
|
225
|
+
status: 'enabled'
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
return {
|
|
229
|
+
status: 'disabled'
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
policy(req, auth) {
|
|
233
|
+
if (this.sms && auth?.pending && Object.keys(auth).length === 1) {
|
|
234
|
+
return 'default';
|
|
235
|
+
}
|
|
236
|
+
return 'additional';
|
|
237
|
+
}
|
|
238
|
+
async setupMobileOTP(mobile) {
|
|
239
|
+
const {
|
|
240
|
+
token,
|
|
241
|
+
expiry
|
|
242
|
+
} = await this.sendSMS(mobile);
|
|
243
|
+
return {
|
|
244
|
+
save: {
|
|
245
|
+
pending: {
|
|
246
|
+
[mobile]: {
|
|
247
|
+
token,
|
|
248
|
+
expiry
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
async sendSMS(mobile) {
|
|
255
|
+
if (!/^[+]*[(]{0,1}[0-9]{1,3}[)]{0,1}[-\s\./0-9]*$/g.test(mobile)) {
|
|
256
|
+
throw 'Invalid mobile number.';
|
|
257
|
+
}
|
|
258
|
+
let token = '';
|
|
259
|
+
while (token.length < this.digits) {
|
|
260
|
+
token += (0, _cryptoUtils.randomString)(10).replace(/\D/g, '');
|
|
261
|
+
}
|
|
262
|
+
token = token.substring(0, this.digits);
|
|
263
|
+
await Promise.resolve(this.smsCallback(token, mobile));
|
|
264
|
+
const expiry = new Date(new Date().getTime() + this.period * 1000);
|
|
265
|
+
return {
|
|
266
|
+
token,
|
|
267
|
+
expiry
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
async confirmSMSOTP(inputData, authData) {
|
|
271
|
+
const {
|
|
272
|
+
mobile,
|
|
273
|
+
token
|
|
274
|
+
} = inputData;
|
|
275
|
+
if (!authData.pending?.[mobile]) {
|
|
276
|
+
throw 'This number is not pending';
|
|
277
|
+
}
|
|
278
|
+
const pendingData = authData.pending[mobile];
|
|
279
|
+
if (token !== pendingData.token) {
|
|
280
|
+
throw 'Invalid MFA token';
|
|
281
|
+
}
|
|
282
|
+
if (new Date() > pendingData.expiry) {
|
|
283
|
+
throw 'Invalid MFA token';
|
|
284
|
+
}
|
|
285
|
+
delete authData.pending[mobile];
|
|
286
|
+
authData.mobile = mobile;
|
|
287
|
+
return {
|
|
288
|
+
save: authData
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
setupTOTP(mfaData) {
|
|
292
|
+
const {
|
|
293
|
+
secret,
|
|
294
|
+
token
|
|
295
|
+
} = mfaData;
|
|
296
|
+
if (!secret || !token || secret.length < 20) {
|
|
297
|
+
throw 'Invalid MFA data';
|
|
298
|
+
}
|
|
299
|
+
const totp = new _otpauth.TOTP({
|
|
300
|
+
algorithm: this.algorithm,
|
|
301
|
+
digits: this.digits,
|
|
302
|
+
period: this.period,
|
|
303
|
+
secret: _otpauth.Secret.fromBase32(secret)
|
|
304
|
+
});
|
|
305
|
+
const valid = totp.validate({
|
|
306
|
+
token
|
|
307
|
+
});
|
|
308
|
+
if (valid === null) {
|
|
309
|
+
throw 'Invalid MFA token';
|
|
310
|
+
}
|
|
311
|
+
const recovery = [(0, _cryptoUtils.randomString)(30), (0, _cryptoUtils.randomString)(30)];
|
|
312
|
+
return {
|
|
313
|
+
response: {
|
|
314
|
+
recovery: recovery.join(', ')
|
|
315
|
+
},
|
|
316
|
+
save: {
|
|
317
|
+
secret,
|
|
318
|
+
recovery
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
var _default = exports.default = new MFAAdapter();
|
|
324
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfb3RwYXV0aCIsInJlcXVpcmUiLCJfY3J5cHRvVXRpbHMiLCJfQXV0aEFkYXB0ZXIiLCJfaW50ZXJvcFJlcXVpcmVEZWZhdWx0IiwiZSIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiTUZBQWRhcHRlciIsIkF1dGhBZGFwdGVyIiwidmFsaWRhdGVPcHRpb25zIiwib3B0cyIsInZhbGlkT3B0aW9ucyIsIm9wdGlvbnMiLCJBcnJheSIsImlzQXJyYXkiLCJzbXMiLCJpbmNsdWRlcyIsInRvdHAiLCJkaWdpdHMiLCJwZXJpb2QiLCJzZW5kU01TIiwic21zQ2FsbGJhY2siLCJhbGdvcml0aG0iLCJ2YWxpZGF0ZVNldFVwIiwibWZhRGF0YSIsIm1vYmlsZSIsInNldHVwTW9iaWxlT1RQIiwic2V0dXBUT1RQIiwidmFsaWRhdGVMb2dpbiIsImxvZ2luRGF0YSIsIl8iLCJyZXEiLCJzYXZlUmVzcG9uc2UiLCJkb05vdFNhdmUiLCJ0b2tlbiIsImF1dGgiLCJvcmlnaW5hbCIsImdldCIsInNlY3JldCIsInJlY292ZXJ5Iiwic2F2ZWQiLCJleHBpcnkiLCJtZmEiLCJzZW5kVG9rZW4iLCJvYmplY3QiLCJzZXQiLCJzYXZlIiwidXNlTWFzdGVyS2V5IiwiRGF0ZSIsIlRPVFAiLCJTZWNyZXQiLCJmcm9tQmFzZTMyIiwidmFsaWQiLCJ2YWxpZGF0ZSIsInZhbGlkYXRlVXBkYXRlIiwiYXV0aERhdGEiLCJtYXN0ZXIiLCJjb25maXJtU01TT1RQIiwib2xkIiwiYWZ0ZXJGaW5kIiwic3RhdHVzIiwicG9saWN5IiwicGVuZGluZyIsIk9iamVjdCIsImtleXMiLCJsZW5ndGgiLCJ0ZXN0IiwicmFuZG9tU3RyaW5nIiwicmVwbGFjZSIsInN1YnN0cmluZyIsIlByb21pc2UiLCJyZXNvbHZlIiwiZ2V0VGltZSIsImlucHV0RGF0YSIsInBlbmRpbmdEYXRhIiwicmVzcG9uc2UiLCJqb2luIiwiX2RlZmF1bHQiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL0FkYXB0ZXJzL0F1dGgvbWZhLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUGFyc2UgU2VydmVyIGF1dGhlbnRpY2F0aW9uIGFkYXB0ZXIgZm9yIE11bHRpLUZhY3RvciBBdXRoZW50aWNhdGlvbiAoTUZBKS5cbiAqXG4gKiBAY2xhc3MgTUZBQWRhcHRlclxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBUaGUgYWRhcHRlciBvcHRpb25zLlxuICogQHBhcmFtIHtBcnJheTxTdHJpbmc+fSBvcHRpb25zLm9wdGlvbnMgLSBTdXBwb3J0ZWQgTUZBIG1ldGhvZHMuIE11c3QgaW5jbHVkZSBgXCJTTVNcImAgb3IgYFwiVE9UUFwiYC5cbiAqIEBwYXJhbSB7TnVtYmVyfSBbb3B0aW9ucy5kaWdpdHM9Nl0gLSBUaGUgbnVtYmVyIG9mIGRpZ2l0cyBmb3IgdGhlIG9uZS10aW1lIHBhc3N3b3JkIChPVFApLiBNdXN0IGJlIGJldHdlZW4gNCBhbmQgMTAuXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMucGVyaW9kPTMwXSAtIFRoZSB2YWxpZGl0eSBwZXJpb2Qgb2YgdGhlIE9UUCBpbiBzZWNvbmRzLiBNdXN0IGJlIGdyZWF0ZXIgdGhhbiAxMC5cbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5hbGdvcml0aG09XCJTSEExXCJdIC0gVGhlIGFsZ29yaXRobSB1c2VkIGZvciBUT1RQIGdlbmVyYXRpb24uIERlZmF1bHRzIHRvIGBcIlNIQTFcImAuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBbb3B0aW9ucy5zZW5kU01TXSAtIEEgY2FsbGJhY2sgZnVuY3Rpb24gZm9yIHNlbmRpbmcgU01TIE9UUHMuIFJlcXVpcmVkIGlmIGBcIlNNU1wiYCBpcyBpbmNsdWRlZCBpbiBgb3B0aW9uc2AuXG4gKlxuICogQGRlc2NyaXB0aW9uXG4gKiAjIyBQYXJzZSBTZXJ2ZXIgQ29uZmlndXJhdGlvblxuICogVG8gY29uZmlndXJlIFBhcnNlIFNlcnZlciBmb3IgTUZBLCB1c2UgdGhlIGZvbGxvd2luZyBzdHJ1Y3R1cmU6XG4gKiBgYGBqYXZhc2NyaXB0XG4gKiB7XG4gKiAgIGF1dGg6IHtcbiAqICAgICBtZmE6IHtcbiAqICAgICAgIG9wdGlvbnM6IFtcIlNNU1wiLCBcIlRPVFBcIl0sXG4gKiAgICAgICBkaWdpdHM6IDYsXG4gKiAgICAgICBwZXJpb2Q6IDMwLFxuICogICAgICAgYWxnb3JpdGhtOiBcIlNIQTFcIixcbiAqICAgICAgIHNlbmRTTVM6ICh0b2tlbiwgbW9iaWxlKSA9PiB7XG4gKiAgICAgICAgIC8vIFNlbmQgdGhlIFNNUyB1c2luZyB5b3VyIHByZWZlcnJlZCBTTVMgcHJvdmlkZXIuXG4gKiAgICAgICAgIGNvbnNvbGUubG9nKGBTZW5kaW5nIFNNUyB0byAke21vYmlsZX0gd2l0aCB0b2tlbjogJHt0b2tlbn1gKTtcbiAqICAgICAgIH1cbiAqICAgICB9XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICpcbiAqICMjIE1GQSBNZXRob2RzXG4gKiAtICoqU01TKio6XG4gKiAgIC0gUmVxdWlyZXMgYSB2YWxpZCBtb2JpbGUgbnVtYmVyLlxuICogICAtIFNlbmRzIGEgb25lLXRpbWUgcGFzc3dvcmQgKE9UUCkgdmlhIFNNUyBmb3IgbG9naW4gb3IgdmVyaWZpY2F0aW9uLlxuICogICAtIFVzZXMgdGhlIGBzZW5kU01TYCBjYWxsYmFjayBmb3Igc2VuZGluZyB0aGUgT1RQLlxuICpcbiAqIC0gKipUT1RQKio6XG4gKiAgIC0gUmVxdWlyZXMgYSBzZWNyZXQga2V5IGZvciBzZXR1cC5cbiAqICAgLSBWYWxpZGF0ZXMgdGhlIHVzZXIncyBPVFAgYWdhaW5zdCBhIHRpbWUtYmFzZWQgb25lLXRpbWUgcGFzc3dvcmQgKFRPVFApIGdlbmVyYXRlZCB1c2luZyB0aGUgc2VjcmV0IGtleS5cbiAqICAgLSBTdXBwb3J0cyBjb25maWd1cmFibGUgZGlnaXRzLCBwZXJpb2QsIGFuZCBhbGdvcml0aG0gZm9yIFRPVFAgZ2VuZXJhdGlvbi5cbiAqXG4gKiAjIyBNRkEgUGF5bG9hZFxuICogVGhlIGFkYXB0ZXIgcmVxdWlyZXMgdGhlIGZvbGxvd2luZyBgYXV0aERhdGFgIGZpZWxkczpcbiAqIC0gKipGb3IgU01TLWJhc2VkIE1GQSoqOlxuICogICAtIGBtb2JpbGVgOiBUaGUgdXNlcidzIG1vYmlsZSBudW1iZXIgKHJlcXVpcmVkIGZvciBzZXR1cCkuXG4gKiAgIC0gYHRva2VuYDogVGhlIE9UUCBwcm92aWRlZCBieSB0aGUgdXNlciBmb3IgbG9naW4gb3IgdmVyaWZpY2F0aW9uLlxuICogLSAqKkZvciBUT1RQLWJhc2VkIE1GQSoqOlxuICogICAtIGBzZWNyZXRgOiBUaGUgVE9UUCBzZWNyZXQga2V5IGZvciB0aGUgdXNlciAocmVxdWlyZWQgZm9yIHNldHVwKS5cbiAqICAgLSBgdG9rZW5gOiBUaGUgT1RQIHByb3ZpZGVkIGJ5IHRoZSB1c2VyIGZvciBsb2dpbiBvciB2ZXJpZmljYXRpb24uXG4gKlxuICogIyMgRXhhbXBsZSBQYXlsb2Fkc1xuICogIyMjIFNNUyBTZXR1cCBQYXlsb2FkXG4gKiBgYGBqc29uXG4gKiB7XG4gKiAgIFwibW9iaWxlXCI6IFwiKzEyMzQ1Njc4OTBcIlxuICogfVxuICogYGBgXG4gKlxuICogIyMjIFRPVFAgU2V0dXAgUGF5bG9hZFxuICogYGBganNvblxuICoge1xuICogICBcInNlY3JldFwiOiBcIkJBU0UzMkVOQ09ERURTRUNSRVRcIixcbiAqICAgXCJ0b2tlblwiOiBcIjEyMzQ1NlwiXG4gKiB9XG4gKiBgYGBcbiAqXG4gKiAjIyMgTG9naW4gUGF5bG9hZFxuICogYGBganNvblxuICoge1xuICogICBcInRva2VuXCI6IFwiMTIzNDU2XCJcbiAqIH1cbiAqIGBgYFxuICpcbiAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1RpbWUtYmFzZWRfT25lLVRpbWVfUGFzc3dvcmRfYWxnb3JpdGhtIFRpbWUtYmFzZWQgT25lLVRpbWUgUGFzc3dvcmQgQWxnb3JpdGhtIChUT1RQKX1cbiAqIEBzZWUge0BsaW5rIGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM2MjM4IFJGQyA2MjM4OiBUT1RQOiBUaW1lLUJhc2VkIE9uZS1UaW1lIFBhc3N3b3JkIEFsZ29yaXRobX1cbiAqL1xuXG5pbXBvcnQgeyBUT1RQLCBTZWNyZXQgfSBmcm9tICdvdHBhdXRoJztcbmltcG9ydCB7IHJhbmRvbVN0cmluZyB9IGZyb20gJy4uLy4uL2NyeXB0b1V0aWxzJztcbmltcG9ydCBBdXRoQWRhcHRlciBmcm9tICcuL0F1dGhBZGFwdGVyJztcbmNsYXNzIE1GQUFkYXB0ZXIgZXh0ZW5kcyBBdXRoQWRhcHRlciB7XG4gIHZhbGlkYXRlT3B0aW9ucyhvcHRzKSB7XG4gICAgY29uc3QgdmFsaWRPcHRpb25zID0gb3B0cy5vcHRpb25zO1xuICAgIGlmICghQXJyYXkuaXNBcnJheSh2YWxpZE9wdGlvbnMpKSB7XG4gICAgICB0aHJvdyAnbWZhLm9wdGlvbnMgbXVzdCBiZSBhbiBhcnJheSc7XG4gICAgfVxuICAgIHRoaXMuc21zID0gdmFsaWRPcHRpb25zLmluY2x1ZGVzKCdTTVMnKTtcbiAgICB0aGlzLnRvdHAgPSB2YWxpZE9wdGlvbnMuaW5jbHVkZXMoJ1RPVFAnKTtcbiAgICBpZiAoIXRoaXMuc21zICYmICF0aGlzLnRvdHApIHtcbiAgICAgIHRocm93ICdtZmEub3B0aW9ucyBtdXN0IGluY2x1ZGUgU01TIG9yIFRPVFAnO1xuICAgIH1cbiAgICBjb25zdCBkaWdpdHMgPSBvcHRzLmRpZ2l0cyB8fCA2O1xuICAgIGNvbnN0IHBlcmlvZCA9IG9wdHMucGVyaW9kIHx8IDMwO1xuICAgIGlmICh0eXBlb2YgZGlnaXRzICE9PSAnbnVtYmVyJykge1xuICAgICAgdGhyb3cgJ21mYS5kaWdpdHMgbXVzdCBiZSBhIG51bWJlcic7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgcGVyaW9kICE9PSAnbnVtYmVyJykge1xuICAgICAgdGhyb3cgJ21mYS5wZXJpb2QgbXVzdCBiZSBhIG51bWJlcic7XG4gICAgfVxuICAgIGlmIChkaWdpdHMgPCA0IHx8IGRpZ2l0cyA+IDEwKSB7XG4gICAgICB0aHJvdyAnbWZhLmRpZ2l0cyBtdXN0IGJlIGJldHdlZW4gNCBhbmQgMTAnO1xuICAgIH1cbiAgICBpZiAocGVyaW9kIDwgMTApIHtcbiAgICAgIHRocm93ICdtZmEucGVyaW9kIG11c3QgYmUgZ3JlYXRlciB0aGFuIDEwJztcbiAgICB9XG4gICAgY29uc3Qgc2VuZFNNUyA9IG9wdHMuc2VuZFNNUztcbiAgICBpZiAodGhpcy5zbXMgJiYgdHlwZW9mIHNlbmRTTVMgIT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHRocm93ICdtZmEuc2VuZFNNUyBjYWxsYmFjayBtdXN0IGJlIGRlZmluZWQgd2hlbiB1c2luZyBTTVMgT1RQcyc7XG4gICAgfVxuICAgIHRoaXMuc21zQ2FsbGJhY2sgPSBzZW5kU01TO1xuICAgIHRoaXMuZGlnaXRzID0gZGlnaXRzO1xuICAgIHRoaXMucGVyaW9kID0gcGVyaW9kO1xuICAgIHRoaXMuYWxnb3JpdGhtID0gb3B0cy5hbGdvcml0aG0gfHwgJ1NIQTEnO1xuICB9XG4gIHZhbGlkYXRlU2V0VXAobWZhRGF0YSkge1xuICAgIGlmIChtZmFEYXRhLm1vYmlsZSAmJiB0aGlzLnNtcykge1xuICAgICAgcmV0dXJuIHRoaXMuc2V0dXBNb2JpbGVPVFAobWZhRGF0YS5tb2JpbGUpO1xuICAgIH1cbiAgICBpZiAodGhpcy50b3RwKSB7XG4gICAgICByZXR1cm4gdGhpcy5zZXR1cFRPVFAobWZhRGF0YSk7XG4gICAgfVxuICAgIHRocm93ICdJbnZhbGlkIE1GQSBkYXRhJztcbiAgfVxuICBhc3luYyB2YWxpZGF0ZUxvZ2luKGxvZ2luRGF0YSwgXywgcmVxKSB7XG4gICAgY29uc3Qgc2F2ZVJlc3BvbnNlID0ge1xuICAgICAgZG9Ob3RTYXZlOiB0cnVlLFxuICAgIH07XG4gICAgY29uc3QgdG9rZW4gPSBsb2dpbkRhdGEudG9rZW47XG4gICAgY29uc3QgYXV0aCA9IHJlcS5vcmlnaW5hbC5nZXQoJ2F1dGhEYXRhJykgfHwge307XG4gICAgY29uc3QgeyBzZWNyZXQsIHJlY292ZXJ5LCBtb2JpbGUsIHRva2VuOiBzYXZlZCwgZXhwaXJ5IH0gPSBhdXRoLm1mYSB8fCB7fTtcbiAgICBpZiAodGhpcy5zbXMgJiYgbW9iaWxlKSB7XG4gICAgICBpZiAodG9rZW4gPT09ICdyZXF1ZXN0Jykge1xuICAgICAgICBjb25zdCB7IHRva2VuOiBzZW5kVG9rZW4sIGV4cGlyeSB9ID0gYXdhaXQgdGhpcy5zZW5kU01TKG1vYmlsZSk7XG4gICAgICAgIGF1dGgubWZhLnRva2VuID0gc2VuZFRva2VuO1xuICAgICAgICBhdXRoLm1mYS5leHBpcnkgPSBleHBpcnk7XG4gICAgICAgIHJlcS5vYmplY3Quc2V0KCdhdXRoRGF0YScsIGF1dGgpO1xuICAgICAgICBhd2FpdCByZXEub2JqZWN0LnNhdmUobnVsbCwgeyB1c2VNYXN0ZXJLZXk6IHRydWUgfSk7XG4gICAgICAgIHRocm93ICdQbGVhc2UgZW50ZXIgdGhlIHRva2VuJztcbiAgICAgIH1cbiAgICAgIGlmICghc2F2ZWQgfHwgdG9rZW4gIT09IHNhdmVkKSB7XG4gICAgICAgIHRocm93ICdJbnZhbGlkIE1GQSB0b2tlbiAxJztcbiAgICAgIH1cbiAgICAgIGlmIChuZXcgRGF0ZSgpID4gZXhwaXJ5KSB7XG4gICAgICAgIHRocm93ICdJbnZhbGlkIE1GQSB0b2tlbiAyJztcbiAgICAgIH1cbiAgICAgIGRlbGV0ZSBhdXRoLm1mYS50b2tlbjtcbiAgICAgIGRlbGV0ZSBhdXRoLm1mYS5leHBpcnk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBzYXZlOiBhdXRoLm1mYSxcbiAgICAgIH07XG4gICAgfVxuICAgIGlmICh0aGlzLnRvdHApIHtcbiAgICAgIGlmICh0eXBlb2YgdG9rZW4gIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRocm93ICdJbnZhbGlkIE1GQSB0b2tlbic7XG4gICAgICB9XG4gICAgICBpZiAoIXNlY3JldCkge1xuICAgICAgICByZXR1cm4gc2F2ZVJlc3BvbnNlO1xuICAgICAgfVxuICAgICAgaWYgKHJlY292ZXJ5WzBdID09PSB0b2tlbiB8fCByZWNvdmVyeVsxXSA9PT0gdG9rZW4pIHtcbiAgICAgICAgcmV0dXJuIHNhdmVSZXNwb25zZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHRvdHAgPSBuZXcgVE9UUCh7XG4gICAgICAgIGFsZ29yaXRobTogdGhpcy5hbGdvcml0aG0sXG4gICAgICAgIGRpZ2l0czogdGhpcy5kaWdpdHMsXG4gICAgICAgIHBlcmlvZDogdGhpcy5wZXJpb2QsXG4gICAgICAgIHNlY3JldDogU2VjcmV0LmZyb21CYXNlMzIoc2VjcmV0KSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgdmFsaWQgPSB0b3RwLnZhbGlkYXRlKHtcbiAgICAgICAgdG9rZW4sXG4gICAgICB9KTtcbiAgICAgIGlmICh2YWxpZCA9PT0gbnVsbCkge1xuICAgICAgICB0aHJvdyAnSW52YWxpZCBNRkEgdG9rZW4nO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gc2F2ZVJlc3BvbnNlO1xuICB9XG4gIGFzeW5jIHZhbGlkYXRlVXBkYXRlKGF1dGhEYXRhLCBfLCByZXEpIHtcbiAgICBpZiAocmVxLm1hc3Rlcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoYXV0aERhdGEubW9iaWxlICYmIHRoaXMuc21zKSB7XG4gICAgICBpZiAoIWF1dGhEYXRhLnRva2VuKSB7XG4gICAgICAgIHRocm93ICdNRkEgaXMgYWxyZWFkeSBzZXQgdXAgb24gdGhpcyBhY2NvdW50JztcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLmNvbmZpcm1TTVNPVFAoYXV0aERhdGEsIHJlcS5vcmlnaW5hbC5nZXQoJ2F1dGhEYXRhJyk/Lm1mYSB8fCB7fSk7XG4gICAgfVxuICAgIGlmICh0aGlzLnRvdHApIHtcbiAgICAgIGF3YWl0IHRoaXMudmFsaWRhdGVMb2dpbih7IHRva2VuOiBhdXRoRGF0YS5vbGQgfSwgbnVsbCwgcmVxKTtcbiAgICAgIHJldHVybiB0aGlzLnZhbGlkYXRlU2V0VXAoYXV0aERhdGEpO1xuICAgIH1cbiAgICB0aHJvdyAnSW52YWxpZCBNRkEgZGF0YSc7XG4gIH1cbiAgYWZ0ZXJGaW5kKGF1dGhEYXRhLCBvcHRpb25zLCByZXEpIHtcbiAgICBpZiAocmVxLm1hc3Rlcikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAodGhpcy50b3RwICYmIGF1dGhEYXRhLnNlY3JldCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc3RhdHVzOiAnZW5hYmxlZCcsXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAodGhpcy5zbXMgJiYgYXV0aERhdGEubW9iaWxlKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBzdGF0dXM6ICdlbmFibGVkJyxcbiAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBzdGF0dXM6ICdkaXNhYmxlZCcsXG4gICAgfTtcbiAgfVxuXG4gIHBvbGljeShyZXEsIGF1dGgpIHtcbiAgICBpZiAodGhpcy5zbXMgJiYgYXV0aD8ucGVuZGluZyAmJiBPYmplY3Qua2V5cyhhdXRoKS5sZW5ndGggPT09IDEpIHtcbiAgICAgIHJldHVybiAnZGVmYXVsdCc7XG4gICAgfVxuICAgIHJldHVybiAnYWRkaXRpb25hbCc7XG4gIH1cblxuICBhc3luYyBzZXR1cE1vYmlsZU9UUChtb2JpbGUpIHtcbiAgICBjb25zdCB7IHRva2VuLCBleHBpcnkgfSA9IGF3YWl0IHRoaXMuc2VuZFNNUyhtb2JpbGUpO1xuICAgIHJldHVybiB7XG4gICAgICBzYXZlOiB7XG4gICAgICAgIHBlbmRpbmc6IHtcbiAgICAgICAgICBbbW9iaWxlXToge1xuICAgICAgICAgICAgdG9rZW4sXG4gICAgICAgICAgICBleHBpcnksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIGFzeW5jIHNlbmRTTVMobW9iaWxlKSB7XG4gICAgaWYgKCEvXlsrXSpbKF17MCwxfVswLTldezEsM31bKV17MCwxfVstXFxzXFwuLzAtOV0qJC9nLnRlc3QobW9iaWxlKSkge1xuICAgICAgdGhyb3cgJ0ludmFsaWQgbW9iaWxlIG51bWJlci4nO1xuICAgIH1cbiAgICBsZXQgdG9rZW4gPSAnJztcbiAgICB3aGlsZSAodG9rZW4ubGVuZ3RoIDwgdGhpcy5kaWdpdHMpIHtcbiAgICAgIHRva2VuICs9IHJhbmRvbVN0cmluZygxMCkucmVwbGFjZSgvXFxEL2csICcnKTtcbiAgICB9XG4gICAgdG9rZW4gPSB0b2tlbi5zdWJzdHJpbmcoMCwgdGhpcy5kaWdpdHMpO1xuICAgIGF3YWl0IFByb21pc2UucmVzb2x2ZSh0aGlzLnNtc0NhbGxiYWNrKHRva2VuLCBtb2JpbGUpKTtcbiAgICBjb25zdCBleHBpcnkgPSBuZXcgRGF0ZShuZXcgRGF0ZSgpLmdldFRpbWUoKSArIHRoaXMucGVyaW9kICogMTAwMCk7XG4gICAgcmV0dXJuIHsgdG9rZW4sIGV4cGlyeSB9O1xuICB9XG5cbiAgYXN5bmMgY29uZmlybVNNU09UUChpbnB1dERhdGEsIGF1dGhEYXRhKSB7XG4gICAgY29uc3QgeyBtb2JpbGUsIHRva2VuIH0gPSBpbnB1dERhdGE7XG4gICAgaWYgKCFhdXRoRGF0YS5wZW5kaW5nPy5bbW9iaWxlXSkge1xuICAgICAgdGhyb3cgJ1RoaXMgbnVtYmVyIGlzIG5vdCBwZW5kaW5nJztcbiAgICB9XG4gICAgY29uc3QgcGVuZGluZ0RhdGEgPSBhdXRoRGF0YS5wZW5kaW5nW21vYmlsZV07XG4gICAgaWYgKHRva2VuICE9PSBwZW5kaW5nRGF0YS50b2tlbikge1xuICAgICAgdGhyb3cgJ0ludmFsaWQgTUZBIHRva2VuJztcbiAgICB9XG4gICAgaWYgKG5ldyBEYXRlKCkgPiBwZW5kaW5nRGF0YS5leHBpcnkpIHtcbiAgICAgIHRocm93ICdJbnZhbGlkIE1GQSB0b2tlbic7XG4gICAgfVxuICAgIGRlbGV0ZSBhdXRoRGF0YS5wZW5kaW5nW21vYmlsZV07XG4gICAgYXV0aERhdGEubW9iaWxlID0gbW9iaWxlO1xuICAgIHJldHVybiB7XG4gICAgICBzYXZlOiBhdXRoRGF0YSxcbiAgICB9O1xuICB9XG5cbiAgc2V0dXBUT1RQKG1mYURhdGEpIHtcbiAgICBjb25zdCB7IHNlY3JldCwgdG9rZW4gfSA9IG1mYURhdGE7XG4gICAgaWYgKCFzZWNyZXQgfHwgIXRva2VuIHx8IHNlY3JldC5sZW5ndGggPCAyMCkge1xuICAgICAgdGhyb3cgJ0ludmFsaWQgTUZBIGRhdGEnO1xuICAgIH1cbiAgICBjb25zdCB0b3RwID0gbmV3IFRPVFAoe1xuICAgICAgYWxnb3JpdGhtOiB0aGlzLmFsZ29yaXRobSxcbiAgICAgIGRpZ2l0czogdGhpcy5kaWdpdHMsXG4gICAgICBwZXJpb2Q6IHRoaXMucGVyaW9kLFxuICAgICAgc2VjcmV0OiBTZWNyZXQuZnJvbUJhc2UzMihzZWNyZXQpLFxuICAgIH0pO1xuICAgIGNvbnN0IHZhbGlkID0gdG90cC52YWxpZGF0ZSh7XG4gICAgICB0b2tlbixcbiAgICB9KTtcbiAgICBpZiAodmFsaWQgPT09IG51bGwpIHtcbiAgICAgIHRocm93ICdJbnZhbGlkIE1GQSB0b2tlbic7XG4gICAgfVxuICAgIGNvbnN0IHJlY292ZXJ5ID0gW3JhbmRvbVN0cmluZygzMCksIHJhbmRvbVN0cmluZygzMCldO1xuICAgIHJldHVybiB7XG4gICAgICByZXNwb25zZTogeyByZWNvdmVyeTogcmVjb3Zlcnkuam9pbignLCAnKSB9LFxuICAgICAgc2F2ZTogeyBzZWNyZXQsIHJlY292ZXJ5IH0sXG4gICAgfTtcbiAgfVxufVxuZXhwb3J0IGRlZmF1bHQgbmV3IE1GQUFkYXB0ZXIoKTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBOEVBLElBQUFBLFFBQUEsR0FBQUMsT0FBQTtBQUNBLElBQUFDLFlBQUEsR0FBQUQsT0FBQTtBQUNBLElBQUFFLFlBQUEsR0FBQUMsc0JBQUEsQ0FBQUgsT0FBQTtBQUF3QyxTQUFBRyx1QkFBQUMsQ0FBQSxXQUFBQSxDQUFBLElBQUFBLENBQUEsQ0FBQUMsVUFBQSxHQUFBRCxDQUFBLEtBQUFFLE9BQUEsRUFBQUYsQ0FBQTtBQWhGeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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QUt3QyxXQUFXLENBQUN4QyxLQUFLLEVBQUU7TUFDL0IsTUFBTSxtQkFBbUI7SUFDM0I7SUFDQSxJQUFJLElBQUljLElBQUksQ0FBQyxDQUFDLEdBQUcwQixXQUFXLENBQUNqQyxNQUFNLEVBQUU7TUFDbkMsTUFBTSxtQkFBbUI7SUFDM0I7SUFDQSxPQUFPYyxRQUFRLENBQUNPLE9BQU8sQ0FBQ3JDLE1BQU0sQ0FBQztJQUMvQjhCLFFBQVEsQ0FBQzlCLE1BQU0sR0FBR0EsTUFBTTtJQUN4QixPQUFPO01BQ0xxQixJQUFJLEVBQUVTO0lBQ1IsQ0FBQztFQUNIO0VBRUE1QixTQUFTQSxDQUFDSCxPQUFPLEVBQUU7SUFDakIsTUFBTTtNQUFFYyxNQUFNO01BQUVKO0lBQU0sQ0FBQyxHQUFHVixPQUFPO0lBQ2pDLElBQUksQ0FBQ2MsTUFBTSxJQUFJLENBQUNKLEtBQUssSUFBSUksTUFBTSxDQUFDMkIsTUFBTSxHQUFHLEVBQUUsRUFBRTtNQUMzQyxNQUFNLGtCQUFrQjtJQUMxQjtJQUNBLE1BQU1oRCxJQUFJLEdBQUcsSUFBSWdDLGFBQUksQ0FBQztNQUNwQjNCLFNBQVMsRUFBRSxJQUFJLENBQUNBLFNBQVM7TUFDekJKLE1BQU0sRUFBRSxJQUFJLENBQUNBLE1BQU07TUFDbkJDLE1BQU0sRUFBRSxJQUFJLENBQUNBLE1BQU07TUFDbkJtQixNQUFNLEVBQUVZLGVBQU0sQ0FBQ0MsVUFBVSxDQUFDYixNQUFNO0lBQ2xDLENBQUMsQ0FBQztJQUNGLE1BQU1jLEtBQUssR0FBR25DLElBQUksQ0FBQ29DLFFBQVEsQ0FBQztNQUMxQm5CO0lBQ0YsQ0FBQyxDQUFDO0lBQ0YsSUFBSWtCLEtBQUssS0FBSyxJQUFJLEVBQUU7TUFDbEIsTUFBTSxtQkFBbUI7SUFDM0I7SUFDQSxNQUFNYixRQUFRLEdBQUcsQ0FBQyxJQUFBNEIseUJBQVksRUFBQyxFQUFFLENBQUMsRUFBRSxJQUFBQSx5QkFBWSxFQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3JELE9BQU87TUFDTFEsUUFBUSxFQUFFO1FBQUVwQyxRQUFRLEVBQUVBLFFBQVEsQ0FBQ3FDLElBQUksQ0FBQyxJQUFJO01BQUUsQ0FBQztNQUMzQzlCLElBQUksRUFBRTtRQUFFUixNQUFNO1FBQUVDO01BQVM7SUFDM0IsQ0FBQztFQUNIO0FBQ0Y7QUFBQyxJQUFBc0MsUUFBQSxHQUFBQyxPQUFBLENBQUF4RSxPQUFBLEdBQ2MsSUFBSUMsVUFBVSxDQUFDLENBQUMiLCJpZ25vcmVMaXN0IjpbXX0=
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _BaseCodeAuthAdapter = _interopRequireDefault(require("./BaseCodeAuthAdapter"));
|
|
8
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
+
/**
|
|
10
|
+
* Parse Server authentication adapter for Microsoft.
|
|
11
|
+
*
|
|
12
|
+
* @class MicrosoftAdapter
|
|
13
|
+
* @param {Object} options - The adapter configuration options.
|
|
14
|
+
* @param {string} options.clientId - Your Microsoft App Client ID. Required for secure authentication.
|
|
15
|
+
* @param {string} options.clientSecret - Your Microsoft App Client Secret. Required for secure authentication.
|
|
16
|
+
* @param {boolean} [options.enableInsecureAuth=false] - **[DEPRECATED]** Enable insecure authentication (not recommended).
|
|
17
|
+
*
|
|
18
|
+
* @description
|
|
19
|
+
* ## Parse Server Configuration
|
|
20
|
+
* To configure Parse Server for Microsoft authentication, use the following structure:
|
|
21
|
+
* ### Secure Configuration
|
|
22
|
+
* ```json
|
|
23
|
+
* {
|
|
24
|
+
* "auth": {
|
|
25
|
+
* "microsoft": {
|
|
26
|
+
* "clientId": "your-client-id",
|
|
27
|
+
* "clientSecret": "your-client-secret"
|
|
28
|
+
* }
|
|
29
|
+
* }
|
|
30
|
+
* }
|
|
31
|
+
* ```
|
|
32
|
+
* ### Insecure Configuration (Not Recommended)
|
|
33
|
+
* ```json
|
|
34
|
+
* {
|
|
35
|
+
* "auth": {
|
|
36
|
+
* "microsoft": {
|
|
37
|
+
* "enableInsecureAuth": true
|
|
38
|
+
* }
|
|
39
|
+
* }
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* The adapter requires the following `authData` fields:
|
|
44
|
+
* - **Secure Authentication**: `code`, `redirect_uri`.
|
|
45
|
+
* - **Insecure Authentication (Not Recommended)**: `id`, `access_token`.
|
|
46
|
+
*
|
|
47
|
+
* ## Auth Payloads
|
|
48
|
+
* ### Secure Authentication Payload
|
|
49
|
+
* ```json
|
|
50
|
+
* {
|
|
51
|
+
* "microsoft": {
|
|
52
|
+
* "code": "lmn789opq012rst345uvw",
|
|
53
|
+
* "redirect_uri": "https://your-redirect-uri.com/callback"
|
|
54
|
+
* }
|
|
55
|
+
* }
|
|
56
|
+
* ```
|
|
57
|
+
* ### Insecure Authentication Payload (Not Recommended)
|
|
58
|
+
* ```json
|
|
59
|
+
* {
|
|
60
|
+
* "microsoft": {
|
|
61
|
+
* "id": "7654321",
|
|
62
|
+
* "access_token": "AQXNnd2hIT6z9bHFzZz2Kp1ghiMz_RtyuvwXYZ123abc"
|
|
63
|
+
* }
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* ## Notes
|
|
68
|
+
* - Secure authentication exchanges the `code` and `redirect_uri` provided by the client for an access token using Microsoft's OAuth API.
|
|
69
|
+
* - **Insecure authentication** validates the user ID and access token directly, bypassing OAuth flows (not recommended). This method is deprecated and may be removed in future versions.
|
|
70
|
+
*
|
|
71
|
+
* @see {@link https://docs.microsoft.com/en-us/graph/auth/auth-concepts Microsoft Authentication Documentation}
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
class MicrosoftAdapter extends _BaseCodeAuthAdapter.default {
|
|
75
|
+
constructor() {
|
|
76
|
+
super('Microsoft');
|
|
77
|
+
}
|
|
78
|
+
async getUserFromAccessToken(access_token) {
|
|
79
|
+
const userResponse = await fetch('https://graph.microsoft.com/v1.0/me', {
|
|
80
|
+
headers: {
|
|
81
|
+
Authorization: 'Bearer ' + access_token
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
if (!userResponse.ok) {
|
|
85
|
+
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Microsoft API request failed.');
|
|
86
|
+
}
|
|
87
|
+
return userResponse.json();
|
|
88
|
+
}
|
|
89
|
+
async getAccessTokenFromCode(authData) {
|
|
90
|
+
const response = await fetch('https://login.microsoftonline.com/common/oauth2/v2.0/token', {
|
|
91
|
+
method: 'POST',
|
|
92
|
+
headers: {
|
|
93
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
94
|
+
},
|
|
95
|
+
body: new URLSearchParams({
|
|
96
|
+
client_id: this.clientId,
|
|
97
|
+
client_secret: this.clientSecret,
|
|
98
|
+
grant_type: 'authorization_code',
|
|
99
|
+
redirect_uri: authData.redirect_uri,
|
|
100
|
+
code: authData.code
|
|
101
|
+
})
|
|
102
|
+
});
|
|
103
|
+
if (!response.ok) {
|
|
104
|
+
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Microsoft API request failed.');
|
|
105
|
+
}
|
|
106
|
+
const json = await response.json();
|
|
107
|
+
return json.access_token;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
var _default = exports.default = new MicrosoftAdapter();
|
|
111
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfQmFzZUNvZGVBdXRoQWRhcHRlciIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJyZXF1aXJlIiwiZSIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiTWljcm9zb2Z0QWRhcHRlciIsIkJhc2VBdXRoQ29kZUFkYXB0ZXIiLCJjb25zdHJ1Y3RvciIsImdldFVzZXJGcm9tQWNjZXNzVG9rZW4iLCJhY2Nlc3NfdG9rZW4iLCJ1c2VyUmVzcG9uc2UiLCJmZXRjaCIsImhlYWRlcnMiLCJBdXRob3JpemF0aW9uIiwib2siLCJQYXJzZSIsIkVycm9yIiwiT0JKRUNUX05PVF9GT1VORCIsImpzb24iLCJnZXRBY2Nlc3NUb2tlbkZyb21Db2RlIiwiYXV0aERhdGEiLCJyZXNwb25zZSIsIm1ldGhvZCIsImJvZHkiLCJVUkxTZWFyY2hQYXJhbXMiLCJjbGllbnRfaWQiLCJjbGllbnRJZCIsImNsaWVudF9zZWNyZXQiLCJjbGllbnRTZWNyZXQiLCJncmFudF90eXBlIiwicmVkaXJlY3RfdXJpIiwiY29kZSIsIl9kZWZhdWx0IiwiZXhwb3J0cyJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL21pY3Jvc29mdC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFBhcnNlIFNlcnZlciBhdXRoZW50aWNhdGlvbiBhZGFwdGVyIGZvciBNaWNyb3NvZnQuXG4gKlxuICogQGNsYXNzIE1pY3Jvc29mdEFkYXB0ZXJcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gVGhlIGFkYXB0ZXIgY29uZmlndXJhdGlvbiBvcHRpb25zLlxuICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMuY2xpZW50SWQgLSBZb3VyIE1pY3Jvc29mdCBBcHAgQ2xpZW50IElELiBSZXF1aXJlZCBmb3Igc2VjdXJlIGF1dGhlbnRpY2F0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMuY2xpZW50U2VjcmV0IC0gWW91ciBNaWNyb3NvZnQgQXBwIENsaWVudCBTZWNyZXQuIFJlcXVpcmVkIGZvciBzZWN1cmUgYXV0aGVudGljYXRpb24uXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmVuYWJsZUluc2VjdXJlQXV0aD1mYWxzZV0gLSAqKltERVBSRUNBVEVEXSoqIEVuYWJsZSBpbnNlY3VyZSBhdXRoZW50aWNhdGlvbiAobm90IHJlY29tbWVuZGVkKS5cbiAqXG4gKiBAZGVzY3JpcHRpb25cbiAqICMjIFBhcnNlIFNlcnZlciBDb25maWd1cmF0aW9uXG4gKiBUbyBjb25maWd1cmUgUGFyc2UgU2VydmVyIGZvciBNaWNyb3NvZnQgYXV0aGVudGljYXRpb24sIHVzZSB0aGUgZm9sbG93aW5nIHN0cnVjdHVyZTpcbiAqICMjIyBTZWN1cmUgQ29uZmlndXJhdGlvblxuICogYGBganNvblxuICoge1xuICogICBcImF1dGhcIjoge1xuICogICAgIFwibWljcm9zb2Z0XCI6IHtcbiAqICAgICAgIFwiY2xpZW50SWRcIjogXCJ5b3VyLWNsaWVudC1pZFwiLFxuICogICAgICAgXCJjbGllbnRTZWNyZXRcIjogXCJ5b3VyLWNsaWVudC1zZWNyZXRcIlxuICogICAgIH1cbiAqICAgfVxuICogfVxuICogYGBgXG4gKiAjIyMgSW5zZWN1cmUgQ29uZmlndXJhdGlvbiAoTm90IFJlY29tbWVuZGVkKVxuICogYGBganNvblxuICoge1xuICogICBcImF1dGhcIjoge1xuICogICAgIFwibWljcm9zb2Z0XCI6IHtcbiAqICAgICAgIFwiZW5hYmxlSW5zZWN1cmVBdXRoXCI6IHRydWVcbiAqICAgICB9XG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICpcbiAqIFRoZSBhZGFwdGVyIHJlcXVpcmVzIHRoZSBmb2xsb3dpbmcgYGF1dGhEYXRhYCBmaWVsZHM6XG4gKiAtICoqU2VjdXJlIEF1dGhlbnRpY2F0aW9uKio6IGBjb2RlYCwgYHJlZGlyZWN0X3VyaWAuXG4gKiAtICoqSW5zZWN1cmUgQXV0aGVudGljYXRpb24gKE5vdCBSZWNvbW1lbmRlZCkqKjogYGlkYCwgYGFjY2Vzc190b2tlbmAuXG4gKlxuICogIyMgQXV0aCBQYXlsb2Fkc1xuICogIyMjIFNlY3VyZSBBdXRoZW50aWNhdGlvbiBQYXlsb2FkXG4gKiBgYGBqc29uXG4gKiB7XG4gKiAgIFwibWljcm9zb2Z0XCI6IHtcbiAqICAgICBcImNvZGVcIjogXCJsbW43ODlvcHEwMTJyc3QzNDV1dndcIixcbiAqICAgICBcInJlZGlyZWN0X3VyaVwiOiBcImh0dHBzOi8veW91ci1yZWRpcmVjdC11cmkuY29tL2NhbGxiYWNrXCJcbiAqICAgfVxuICogfVxuICogYGBgXG4gKiAjIyMgSW5zZWN1cmUgQXV0aGVudGljYXRpb24gUGF5bG9hZCAoTm90IFJlY29tbWVuZGVkKVxuICogYGBganNvblxuICoge1xuICogICBcIm1pY3Jvc29mdFwiOiB7XG4gKiAgICAgXCJpZFwiOiBcIjc2NTQzMjFcIixcbiAqICAgICBcImFjY2Vzc190b2tlblwiOiBcIkFRWE5uZDJoSVQ2ejliSEZ6WnoyS3AxZ2hpTXpfUnR5dXZ3WFlaMTIzYWJjXCJcbiAqICAgfVxuICogfVxuICogYGBgXG4gKlxuICogIyMgTm90ZXNcbiAqIC0gU2VjdXJlIGF1dGhlbnRpY2F0aW9uIGV4Y2hhbmdlcyB0aGUgYGNvZGVgIGFuZCBgcmVkaXJlY3RfdXJpYCBwcm92aWRlZCBieSB0aGUgY2xpZW50IGZvciBhbiBhY2Nlc3MgdG9rZW4gdXNpbmcgTWljcm9zb2Z0J3MgT0F1dGggQVBJLlxuICogLSAqKkluc2VjdXJlIGF1dGhlbnRpY2F0aW9uKiogdmFsaWRhdGVzIHRoZSB1c2VyIElEIGFuZCBhY2Nlc3MgdG9rZW4gZGlyZWN0bHksIGJ5cGFzc2luZyBPQXV0aCBmbG93cyAobm90IHJlY29tbWVuZGVkKS4gVGhpcyBtZXRob2QgaXMgZGVwcmVjYXRlZCBhbmQgbWF5IGJlIHJlbW92ZWQgaW4gZnV0dXJlIHZlcnNpb25zLlxuICpcbiAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZG9jcy5taWNyb3NvZnQuY29tL2VuLXVzL2dyYXBoL2F1dGgvYXV0aC1jb25jZXB0cyBNaWNyb3NvZnQgQXV0aGVudGljYXRpb24gRG9jdW1lbnRhdGlvbn1cbiAqL1xuXG5pbXBvcnQgQmFzZUF1dGhDb2RlQWRhcHRlciBmcm9tICcuL0Jhc2VDb2RlQXV0aEFkYXB0ZXInO1xuY2xhc3MgTWljcm9zb2Z0QWRhcHRlciBleHRlbmRzIEJhc2VBdXRoQ29kZUFkYXB0ZXIge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcignTWljcm9zb2Z0Jyk7XG4gIH1cbiAgYXN5bmMgZ2V0VXNlckZyb21BY2Nlc3NUb2tlbihhY2Nlc3NfdG9rZW4pIHtcbiAgICBjb25zdCB1c2VyUmVzcG9uc2UgPSBhd2FpdCBmZXRjaCgnaHR0cHM6Ly9ncmFwaC5taWNyb3NvZnQuY29tL3YxLjAvbWUnLCB7XG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIEF1dGhvcml6YXRpb246ICdCZWFyZXIgJyArIGFjY2Vzc190b2tlbixcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBpZiAoIXVzZXJSZXNwb25zZS5vaykge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsICdNaWNyb3NvZnQgQVBJIHJlcXVlc3QgZmFpbGVkLicpO1xuICAgIH1cblxuICAgIHJldHVybiB1c2VyUmVzcG9uc2UuanNvbigpO1xuICB9XG5cbiAgYXN5bmMgZ2V0QWNjZXNzVG9rZW5Gcm9tQ29kZShhdXRoRGF0YSkge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goJ2h0dHBzOi8vbG9naW4ubWljcm9zb2Z0b25saW5lLmNvbS9jb21tb24vb2F1dGgyL3YyLjAvdG9rZW4nLCB7XG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnLFxuICAgICAgfSxcbiAgICAgIGJvZHk6IG5ldyBVUkxTZWFyY2hQYXJhbXMoe1xuICAgICAgICBjbGllbnRfaWQ6IHRoaXMuY2xpZW50SWQsXG4gICAgICAgIGNsaWVudF9zZWNyZXQ6IHRoaXMuY2xpZW50U2VjcmV0LFxuICAgICAgICBncmFudF90eXBlOiAnYXV0aG9yaXphdGlvbl9jb2RlJyxcbiAgICAgICAgcmVkaXJlY3RfdXJpOiBhdXRoRGF0YS5yZWRpcmVjdF91cmksXG4gICAgICAgIGNvZGU6IGF1dGhEYXRhLmNvZGUsXG4gICAgICB9KSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELCAnTWljcm9zb2Z0IEFQSSByZXF1ZXN0IGZhaWxlZC4nKTtcbiAgICB9XG5cbiAgICBjb25zdCBqc29uID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuICAgIHJldHVybiBqc29uLmFjY2Vzc190b2tlbjtcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBuZXcgTWljcm9zb2Z0QWRhcHRlcigpO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFpRUEsSUFBQUEsb0JBQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUF3RCxTQUFBRCx1QkFBQUUsQ0FBQSxXQUFBQSxDQUFBLElBQUFBLENBQUEsQ0FBQUMsVUFBQSxHQUFBRCxDQUFBLEtBQUFFLE9BQUEsRUFBQUYsQ0FBQTtBQWpFeEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBR0EsTUFBTUcsZ0JBQWdCLFNBQVNDLDRCQUFtQixDQUFDO0VBQ2pEQyxXQUFXQSxDQUFBLEVBQUc7SUFDWixLQUFLLENBQUMsV0FBVyxDQUFDO0VBQ3BCO0VBQ0EsTUFBTUMsc0JBQXNCQSxDQUFDQyxZQUFZLEVBQUU7SUFDekMsTUFBTUMsWUFBWSxHQUFHLE1BQU1DLEtBQUssQ0FBQyxxQ0FBcUMsRUFBRTtNQUN0RUMsT0FBTyxFQUFFO1FBQ1BDLGFBQWEsRUFBRSxTQUFTLEdBQUdKO01BQzdCO0lBQ0YsQ0FBQyxDQUFDO0lBRUYsSUFBSSxDQUFDQyxZQUFZLENBQUNJLEVBQUUsRUFBRTtNQUNwQixNQUFNLElBQUlDLEtBQUssQ0FBQ0MsS0FBSyxDQUFDRCxLQUFLLENBQUNDLEtBQUssQ0FBQ0MsZ0JBQWdCLEVBQUUsK0JBQStCLENBQUM7SUFDdEY7SUFFQSxPQUFPUCxZQUFZLENBQUNRLElBQUksQ0FBQyxDQUFDO0VBQzVCO0VBRUEsTUFBTUMsc0JBQXNCQSxDQUFDQyxRQUFRLEVBQUU7SUFDckMsTUFBTUMsUUFBUSxHQUFHLE1BQU1WLEtBQUssQ0FBQyw0REFBNEQsRUFBRTtNQUN6RlcsTUFBTSxFQUFFLE1BQU07TUFDZFYsT0FBTyxFQUFFO1FBQ1AsY0FBYyxFQUFFO01BQ2xCLENBQUM7TUFDRFcsSUFBSSxFQUFFLElBQUlDLGVBQWUsQ0FBQztRQUN4QkMsU0FBUyxFQUFFLElBQUksQ0FBQ0MsUUFBUTtRQUN4QkMsYUFBYSxFQUFFLElBQUksQ0FBQ0MsWUFBWTtRQUNoQ0MsVUFBVSxFQUFFLG9CQUFvQjtRQUNoQ0MsWUFBWSxFQUFFVixRQUFRLENBQUNVLFlBQVk7UUFDbkNDLElBQUksRUFBRVgsUUFBUSxDQUFDVztNQUNqQixDQUFDO0lBQ0gsQ0FBQyxDQUFDO0lBRUYsSUFBSSxDQUFDVixRQUFRLENBQUNQLEVBQUUsRUFBRTtNQUNoQixNQUFNLElBQUlDLEtBQUssQ0FBQ0MsS0FBSyxDQUFDRCxLQUFLLENBQUNDLEtBQUssQ0FBQ0MsZ0JBQWdCLEVBQUUsK0JBQStCLENBQUM7SUFDdEY7SUFFQSxNQUFNQyxJQUFJLEdBQUcsTUFBTUcsUUFBUSxDQUFDSCxJQUFJLENBQUMsQ0FBQztJQUNsQyxPQUFPQSxJQUFJLENBQUNULFlBQVk7RUFDMUI7QUFDRjtBQUFDLElBQUF1QixRQUFBLEdBQUFDLE9BQUEsQ0FBQTdCLE9BQUEsR0FFYyxJQUFJQyxnQkFBZ0IsQ0FBQyxDQUFDIiwiaWdub3JlTGlzdCI6W119
|