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
|
@@ -1,55 +1,125 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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 GitHub.
|
|
11
|
+
* @class GitHubAdapter
|
|
12
|
+
* @param {Object} options - The adapter configuration options.
|
|
13
|
+
* @param {string} options.clientId - The GitHub App Client ID. Required for secure authentication.
|
|
14
|
+
* @param {string} options.clientSecret - The GitHub App Client Secret. Required for secure authentication.
|
|
15
|
+
* @param {boolean} [options.enableInsecureAuth=false] - **[DEPRECATED]** Enable insecure authentication (not recommended).
|
|
16
|
+
*
|
|
17
|
+
* @param {Object} authData - The authentication data provided by the client.
|
|
18
|
+
* @param {string} authData.code - The authorization code from GitHub. Required for secure authentication.
|
|
19
|
+
* @param {string} [authData.id] - **[DEPRECATED]** The GitHub user ID (required for insecure authentication).
|
|
20
|
+
* @param {string} [authData.access_token] - **[DEPRECATED]** The GitHub access token (required for insecure authentication).
|
|
21
|
+
*
|
|
22
|
+
* @description
|
|
23
|
+
* ## Parse Server Configuration
|
|
24
|
+
* * To configure Parse Server for GitHub authentication, use the following structure:
|
|
25
|
+
* ```json
|
|
26
|
+
* {
|
|
27
|
+
* "auth": {
|
|
28
|
+
* "github": {
|
|
29
|
+
* "clientId": "12345",
|
|
30
|
+
* "clientSecret": "abcde"
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* The GitHub adapter exchanges the `authData.code` provided by the client for an access token using GitHub's OAuth API. The following `authData` field is required:
|
|
36
|
+
* - `code`
|
|
37
|
+
*
|
|
38
|
+
* ## Insecure Authentication (Not Recommended)
|
|
39
|
+
* Insecure authentication uses the `authData.id` and `authData.access_token` provided by the client. This flow is insecure, deprecated, and poses potential security risks. The following `authData` fields are required:
|
|
40
|
+
* - `id` (**[DEPRECATED]**): The GitHub user ID.
|
|
41
|
+
* - `access_token` (**[DEPRECATED]**): The GitHub access token.
|
|
42
|
+
* To configure Parse Server for insecure authentication, use the following structure:
|
|
43
|
+
* ```json
|
|
44
|
+
* {
|
|
45
|
+
* "auth": {
|
|
46
|
+
* "github": {
|
|
47
|
+
* "enableInsecureAuth": true
|
|
48
|
+
* }
|
|
49
|
+
* }
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* ### Deprecation Notice
|
|
53
|
+
* The `enableInsecureAuth` option and insecure `authData` fields (`id`, `access_token`) are deprecated and will be removed in future versions. Use secure authentication with `clientId` and `clientSecret`.
|
|
54
|
+
*
|
|
55
|
+
* @example <caption>Secure Authentication Example</caption>
|
|
56
|
+
* // Example authData for secure authentication:
|
|
57
|
+
* const authData = {
|
|
58
|
+
* github: {
|
|
59
|
+
* code: "abc123def456ghi789"
|
|
60
|
+
* }
|
|
61
|
+
* };
|
|
62
|
+
*
|
|
63
|
+
* @example <caption>Insecure Authentication Example (Not Recommended)</caption>
|
|
64
|
+
* // Example authData for insecure authentication:
|
|
65
|
+
* const authData = {
|
|
66
|
+
* github: {
|
|
67
|
+
* id: "1234567",
|
|
68
|
+
* access_token: "abc123def456ghi789" // Deprecated.
|
|
69
|
+
* }
|
|
70
|
+
* };
|
|
71
|
+
*
|
|
72
|
+
* @note `enableInsecureAuth` will be removed in future versions. Use secure authentication with `clientId` and `clientSecret`.
|
|
73
|
+
* @note Secure authentication exchanges the `code` provided by the client for an access token using GitHub's OAuth API.
|
|
74
|
+
*
|
|
75
|
+
* @see {@link https://docs.github.com/en/developers/apps/authorizing-oauth-apps GitHub OAuth Documentation}
|
|
76
|
+
*/
|
|
6
77
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
78
|
+
class GitHubAdapter extends _BaseCodeAuthAdapter.default {
|
|
79
|
+
constructor() {
|
|
80
|
+
super('GitHub');
|
|
81
|
+
}
|
|
82
|
+
async getAccessTokenFromCode(authData) {
|
|
83
|
+
const tokenUrl = 'https://github.com/login/oauth/access_token';
|
|
84
|
+
const response = await fetch(tokenUrl, {
|
|
85
|
+
method: 'POST',
|
|
86
|
+
headers: {
|
|
87
|
+
'Content-Type': 'application/json',
|
|
88
|
+
Accept: 'application/json'
|
|
89
|
+
},
|
|
90
|
+
body: JSON.stringify({
|
|
91
|
+
client_id: this.clientId,
|
|
92
|
+
client_secret: this.clientSecret,
|
|
93
|
+
code: authData.code
|
|
94
|
+
})
|
|
95
|
+
});
|
|
96
|
+
if (!response.ok) {
|
|
97
|
+
throw new Parse.Error(Parse.Error.VALIDATION_ERROR, `Failed to exchange code for token: ${response.statusText}`);
|
|
12
98
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
function request(path, access_token) {
|
|
24
|
-
return new Promise(function (resolve, reject) {
|
|
25
|
-
https.get({
|
|
26
|
-
host: 'api.github.com',
|
|
27
|
-
path: '/' + path,
|
|
99
|
+
const data = await response.json();
|
|
100
|
+
if (data.error) {
|
|
101
|
+
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, data.error_description || data.error);
|
|
102
|
+
}
|
|
103
|
+
return data.access_token;
|
|
104
|
+
}
|
|
105
|
+
async getUserFromAccessToken(accessToken) {
|
|
106
|
+
const userApiUrl = 'https://api.github.com/user';
|
|
107
|
+
const response = await fetch(userApiUrl, {
|
|
108
|
+
method: 'GET',
|
|
28
109
|
headers: {
|
|
29
|
-
|
|
30
|
-
|
|
110
|
+
Authorization: `Bearer ${accessToken}`,
|
|
111
|
+
Accept: 'application/json'
|
|
31
112
|
}
|
|
32
|
-
}, function (res) {
|
|
33
|
-
var data = '';
|
|
34
|
-
res.on('data', function (chunk) {
|
|
35
|
-
data += chunk;
|
|
36
|
-
});
|
|
37
|
-
res.on('end', function () {
|
|
38
|
-
try {
|
|
39
|
-
data = JSON.parse(data);
|
|
40
|
-
} catch (e) {
|
|
41
|
-
return reject(e);
|
|
42
|
-
}
|
|
43
|
-
resolve(data);
|
|
44
|
-
});
|
|
45
|
-
}).on('error', function () {
|
|
46
|
-
reject('Failed to validate this access token with Github.');
|
|
47
113
|
});
|
|
48
|
-
|
|
114
|
+
if (!response.ok) {
|
|
115
|
+
throw new Parse.Error(Parse.Error.VALIDATION_ERROR, `Failed to fetch GitHub user: ${response.statusText}`);
|
|
116
|
+
}
|
|
117
|
+
const userData = await response.json();
|
|
118
|
+
if (!userData.id || !userData.login) {
|
|
119
|
+
throw new Parse.Error(Parse.Error.VALIDATION_ERROR, 'Invalid GitHub user data received.');
|
|
120
|
+
}
|
|
121
|
+
return userData;
|
|
122
|
+
}
|
|
49
123
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
validateAppId: validateAppId,
|
|
53
|
-
validateAuthData: validateAuthData
|
|
54
|
-
};
|
|
55
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2dpdGh1Yi5qcyJdLCJuYW1lcyI6WyJodHRwcyIsInJlcXVpcmUiLCJQYXJzZSIsInZhbGlkYXRlQXV0aERhdGEiLCJhdXRoRGF0YSIsInJlcXVlc3QiLCJhY2Nlc3NfdG9rZW4iLCJ0aGVuIiwiZGF0YSIsImlkIiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwidmFsaWRhdGVBcHBJZCIsIlByb21pc2UiLCJyZXNvbHZlIiwicGF0aCIsInJlamVjdCIsImdldCIsImhvc3QiLCJoZWFkZXJzIiwicmVzIiwib24iLCJjaHVuayIsIkpTT04iLCJwYXJzZSIsImUiLCJtb2R1bGUiLCJleHBvcnRzIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0EsSUFBSUEsUUFBUUMsUUFBUSxPQUFSLENBQVo7QUFDQSxJQUFJQyxRQUFRRCxRQUFRLFlBQVIsRUFBc0JDLEtBQWxDOztBQUVBO0FBQ0EsU0FBU0MsZ0JBQVQsQ0FBMEJDLFFBQTFCLEVBQW9DO0FBQ2xDLFNBQU9DLFFBQVEsTUFBUixFQUFnQkQsU0FBU0UsWUFBekIsRUFDSkMsSUFESSxDQUNFQyxJQUFELElBQVU7QUFDZCxRQUFJQSxRQUFRQSxLQUFLQyxFQUFMLElBQVdMLFNBQVNLLEVBQWhDLEVBQW9DO0FBQ2xDO0FBQ0Q7QUFDRCxVQUFNLElBQUlQLE1BQU1RLEtBQVYsQ0FDSlIsTUFBTVEsS0FBTixDQUFZQyxnQkFEUixFQUVKLHVDQUZJLENBQU47QUFHRCxHQVJJLENBQVA7QUFTRDs7QUFFRDtBQUNBLFNBQVNDLGFBQVQsR0FBeUI7QUFDdkIsU0FBT0MsUUFBUUMsT0FBUixFQUFQO0FBQ0Q7O0FBRUQ7QUFDQSxTQUFTVCxPQUFULENBQWlCVSxJQUFqQixFQUF1QlQsWUFBdkIsRUFBcUM7QUFDbkMsU0FBTyxJQUFJTyxPQUFKLENBQVksVUFBU0MsT0FBVCxFQUFrQkUsTUFBbEIsRUFBMEI7QUFDM0NoQixVQUFNaUIsR0FBTixDQUFVO0FBQ1JDLFlBQU0sZ0JBREU7QUFFUkgsWUFBTSxNQUFNQSxJQUZKO0FBR1JJLGVBQVM7QUFDUCx5QkFBaUIsWUFBWWIsWUFEdEI7QUFFUCxzQkFBYztBQUZQO0FBSEQsS0FBVixFQU9HLFVBQVNjLEdBQVQsRUFBYztBQUNmLFVBQUlaLE9BQU8sRUFBWDtBQUNBWSxVQUFJQyxFQUFKLENBQU8sTUFBUCxFQUFlLFVBQVNDLEtBQVQsRUFBZ0I7QUFDN0JkLGdCQUFRYyxLQUFSO0FBQ0QsT0FGRDtBQUdBRixVQUFJQyxFQUFKLENBQU8sS0FBUCxFQUFjLFlBQVc7QUFDdkIsWUFBSTtBQUNGYixpQkFBT2UsS0FBS0MsS0FBTCxDQUFXaEIsSUFBWCxDQUFQO0FBQ0QsU0FGRCxDQUVFLE9BQU1pQixDQUFOLEVBQVM7QUFDVCxpQkFBT1QsT0FBT1MsQ0FBUCxDQUFQO0FBQ0Q7QUFDRFgsZ0JBQVFOLElBQVI7QUFDRCxPQVBEO0FBUUQsS0FwQkQsRUFvQkdhLEVBcEJILENBb0JNLE9BcEJOLEVBb0JlLFlBQVc7QUFDeEJMLGFBQU8sbURBQVA7QUFDRCxLQXRCRDtBQXVCRCxHQXhCTSxDQUFQO0FBeUJEOztBQUVEVSxPQUFPQyxPQUFQLEdBQWlCO0FBQ2ZmLGlCQUFlQSxhQURBO0FBRWZULG9CQUFrQkE7QUFGSCxDQUFqQiIsImZpbGUiOiJnaXRodWIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBIZWxwZXIgZnVuY3Rpb25zIGZvciBhY2Nlc3NpbmcgdGhlIGdpdGh1YiBBUEkuXG52YXIgaHR0cHMgPSByZXF1aXJlKCdodHRwcycpO1xudmFyIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmZiB0aGlzIHVzZXIgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUF1dGhEYXRhKGF1dGhEYXRhKSB7XG4gIHJldHVybiByZXF1ZXN0KCd1c2VyJywgYXV0aERhdGEuYWNjZXNzX3Rva2VuKVxuICAgIC50aGVuKChkYXRhKSA9PiB7XG4gICAgICBpZiAoZGF0YSAmJiBkYXRhLmlkID09IGF1dGhEYXRhLmlkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICAgJ0dpdGh1YiBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nKTtcbiAgICB9KTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZmYgdGhpcyBhcHAgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKCkge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59XG5cbi8vIEEgcHJvbWlzZXkgd3JhcHBlciBmb3IgYXBpIHJlcXVlc3RzXG5mdW5jdGlvbiByZXF1ZXN0KHBhdGgsIGFjY2Vzc190b2tlbikge1xuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgaHR0cHMuZ2V0KHtcbiAgICAgIGhvc3Q6ICdhcGkuZ2l0aHViLmNvbScsXG4gICAgICBwYXRoOiAnLycgKyBwYXRoLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnQXV0aG9yaXphdGlvbic6ICdiZWFyZXIgJyArIGFjY2Vzc190b2tlbixcbiAgICAgICAgJ1VzZXItQWdlbnQnOiAncGFyc2Utc2VydmVyJ1xuICAgICAgfVxuICAgIH0sIGZ1bmN0aW9uKHJlcykge1xuICAgICAgdmFyIGRhdGEgPSAnJztcbiAgICAgIHJlcy5vbignZGF0YScsIGZ1bmN0aW9uKGNodW5rKSB7XG4gICAgICAgIGRhdGEgKz0gY2h1bms7XG4gICAgICB9KTtcbiAgICAgIHJlcy5vbignZW5kJywgZnVuY3Rpb24oKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZGF0YSA9IEpTT04ucGFyc2UoZGF0YSk7XG4gICAgICAgIH0gY2F0Y2goZSkge1xuICAgICAgICAgIHJldHVybiByZWplY3QoZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmVzb2x2ZShkYXRhKTtcbiAgICAgIH0pO1xuICAgIH0pLm9uKCdlcnJvcicsIGZ1bmN0aW9uKCkge1xuICAgICAgcmVqZWN0KCdGYWlsZWQgdG8gdmFsaWRhdGUgdGhpcyBhY2Nlc3MgdG9rZW4gd2l0aCBHaXRodWIuJyk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgdmFsaWRhdGVBcHBJZDogdmFsaWRhdGVBcHBJZCxcbiAgdmFsaWRhdGVBdXRoRGF0YTogdmFsaWRhdGVBdXRoRGF0YVxufTtcbiJdfQ==
|
|
124
|
+
var _default = exports.default = new GitHubAdapter();
|
|
125
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfQmFzZUNvZGVBdXRoQWRhcHRlciIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJyZXF1aXJlIiwiZSIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiR2l0SHViQWRhcHRlciIsIkJhc2VDb2RlQXV0aEFkYXB0ZXIiLCJjb25zdHJ1Y3RvciIsImdldEFjY2Vzc1Rva2VuRnJvbUNvZGUiLCJhdXRoRGF0YSIsInRva2VuVXJsIiwicmVzcG9uc2UiLCJmZXRjaCIsIm1ldGhvZCIsImhlYWRlcnMiLCJBY2NlcHQiLCJib2R5IiwiSlNPTiIsInN0cmluZ2lmeSIsImNsaWVudF9pZCIsImNsaWVudElkIiwiY2xpZW50X3NlY3JldCIsImNsaWVudFNlY3JldCIsImNvZGUiLCJvayIsIlBhcnNlIiwiRXJyb3IiLCJWQUxJREFUSU9OX0VSUk9SIiwic3RhdHVzVGV4dCIsImRhdGEiLCJqc29uIiwiZXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwiZXJyb3JfZGVzY3JpcHRpb24iLCJhY2Nlc3NfdG9rZW4iLCJnZXRVc2VyRnJvbUFjY2Vzc1Rva2VuIiwiYWNjZXNzVG9rZW4iLCJ1c2VyQXBpVXJsIiwiQXV0aG9yaXphdGlvbiIsInVzZXJEYXRhIiwiaWQiLCJsb2dpbiIsIl9kZWZhdWx0IiwiZXhwb3J0cyJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2dpdGh1Yi5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFBhcnNlIFNlcnZlciBhdXRoZW50aWNhdGlvbiBhZGFwdGVyIGZvciBHaXRIdWIuXG4gKiBAY2xhc3MgR2l0SHViQWRhcHRlclxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBUaGUgYWRhcHRlciBjb25maWd1cmF0aW9uIG9wdGlvbnMuXG4gKiBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy5jbGllbnRJZCAtIFRoZSBHaXRIdWIgQXBwIENsaWVudCBJRC4gUmVxdWlyZWQgZm9yIHNlY3VyZSBhdXRoZW50aWNhdGlvbi5cbiAqIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLmNsaWVudFNlY3JldCAtIFRoZSBHaXRIdWIgQXBwIENsaWVudCBTZWNyZXQuIFJlcXVpcmVkIGZvciBzZWN1cmUgYXV0aGVudGljYXRpb24uXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmVuYWJsZUluc2VjdXJlQXV0aD1mYWxzZV0gLSAqKltERVBSRUNBVEVEXSoqIEVuYWJsZSBpbnNlY3VyZSBhdXRoZW50aWNhdGlvbiAobm90IHJlY29tbWVuZGVkKS5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gYXV0aERhdGEgLSBUaGUgYXV0aGVudGljYXRpb24gZGF0YSBwcm92aWRlZCBieSB0aGUgY2xpZW50LlxuICogQHBhcmFtIHtzdHJpbmd9IGF1dGhEYXRhLmNvZGUgLSBUaGUgYXV0aG9yaXphdGlvbiBjb2RlIGZyb20gR2l0SHViLiBSZXF1aXJlZCBmb3Igc2VjdXJlIGF1dGhlbnRpY2F0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IFthdXRoRGF0YS5pZF0gLSAqKltERVBSRUNBVEVEXSoqIFRoZSBHaXRIdWIgdXNlciBJRCAocmVxdWlyZWQgZm9yIGluc2VjdXJlIGF1dGhlbnRpY2F0aW9uKS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBbYXV0aERhdGEuYWNjZXNzX3Rva2VuXSAtICoqW0RFUFJFQ0FURURdKiogVGhlIEdpdEh1YiBhY2Nlc3MgdG9rZW4gKHJlcXVpcmVkIGZvciBpbnNlY3VyZSBhdXRoZW50aWNhdGlvbikuXG4gKlxuICogQGRlc2NyaXB0aW9uXG4gKiAjIyBQYXJzZSBTZXJ2ZXIgQ29uZmlndXJhdGlvblxuICogKiBUbyBjb25maWd1cmUgUGFyc2UgU2VydmVyIGZvciBHaXRIdWIgYXV0aGVudGljYXRpb24sIHVzZSB0aGUgZm9sbG93aW5nIHN0cnVjdHVyZTpcbiAqIGBgYGpzb25cbiAqIHtcbiAqICBcImF1dGhcIjoge1xuICogICBcImdpdGh1YlwiOiB7XG4gKiAgICAgXCJjbGllbnRJZFwiOiBcIjEyMzQ1XCIsXG4gKiAgICAgXCJjbGllbnRTZWNyZXRcIjogXCJhYmNkZVwiXG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICpcbiAqIFRoZSBHaXRIdWIgYWRhcHRlciBleGNoYW5nZXMgdGhlIGBhdXRoRGF0YS5jb2RlYCBwcm92aWRlZCBieSB0aGUgY2xpZW50IGZvciBhbiBhY2Nlc3MgdG9rZW4gdXNpbmcgR2l0SHViJ3MgT0F1dGggQVBJLiBUaGUgZm9sbG93aW5nIGBhdXRoRGF0YWAgZmllbGQgaXMgcmVxdWlyZWQ6XG4gKiAtIGBjb2RlYFxuICpcbiAqICMjIEluc2VjdXJlIEF1dGhlbnRpY2F0aW9uIChOb3QgUmVjb21tZW5kZWQpXG4gKiBJbnNlY3VyZSBhdXRoZW50aWNhdGlvbiB1c2VzIHRoZSBgYXV0aERhdGEuaWRgIGFuZCBgYXV0aERhdGEuYWNjZXNzX3Rva2VuYCBwcm92aWRlZCBieSB0aGUgY2xpZW50LiBUaGlzIGZsb3cgaXMgaW5zZWN1cmUsIGRlcHJlY2F0ZWQsIGFuZCBwb3NlcyBwb3RlbnRpYWwgc2VjdXJpdHkgcmlza3MuIFRoZSBmb2xsb3dpbmcgYGF1dGhEYXRhYCBmaWVsZHMgYXJlIHJlcXVpcmVkOlxuICogLSBgaWRgICgqKltERVBSRUNBVEVEXSoqKTogVGhlIEdpdEh1YiB1c2VyIElELlxuICogLSBgYWNjZXNzX3Rva2VuYCAoKipbREVQUkVDQVRFRF0qKik6IFRoZSBHaXRIdWIgYWNjZXNzIHRva2VuLlxuICogVG8gY29uZmlndXJlIFBhcnNlIFNlcnZlciBmb3IgaW5zZWN1cmUgYXV0aGVudGljYXRpb24sIHVzZSB0aGUgZm9sbG93aW5nIHN0cnVjdHVyZTpcbiAqIGBgYGpzb25cbiAqIHtcbiAqICBcImF1dGhcIjoge1xuICogICAgXCJnaXRodWJcIjoge1xuICogICAgXCJlbmFibGVJbnNlY3VyZUF1dGhcIjogdHJ1ZVxuICogIH1cbiAqIH1cbiAqIGBgYFxuICpcbiAqICMjIyBEZXByZWNhdGlvbiBOb3RpY2VcbiAqIFRoZSBgZW5hYmxlSW5zZWN1cmVBdXRoYCBvcHRpb24gYW5kIGluc2VjdXJlIGBhdXRoRGF0YWAgZmllbGRzIChgaWRgLCBgYWNjZXNzX3Rva2VuYCkgYXJlIGRlcHJlY2F0ZWQgYW5kIHdpbGwgYmUgcmVtb3ZlZCBpbiBmdXR1cmUgdmVyc2lvbnMuIFVzZSBzZWN1cmUgYXV0aGVudGljYXRpb24gd2l0aCBgY2xpZW50SWRgIGFuZCBgY2xpZW50U2VjcmV0YC5cbiAqXG4gKiBAZXhhbXBsZSA8Y2FwdGlvbj5TZWN1cmUgQXV0aGVudGljYXRpb24gRXhhbXBsZTwvY2FwdGlvbj5cbiAqIC8vIEV4YW1wbGUgYXV0aERhdGEgZm9yIHNlY3VyZSBhdXRoZW50aWNhdGlvbjpcbiAqIGNvbnN0IGF1dGhEYXRhID0ge1xuICogICBnaXRodWI6IHtcbiAqICAgICBjb2RlOiBcImFiYzEyM2RlZjQ1NmdoaTc4OVwiXG4gKiAgIH1cbiAqIH07XG4gKlxuICogQGV4YW1wbGUgPGNhcHRpb24+SW5zZWN1cmUgQXV0aGVudGljYXRpb24gRXhhbXBsZSAoTm90IFJlY29tbWVuZGVkKTwvY2FwdGlvbj5cbiAqIC8vIEV4YW1wbGUgYXV0aERhdGEgZm9yIGluc2VjdXJlIGF1dGhlbnRpY2F0aW9uOlxuICogY29uc3QgYXV0aERhdGEgPSB7XG4gKiAgIGdpdGh1Yjoge1xuICogICAgIGlkOiBcIjEyMzQ1NjdcIixcbiAqICAgICBhY2Nlc3NfdG9rZW46IFwiYWJjMTIzZGVmNDU2Z2hpNzg5XCIgLy8gRGVwcmVjYXRlZC5cbiAqICAgfVxuICogfTtcbiAqXG4gKiBAbm90ZSBgZW5hYmxlSW5zZWN1cmVBdXRoYCB3aWxsIGJlIHJlbW92ZWQgaW4gZnV0dXJlIHZlcnNpb25zLiBVc2Ugc2VjdXJlIGF1dGhlbnRpY2F0aW9uIHdpdGggYGNsaWVudElkYCBhbmQgYGNsaWVudFNlY3JldGAuXG4gKiBAbm90ZSBTZWN1cmUgYXV0aGVudGljYXRpb24gZXhjaGFuZ2VzIHRoZSBgY29kZWAgcHJvdmlkZWQgYnkgdGhlIGNsaWVudCBmb3IgYW4gYWNjZXNzIHRva2VuIHVzaW5nIEdpdEh1YidzIE9BdXRoIEFQSS5cbiAqXG4gKiBAc2VlIHtAbGluayBodHRwczovL2RvY3MuZ2l0aHViLmNvbS9lbi9kZXZlbG9wZXJzL2FwcHMvYXV0aG9yaXppbmctb2F1dGgtYXBwcyBHaXRIdWIgT0F1dGggRG9jdW1lbnRhdGlvbn1cbiAqL1xuXG5pbXBvcnQgQmFzZUNvZGVBdXRoQWRhcHRlciBmcm9tICcuL0Jhc2VDb2RlQXV0aEFkYXB0ZXInO1xuY2xhc3MgR2l0SHViQWRhcHRlciBleHRlbmRzIEJhc2VDb2RlQXV0aEFkYXB0ZXIge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcignR2l0SHViJyk7XG4gIH1cbiAgYXN5bmMgZ2V0QWNjZXNzVG9rZW5Gcm9tQ29kZShhdXRoRGF0YSkge1xuICAgIGNvbnN0IHRva2VuVXJsID0gJ2h0dHBzOi8vZ2l0aHViLmNvbS9sb2dpbi9vYXV0aC9hY2Nlc3NfdG9rZW4nO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godG9rZW5VcmwsIHtcbiAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICBBY2NlcHQ6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgIH0sXG4gICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgIGNsaWVudF9pZDogdGhpcy5jbGllbnRJZCxcbiAgICAgICAgY2xpZW50X3NlY3JldDogdGhpcy5jbGllbnRTZWNyZXQsXG4gICAgICAgIGNvZGU6IGF1dGhEYXRhLmNvZGUsXG4gICAgICB9KSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5WQUxJREFUSU9OX0VSUk9SLCBgRmFpbGVkIHRvIGV4Y2hhbmdlIGNvZGUgZm9yIHRva2VuOiAke3Jlc3BvbnNlLnN0YXR1c1RleHR9YCk7XG4gICAgfVxuXG4gICAgY29uc3QgZGF0YSA9IGF3YWl0IHJlc3BvbnNlLmpzb24oKTtcbiAgICBpZiAoZGF0YS5lcnJvcikge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsIGRhdGEuZXJyb3JfZGVzY3JpcHRpb24gfHwgZGF0YS5lcnJvcik7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRhdGEuYWNjZXNzX3Rva2VuO1xuICB9XG5cbiAgYXN5bmMgZ2V0VXNlckZyb21BY2Nlc3NUb2tlbihhY2Nlc3NUb2tlbikge1xuICAgIGNvbnN0IHVzZXJBcGlVcmwgPSAnaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS91c2VyJztcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHVzZXJBcGlVcmwsIHtcbiAgICAgIG1ldGhvZDogJ0dFVCcsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIEF1dGhvcml6YXRpb246IGBCZWFyZXIgJHthY2Nlc3NUb2tlbn1gLFxuICAgICAgICBBY2NlcHQ6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBpZiAoIXJlc3BvbnNlLm9rKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuVkFMSURBVElPTl9FUlJPUiwgYEZhaWxlZCB0byBmZXRjaCBHaXRIdWIgdXNlcjogJHtyZXNwb25zZS5zdGF0dXNUZXh0fWApO1xuICAgIH1cblxuICAgIGNvbnN0IHVzZXJEYXRhID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuICAgIGlmICghdXNlckRhdGEuaWQgfHwgIXVzZXJEYXRhLmxvZ2luKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuVkFMSURBVElPTl9FUlJPUiwgJ0ludmFsaWQgR2l0SHViIHVzZXIgZGF0YSByZWNlaXZlZC4nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdXNlckRhdGE7XG4gIH1cblxufVxuXG5leHBvcnQgZGVmYXVsdCBuZXcgR2l0SHVi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
|
|
@@ -1,71 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse Server authentication adapter for Google.
|
|
3
|
+
*
|
|
4
|
+
* @class GoogleAdapter
|
|
5
|
+
* @param {Object} options - The adapter configuration options.
|
|
6
|
+
* @param {string} options.clientId - Your Google application Client ID. Required for authentication.
|
|
7
|
+
*
|
|
8
|
+
* @description
|
|
9
|
+
* ## Parse Server Configuration
|
|
10
|
+
* To configure Parse Server for Google authentication, use the following structure:
|
|
11
|
+
* ```json
|
|
12
|
+
* {
|
|
13
|
+
* "auth": {
|
|
14
|
+
* "google": {
|
|
15
|
+
* "clientId": "your-client-id"
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* The adapter requires the following `authData` fields:
|
|
22
|
+
* - **id**: The Google user ID.
|
|
23
|
+
* - **id_token**: The Google ID token.
|
|
24
|
+
* - **access_token**: The Google access token.
|
|
25
|
+
*
|
|
26
|
+
* ## Auth Payload
|
|
27
|
+
* ### Example Auth Data Payload
|
|
28
|
+
* ```json
|
|
29
|
+
* {
|
|
30
|
+
* "google": {
|
|
31
|
+
* "id": "1234567",
|
|
32
|
+
* "id_token": "xxxxx.yyyyy.zzzzz",
|
|
33
|
+
* "access_token": "abc123def456ghi789"
|
|
34
|
+
* }
|
|
35
|
+
* }
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* ## Notes
|
|
39
|
+
* - Ensure your Google Client ID is configured properly in the Parse Server configuration.
|
|
40
|
+
* - The `id_token` and `access_token` are validated against Google's authentication services.
|
|
41
|
+
*
|
|
42
|
+
* @see {@link https://developers.google.com/identity/sign-in/web/backend-auth Google Authentication Documentation}
|
|
43
|
+
*/
|
|
44
|
+
|
|
1
45
|
'use strict';
|
|
2
46
|
|
|
3
47
|
// Helper functions for accessing the google API.
|
|
4
|
-
var https = require('https');
|
|
5
48
|
var Parse = require('parse/node').Parse;
|
|
49
|
+
const https = require('https');
|
|
50
|
+
const jwt = require('jsonwebtoken');
|
|
51
|
+
const authUtils = require('./utils');
|
|
52
|
+
const TOKEN_ISSUER = 'accounts.google.com';
|
|
53
|
+
const HTTPS_TOKEN_ISSUER = 'https://accounts.google.com';
|
|
54
|
+
let cache = {};
|
|
6
55
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
56
|
+
// Retrieve Google Signin Keys (with cache control)
|
|
57
|
+
function getGoogleKeyByKeyId(keyId) {
|
|
58
|
+
if (cache[keyId] && cache.expiresAt > new Date()) {
|
|
59
|
+
return cache[keyId];
|
|
60
|
+
}
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
https.get(`https://www.googleapis.com/oauth2/v3/certs`, res => {
|
|
63
|
+
let data = '';
|
|
64
|
+
res.on('data', chunk => {
|
|
65
|
+
data += chunk.toString('utf8');
|
|
66
|
+
});
|
|
67
|
+
res.on('end', () => {
|
|
68
|
+
const {
|
|
69
|
+
keys
|
|
70
|
+
} = JSON.parse(data);
|
|
71
|
+
const pems = keys.reduce((pems, {
|
|
72
|
+
n: modulus,
|
|
73
|
+
e: exposant,
|
|
74
|
+
kid
|
|
75
|
+
}) => Object.assign(pems, {
|
|
76
|
+
[kid]: rsaPublicKeyToPEM(modulus, exposant)
|
|
77
|
+
}), {});
|
|
78
|
+
if (res.headers['cache-control']) {
|
|
79
|
+
var expire = res.headers['cache-control'].match(/max-age=([0-9]+)/);
|
|
80
|
+
if (expire) {
|
|
81
|
+
cache = Object.assign({}, pems, {
|
|
82
|
+
expiresAt: new Date(new Date().getTime() + Number(expire[1]) * 1000)
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
resolve(pems[keyId]);
|
|
87
|
+
});
|
|
88
|
+
}).on('error', reject);
|
|
13
89
|
});
|
|
14
90
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
91
|
+
async function verifyIdToken({
|
|
92
|
+
id_token: token,
|
|
93
|
+
id
|
|
94
|
+
}, {
|
|
95
|
+
clientId
|
|
96
|
+
}) {
|
|
97
|
+
if (!token) {
|
|
98
|
+
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, `id token is invalid for this user.`);
|
|
99
|
+
}
|
|
100
|
+
const {
|
|
101
|
+
kid: keyId,
|
|
102
|
+
alg: algorithm
|
|
103
|
+
} = authUtils.getHeaderFromToken(token);
|
|
104
|
+
let jwtClaims;
|
|
105
|
+
const googleKey = await getGoogleKeyByKeyId(keyId);
|
|
106
|
+
try {
|
|
107
|
+
jwtClaims = jwt.verify(token, googleKey, {
|
|
108
|
+
algorithms: algorithm,
|
|
109
|
+
audience: clientId
|
|
110
|
+
});
|
|
111
|
+
} catch (exception) {
|
|
112
|
+
const message = exception.message;
|
|
113
|
+
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, `${message}`);
|
|
114
|
+
}
|
|
115
|
+
if (jwtClaims.iss !== TOKEN_ISSUER && jwtClaims.iss !== HTTPS_TOKEN_ISSUER) {
|
|
116
|
+
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, `id token not issued by correct provider - expected: ${TOKEN_ISSUER} or ${HTTPS_TOKEN_ISSUER} | from: ${jwtClaims.iss}`);
|
|
117
|
+
}
|
|
118
|
+
if (jwtClaims.sub !== id) {
|
|
119
|
+
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, `auth data is invalid for this user.`);
|
|
120
|
+
}
|
|
121
|
+
if (clientId && jwtClaims.aud !== clientId) {
|
|
122
|
+
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, `id token not authorized for this clientId.`);
|
|
123
|
+
}
|
|
124
|
+
return jwtClaims;
|
|
23
125
|
}
|
|
24
126
|
|
|
25
127
|
// Returns a promise that fulfills if this user id is valid.
|
|
26
|
-
function validateAuthData(authData) {
|
|
27
|
-
|
|
28
|
-
return validateIdToken(authData.id, authData.id_token);
|
|
29
|
-
} else {
|
|
30
|
-
return validateAuthToken(authData.id, authData.access_token).then(() => {
|
|
31
|
-
// Validation with auth token worked
|
|
32
|
-
return;
|
|
33
|
-
}, () => {
|
|
34
|
-
// Try with the id_token param
|
|
35
|
-
return validateIdToken(authData.id, authData.access_token);
|
|
36
|
-
});
|
|
37
|
-
}
|
|
128
|
+
function validateAuthData(authData, options = {}) {
|
|
129
|
+
return verifyIdToken(authData, options);
|
|
38
130
|
}
|
|
39
131
|
|
|
40
132
|
// Returns a promise that fulfills if this app id is valid.
|
|
41
133
|
function validateAppId() {
|
|
42
134
|
return Promise.resolve();
|
|
43
135
|
}
|
|
44
|
-
|
|
45
|
-
// A promisey wrapper for api requests
|
|
46
|
-
function request(path) {
|
|
47
|
-
return new Promise(function (resolve, reject) {
|
|
48
|
-
https.get("https://www.googleapis.com/oauth2/v3/" + path, function (res) {
|
|
49
|
-
var data = '';
|
|
50
|
-
res.on('data', function (chunk) {
|
|
51
|
-
data += chunk;
|
|
52
|
-
});
|
|
53
|
-
res.on('end', function () {
|
|
54
|
-
try {
|
|
55
|
-
data = JSON.parse(data);
|
|
56
|
-
} catch (e) {
|
|
57
|
-
return reject(e);
|
|
58
|
-
}
|
|
59
|
-
resolve(data);
|
|
60
|
-
});
|
|
61
|
-
}).on('error', function () {
|
|
62
|
-
reject('Failed to validate this access token with Google.');
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
|
|
67
136
|
module.exports = {
|
|
68
137
|
validateAppId: validateAppId,
|
|
69
138
|
validateAuthData: validateAuthData
|
|
70
139
|
};
|
|
71
|
-
|
|
140
|
+
|
|
141
|
+
// Helpers functions to convert the RSA certs to PEM (from jwks-rsa)
|
|
142
|
+
function rsaPublicKeyToPEM(modulusB64, exponentB64) {
|
|
143
|
+
const modulus = new Buffer(modulusB64, 'base64');
|
|
144
|
+
const exponent = new Buffer(exponentB64, 'base64');
|
|
145
|
+
const modulusHex = prepadSigned(modulus.toString('hex'));
|
|
146
|
+
const exponentHex = prepadSigned(exponent.toString('hex'));
|
|
147
|
+
const modlen = modulusHex.length / 2;
|
|
148
|
+
const explen = exponentHex.length / 2;
|
|
149
|
+
const encodedModlen = encodeLengthHex(modlen);
|
|
150
|
+
const encodedExplen = encodeLengthHex(explen);
|
|
151
|
+
const encodedPubkey = '30' + encodeLengthHex(modlen + explen + encodedModlen.length / 2 + encodedExplen.length / 2 + 2) + '02' + encodedModlen + modulusHex + '02' + encodedExplen + exponentHex;
|
|
152
|
+
const der = new Buffer(encodedPubkey, 'hex').toString('base64');
|
|
153
|
+
let pem = '-----BEGIN RSA PUBLIC KEY-----\n';
|
|
154
|
+
pem += `${der.match(/.{1,64}/g).join('\n')}`;
|
|
155
|
+
pem += '\n-----END RSA PUBLIC KEY-----\n';
|
|
156
|
+
return pem;
|
|
157
|
+
}
|
|
158
|
+
function prepadSigned(hexStr) {
|
|
159
|
+
const msb = hexStr[0];
|
|
160
|
+
if (msb < '0' || msb > '7') {
|
|
161
|
+
return `00${hexStr}`;
|
|
162
|
+
}
|
|
163
|
+
return hexStr;
|
|
164
|
+
}
|
|
165
|
+
function toHex(number) {
|
|
166
|
+
const nstr = number.toString(16);
|
|
167
|
+
if (nstr.length % 2) {
|
|
168
|
+
return `0${nstr}`;
|
|
169
|
+
}
|
|
170
|
+
return nstr;
|
|
171
|
+
}
|
|
172
|
+
function encodeLengthHex(n) {
|
|
173
|
+
if (n <= 127) {
|
|
174
|
+
return toHex(n);
|
|
175
|
+
}
|
|
176
|
+
const nHex = toHex(n);
|
|
177
|
+
const lengthOfLengthByte = 128 + nHex.length / 2;
|
|
178
|
+
return toHex(lengthOfLengthByte) + nHex;
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJQYXJzZSIsInJlcXVpcmUiLCJodHRwcyIsImp3dCIsImF1dGhVdGlscyIsIlRPS0VOX0lTU1VFUiIsIkhUVFBTX1RPS0VOX0lTU1VFUiIsImNhY2hlIiwiZ2V0R29vZ2xlS2V5QnlLZXlJZCIsImtleUlkIiwiZXhwaXJlc0F0IiwiRGF0ZSIsIlByb21pc2UiLCJyZXNvbHZlIiwicmVqZWN0IiwiZ2V0IiwicmVzIiwiZGF0YSIsIm9uIiwiY2h1bmsiLCJ0b1N0cmluZyIsImtleXMiLCJKU09OIiwicGFyc2UiLCJwZW1zIiwicmVkdWNlIiwibiIsIm1vZHVsdXMiLCJlIiwiZXhwb3NhbnQiLCJraWQiLCJPYmplY3QiLCJhc3NpZ24iLCJyc2FQdWJsaWNLZXlUb1BFTSIsImhlYWRlcnMiLCJleHBpcmUiLCJtYXRjaCIsImdldFRpbWUiLCJOdW1iZXIiLCJ2ZXJpZnlJZFRva2VuIiwiaWRfdG9rZW4iLCJ0b2tlbiIsImlkIiwiY2xpZW50SWQiLCJFcnJvciIsIk9CSkVDVF9OT1RfRk9VTkQiLCJhbGciLCJhbGdvcml0aG0iLCJnZXRIZWFkZXJGcm9tVG9rZW4iLCJqd3RDbGFpbXMiLCJnb29nbGVLZXkiLCJ2ZXJpZnkiLCJhbGdvcml0aG1zIiwiYXVkaWVuY2UiLCJleGNlcHRpb24iLCJtZXNzYWdlIiwiaXNzIiwic3ViIiwiYXVkIiwidmFsaWRhdGVBdXRoRGF0YSIsImF1dGhEYXRhIiwib3B0aW9ucyIsInZhbGlkYXRlQXBwSWQiLCJtb2R1bGUiLCJleHBvcnRzIiwibW9kdWx1c0I2NCIsImV4cG9uZW50QjY0IiwiQnVmZmVyIiwiZXhwb25lbnQiLCJtb2R1bHVzSGV4IiwicHJlcGFkU2lnbmVkIiwiZXhwb25lbnRIZXgiLCJtb2RsZW4iLCJsZW5ndGgiLCJleHBsZW4iLCJlbmNvZGVkTW9kbGVuIiwiZW5jb2RlTGVuZ3RoSGV4IiwiZW5jb2RlZEV4cGxlbiIsImVuY29kZWRQdWJrZXkiLCJkZXIiLCJwZW0iLCJqb2luIiwiaGV4U3RyIiwibXNiIiwidG9IZXgiLCJudW1iZXIiLCJuc3RyIiwibkhleCIsImxlbmd0aE9mTGVuZ3RoQnl0ZSJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2dvb2dsZS5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFBhcnNlIFNlcnZlciBhdXRoZW50aWNhdGlvbiBhZGFwdGVyIGZvciBHb29nbGUuXG4gKlxuICogQGNsYXNzIEdvb2dsZUFkYXB0ZXJcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gVGhlIGFkYXB0ZXIgY29uZmlndXJhdGlvbiBvcHRpb25zLlxuICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMuY2xpZW50SWQgLSBZb3VyIEdvb2dsZSBhcHBsaWNhdGlvbiBDbGllbnQgSUQuIFJlcXVpcmVkIGZvciBhdXRoZW50aWNhdGlvbi5cbiAqXG4gKiBAZGVzY3JpcHRpb25cbiAqICMjIFBhcnNlIFNlcnZlciBDb25maWd1cmF0aW9uXG4gKiBUbyBjb25maWd1cmUgUGFyc2UgU2VydmVyIGZvciBHb29nbGUgYXV0aGVudGljYXRpb24sIHVzZSB0aGUgZm9sbG93aW5nIHN0cnVjdHVyZTpcbiAqIGBgYGpzb25cbiAqIHtcbiAqICAgXCJhdXRoXCI6IHtcbiAqICAgICBcImdvb2dsZVwiOiB7XG4gKiAgICAgICBcImNsaWVudElkXCI6IFwieW91ci1jbGllbnQtaWRcIlxuICogICAgIH1cbiAqICAgfVxuICogfVxuICogYGBgXG4gKlxuICogVGhlIGFkYXB0ZXIgcmVxdWlyZXMgdGhlIGZvbGxvd2luZyBgYXV0aERhdGFgIGZpZWxkczpcbiAqIC0gKippZCoqOiBUaGUgR29vZ2xlIHVzZXIgSUQuXG4gKiAtICoqaWRfdG9rZW4qKjogVGhlIEdvb2dsZSBJRCB0b2tlbi5cbiAqIC0gKiphY2Nlc3NfdG9rZW4qKjogVGhlIEdvb2dsZSBhY2Nlc3MgdG9rZW4uXG4gKlxuICogIyMgQXV0aCBQYXlsb2FkXG4gKiAjIyMgRXhhbXBsZSBBdXRoIERhdGEgUGF5bG9hZFxuICogYGBganNvblxuICoge1xuICogICBcImdvb2dsZVwiOiB7XG4gKiAgICAgXCJpZFwiOiBcIjEyMzQ1NjdcIixcbiAqICAgICBcImlkX3Rva2VuXCI6IFwieHh4eHgueXl5eXkuenp6enpcIixcbiAqICAgICBcImFjY2Vzc190b2tlblwiOiBcImFiYzEyM2RlZjQ1NmdoaTc4OVwiXG4gKiAgIH1cbiAqIH1cbiAqIGBgYFxuICpcbiAqICMjIE5vdGVzXG4gKiAtIEVuc3VyZSB5b3VyIEdvb2dsZSBDbGllbnQgSUQgaXMgY29uZmlndXJlZCBwcm9wZXJseSBpbiB0aGUgUGFyc2UgU2VydmVyIGNvbmZpZ3VyYXRpb24uXG4gKiAtIFRoZSBgaWRfdG9rZW5gIGFuZCBgYWNjZXNzX3Rva2VuYCBhcmUgdmFsaWRhdGVkIGFnYWluc3QgR29vZ2xlJ3MgYXV0aGVudGljYXRpb24gc2VydmljZXMuXG4gKlxuICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXJzLmdvb2dsZS5jb20vaWRlbnRpdHkvc2lnbi1pbi93ZWIvYmFja2VuZC1hdXRoIEdvb2dsZSBBdXRoZW50aWNhdGlvbiBEb2N1bWVudGF0aW9ufVxuICovXG5cbid1c2Ugc3RyaWN0JztcblxuLy8gSGVscGVyIGZ1bmN0aW9ucyBmb3IgYWNjZXNzaW5nIHRoZSBnb29nbGUgQVBJLlxudmFyIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xuXG5jb25zdCBodHRwcyA9IHJlcXVpcmUoJ2h0dHBzJyk7XG5jb25zdCBqd3QgPSByZXF1aXJlKCdqc29ud2VidG9rZW4nKTtcbmNvbnN0IGF1dGhVdGlscyA9IHJlcXVpcmUoJy4vdXRpbHMnKTtcblxuY29uc3QgVE9LRU5fSVNTVUVSID0gJ2FjY291bnRzLmdvb2dsZS5jb20nO1xuY29uc3QgSFRUUFNfVE9LRU5fSVNTVUVSID0gJ2h0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbSc7XG5cbmxldCBjYWNoZSA9IHt9O1xuXG4vLyBSZXRyaWV2ZSBHb29nbGUgU2lnbmluIEtleXMgKHdpdGggY2FjaGUgY29udHJvbClcbmZ1bmN0aW9uIGdldEdvb2dsZUtleUJ5S2V5SWQoa2V5SWQpIHtcbiAgaWYgKGNhY2hlW2tleUlkXSAmJiBjYWNoZS5leHBpcmVzQXQgPiBuZXcgRGF0ZSgpKSB7XG4gICAgcmV0dXJuIGNhY2hlW2tleUlkXTtcbiAgfVxuXG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgaHR0cHNcbiAgICAgIC5nZXQoYGh0dHBzOi8vd3d3Lmdvb2dsZWFwaXMuY29tL29hdXRoMi92My9jZXJ0c2AsIHJlcyA9PiB7XG4gICAgICAgIGxldCBkYXRhID0gJyc7XG4gICAgICAgIHJlcy5vbignZGF0YScsIGNodW5rID0+IHtcbiAgICAgICAgICBkYXRhICs9IGNodW5rLnRvU3RyaW5nKCd1dGY4Jyk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXMub24oJ2VuZCcsICgpID0+IHtcbiAgICAgICAgICBjb25zdCB7IGtleXMgfSA9IEpTT04ucGFyc2UoZGF0YSk7XG4gICAgICAgICAgY29uc3QgcGVtcyA9IGtleXMucmVkdWNlKFxuICAgICAgICAgICAgKHBlbXMsIHsgbjogbW9kdWx1cywgZTogZXhwb3NhbnQsIGtpZCB9KSA9PlxuICAgICAgICAgICAgICBPYmplY3QuYXNzaWduKHBlbXMsIHtcbiAgICAgICAgICAgICAgICBba2lkXTogcnNhUHVibGljS2V5VG9QRU0obW9kdWx1cywgZXhwb3NhbnQpLFxuICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgIHt9XG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGlmIChyZXMuaGVhZGVyc1snY2FjaGUtY29udHJvbCddKSB7XG4gICAgICAgICAgICB2YXIgZXhwaXJlID0gcmVzLmhlYWRlcnNbJ2NhY2hlLWNvbnRyb2wnXS5tYXRjaCgvbWF4LWFnZT0oWzAtOV0rKS8pO1xuXG4gICAgICAgICAgICBpZiAoZXhwaXJlKSB7XG4gICAgICAgICAgICAgIGNhY2hlID0gT2JqZWN0LmFzc2lnbih7fSwgcGVtcywge1xuICAgICAgICAgICAgICAgIGV4cGlyZXNBdDogbmV3IERhdGUobmV3IERhdGUoKS5nZXRUaW1lKCkgKyBOdW1iZXIoZXhwaXJlWzFdKSAqIDEwMDApLFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXNvbHZlKHBlbXNba2V5SWRdKTtcbiAgICAgICAgfSk7XG4gICAgICB9KVxuICAgICAgLm9uKCdlcnJvcicsIHJlamVjdCk7XG4gIH0pO1xufVxuXG5hc3luYyBmdW5jdGlvbiB2ZXJpZnlJZFRva2VuKHsgaWRfdG9rZW46IHRva2VuLCBpZCB9LCB7IGNsaWVudElkIH0pIHtcbiAgaWYgKCF0b2tlbikge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELCBgaWQgdG9rZW4gaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLmApO1xuICB9XG5cbiAgY29uc3QgeyBraWQ6IGtleUlkLCBhbGc6IGFsZ29yaXRobSB9ID0gYXV0aFV0aWxzLmdldEhlYWRlckZyb21Ub2tlbih0b2tlbik7XG4gIGxldCBqd3RDbGFpbXM7XG4gIGNvbnN0IGdvb2dsZUtleSA9IGF3YWl0IGdldEdvb2dsZUtleUJ5S2V5SWQoa2V5SWQpO1xuXG4gIHRyeSB7XG4gICAgand0Q2xhaW1zID0gand0LnZlcmlmeSh0b2tlbiwgZ29vZ2xlS2V5LCB7XG4gICAgICBhbGdvcml0aG1zOiBhbGdvcml0aG0sXG4gICAgICBhdWRpZW5jZTogY2xpZW50SWQsXG4gICAgfSk7XG4gIH0gY2F0Y2ggKGV4Y2VwdGlvbikge1xuICAgIGNvbnN0IG1lc3NhZ2UgPSBleGNlcHRpb24ubWVzc2FnZTtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgYCR7bWVzc2FnZX1gKTtcbiAgfVxuXG4gIGlmIChqd3RDbGFpbXMuaXNzICE9PSBUT0tFTl9JU1NVRVIgJiYgand0Q2xhaW1zLmlzcyAhPT0gSFRUUFNfVE9LRU5fSVNTVUVSKSB7XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgIGBpZCB0b2tlbiBub3QgaXNzdWVkIGJ5IGNvcnJlY3QgcHJvdmlkZXIgLSBleHBlY3RlZDogJHtUT0tFTl9JU1NVRVJ9IG9yICR7SFRUUFNfVE9LRU5fSVNTVUVSfSB8IGZyb206ICR7and0Q2xhaW1zLmlzc31gXG4gICAgKTtcbiAgfVxuXG4gIGlmIChqd3RDbGFpbXMuc3ViICE9PSBpZCkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELCBgYXV0aCBkYXRhIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci5gKTtcbiAgfVxuXG4gIGlmIChjbGllbnRJZCAmJiBqd3RDbGFpbXMuYXVkICE9PSBjbGllbnRJZCkge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICBgaWQgdG9rZW4gbm90IGF1dGhvcml6ZWQgZm9yIHRoaXMgY2xpZW50SWQuYFxuICAgICk7XG4gIH1cblxuICByZXR1cm4gand0Q2xhaW1zO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEsIG9wdGlvbnMgPSB7fSkge1xuICByZXR1cm4gdmVyaWZ5SWRUb2tlbihhdXRoRGF0YSwgb3B0aW9ucyk7XG59XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWYgdGhpcyBhcHAgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKCkge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkOiB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhOiB2YWxpZGF0ZUF1dGhEYXRhLFxufTtcblxuLy8gSGVscGVycyBmdW5jdGlvbnMgdG8gY29udmVydCB0aGUgUlNBIGNlcnRzIHRvIFBFTSAoZnJvbSBqd2tzLXJzYSlcbmZ1bmN0aW9uIHJzYVB1YmxpY0tleVRvUEVNKG1vZHVsdXNCNjQsIGV4cG9uZW50QjY0KSB7XG4gIGNvbnN0IG1vZHVsdXMgPSBuZXcgQnVmZmVyKG1vZHVsdXNCNjQsICdiYXNlNjQnKTtcbiAgY29uc3QgZXhwb25lbnQgPSBuZXcgQnVmZmVyKGV4cG9uZW50QjY0LCAnYmFzZTY0Jyk7XG4gIGNvbnN0IG1vZHVsdXNIZXggPSBwcmVwYWRTaWduZWQobW9kdWx1cy50b1N0cmluZygnaGV4JykpO1xuICBjb25zdCBleHBvbmVudEhleCA9IHByZXBhZFNpZ25lZChleHBvbmVudC50b1N0cmluZygnaGV4JykpO1xuICBjb25zdCBtb2RsZW4gPSBtb2R1bHVzSGV4Lmxlbmd0aCAvIDI7XG4gIGNvbnN0IGV4cGxlbiA9IGV4cG9uZW50SGV4Lmxlbmd0aCAvIDI7XG5cbiAgY29uc3QgZW5jb2RlZE1vZGxlbiA9IGVuY29kZUxlbmd0aEhleChtb2RsZW4pO1xuICBjb25zdCBlbmNvZGVkRXhwbGVuID0gZW5jb2RlTGVuZ3RoSGV4KGV4cGxlbik7XG4gIGNvbnN0IGVuY29kZWRQdWJrZXkgPVxuICAgICczMCcgK1xuICAgIGVuY29kZUxlbmd0aEhleChtb2RsZW4gKyBleHBsZW4gKyBlbmNvZGVkTW9kbGVuLmxlbmd0aCAvIDIgKyBlbmNvZGVkRXhwbGVuLmxlbmd0aCAvIDIgKyAyKSArXG4gICAgJzAyJyArXG4gICAgZW5jb2RlZE1vZGxlbiArXG4gICAgbW9kdWx1c0hleCArXG4gICAgJzAyJyArXG4gICAgZW5jb2RlZEV4cGxlbiArXG4gICAgZXhwb25lbnRIZXg7XG5cbiAgY29uc3QgZGVyID0gbmV3IEJ1ZmZlcihlbmNvZGVkUHVia2V5LCAnaGV4JykudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuXG4gIGxldCBwZW0gPSAnLS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tXFxuJztcbiAgcGVtICs9IGAke2Rlci5tYXRjaCgvLnsxLDY0fS9nKS5qb2luKCdcXG4nKX1gO1xuICBwZW0gKz0gJ1xcbi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS1cXG4nO1xuICByZXR1cm4gcGVtO1xufVxuXG5mdW5jdGlvbiBwcmVwYWRTaWduZWQoaGV4U3RyKSB7XG4gIGNvbnN0IG1zYiA9IGhleFN0clswXTtcbiAgaWYgKG1zYiA8ICcwJyB8fCBtc2IgPiAnNycpIHtcbiAgICByZXR1cm4gYDAwJHtoZXhTdHJ9YDtcbiAgfVxuICByZXR1cm4gaGV4U3RyO1xufVxuXG5mdW5jdGlvbiB0b0hleChudW1iZXIpIHtcbiAgY29uc3QgbnN0ciA9IG51bWJlci50b1N0cmluZygxNik7XG4gIGlmIChuc3RyLmxlbmd0aCAlIDIpIHtcbiAgICByZXR1cm4gYDAke25zdHJ9YDtcbiAgfVxuICByZXR1cm4gbnN0cjtcbn1cblxuZnVuY3Rpb24gZW5jb2RlTGVuZ3RoSGV4KG4pIHtcbiAgaWYgKG4gPD0gMTI3KSB7XG4gICAgcmV0dXJuIHRvSGV4KG4pO1xuICB9XG4gIGNvbnN0IG5IZXggPSB0b0hleChuKTtcbiAgY29uc3QgbGVuZ3RoT2ZMZW5ndGhCeXRlID0gMTI4ICsgbkhleC5sZW5ndGggLyAyO1xuICByZXR1cm4gdG9IZXgobGVuZ3RoT2ZMZW5ndGhCeXRlKSArIG5IZXg7XG59XG4iXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztB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QUFDSixNQUFNLEdBQUdFLE1BQU0sR0FBR0MsYUFBYSxDQUFDRixNQUFNLEdBQUcsQ0FBQyxHQUFHSSxhQUFhLENBQUNKLE1BQU0sR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQzFGLElBQUksR0FDSkUsYUFBYSxHQUNiTixVQUFVLEdBQ1YsSUFBSSxHQUNKUSxhQUFhLEdBQ2JOLFdBQVc7RUFFYixNQUFNUSxHQUFHLEdBQUcsSUFBSVosTUFBTSxDQUFDVyxhQUFhLEVBQUUsS0FBSyxDQUFDLENBQUMxRCxRQUFRLENBQUMsUUFBUSxDQUFDO0VBRS9ELElBQUk0RCxHQUFHLEdBQUcsa0NBQWtDO0VBQzVDQSxHQUFHLElBQUksR0FBR0QsR0FBRyxDQUFDM0MsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDNkMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFO0VBQzVDRCxHQUFHLElBQUksa0NBQWtDO0VBQ3pDLE9BQU9BLEdBQUc7QUFDWjtBQUVBLFNBQVNWLFlBQVlBLENBQUNZLE1BQU0sRUFBRTtFQUM1QixNQUFNQyxHQUFHLEdBQUdELE1BQU0sQ0FBQyxDQUFDLENBQUM7RUFDckIsSUFBSUMsR0FBRyxHQUFHLEdBQUcsSUFBSUEsR0FBRyxHQUFHLEdBQUcsRUFBRTtJQUMxQixPQUFPLEtBQUtELE1BQU0sRUFBRTtFQUN0QjtFQUNBLE9BQU9BLE1BQU07QUFDZjtBQUVBLFNBQVNFLEtBQUtBLENBQUNDLE1BQU0sRUFBRTtFQUNyQixNQUFNQyxJQUFJLEdBQUdELE1BQU0sQ0FBQ2pFLFFBQVEsQ0FBQyxFQUFFLENBQUM7RUFDaEMsSUFBSWtFLElBQUksQ0FBQ2IsTUFBTSxHQUFHLENBQUMsRUFBRTtJQUNuQixPQUFPLElBQUlhLElBQUksRUFBRTtFQUNuQjtFQUNBLE9BQU9BLElBQUk7QUFDYjtBQUVBLFNBQVNWLGVBQWVBLENBQUNsRCxDQUFDLEVBQUU7RUFDMUIsSUFBSUEsQ0FBQyxJQUFJLEdBQUcsRUFBRTtJQUNaLE9BQU8wRCxLQUFLLENBQUMxRCxDQUFDLENBQUM7RUFDakI7RUFDQSxNQUFNNkQsSUFBSSxHQUFHSCxLQUFLLENBQUMxRCxDQUFDLENBQUM7RUFDckIsTUFBTThELGtCQUFrQixHQUFHLEdBQUcsR0FBR0QsSUFBSSxDQUFDZCxNQUFNLEdBQUcsQ0FBQztFQUNoRCxPQUFPVyxLQUFLLENBQUNJLGtCQUFrQixDQUFDLEdBQUdELElBQUk7QUFDekMiLCJpZ25vcmVMaXN0IjpbXX0=
|
|
@@ -0,0 +1,125 @@
|
|
|
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 Google Play Games Services.
|
|
11
|
+
*
|
|
12
|
+
* @class GooglePlayGamesServicesAdapter
|
|
13
|
+
* @param {Object} options - The adapter configuration options.
|
|
14
|
+
* @param {string} options.clientId - Your Google Play Games Services App Client ID. Required for secure authentication.
|
|
15
|
+
* @param {string} options.clientSecret - Your Google Play Games Services 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 Google Play Games Services authentication, use the following structure:
|
|
21
|
+
* ```json
|
|
22
|
+
* {
|
|
23
|
+
* "auth": {
|
|
24
|
+
* "gpgames": {
|
|
25
|
+
* "clientId": "your-client-id",
|
|
26
|
+
* "clientSecret": "your-client-secret"
|
|
27
|
+
* }
|
|
28
|
+
* }
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
* ### Insecure Configuration (Not Recommended)
|
|
32
|
+
* ```json
|
|
33
|
+
* {
|
|
34
|
+
* "auth": {
|
|
35
|
+
* "gpgames": {
|
|
36
|
+
* "enableInsecureAuth": true
|
|
37
|
+
* }
|
|
38
|
+
* }
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* The adapter requires the following `authData` fields:
|
|
43
|
+
* - **Secure Authentication**: `code`, `redirect_uri`.
|
|
44
|
+
* - **Insecure Authentication (Not Recommended)**: `id`, `access_token`.
|
|
45
|
+
*
|
|
46
|
+
* ## Auth Payloads
|
|
47
|
+
* ### Secure Authentication Payload
|
|
48
|
+
* ```json
|
|
49
|
+
* {
|
|
50
|
+
* "gpgames": {
|
|
51
|
+
* "code": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
|
52
|
+
* "redirect_uri": "https://example.com/callback"
|
|
53
|
+
* }
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*
|
|
57
|
+
* ### Insecure Authentication Payload (Not Recommended)
|
|
58
|
+
* ```json
|
|
59
|
+
* {
|
|
60
|
+
* "gpgames": {
|
|
61
|
+
* "id": "123456789",
|
|
62
|
+
* "access_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
63
|
+
* }
|
|
64
|
+
* }
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* ## Notes
|
|
68
|
+
* - `enableInsecureAuth` is **not recommended** and may be removed in future versions. Use secure authentication with `code` and `redirect_uri`.
|
|
69
|
+
* - Secure authentication exchanges the `code` provided by the client for an access token using Google Play Games Services' OAuth API.
|
|
70
|
+
*
|
|
71
|
+
* @see {@link https://developers.google.com/games/services/console/enabling Google Play Games Services Authentication Documentation}
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
class GooglePlayGamesServicesAdapter extends _BaseCodeAuthAdapter.default {
|
|
75
|
+
constructor() {
|
|
76
|
+
super("gpgames");
|
|
77
|
+
}
|
|
78
|
+
async getAccessTokenFromCode(authData) {
|
|
79
|
+
const tokenUrl = 'https://oauth2.googleapis.com/token';
|
|
80
|
+
const response = await fetch(tokenUrl, {
|
|
81
|
+
method: 'POST',
|
|
82
|
+
headers: {
|
|
83
|
+
'Content-Type': 'application/json',
|
|
84
|
+
Accept: 'application/json'
|
|
85
|
+
},
|
|
86
|
+
body: JSON.stringify({
|
|
87
|
+
client_id: this.clientId,
|
|
88
|
+
client_secret: this.clientSecret,
|
|
89
|
+
code: authData.code,
|
|
90
|
+
redirect_uri: authData.redirectUri,
|
|
91
|
+
grant_type: 'authorization_code'
|
|
92
|
+
})
|
|
93
|
+
});
|
|
94
|
+
if (!response.ok) {
|
|
95
|
+
throw new Parse.Error(Parse.Error.VALIDATION_ERROR, `Failed to exchange code for token: ${response.statusText}`);
|
|
96
|
+
}
|
|
97
|
+
const data = await response.json();
|
|
98
|
+
if (data.error) {
|
|
99
|
+
throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, data.error_description || data.error);
|
|
100
|
+
}
|
|
101
|
+
return data.access_token;
|
|
102
|
+
}
|
|
103
|
+
async getUserFromAccessToken(accessToken, authData) {
|
|
104
|
+
const userApiUrl = `https://www.googleapis.com/games/v1/players/${authData.id}`;
|
|
105
|
+
const response = await fetch(userApiUrl, {
|
|
106
|
+
method: 'GET',
|
|
107
|
+
headers: {
|
|
108
|
+
Authorization: `Bearer ${accessToken}`,
|
|
109
|
+
Accept: 'application/json'
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
if (!response.ok) {
|
|
113
|
+
throw new Parse.Error(Parse.Error.VALIDATION_ERROR, `Failed to fetch Google Play Games Services user: ${response.statusText}`);
|
|
114
|
+
}
|
|
115
|
+
const userData = await response.json();
|
|
116
|
+
if (!userData.playerId || userData.playerId !== authData.id) {
|
|
117
|
+
throw new Parse.Error(Parse.Error.VALIDATION_ERROR, 'Invalid Google Play Games Services user data received.');
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
id: userData.playerId
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
var _default = exports.default = new GooglePlayGamesServicesAdapter();
|
|
125
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfQmFzZUNvZGVBdXRoQWRhcHRlciIsIl9pbnRlcm9wUmVxdWlyZURlZmF1bHQiLCJyZXF1aXJlIiwiZSIsIl9fZXNNb2R1bGUiLCJkZWZhdWx0IiwiR29vZ2xlUGxheUdhbWVzU2VydmljZXNBZGFwdGVyIiwiQmFzZUNvZGVBdXRoQWRhcHRlciIsImNvbnN0cnVjdG9yIiwiZ2V0QWNjZXNzVG9rZW5Gcm9tQ29kZSIsImF1dGhEYXRhIiwidG9rZW5VcmwiLCJyZXNwb25zZSIsImZldGNoIiwibWV0aG9kIiwiaGVhZGVycyIsIkFjY2VwdCIsImJvZHkiLCJKU09OIiwic3RyaW5naWZ5IiwiY2xpZW50X2lkIiwiY2xpZW50SWQiLCJjbGllbnRfc2VjcmV0IiwiY2xpZW50U2VjcmV0IiwiY29kZSIsInJlZGlyZWN0X3VyaSIsInJlZGlyZWN0VXJpIiwiZ3JhbnRfdHlwZSIsIm9rIiwiUGFyc2UiLCJFcnJvciIsIlZBTElEQVRJT05fRVJST1IiLCJzdGF0dXNUZXh0IiwiZGF0YSIsImpzb24iLCJlcnJvciIsIk9CSkVDVF9OT1RfRk9VTkQiLCJlcnJvcl9kZXNjcmlwdGlvbiIsImFjY2Vzc190b2tlbiIsImdldFVzZXJGcm9tQWNjZXNzVG9rZW4iLCJhY2Nlc3NUb2tlbiIsInVzZXJBcGlVcmwiLCJpZCIsIkF1dGhvcml6YXRpb24iLCJ1c2VyRGF0YSIsInBsYXllcklkIiwiX2RlZmF1bHQiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL0FkYXB0ZXJzL0F1dGgvZ3BnYW1lcy5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFBhcnNlIFNlcnZlciBhdXRoZW50aWNhdGlvbiBhZGFwdGVyIGZvciBHb29nbGUgUGxheSBHYW1lcyBTZXJ2aWNlcy5cbiAqXG4gKiBAY2xhc3MgR29vZ2xlUGxheUdhbWVzU2VydmljZXNBZGFwdGVyXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIFRoZSBhZGFwdGVyIGNvbmZpZ3VyYXRpb24gb3B0aW9ucy5cbiAqIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLmNsaWVudElkIC0gWW91ciBHb29nbGUgUGxheSBHYW1lcyBTZXJ2aWNlcyBBcHAgQ2xpZW50IElELiBSZXF1aXJlZCBmb3Igc2VjdXJlIGF1dGhlbnRpY2F0aW9uLlxuICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMuY2xpZW50U2VjcmV0IC0gWW91ciBHb29nbGUgUGxheSBHYW1lcyBTZXJ2aWNlcyBBcHAgQ2xpZW50IFNlY3JldC4gUmVxdWlyZWQgZm9yIHNlY3VyZSBhdXRoZW50aWNhdGlvbi5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdGlvbnMuZW5hYmxlSW5zZWN1cmVBdXRoPWZhbHNlXSAtICoqW0RFUFJFQ0FURURdKiogRW5hYmxlIGluc2VjdXJlIGF1dGhlbnRpY2F0aW9uIChub3QgcmVjb21tZW5kZWQpLlxuICpcbiAqIEBkZXNjcmlwdGlvblxuICogIyMgUGFyc2UgU2VydmVyIENvbmZpZ3VyYXRpb25cbiAqIFRvIGNvbmZpZ3VyZSBQYXJzZSBTZXJ2ZXIgZm9yIEdvb2dsZSBQbGF5IEdhbWVzIFNlcnZpY2VzIGF1dGhlbnRpY2F0aW9uLCB1c2UgdGhlIGZvbGxvd2luZyBzdHJ1Y3R1cmU6XG4gKiBgYGBqc29uXG4gKiB7XG4gKiAgIFwiYXV0aFwiOiB7XG4gKiAgICAgXCJncGdhbWVzXCI6IHtcbiAqICAgICAgIFwiY2xpZW50SWRcIjogXCJ5b3VyLWNsaWVudC1pZFwiLFxuICogICAgICAgXCJjbGllbnRTZWNyZXRcIjogXCJ5b3VyLWNsaWVudC1zZWNyZXRcIlxuICogICAgIH1cbiAqICAgfVxuICogfVxuICogYGBgXG4gKiAjIyMgSW5zZWN1cmUgQ29uZmlndXJhdGlvbiAoTm90IFJlY29tbWVuZGVkKVxuICogYGBganNvblxuICoge1xuICogICBcImF1dGhcIjoge1xuICogICAgIFwiZ3BnYW1lc1wiOiB7XG4gKiAgICAgICBcImVuYWJsZUluc2VjdXJlQXV0aFwiOiB0cnVlXG4gKiAgICAgfVxuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBUaGUgYWRhcHRlciByZXF1aXJlcyB0aGUgZm9sbG93aW5nIGBhdXRoRGF0YWAgZmllbGRzOlxuICogLSAqKlNlY3VyZSBBdXRoZW50aWNhdGlvbioqOiBgY29kZWAsIGByZWRpcmVjdF91cmlgLlxuICogLSAqKkluc2VjdXJlIEF1dGhlbnRpY2F0aW9uIChOb3QgUmVjb21tZW5kZWQpKio6IGBpZGAsIGBhY2Nlc3NfdG9rZW5gLlxuICpcbiAqICMjIEF1dGggUGF5bG9hZHNcbiAqICMjIyBTZWN1cmUgQXV0aGVudGljYXRpb24gUGF5bG9hZFxuICogYGBganNvblxuICoge1xuICogICBcImdwZ2FtZXNcIjoge1xuICogICAgIFwiY29kZVwiOiBcInh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHhcIixcbiAqICAgICBcInJlZGlyZWN0X3VyaVwiOiBcImh0dHBzOi8vZXhhbXBsZS5jb20vY2FsbGJhY2tcIlxuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiAjIyMgSW5zZWN1cmUgQXV0aGVudGljYXRpb24gUGF5bG9hZCAoTm90IFJlY29tbWVuZGVkKVxuICogYGBganNvblxuICoge1xuICogICBcImdwZ2FtZXNcIjoge1xuICogICAgIFwiaWRcIjogXCIxMjM0NTY3ODlcIixcbiAqICAgICBcImFjY2Vzc190b2tlblwiOiBcInh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHhcIlxuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiAjIyBOb3Rlc1xuICogLSBgZW5hYmxlSW5zZWN1cmVBdXRoYCBpcyAqKm5vdCByZWNvbW1lbmRlZCoqIGFuZCBtYXkgYmUgcmVtb3ZlZCBpbiBmdXR1cmUgdmVyc2lvbnMuIFVzZSBzZWN1cmUgYXV0aGVudGljYXRpb24gd2l0aCBgY29kZWAgYW5kIGByZWRpcmVjdF91cmlgLlxuICogLSBTZWN1cmUgYXV0aGVudGljYXRpb24gZXhjaGFuZ2VzIHRoZSBgY29kZWAgcHJvdmlkZWQgYnkgdGhlIGNsaWVudCBmb3IgYW4gYWNjZXNzIHRva2VuIHVzaW5nIEdvb2dsZSBQbGF5IEdhbWVzIFNlcnZpY2VzJyBPQXV0aCBBUEkuXG4gKlxuICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXJzLmdvb2dsZS5jb20vZ2FtZXMvc2VydmljZXMvY29uc29sZS9lbmFibGluZyBHb29nbGUgUGxheSBHYW1lcyBTZXJ2aWNlcyBBdXRoZW50aWNhdGlvbiBEb2N1bWVudGF0aW9ufVxuICovXG5cbmltcG9ydCBCYXNlQ29kZUF1dGhBZGFwdGVyIGZyb20gJy4vQmFzZUNvZGVBdXRoQWRhcHRlcic7XG5jbGFzcyBHb29nbGVQbGF5R2FtZXNTZXJ2aWNlc0FkYXB0ZXIgZXh0ZW5kcyBCYXNlQ29kZUF1dGhBZGFwdGVyIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoXCJncGdhbWVzXCIpO1xuICB9XG5cbiAgYXN5bmMgZ2V0QWNjZXNzVG9rZW5Gcm9tQ29kZShhdXRoRGF0YSkge1xuICAgIGNvbnN0IHRva2VuVXJsID0gJ2h0dHBzOi8vb2F1dGgyLmdvb2dsZWFwaXMuY29tL3Rva2VuJztcbiAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKHRva2VuVXJsLCB7XG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgQWNjZXB0OiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICB9LFxuICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICBjbGllbnRfaWQ6IHRoaXMuY2xpZW50SWQsXG4gICAgICAgIGNsaWVudF9zZWNyZXQ6IHRoaXMuY2xpZW50U2VjcmV0LFxuICAgICAgICBjb2RlOiBhdXRoRGF0YS5jb2RlLFxuICAgICAgICByZWRpcmVjdF91cmk6IGF1dGhEYXRhLnJlZGlyZWN0VXJpLFxuICAgICAgICBncmFudF90eXBlOiAnYXV0aG9yaXphdGlvbl9jb2RlJyxcbiAgICAgIH0pLFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5WQUxJREFUSU9OX0VSUk9SLFxuICAgICAgICBgRmFpbGVkIHRvIGV4Y2hhbmdlIGNvZGUgZm9yIHRva2VuOiAke3Jlc3BvbnNlLnN0YXR1c1RleHR9YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBkYXRhID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuICAgIGlmIChkYXRhLmVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgIGRhdGEuZXJyb3JfZGVzY3JpcHRpb24gfHwgZGF0YS5lcnJvclxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZGF0YS5hY2Nlc3NfdG9rZW47XG4gIH1cblxuICBhc3luYyBnZXRVc2VyRnJvbUFjY2Vzc1Rva2VuKGFjY2Vzc1Rva2VuLCBhdXRoRGF0YSkge1xuICAgIGNvbnN0IHVzZXJBcGlVcmwgPSBgaHR0cHM6Ly93d3cuZ29vZ2xlYXBpcy5jb20vZ2FtZXMvdjEvcGxheWVycy8ke2F1dGhEYXRhLmlkfWA7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh1c2VyQXBpVXJsLCB7XG4gICAgICBtZXRob2Q6ICdHRVQnLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICBBdXRob3JpemF0aW9uOiBgQmVhcmVyICR7YWNjZXNzVG9rZW59YCxcbiAgICAgICAgQWNjZXB0OiAnYXBwbGljYXRpb24vanNvbicsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5WQUxJREFUSU9OX0VSUk9SLFxuICAgICAgICBgRmFpbGVkIHRvIGZldGNoIEdvb2dsZSBQbGF5IEdhbWVzIFNlcnZpY2VzIHVzZXI6ICR7cmVzcG9uc2Uuc3RhdHVzVGV4dH1gXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHVzZXJEYXRhID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuICAgIGlmICghdXNlckRhdGEucGxheWVySWQgfHwgdXNlckRhdGEucGxheWVySWQgIT09IGF1dGhEYXRhLmlkKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgIFBhcnNlLkVycm9yLlZBTElEQVRJT05fRVJST1IsXG4gICAgICAgICdJbnZhbGlkIEdvb2dsZSBQbGF5IEdhbWVzIFNlcnZpY2VzIHVzZXIgZGF0YSByZWNlaXZlZC4nXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBpZDogdXNlckRhdGEucGxheWVySWRcbiAgICB9O1xuICB9XG5cbn1cblxuZXhwb3J0IGRlZmF1bHQgbmV3IEdvb2dsZVBsYXlHYW1lc1NlcnZpY2VzQWRhcHRlcigpO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUFpRUEsSUFBQUEsb0JBQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUF3RCxTQUFBRCx1QkFBQUUsQ0FBQSxXQUFBQSxDQUFBLElBQUFBLENBQUEsQ0FBQUMsVUFBQSxHQUFBRCxDQUFBLEtBQUFFLE9BQUEsRUFBQUYsQ0FBQTtBQWpFeEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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
|