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.
Files changed (240) hide show
  1. package/LICENSE +167 -25
  2. package/NOTICE +10 -0
  3. package/README.md +929 -278
  4. package/lib/AccountLockout.js +47 -30
  5. package/lib/Adapters/AdapterLoader.js +21 -6
  6. package/lib/Adapters/Analytics/AnalyticsAdapter.js +15 -12
  7. package/lib/Adapters/Auth/AuthAdapter.js +116 -13
  8. package/lib/Adapters/Auth/BaseCodeAuthAdapter.js +99 -0
  9. package/lib/Adapters/Auth/OAuth1Client.js +27 -46
  10. package/lib/Adapters/Auth/apple.js +123 -0
  11. package/lib/Adapters/Auth/facebook.js +162 -35
  12. package/lib/Adapters/Auth/gcenter.js +217 -0
  13. package/lib/Adapters/Auth/github.js +118 -48
  14. package/lib/Adapters/Auth/google.js +160 -51
  15. package/lib/Adapters/Auth/gpgames.js +125 -0
  16. package/lib/Adapters/Auth/httpsRequest.js +6 -7
  17. package/lib/Adapters/Auth/index.js +170 -62
  18. package/lib/Adapters/Auth/instagram.js +114 -40
  19. package/lib/Adapters/Auth/janraincapture.js +52 -23
  20. package/lib/Adapters/Auth/janrainengage.js +19 -36
  21. package/lib/Adapters/Auth/keycloak.js +148 -0
  22. package/lib/Adapters/Auth/ldap.js +167 -0
  23. package/lib/Adapters/Auth/line.js +125 -0
  24. package/lib/Adapters/Auth/linkedin.js +111 -55
  25. package/lib/Adapters/Auth/meetup.js +24 -34
  26. package/lib/Adapters/Auth/mfa.js +324 -0
  27. package/lib/Adapters/Auth/microsoft.js +111 -0
  28. package/lib/Adapters/Auth/oauth2.js +97 -162
  29. package/lib/Adapters/Auth/phantauth.js +53 -0
  30. package/lib/Adapters/Auth/qq.js +108 -49
  31. package/lib/Adapters/Auth/spotify.js +107 -55
  32. package/lib/Adapters/Auth/twitter.js +188 -48
  33. package/lib/Adapters/Auth/utils.js +28 -0
  34. package/lib/Adapters/Auth/vkontakte.js +26 -39
  35. package/lib/Adapters/Auth/wechat.js +106 -44
  36. package/lib/Adapters/Auth/weibo.js +132 -58
  37. package/lib/Adapters/Cache/CacheAdapter.js +13 -8
  38. package/lib/Adapters/Cache/InMemoryCache.js +3 -13
  39. package/lib/Adapters/Cache/InMemoryCacheAdapter.js +5 -13
  40. package/lib/Adapters/Cache/LRUCache.js +13 -27
  41. package/lib/Adapters/Cache/NullCacheAdapter.js +3 -8
  42. package/lib/Adapters/Cache/RedisCacheAdapter.js +85 -76
  43. package/lib/Adapters/Cache/SchemaCache.js +25 -0
  44. package/lib/Adapters/Email/MailAdapter.js +10 -8
  45. package/lib/Adapters/Files/FilesAdapter.js +83 -25
  46. package/lib/Adapters/Files/GridFSBucketAdapter.js +231 -0
  47. package/lib/Adapters/Files/GridStoreAdapter.js +4 -91
  48. package/lib/Adapters/Logger/LoggerAdapter.js +18 -14
  49. package/lib/Adapters/Logger/WinstonLogger.js +69 -88
  50. package/lib/Adapters/Logger/WinstonLoggerAdapter.js +7 -16
  51. package/lib/Adapters/MessageQueue/EventEmitterMQ.js +8 -26
  52. package/lib/Adapters/PubSub/EventEmitterPubSub.js +12 -25
  53. package/lib/Adapters/PubSub/PubSubAdapter.js +34 -0
  54. package/lib/Adapters/PubSub/RedisPubSub.js +42 -19
  55. package/lib/Adapters/Push/PushAdapter.js +14 -7
  56. package/lib/Adapters/Storage/Mongo/MongoCollection.js +137 -45
  57. package/lib/Adapters/Storage/Mongo/MongoSchemaCollection.js +158 -63
  58. package/lib/Adapters/Storage/Mongo/MongoStorageAdapter.js +320 -168
  59. package/lib/Adapters/Storage/Mongo/MongoTransform.js +279 -306
  60. package/lib/Adapters/Storage/Postgres/PostgresClient.js +14 -10
  61. package/lib/Adapters/Storage/Postgres/PostgresConfigParser.js +47 -21
  62. package/lib/Adapters/Storage/Postgres/PostgresStorageAdapter.js +854 -468
  63. package/lib/Adapters/Storage/Postgres/sql/index.js +4 -6
  64. package/lib/Adapters/Storage/StorageAdapter.js +1 -1
  65. package/lib/Adapters/WebSocketServer/WSAdapter.js +35 -0
  66. package/lib/Adapters/WebSocketServer/WSSAdapter.js +66 -0
  67. package/lib/Auth.js +488 -125
  68. package/lib/ClientSDK.js +2 -6
  69. package/lib/Config.js +525 -94
  70. package/lib/Controllers/AdaptableController.js +5 -25
  71. package/lib/Controllers/AnalyticsController.js +22 -23
  72. package/lib/Controllers/CacheController.js +10 -31
  73. package/lib/Controllers/DatabaseController.js +767 -313
  74. package/lib/Controllers/FilesController.js +49 -54
  75. package/lib/Controllers/HooksController.js +80 -84
  76. package/lib/Controllers/LiveQueryController.js +35 -22
  77. package/lib/Controllers/LoggerController.js +22 -58
  78. package/lib/Controllers/ParseGraphQLController.js +293 -0
  79. package/lib/Controllers/PushController.js +58 -49
  80. package/lib/Controllers/SchemaController.js +916 -422
  81. package/lib/Controllers/UserController.js +265 -180
  82. package/lib/Controllers/index.js +90 -125
  83. package/lib/Controllers/types.js +1 -1
  84. package/lib/Deprecator/Deprecations.js +30 -0
  85. package/lib/Deprecator/Deprecator.js +127 -0
  86. package/lib/Error.js +48 -0
  87. package/lib/GraphQL/ParseGraphQLSchema.js +375 -0
  88. package/lib/GraphQL/ParseGraphQLServer.js +214 -0
  89. package/lib/GraphQL/helpers/objectsMutations.js +30 -0
  90. package/lib/GraphQL/helpers/objectsQueries.js +246 -0
  91. package/lib/GraphQL/loaders/configMutations.js +87 -0
  92. package/lib/GraphQL/loaders/configQueries.js +79 -0
  93. package/lib/GraphQL/loaders/defaultGraphQLMutations.js +21 -0
  94. package/lib/GraphQL/loaders/defaultGraphQLQueries.js +23 -0
  95. package/lib/GraphQL/loaders/defaultGraphQLTypes.js +1098 -0
  96. package/lib/GraphQL/loaders/defaultRelaySchema.js +53 -0
  97. package/lib/GraphQL/loaders/filesMutations.js +107 -0
  98. package/lib/GraphQL/loaders/functionsMutations.js +78 -0
  99. package/lib/GraphQL/loaders/parseClassMutations.js +268 -0
  100. package/lib/GraphQL/loaders/parseClassQueries.js +127 -0
  101. package/lib/GraphQL/loaders/parseClassTypes.js +493 -0
  102. package/lib/GraphQL/loaders/schemaDirectives.js +62 -0
  103. package/lib/GraphQL/loaders/schemaMutations.js +162 -0
  104. package/lib/GraphQL/loaders/schemaQueries.js +81 -0
  105. package/lib/GraphQL/loaders/schemaTypes.js +341 -0
  106. package/lib/GraphQL/loaders/usersMutations.js +433 -0
  107. package/lib/GraphQL/loaders/usersQueries.js +90 -0
  108. package/lib/GraphQL/parseGraphQLUtils.js +63 -0
  109. package/lib/GraphQL/transformers/className.js +14 -0
  110. package/lib/GraphQL/transformers/constraintType.js +53 -0
  111. package/lib/GraphQL/transformers/inputType.js +51 -0
  112. package/lib/GraphQL/transformers/mutation.js +274 -0
  113. package/lib/GraphQL/transformers/outputType.js +51 -0
  114. package/lib/GraphQL/transformers/query.js +237 -0
  115. package/lib/GraphQL/transformers/schemaFields.js +99 -0
  116. package/lib/KeyPromiseQueue.js +48 -0
  117. package/lib/LiveQuery/Client.js +25 -33
  118. package/lib/LiveQuery/Id.js +2 -5
  119. package/lib/LiveQuery/ParseCloudCodePublisher.js +26 -23
  120. package/lib/LiveQuery/ParseLiveQueryServer.js +560 -285
  121. package/lib/LiveQuery/ParsePubSub.js +7 -16
  122. package/lib/LiveQuery/ParseWebSocketServer.js +42 -39
  123. package/lib/LiveQuery/QueryTools.js +76 -15
  124. package/lib/LiveQuery/RequestSchema.js +111 -97
  125. package/lib/LiveQuery/SessionTokenCache.js +23 -36
  126. package/lib/LiveQuery/Subscription.js +8 -17
  127. package/lib/LiveQuery/equalObjects.js +2 -3
  128. package/lib/Options/Definitions.js +1355 -382
  129. package/lib/Options/docs.js +301 -62
  130. package/lib/Options/index.js +11 -1
  131. package/lib/Options/parsers.js +14 -10
  132. package/lib/Page.js +44 -0
  133. package/lib/ParseMessageQueue.js +6 -13
  134. package/lib/ParseServer.js +474 -235
  135. package/lib/ParseServerRESTController.js +102 -40
  136. package/lib/PromiseRouter.js +39 -50
  137. package/lib/Push/PushQueue.js +24 -30
  138. package/lib/Push/PushWorker.js +32 -56
  139. package/lib/Push/utils.js +22 -35
  140. package/lib/RestQuery.js +361 -139
  141. package/lib/RestWrite.js +713 -344
  142. package/lib/Routers/AggregateRouter.js +97 -71
  143. package/lib/Routers/AnalyticsRouter.js +8 -14
  144. package/lib/Routers/AudiencesRouter.js +16 -35
  145. package/lib/Routers/ClassesRouter.js +86 -72
  146. package/lib/Routers/CloudCodeRouter.js +28 -37
  147. package/lib/Routers/FeaturesRouter.js +22 -25
  148. package/lib/Routers/FilesRouter.js +266 -171
  149. package/lib/Routers/FunctionsRouter.js +87 -103
  150. package/lib/Routers/GlobalConfigRouter.js +94 -33
  151. package/lib/Routers/GraphQLRouter.js +41 -0
  152. package/lib/Routers/HooksRouter.js +43 -47
  153. package/lib/Routers/IAPValidationRouter.js +57 -70
  154. package/lib/Routers/InstallationsRouter.js +17 -25
  155. package/lib/Routers/LogsRouter.js +10 -25
  156. package/lib/Routers/PagesRouter.js +647 -0
  157. package/lib/Routers/PublicAPIRouter.js +104 -112
  158. package/lib/Routers/PurgeRouter.js +19 -29
  159. package/lib/Routers/PushRouter.js +14 -28
  160. package/lib/Routers/RolesRouter.js +7 -14
  161. package/lib/Routers/SchemasRouter.js +63 -42
  162. package/lib/Routers/SecurityRouter.js +34 -0
  163. package/lib/Routers/SessionsRouter.js +25 -38
  164. package/lib/Routers/UsersRouter.js +463 -190
  165. package/lib/SchemaMigrations/DefinedSchemas.js +379 -0
  166. package/lib/SchemaMigrations/Migrations.js +30 -0
  167. package/lib/Security/Check.js +109 -0
  168. package/lib/Security/CheckGroup.js +44 -0
  169. package/lib/Security/CheckGroups/CheckGroupDatabase.js +44 -0
  170. package/lib/Security/CheckGroups/CheckGroupServerConfig.js +96 -0
  171. package/lib/Security/CheckGroups/CheckGroups.js +21 -0
  172. package/lib/Security/CheckRunner.js +213 -0
  173. package/lib/SharedRest.js +29 -0
  174. package/lib/StatusHandler.js +96 -93
  175. package/lib/TestUtils.js +70 -14
  176. package/lib/Utils.js +468 -0
  177. package/lib/batch.js +74 -40
  178. package/lib/cache.js +8 -8
  179. package/lib/cli/definitions/parse-live-query-server.js +4 -3
  180. package/lib/cli/definitions/parse-server.js +4 -3
  181. package/lib/cli/parse-live-query-server.js +9 -17
  182. package/lib/cli/parse-server.js +49 -47
  183. package/lib/cli/utils/commander.js +20 -29
  184. package/lib/cli/utils/runner.js +31 -32
  185. package/lib/cloud-code/Parse.Cloud.js +711 -36
  186. package/lib/cloud-code/Parse.Server.js +21 -0
  187. package/lib/cryptoUtils.js +6 -11
  188. package/lib/defaults.js +21 -15
  189. package/lib/deprecated.js +1 -1
  190. package/lib/index.js +78 -67
  191. package/lib/logger.js +12 -20
  192. package/lib/middlewares.js +484 -160
  193. package/lib/password.js +10 -6
  194. package/lib/request.js +175 -0
  195. package/lib/requiredParameter.js +4 -3
  196. package/lib/rest.js +157 -82
  197. package/lib/triggers.js +627 -185
  198. package/lib/vendor/README.md +3 -3
  199. package/lib/vendor/mongodbUrl.js +224 -137
  200. package/package.json +135 -57
  201. package/postinstall.js +38 -50
  202. package/public_html/invalid_verification_link.html +3 -3
  203. package/types/@types/@parse/fs-files-adapter/index.d.ts +5 -0
  204. package/types/@types/deepcopy/index.d.ts +5 -0
  205. package/types/LiveQuery/ParseLiveQueryServer.d.ts +40 -0
  206. package/types/Options/index.d.ts +301 -0
  207. package/types/ParseServer.d.ts +65 -0
  208. package/types/eslint.config.mjs +30 -0
  209. package/types/index.d.ts +21 -0
  210. package/types/logger.d.ts +2 -0
  211. package/types/tests.ts +44 -0
  212. package/types/tsconfig.json +24 -0
  213. package/CHANGELOG.md +0 -1246
  214. package/PATENTS +0 -37
  215. package/bin/dev +0 -37
  216. package/lib/.DS_Store +0 -0
  217. package/lib/Adapters/Auth/common.js +0 -2
  218. package/lib/Adapters/Auth/facebookaccountkit.js +0 -69
  219. package/lib/Controllers/SchemaCache.js +0 -97
  220. package/lib/LiveQuery/.DS_Store +0 -0
  221. package/lib/cli/utils/parsers.js +0 -77
  222. package/lib/cloud-code/.DS_Store +0 -0
  223. package/lib/cloud-code/HTTPResponse.js +0 -57
  224. package/lib/cloud-code/Untitled-1 +0 -123
  225. package/lib/cloud-code/httpRequest.js +0 -102
  226. package/lib/cloud-code/team.html +0 -123
  227. package/lib/graphql/ParseClass.js +0 -234
  228. package/lib/graphql/Schema.js +0 -197
  229. package/lib/graphql/index.js +0 -1
  230. package/lib/graphql/types/ACL.js +0 -35
  231. package/lib/graphql/types/Date.js +0 -25
  232. package/lib/graphql/types/File.js +0 -24
  233. package/lib/graphql/types/GeoPoint.js +0 -35
  234. package/lib/graphql/types/JSONObject.js +0 -30
  235. package/lib/graphql/types/NumberInput.js +0 -43
  236. package/lib/graphql/types/NumberQuery.js +0 -42
  237. package/lib/graphql/types/Pointer.js +0 -35
  238. package/lib/graphql/types/QueryConstraint.js +0 -61
  239. package/lib/graphql/types/StringQuery.js +0 -39
  240. package/lib/graphql/types/index.js +0 -110
@@ -1,9 +1,53 @@
1
- 'use strict';
1
+ "use strict";
2
+
3
+ /**
4
+ * Parse Server authentication adapter for Janrain Capture API.
5
+ *
6
+ * @class JanrainCapture
7
+ * @param {Object} options - The adapter configuration options.
8
+ * @param {String} options.janrain_capture_host - The Janrain Capture API host.
9
+ *
10
+ * @param {Object} authData - The authentication data provided by the client.
11
+ * @param {String} authData.id - The Janrain Capture user ID.
12
+ * @param {String} authData.access_token - The Janrain Capture access token.
13
+ *
14
+ * @description
15
+ * ## Parse Server Configuration
16
+ * To configure Parse Server for Janrain Capture authentication, use the following structure:
17
+ * ```json
18
+ * {
19
+ * "auth": {
20
+ * "janrain": {
21
+ * "janrain_capture_host": "your-janrain-capture-host"
22
+ * }
23
+ * }
24
+ * }
25
+ * ```
26
+ *
27
+ * The adapter requires the following `authData` fields:
28
+ * - `id`: The Janrain Capture user ID.
29
+ * - `access_token`: An authorized Janrain Capture access token for the user.
30
+ *
31
+ * ## Auth Payload Example
32
+ * ```json
33
+ * {
34
+ * "janrain": {
35
+ * "id": "user's Janrain Capture ID as a string",
36
+ * "access_token": "an authorized Janrain Capture access token for the user"
37
+ * }
38
+ * }
39
+ * ```
40
+ *
41
+ * ## Notes
42
+ * Parse Server validates the provided `authData` using the Janrain Capture API.
43
+ *
44
+ * @see {@link https://docs.janrain.com/api/registration/entity/#entity Janrain Capture API Documentation}
45
+ */
2
46
 
3
47
  // Helper functions for accessing the Janrain Capture API.
4
- var https = require('https');
5
48
  var Parse = require('parse/node').Parse;
6
49
  var querystring = require('querystring');
50
+ const httpsRequest = require('./httpsRequest');
7
51
 
8
52
  // Returns a promise that fulfills iff this user id is valid.
9
53
  function validateAuthData(authData, options) {
@@ -25,32 +69,17 @@ function validateAppId() {
25
69
 
26
70
  // A promisey wrapper for api requests
27
71
  function request(host, access_token) {
28
-
29
72
  var query_string_data = querystring.stringify({
30
- 'access_token': access_token,
31
- 'attribute_name': 'uuid' // we only need to pull the uuid for this access token to make sure it matches
73
+ access_token: access_token,
74
+ attribute_name: 'uuid' // we only need to pull the uuid for this access token to make sure it matches
32
75
  });
33
-
34
- return new Promise(function (resolve, reject) {
35
- https.get({
36
- host: host,
37
- path: '/entity?' + query_string_data
38
- }, function (res) {
39
- var data = '';
40
- res.on('data', function (chunk) {
41
- data += chunk;
42
- });
43
- res.on('end', function () {
44
- resolve(JSON.parse(data));
45
- });
46
- }).on('error', function () {
47
- reject('Failed to validate this access token with Janrain capture.');
48
- });
76
+ return httpsRequest.get({
77
+ host: host,
78
+ path: '/entity?' + query_string_data
49
79
  });
50
80
  }
51
-
52
81
  module.exports = {
53
82
  validateAppId: validateAppId,
54
83
  validateAuthData: validateAuthData
55
84
  };
56
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2phbnJhaW5jYXB0dXJlLmpzIl0sIm5hbWVzIjpbImh0dHBzIiwicmVxdWlyZSIsIlBhcnNlIiwicXVlcnlzdHJpbmciLCJ2YWxpZGF0ZUF1dGhEYXRhIiwiYXV0aERhdGEiLCJvcHRpb25zIiwicmVxdWVzdCIsImphbnJhaW5fY2FwdHVyZV9ob3N0IiwiYWNjZXNzX3Rva2VuIiwidGhlbiIsImRhdGEiLCJzdGF0IiwicmVzdWx0IiwiaWQiLCJFcnJvciIsIk9CSkVDVF9OT1RfRk9VTkQiLCJ2YWxpZGF0ZUFwcElkIiwiUHJvbWlzZSIsInJlc29sdmUiLCJob3N0IiwicXVlcnlfc3RyaW5nX2RhdGEiLCJzdHJpbmdpZnkiLCJyZWplY3QiLCJnZXQiLCJwYXRoIiwicmVzIiwib24iLCJjaHVuayIsIkpTT04iLCJwYXJzZSIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQSxJQUFJQSxRQUFRQyxRQUFRLE9BQVIsQ0FBWjtBQUNBLElBQUlDLFFBQVFELFFBQVEsWUFBUixFQUFzQkMsS0FBbEM7QUFDQSxJQUFJQyxjQUFjRixRQUFRLGFBQVIsQ0FBbEI7O0FBRUE7QUFDQSxTQUFTRyxnQkFBVCxDQUEwQkMsUUFBMUIsRUFBb0NDLE9BQXBDLEVBQTZDO0FBQzNDLFNBQU9DLFFBQVFELFFBQVFFLG9CQUFoQixFQUFzQ0gsU0FBU0ksWUFBL0MsRUFDSkMsSUFESSxDQUNFQyxJQUFELElBQVU7QUFDZDtBQUNBO0FBQ0EsUUFBSUEsUUFBUUEsS0FBS0MsSUFBTCxJQUFhLElBQXJCLElBQTZCRCxLQUFLRSxNQUFMLElBQWVSLFNBQVNTLEVBQXpELEVBQTZEO0FBQzNEO0FBQ0Q7QUFDRCxVQUFNLElBQUlaLE1BQU1hLEtBQVYsQ0FBZ0JiLE1BQU1hLEtBQU4sQ0FBWUMsZ0JBQTVCLEVBQThDLGdEQUE5QyxDQUFOO0FBQ0QsR0FSSSxDQUFQO0FBU0Q7O0FBRUQ7QUFDQSxTQUFTQyxhQUFULEdBQXlCO0FBQ3ZCO0FBQ0EsU0FBT0MsUUFBUUMsT0FBUixFQUFQO0FBQ0Q7O0FBRUQ7QUFDQSxTQUFTWixPQUFULENBQWlCYSxJQUFqQixFQUF1QlgsWUFBdkIsRUFBcUM7O0FBRW5DLE1BQUlZLG9CQUFvQmxCLFlBQVltQixTQUFaLENBQXNCO0FBQzVDLG9CQUFnQmIsWUFENEI7QUFFNUMsc0JBQWtCLE1BRjBCLENBRW5CO0FBRm1CLEdBQXRCLENBQXhCOztBQUtBLFNBQU8sSUFBSVMsT0FBSixDQUFZLFVBQVNDLE9BQVQsRUFBa0JJLE1BQWxCLEVBQTBCO0FBQzNDdkIsVUFBTXdCLEdBQU4sQ0FBVTtBQUNSSixZQUFNQSxJQURFO0FBRVJLLFlBQU0sYUFBYUo7QUFGWCxLQUFWLEVBR0csVUFBU0ssR0FBVCxFQUFjO0FBQ2YsVUFBSWYsT0FBTyxFQUFYO0FBQ0FlLFVBQUlDLEVBQUosQ0FBTyxNQUFQLEVBQWUsVUFBU0MsS0FBVCxFQUFnQjtBQUM3QmpCLGdCQUFRaUIsS0FBUjtBQUNELE9BRkQ7QUFHQUYsVUFBSUMsRUFBSixDQUFPLEtBQVAsRUFBYyxZQUFZO0FBQ3hCUixnQkFBUVUsS0FBS0MsS0FBTCxDQUFXbkIsSUFBWCxDQUFSO0FBQ0QsT0FGRDtBQUdELEtBWEQsRUFXR2dCLEVBWEgsQ0FXTSxPQVhOLEVBV2UsWUFBVztBQUN4QkosYUFBTyw0REFBUDtBQUNELEtBYkQ7QUFjRCxHQWZNLENBQVA7QUFnQkQ7O0FBRURRLE9BQU9DLE9BQVAsR0FBaUI7QUFDZmYsaUJBQWVBLGFBREE7QUFFZmIsb0JBQWtCQTtBQUZILENBQWpCIiwiZmlsZSI6ImphbnJhaW5jYXB0dXJlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gSGVscGVyIGZ1bmN0aW9ucyBmb3IgYWNjZXNzaW5nIHRoZSBKYW5yYWluIENhcHR1cmUgQVBJLlxudmFyIGh0dHBzID0gcmVxdWlyZSgnaHR0cHMnKTtcbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcbnZhciBxdWVyeXN0cmluZyA9IHJlcXVpcmUoJ3F1ZXJ5c3RyaW5nJyk7XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIHJlcXVlc3Qob3B0aW9ucy5qYW5yYWluX2NhcHR1cmVfaG9zdCwgYXV0aERhdGEuYWNjZXNzX3Rva2VuKVxuICAgIC50aGVuKChkYXRhKSA9PiB7XG4gICAgICAvL3N1Y2Nlc3NmdWwgcmVzcG9uc2Ugd2lsbCBoYXZlIGEgXCJzdGF0XCIgKHN0YXR1cykgb2YgJ29rJyBhbmQgYSByZXN1bHQgbm9kZSB0aGF0IHN0b3JlcyB0aGUgdXVpZCwgYmVjYXVzZSB0aGF0J3MgYWxsIHdlIGFza2VkIGZvclxuICAgICAgLy9zZWU6IGh0dHBzOi8vZG9jcy5qYW5yYWluLmNvbS9hcGkvcmVnaXN0cmF0aW9uL2VudGl0eS8jZW50aXR5XG4gICAgICBpZiAoZGF0YSAmJiBkYXRhLnN0YXQgPT0gJ29rJyAmJiBkYXRhLnJlc3VsdCA9PSBhdXRoRGF0YS5pZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ0phbnJhaW4gY2FwdHVyZSBhdXRoIGlzIGludmFsaWQgZm9yIHRoaXMgdXNlci4nKTtcbiAgICB9KTtcbn1cblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZmYgdGhpcyBhcHAgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKCkge1xuICAvL25vLW9wXG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn1cblxuLy8gQSBwcm9taXNleSB3cmFwcGVyIGZvciBhcGkgcmVxdWVzdHNcbmZ1bmN0aW9uIHJlcXVlc3QoaG9zdCwgYWNjZXNzX3Rva2VuKSB7XG5cbiAgdmFyIHF1ZXJ5X3N0cmluZ19kYXRhID0gcXVlcnlzdHJpbmcuc3RyaW5naWZ5KHtcbiAgICAnYWNjZXNzX3Rva2VuJzogYWNjZXNzX3Rva2VuLFxuICAgICdhdHRyaWJ1dGVfbmFtZSc6ICd1dWlkJyAvLyB3ZSBvbmx5IG5lZWQgdG8gcHVsbCB0aGUgdXVpZCBmb3IgdGhpcyBhY2Nlc3MgdG9rZW4gdG8gbWFrZSBzdXJlIGl0IG1hdGNoZXNcbiAgfSk7XG5cbiAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHJlc29sdmUsIHJlamVjdCkge1xuICAgIGh0dHBzLmdldCh7XG4gICAgICBob3N0OiBob3N0LFxuICAgICAgcGF0aDogJy9lbnRpdHk/JyArIHF1ZXJ5X3N0cmluZ19kYXRhXG4gICAgfSwgZnVuY3Rpb24ocmVzKSB7XG4gICAgICB2YXIgZGF0YSA9ICcnO1xuICAgICAgcmVzLm9uKCdkYXRhJywgZnVuY3Rpb24oY2h1bmspIHtcbiAgICAgICAgZGF0YSArPSBjaHVuaztcbiAgICAgIH0pO1xuICAgICAgcmVzLm9uKCdlbmQnLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJlc29sdmUoSlNPTi5wYXJzZShkYXRhKSk7XG4gICAgICB9KTtcbiAgICB9KS5vbignZXJyb3InLCBmdW5jdGlvbigpIHtcbiAgICAgIHJlamVjdCgnRmFpbGVkIHRvIHZhbGlkYXRlIHRoaXMgYWNjZXNzIHRva2VuIHdpdGggSmFucmFpbiBjYXB0dXJlLicpO1xuICAgIH0pO1xuICB9KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHZhbGlkYXRlQXBwSWQ6IHZhbGlkYXRlQXBwSWQsXG4gIHZhbGlkYXRlQXV0aERhdGE6IHZhbGlkYXRlQXV0aERhdGFcbn07XG4iXX0=
85
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJQYXJzZSIsInJlcXVpcmUiLCJxdWVyeXN0cmluZyIsImh0dHBzUmVxdWVzdCIsInZhbGlkYXRlQXV0aERhdGEiLCJhdXRoRGF0YSIsIm9wdGlvbnMiLCJyZXF1ZXN0IiwiamFucmFpbl9jYXB0dXJlX2hvc3QiLCJhY2Nlc3NfdG9rZW4iLCJ0aGVuIiwiZGF0YSIsInN0YXQiLCJyZXN1bHQiLCJpZCIsIkVycm9yIiwiT0JKRUNUX05PVF9GT1VORCIsInZhbGlkYXRlQXBwSWQiLCJQcm9taXNlIiwicmVzb2x2ZSIsImhvc3QiLCJxdWVyeV9zdHJpbmdfZGF0YSIsInN0cmluZ2lmeSIsImF0dHJpYnV0ZV9uYW1lIiwiZ2V0IiwicGF0aCIsIm1vZHVsZSIsImV4cG9ydHMiXSwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvQWRhcHRlcnMvQXV0aC9qYW5yYWluY2FwdHVyZS5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFBhcnNlIFNlcnZlciBhdXRoZW50aWNhdGlvbiBhZGFwdGVyIGZvciBKYW5yYWluIENhcHR1cmUgQVBJLlxuICpcbiAqIEBjbGFzcyBKYW5yYWluQ2FwdHVyZVxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBUaGUgYWRhcHRlciBjb25maWd1cmF0aW9uIG9wdGlvbnMuXG4gKiBAcGFyYW0ge1N0cmluZ30gb3B0aW9ucy5qYW5yYWluX2NhcHR1cmVfaG9zdCAtIFRoZSBKYW5yYWluIENhcHR1cmUgQVBJIGhvc3QuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGF1dGhEYXRhIC0gVGhlIGF1dGhlbnRpY2F0aW9uIGRhdGEgcHJvdmlkZWQgYnkgdGhlIGNsaWVudC5cbiAqIEBwYXJhbSB7U3RyaW5nfSBhdXRoRGF0YS5pZCAtIFRoZSBKYW5yYWluIENhcHR1cmUgdXNlciBJRC5cbiAqIEBwYXJhbSB7U3RyaW5nfSBhdXRoRGF0YS5hY2Nlc3NfdG9rZW4gLSBUaGUgSmFucmFpbiBDYXB0dXJlIGFjY2VzcyB0b2tlbi5cbiAqXG4gKiBAZGVzY3JpcHRpb25cbiAqICMjIFBhcnNlIFNlcnZlciBDb25maWd1cmF0aW9uXG4gKiBUbyBjb25maWd1cmUgUGFyc2UgU2VydmVyIGZvciBKYW5yYWluIENhcHR1cmUgYXV0aGVudGljYXRpb24sIHVzZSB0aGUgZm9sbG93aW5nIHN0cnVjdHVyZTpcbiAqIGBgYGpzb25cbiAqIHtcbiAqICAgXCJhdXRoXCI6IHtcbiAqICAgICBcImphbnJhaW5cIjoge1xuICogICAgICAgXCJqYW5yYWluX2NhcHR1cmVfaG9zdFwiOiBcInlvdXItamFucmFpbi1jYXB0dXJlLWhvc3RcIlxuICogICAgIH1cbiAqICAgfVxuICogfVxuICogYGBgXG4gKlxuICogVGhlIGFkYXB0ZXIgcmVxdWlyZXMgdGhlIGZvbGxvd2luZyBgYXV0aERhdGFgIGZpZWxkczpcbiAqIC0gYGlkYDogVGhlIEphbnJhaW4gQ2FwdHVyZSB1c2VyIElELlxuICogLSBgYWNjZXNzX3Rva2VuYDogQW4gYXV0aG9yaXplZCBKYW5yYWluIENhcHR1cmUgYWNjZXNzIHRva2VuIGZvciB0aGUgdXNlci5cbiAqXG4gKiAjIyBBdXRoIFBheWxvYWQgRXhhbXBsZVxuICogYGBganNvblxuICoge1xuICogICBcImphbnJhaW5cIjoge1xuICogICAgIFwiaWRcIjogXCJ1c2VyJ3MgSmFucmFpbiBDYXB0dXJlIElEIGFzIGEgc3RyaW5nXCIsXG4gKiAgICAgXCJhY2Nlc3NfdG9rZW5cIjogXCJhbiBhdXRob3JpemVkIEphbnJhaW4gQ2FwdHVyZSBhY2Nlc3MgdG9rZW4gZm9yIHRoZSB1c2VyXCJcbiAqICAgfVxuICogfVxuICogYGBgXG4gKlxuICogIyMgTm90ZXNcbiAqIFBhcnNlIFNlcnZlciB2YWxpZGF0ZXMgdGhlIHByb3ZpZGVkIGBhdXRoRGF0YWAgdXNpbmcgdGhlIEphbnJhaW4gQ2FwdHVyZSBBUEkuXG4gKlxuICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kb2NzLmphbnJhaW4uY29tL2FwaS9yZWdpc3RyYXRpb24vZW50aXR5LyNlbnRpdHkgSmFucmFpbiBDYXB0dXJlIEFQSSBEb2N1bWVudGF0aW9ufVxuICovXG5cblxuLy8gSGVscGVyIGZ1bmN0aW9ucyBmb3IgYWNjZXNzaW5nIHRoZSBKYW5yYWluIENhcHR1cmUgQVBJLlxudmFyIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xudmFyIHF1ZXJ5c3RyaW5nID0gcmVxdWlyZSgncXVlcnlzdHJpbmcnKTtcbmNvbnN0IGh0dHBzUmVxdWVzdCA9IHJlcXVpcmUoJy4vaHR0cHNSZXF1ZXN0Jyk7XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWZmIHRoaXMgdXNlciBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIHJlcXVlc3Qob3B0aW9ucy5qYW5yYWluX2NhcHR1cmVfaG9zdCwgYXV0aERhdGEuYWNjZXNzX3Rva2VuKS50aGVuKGRhdGEgPT4ge1xuICAgIC8vc3VjY2Vzc2Z1bCByZXNwb25zZSB3aWxsIGhhdmUgYSBcInN0YXRcIiAoc3RhdHVzKSBvZiAnb2snIGFuZCBhIHJlc3VsdCBub2RlIHRoYXQgc3RvcmVzIHRoZSB1dWlkLCBiZWNhdXNlIHRoYXQncyBhbGwgd2UgYXNrZWQgZm9yXG4gICAgLy9zZWU6IGh0dHBzOi8vZG9jcy5qYW5yYWluLmNvbS9hcGkvcmVnaXN0cmF0aW9uL2VudGl0eS8jZW50aXR5XG4gICAgaWYgKGRhdGEgJiYgZGF0YS5zdGF0ID09ICdvaycgJiYgZGF0YS5yZXN1bHQgPT0gYXV0aERhdGEuaWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCxcbiAgICAgICdKYW5yYWluIGNhcHR1cmUgYXV0aCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJ1xuICAgICk7XG4gIH0pO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmZiB0aGlzIGFwcCBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXBwSWQoKSB7XG4gIC8vbm8tb3BcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufVxuXG4vLyBBIHByb21pc2V5IHdyYXBwZXIgZm9yIGFwaSByZXF1ZXN0c1xuZnVuY3Rpb24gcmVxdWVzdChob3N0LCBhY2Nlc3NfdG9rZW4pIHtcbiAgdmFyIHF1ZXJ5X3N0cmluZ19kYXRhID0gcXVlcnlzdHJpbmcuc3RyaW5naWZ5KHtcbiAgICBhY2Nlc3NfdG9rZW46IGFjY2Vzc190b2tlbixcbiAgICBhdHRyaWJ1dGVfbmFtZTogJ3V1aWQnLCAvLyB3ZSBvbmx5IG5lZWQgdG8gcHVsbCB0aGUgdXVpZCBmb3IgdGhpcyBhY2Nlc3MgdG9rZW4gdG8gbWFrZSBzdXJlIGl0IG1hdGNoZXNcbiAgfSk7XG5cbiAgcmV0dXJuIGh0dHBzUmVxdWVzdC5nZXQoeyBob3N0OiBob3N0LCBwYXRoOiAnL2VudGl0eT8nICsgcXVlcnlfc3RyaW5nX2RhdGEgfSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkOiB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhOiB2YWxpZGF0ZUF1dGhEYXRhLFxufTtcbiJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFHQTtBQUNBLElBQUlBLEtBQUssR0FBR0MsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDRCxLQUFLO0FBQ3ZDLElBQUlFLFdBQVcsR0FBR0QsT0FBTyxDQUFDLGFBQWEsQ0FBQztBQUN4QyxNQUFNRSxZQUFZLEdBQUdGLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQzs7QUFFOUM7QUFDQSxTQUFTRyxnQkFBZ0JBLENBQUNDLFFBQVEsRUFBRUMsT0FBTyxFQUFFO0VBQzNDLE9BQU9DLE9BQU8sQ0FBQ0QsT0FBTyxDQUFDRSxvQkFBb0IsRUFBRUgsUUFBUSxDQUFDSSxZQUFZLENBQUMsQ0FBQ0MsSUFBSSxDQUFDQyxJQUFJLElBQUk7SUFDL0U7SUFDQTtJQUNBLElBQUlBLElBQUksSUFBSUEsSUFBSSxDQUFDQyxJQUFJLElBQUksSUFBSSxJQUFJRCxJQUFJLENBQUNFLE1BQU0sSUFBSVIsUUFBUSxDQUFDUyxFQUFFLEVBQUU7TUFDM0Q7SUFDRjtJQUNBLE1BQU0sSUFBSWQsS0FBSyxDQUFDZSxLQUFLLENBQ25CZixLQUFLLENBQUNlLEtBQUssQ0FBQ0MsZ0JBQWdCLEVBQzVCLGdEQUNGLENBQUM7RUFDSCxDQUFDLENBQUM7QUFDSjs7QUFFQTtBQUNBLFNBQVNDLGFBQWFBLENBQUEsRUFBRztFQUN2QjtFQUNBLE9BQU9DLE9BQU8sQ0FBQ0MsT0FBTyxDQUFDLENBQUM7QUFDMUI7O0FBRUE7QUFDQSxTQUFTWixPQUFPQSxDQUFDYSxJQUFJLEVBQUVYLFlBQVksRUFBRTtFQUNuQyxJQUFJWSxpQkFBaUIsR0FBR25CLFdBQVcsQ0FBQ29CLFNBQVMsQ0FBQztJQUM1Q2IsWUFBWSxFQUFFQSxZQUFZO0lBQzFCYyxjQUFjLEVBQUUsTUFBTSxDQUFFO0VBQzFCLENBQUMsQ0FBQztFQUVGLE9BQU9wQixZQUFZLENBQUNxQixHQUFHLENBQUM7SUFBRUosSUFBSSxFQUFFQSxJQUFJO0lBQUVLLElBQUksRUFBRSxVQUFVLEdBQUdKO0VBQWtCLENBQUMsQ0FBQztBQUMvRTtBQUVBSyxNQUFNLENBQUNDLE9BQU8sR0FBRztFQUNmVixhQUFhLEVBQUVBLGFBQWE7RUFDNUJiLGdCQUFnQixFQUFFQTtBQUNwQixDQUFDIiwiaWdub3JlTGlzdCI6W119
@@ -1,13 +1,22 @@
1
- 'use strict';
1
+ "use strict";
2
2
 
3
+ var _Config = _interopRequireDefault(require("../../Config"));
4
+ var _Deprecator = _interopRequireDefault(require("../../Deprecator/Deprecator"));
5
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
3
6
  // Helper functions for accessing the Janrain Engage API.
4
- var https = require('https');
7
+ var httpsRequest = require('./httpsRequest');
5
8
  var Parse = require('parse/node').Parse;
6
9
  var querystring = require('querystring');
7
-
8
10
  // Returns a promise that fulfills iff this user id is valid.
9
11
  function validateAuthData(authData, options) {
10
- return request(options.api_key, authData.auth_token).then(data => {
12
+ const config = _Config.default.get(Parse.applicationId);
13
+ _Deprecator.default.logRuntimeDeprecation({
14
+ usage: 'janrainengage adapter'
15
+ });
16
+ if (!config?.auth?.janrainengage?.enableInsecureAuth || !config.enableInsecureAuthAdapters) {
17
+ throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'janrainengage adapter only works with enableInsecureAuth: true');
18
+ }
19
+ return apiRequest(options.api_key, authData.auth_token).then(data => {
11
20
  //successful response will have a "stat" (status) of 'ok' and a profile node with an identifier
12
21
  //see: http://developers.janrain.com/overview/social-login/identity-providers/user-profile-data/#normalized-user-profile-data
13
22
  if (data && data.stat == 'ok' && data.profile.identifier == authData.id) {
@@ -24,14 +33,12 @@ function validateAppId() {
24
33
  }
25
34
 
26
35
  // A promisey wrapper for api requests
27
- function request(api_key, auth_token) {
28
-
36
+ function apiRequest(api_key, auth_token) {
29
37
  var post_data = querystring.stringify({
30
- 'token': auth_token,
31
- 'apiKey': api_key,
32
- 'format': 'json'
38
+ token: auth_token,
39
+ apiKey: api_key,
40
+ format: 'json'
33
41
  });
34
-
35
42
  var post_options = {
36
43
  host: 'rpxnow.com',
37
44
  path: '/api/v2/auth_info',
@@ -41,34 +48,10 @@ function request(api_key, auth_token) {
41
48
  'Content-Length': post_data.length
42
49
  }
43
50
  };
44
-
45
- return new Promise(function (resolve, reject) {
46
- // Create the post request.
47
- var post_req = https.request(post_options, function (res) {
48
- var data = '';
49
- res.setEncoding('utf8');
50
- // Append data as we receive it from the Janrain engage server.
51
- res.on('data', function (d) {
52
- data += d;
53
- });
54
- // Once we have all the data, we can parse it and return the data we want.
55
- res.on('end', function () {
56
- try {
57
- data = JSON.parse(data);
58
- } catch (e) {
59
- return reject(e);
60
- }
61
- resolve(data);
62
- });
63
- });
64
-
65
- post_req.write(post_data);
66
- post_req.end();
67
- });
51
+ return httpsRequest.request(post_options, post_data);
68
52
  }
69
-
70
53
  module.exports = {
71
54
  validateAppId: validateAppId,
72
55
  validateAuthData: validateAuthData
73
56
  };
74
- //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2phbnJhaW5lbmdhZ2UuanMiXSwibmFtZXMiOlsiaHR0cHMiLCJyZXF1aXJlIiwiUGFyc2UiLCJxdWVyeXN0cmluZyIsInZhbGlkYXRlQXV0aERhdGEiLCJhdXRoRGF0YSIsIm9wdGlvbnMiLCJyZXF1ZXN0IiwiYXBpX2tleSIsImF1dGhfdG9rZW4iLCJ0aGVuIiwiZGF0YSIsInN0YXQiLCJwcm9maWxlIiwiaWRlbnRpZmllciIsImlkIiwiRXJyb3IiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwidmFsaWRhdGVBcHBJZCIsIlByb21pc2UiLCJyZXNvbHZlIiwicG9zdF9kYXRhIiwic3RyaW5naWZ5IiwicG9zdF9vcHRpb25zIiwiaG9zdCIsInBhdGgiLCJtZXRob2QiLCJoZWFkZXJzIiwibGVuZ3RoIiwicmVqZWN0IiwicG9zdF9yZXEiLCJyZXMiLCJzZXRFbmNvZGluZyIsIm9uIiwiZCIsIkpTT04iLCJwYXJzZSIsImUiLCJ3cml0ZSIsImVuZCIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7O0FBQUE7QUFDQSxJQUFJQSxRQUFRQyxRQUFRLE9BQVIsQ0FBWjtBQUNBLElBQUlDLFFBQVFELFFBQVEsWUFBUixFQUFzQkMsS0FBbEM7QUFDQSxJQUFJQyxjQUFjRixRQUFRLGFBQVIsQ0FBbEI7O0FBRUE7QUFDQSxTQUFTRyxnQkFBVCxDQUEwQkMsUUFBMUIsRUFBb0NDLE9BQXBDLEVBQTZDO0FBQzNDLFNBQU9DLFFBQVFELFFBQVFFLE9BQWhCLEVBQXlCSCxTQUFTSSxVQUFsQyxFQUNKQyxJQURJLENBQ0VDLElBQUQsSUFBVTtBQUNkO0FBQ0E7QUFDQSxRQUFJQSxRQUFRQSxLQUFLQyxJQUFMLElBQWEsSUFBckIsSUFBNkJELEtBQUtFLE9BQUwsQ0FBYUMsVUFBYixJQUEyQlQsU0FBU1UsRUFBckUsRUFBeUU7QUFDdkU7QUFDRDtBQUNELFVBQU0sSUFBSWIsTUFBTWMsS0FBVixDQUFnQmQsTUFBTWMsS0FBTixDQUFZQyxnQkFBNUIsRUFBOEMsK0NBQTlDLENBQU47QUFDRCxHQVJJLENBQVA7QUFTRDs7QUFFRDtBQUNBLFNBQVNDLGFBQVQsR0FBeUI7QUFDdkI7QUFDQSxTQUFPQyxRQUFRQyxPQUFSLEVBQVA7QUFDRDs7QUFFRDtBQUNBLFNBQVNiLE9BQVQsQ0FBaUJDLE9BQWpCLEVBQTBCQyxVQUExQixFQUFzQzs7QUFFcEMsTUFBSVksWUFBWWxCLFlBQVltQixTQUFaLENBQXNCO0FBQ3BDLGFBQVNiLFVBRDJCO0FBRXBDLGNBQVVELE9BRjBCO0FBR3BDLGNBQVU7QUFIMEIsR0FBdEIsQ0FBaEI7O0FBTUEsTUFBSWUsZUFBZTtBQUNqQkMsVUFBTSxZQURXO0FBRWpCQyxVQUFNLG1CQUZXO0FBR2pCQyxZQUFRLE1BSFM7QUFJakJDLGFBQVM7QUFDUCxzQkFBZ0IsbUNBRFQ7QUFFUCx3QkFBa0JOLFVBQVVPO0FBRnJCO0FBSlEsR0FBbkI7O0FBVUEsU0FBTyxJQUFJVCxPQUFKLENBQVksVUFBVUMsT0FBVixFQUFtQlMsTUFBbkIsRUFBMkI7QUFDNUM7QUFDQSxRQUFJQyxXQUFXOUIsTUFBTU8sT0FBTixDQUFjZ0IsWUFBZCxFQUE0QixVQUFVUSxHQUFWLEVBQWU7QUFDeEQsVUFBSXBCLE9BQU8sRUFBWDtBQUNBb0IsVUFBSUMsV0FBSixDQUFnQixNQUFoQjtBQUNBO0FBQ0FELFVBQUlFLEVBQUosQ0FBTyxNQUFQLEVBQWUsVUFBVUMsQ0FBVixFQUFhO0FBQzFCdkIsZ0JBQVF1QixDQUFSO0FBQ0QsT0FGRDtBQUdBO0FBQ0FILFVBQUlFLEVBQUosQ0FBTyxLQUFQLEVBQWMsWUFBWTtBQUN4QixZQUFJO0FBQ0Z0QixpQkFBT3dCLEtBQUtDLEtBQUwsQ0FBV3pCLElBQVgsQ0FBUDtBQUNELFNBRkQsQ0FFRSxPQUFNMEIsQ0FBTixFQUFTO0FBQ1QsaUJBQU9SLE9BQU9RLENBQVAsQ0FBUDtBQUNEO0FBQ0RqQixnQkFBUVQsSUFBUjtBQUNELE9BUEQ7QUFRRCxLQWhCYyxDQUFmOztBQWtCQW1CLGFBQVNRLEtBQVQsQ0FBZWpCLFNBQWY7QUFDQVMsYUFBU1MsR0FBVDtBQUNELEdBdEJNLENBQVA7QUF1QkQ7O0FBRURDLE9BQU9DLE9BQVAsR0FBaUI7QUFDZnZCLGlCQUFlQSxhQURBO0FBRWZkLG9CQUFrQkE7QUFGSCxDQUFqQiIsImZpbGUiOiJqYW5yYWluZW5nYWdlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gSGVscGVyIGZ1bmN0aW9ucyBmb3IgYWNjZXNzaW5nIHRoZSBKYW5yYWluIEVuZ2FnZSBBUEkuXG52YXIgaHR0cHMgPSByZXF1aXJlKCdodHRwcycpO1xudmFyIFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xudmFyIHF1ZXJ5c3RyaW5nID0gcmVxdWlyZSgncXVlcnlzdHJpbmcnKTtcblxuLy8gUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBpZmYgdGhpcyB1c2VyIGlkIGlzIHZhbGlkLlxuZnVuY3Rpb24gdmFsaWRhdGVBdXRoRGF0YShhdXRoRGF0YSwgb3B0aW9ucykge1xuICByZXR1cm4gcmVxdWVzdChvcHRpb25zLmFwaV9rZXksIGF1dGhEYXRhLmF1dGhfdG9rZW4pXG4gICAgLnRoZW4oKGRhdGEpID0+IHtcbiAgICAgIC8vc3VjY2Vzc2Z1bCByZXNwb25zZSB3aWxsIGhhdmUgYSBcInN0YXRcIiAoc3RhdHVzKSBvZiAnb2snIGFuZCBhIHByb2ZpbGUgbm9kZSB3aXRoIGFuIGlkZW50aWZpZXJcbiAgICAgIC8vc2VlOiBodHRwOi8vZGV2ZWxvcGVycy5qYW5yYWluLmNvbS9vdmVydmlldy9zb2NpYWwtbG9naW4vaWRlbnRpdHktcHJvdmlkZXJzL3VzZXItcHJvZmlsZS1kYXRhLyNub3JtYWxpemVkLXVzZXItcHJvZmlsZS1kYXRhXG4gICAgICBpZiAoZGF0YSAmJiBkYXRhLnN0YXQgPT0gJ29rJyAmJiBkYXRhLnByb2ZpbGUuaWRlbnRpZmllciA9PSBhdXRoRGF0YS5pZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ0phbnJhaW4gZW5nYWdlIGF1dGggaXMgaW52YWxpZCBmb3IgdGhpcyB1c2VyLicpO1xuICAgIH0pO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmZiB0aGlzIGFwcCBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXBwSWQoKSB7XG4gIC8vbm8tb3BcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufVxuXG4vLyBBIHByb21pc2V5IHdyYXBwZXIgZm9yIGFwaSByZXF1ZXN0c1xuZnVuY3Rpb24gcmVxdWVzdChhcGlfa2V5LCBhdXRoX3Rva2VuKSB7XG5cbiAgdmFyIHBvc3RfZGF0YSA9IHF1ZXJ5c3RyaW5nLnN0cmluZ2lmeSh7XG4gICAgJ3Rva2VuJzogYXV0aF90b2tlbixcbiAgICAnYXBpS2V5JzogYXBpX2tleSxcbiAgICAnZm9ybWF0JzogJ2pzb24nXG4gIH0pO1xuXG4gIHZhciBwb3N0X29wdGlvbnMgPSB7XG4gICAgaG9zdDogJ3JweG5vdy5jb20nLFxuICAgIHBhdGg6ICcvYXBpL3YyL2F1dGhfaW5mbycsXG4gICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgaGVhZGVyczoge1xuICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnLFxuICAgICAgJ0NvbnRlbnQtTGVuZ3RoJzogcG9zdF9kYXRhLmxlbmd0aFxuICAgIH1cbiAgfTtcblxuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIC8vIENyZWF0ZSB0aGUgcG9zdCByZXF1ZXN0LlxuICAgIHZhciBwb3N0X3JlcSA9IGh0dHBzLnJlcXVlc3QocG9zdF9vcHRpb25zLCBmdW5jdGlvbiAocmVzKSB7XG4gICAgICB2YXIgZGF0YSA9ICcnO1xuICAgICAgcmVzLnNldEVuY29kaW5nKCd1dGY4Jyk7XG4gICAgICAvLyBBcHBlbmQgZGF0YSBhcyB3ZSByZWNlaXZlIGl0IGZyb20gdGhlIEphbnJhaW4gZW5nYWdlIHNlcnZlci5cbiAgICAgIHJlcy5vbignZGF0YScsIGZ1bmN0aW9uIChkKSB7XG4gICAgICAgIGRhdGEgKz0gZDtcbiAgICAgIH0pO1xuICAgICAgLy8gT25jZSB3ZSBoYXZlIGFsbCB0aGUgZGF0YSwgd2UgY2FuIHBhcnNlIGl0IGFuZCByZXR1cm4gdGhlIGRhdGEgd2Ugd2FudC5cbiAgICAgIHJlcy5vbignZW5kJywgZnVuY3Rpb24gKCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGRhdGEgPSBKU09OLnBhcnNlKGRhdGEpO1xuICAgICAgICB9IGNhdGNoKGUpIHtcbiAgICAgICAgICByZXR1cm4gcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICAgIHJlc29sdmUoZGF0YSk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHBvc3RfcmVxLndyaXRlKHBvc3RfZGF0YSk7XG4gICAgcG9zdF9yZXEuZW5kKCk7XG4gIH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgdmFsaWRhdGVBcHBJZDogdmFsaWRhdGVBcHBJZCxcbiAgdmFsaWRhdGVBdXRoRGF0YTogdmFsaWRhdGVBdXRoRGF0YVxufTtcbiJdfQ==
57
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJfQ29uZmlnIiwiX2ludGVyb3BSZXF1aXJlRGVmYXVsdCIsInJlcXVpcmUiLCJfRGVwcmVjYXRvciIsImUiLCJfX2VzTW9kdWxlIiwiZGVmYXVsdCIsImh0dHBzUmVxdWVzdCIsIlBhcnNlIiwicXVlcnlzdHJpbmciLCJ2YWxpZGF0ZUF1dGhEYXRhIiwiYXV0aERhdGEiLCJvcHRpb25zIiwiY29uZmlnIiwiQ29uZmlnIiwiZ2V0IiwiYXBwbGljYXRpb25JZCIsIkRlcHJlY2F0b3IiLCJsb2dSdW50aW1lRGVwcmVjYXRpb24iLCJ1c2FnZSIsImF1dGgiLCJqYW5yYWluZW5nYWdlIiwiZW5hYmxlSW5zZWN1cmVBdXRoIiwiZW5hYmxlSW5zZWN1cmVBdXRoQWRhcHRlcnMiLCJFcnJvciIsIklOVEVSTkFMX1NFUlZFUl9FUlJPUiIsImFwaVJlcXVlc3QiLCJhcGlfa2V5IiwiYXV0aF90b2tlbiIsInRoZW4iLCJkYXRhIiwic3RhdCIsInByb2ZpbGUiLCJpZGVudGlmaWVyIiwiaWQiLCJPQkpFQ1RfTk9UX0ZPVU5EIiwidmFsaWRhdGVBcHBJZCIsIlByb21pc2UiLCJyZXNvbHZlIiwicG9zdF9kYXRhIiwic3RyaW5naWZ5IiwidG9rZW4iLCJhcGlLZXkiLCJmb3JtYXQiLCJwb3N0X29wdGlvbnMiLCJob3N0IiwicGF0aCIsIm1ldGhvZCIsImhlYWRlcnMiLCJsZW5ndGgiLCJyZXF1ZXN0IiwibW9kdWxlIiwiZXhwb3J0cyJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9BZGFwdGVycy9BdXRoL2phbnJhaW5lbmdhZ2UuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gSGVscGVyIGZ1bmN0aW9ucyBmb3IgYWNjZXNzaW5nIHRoZSBKYW5yYWluIEVuZ2FnZSBBUEkuXG52YXIgaHR0cHNSZXF1ZXN0ID0gcmVxdWlyZSgnLi9odHRwc1JlcXVlc3QnKTtcbnZhciBQYXJzZSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKS5QYXJzZTtcbnZhciBxdWVyeXN0cmluZyA9IHJlcXVpcmUoJ3F1ZXJ5c3RyaW5nJyk7XG5pbXBvcnQgQ29uZmlnIGZyb20gJy4uLy4uL0NvbmZpZyc7XG5pbXBvcnQgRGVwcmVjYXRvciBmcm9tICcuLi8uLi9EZXByZWNhdG9yL0RlcHJlY2F0b3InO1xuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmZiB0aGlzIHVzZXIgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUF1dGhEYXRhKGF1dGhEYXRhLCBvcHRpb25zKSB7XG4gIGNvbnN0IGNvbmZpZyA9IENvbmZpZy5nZXQoUGFyc2UuYXBwbGljYXRpb25JZCk7XG5cbiAgRGVwcmVjYXRvci5sb2dSdW50aW1lRGVwcmVjYXRpb24oeyB1c2FnZTogJ2phbnJhaW5lbmdhZ2UgYWRhcHRlcicgfSk7XG4gIGlmICghY29uZmlnPy5hdXRoPy5qYW5yYWluZW5nYWdlPy5lbmFibGVJbnNlY3VyZUF1dGggfHwgIWNvbmZpZy5lbmFibGVJbnNlY3VyZUF1dGhBZGFwdGVycykge1xuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihQYXJzZS5FcnJvci5JTlRFUk5BTF9TRVJWRVJfRVJST1IsICdqYW5yYWluZW5nYWdlIGFkYXB0ZXIgb25seSB3b3JrcyB3aXRoIGVuYWJsZUluc2VjdXJlQXV0aDogdHJ1ZScpO1xuICB9XG5cbiAgcmV0dXJuIGFwaVJlcXVlc3Qob3B0aW9ucy5hcGlfa2V5LCBhdXRoRGF0YS5hdXRoX3Rva2VuKS50aGVuKGRhdGEgPT4ge1xuICAgIC8vc3VjY2Vzc2Z1bCByZXNwb25zZSB3aWxsIGhhdmUgYSBcInN0YXRcIiAoc3RhdHVzKSBvZiAnb2snIGFuZCBhIHByb2ZpbGUgbm9kZSB3aXRoIGFuIGlkZW50aWZpZXJcbiAgICAvL3NlZTogaHR0cDovL2RldmVsb3BlcnMuamFucmFpbi5jb20vb3ZlcnZpZXcvc29jaWFsLWxvZ2luL2lkZW50aXR5LXByb3ZpZGVycy91c2VyLXByb2ZpbGUtZGF0YS8jbm9ybWFsaXplZC11c2VyLXByb2ZpbGUtZGF0YVxuICAgIGlmIChkYXRhICYmIGRhdGEuc3RhdCA9PSAnb2snICYmIGRhdGEucHJvZmlsZS5pZGVudGlmaWVyID09IGF1dGhEYXRhLmlkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRocm93IG5ldyBQYXJzZS5FcnJvcihcbiAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAnSmFucmFpbiBlbmdhZ2UgYXV0aCBpcyBpbnZhbGlkIGZvciB0aGlzIHVzZXIuJ1xuICAgICk7XG4gIH0pO1xufVxuXG4vLyBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGZ1bGZpbGxzIGlmZiB0aGlzIGFwcCBpZCBpcyB2YWxpZC5cbmZ1bmN0aW9uIHZhbGlkYXRlQXBwSWQoKSB7XG4gIC8vbm8tb3BcbiAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xufVxuXG4vLyBBIHByb21pc2V5IHdyYXBwZXIgZm9yIGFwaSByZXF1ZXN0c1xuZnVuY3Rpb24gYXBpUmVxdWVzdChhcGlfa2V5LCBhdXRoX3Rva2VuKSB7XG4gIHZhciBwb3N0X2RhdGEgPSBxdWVyeXN0cmluZy5zdHJpbmdpZnkoe1xuICAgIHRva2VuOiBhdXRoX3Rva2VuLFxuICAgIGFwaUtleTogYXBpX2tleSxcbiAgICBmb3JtYXQ6ICdqc29uJyxcbiAgfSk7XG5cbiAgdmFyIHBvc3Rfb3B0aW9ucyA9IHtcbiAgICBob3N0OiAncnB4bm93LmNvbScsXG4gICAgcGF0aDogJy9hcGkvdjIvYXV0aF9pbmZvJyxcbiAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICBoZWFkZXJzOiB7XG4gICAgICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcsXG4gICAgICAnQ29udGVudC1MZW5ndGgnOiBwb3N0X2RhdGEubGVuZ3RoLFxuICAgIH0sXG4gIH07XG5cbiAgcmV0dXJuIGh0dHBzUmVxdWVzdC5yZXF1ZXN0KHBvc3Rfb3B0aW9ucywgcG9zdF9kYXRhKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHZhbGlkYXRlQXBwSWQ6IHZhbGlkYXRlQXBwSWQsXG4gIHZhbGlkYXRlQXV0aERhdGE6IHZhbGlkYXRlQXV0aERhdGEsXG59O1xuIl0sIm1hcHBpbmdzIjoiOztBQUlBLElBQUFBLE9BQUEsR0FBQUMsc0JBQUEsQ0FBQUMsT0FBQTtBQUNBLElBQUFDLFdBQUEsR0FBQUYsc0JBQUEsQ0FBQUMsT0FBQTtBQUFxRCxTQUFBRCx1QkFBQUcsQ0FBQSxXQUFBQSxDQUFBLElBQUFBLENBQUEsQ0FBQUMsVUFBQSxHQUFBRCxDQUFBLEtBQUFFLE9BQUEsRUFBQUYsQ0FBQTtBQUxyRDtBQUNBLElBQUlHLFlBQVksR0FBR0wsT0FBTyxDQUFDLGdCQUFnQixDQUFDO0FBQzVDLElBQUlNLEtBQUssR0FBR04sT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDTSxLQUFLO0FBQ3ZDLElBQUlDLFdBQVcsR0FBR1AsT0FBTyxDQUFDLGFBQWEsQ0FBQztBQUl4QztBQUNBLFNBQVNRLGdCQUFnQkEsQ0FBQ0MsUUFBUSxFQUFFQyxPQUFPLEVBQUU7RUFDM0MsTUFBTUMsTUFBTSxHQUFHQyxlQUFNLENBQUNDLEdBQUcsQ0FBQ1AsS0FBSyxDQUFDUSxhQUFhLENBQUM7RUFFOUNDLG1CQUFVLENBQUNDLHFCQUFxQixDQUFDO0lBQUVDLEtBQUssRUFBRTtFQUF3QixDQUFDLENBQUM7RUFDcEUsSUFBSSxDQUFDTixNQUFNLEVBQUVPLElBQUksRUFBRUMsYUFBYSxFQUFFQyxrQkFBa0IsSUFBSSxDQUFDVCxNQUFNLENBQUNVLDBCQUEwQixFQUFFO0lBQzFGLE1BQU0sSUFBSWYsS0FBSyxDQUFDZ0IsS0FBSyxDQUFDaEIsS0FBSyxDQUFDZ0IsS0FBSyxDQUFDQyxxQkFBcUIsRUFBRSxnRUFBZ0UsQ0FBQztFQUM1SDtFQUVBLE9BQU9DLFVBQVUsQ0FBQ2QsT0FBTyxDQUFDZSxPQUFPLEVBQUVoQixRQUFRLENBQUNpQixVQUFVLENBQUMsQ0FBQ0MsSUFBSSxDQUFDQyxJQUFJLElBQUk7SUFDbkU7SUFDQTtJQUNBLElBQUlBLElBQUksSUFBSUEsSUFBSSxDQUFDQyxJQUFJLElBQUksSUFBSSxJQUFJRCxJQUFJLENBQUNFLE9BQU8sQ0FBQ0MsVUFBVSxJQUFJdEIsUUFBUSxDQUFDdUIsRUFBRSxFQUFFO01BQ3ZFO0lBQ0Y7SUFDQSxNQUFNLElBQUkxQixLQUFLLENBQUNnQixLQUFLLENBQ25CaEIsS0FBSyxDQUFDZ0IsS0FBSyxDQUFDVyxnQkFBZ0IsRUFDNUIsK0NBQ0YsQ0FBQztFQUNILENBQUMsQ0FBQztBQUNKOztBQUVBO0FBQ0EsU0FBU0MsYUFBYUEsQ0FBQSxFQUFHO0VBQ3ZCO0VBQ0EsT0FBT0MsT0FBTyxDQUFDQyxPQUFPLENBQUMsQ0FBQztBQUMxQjs7QUFFQTtBQUNBLFNBQVNaLFVBQVVBLENBQUNDLE9BQU8sRUFBRUMsVUFBVSxFQUFFO0VBQ3ZDLElBQUlXLFNBQVMsR0FBRzlCLFdBQVcsQ0FBQytCLFNBQVMsQ0FBQztJQUNwQ0MsS0FBSyxFQUFFYixVQUFVO0lBQ2pCYyxNQUFNLEVBQUVmLE9BQU87SUFDZmdCLE1BQU0sRUFBRTtFQUNWLENBQUMsQ0FBQztFQUVGLElBQUlDLFlBQVksR0FBRztJQUNqQkMsSUFBSSxFQUFFLFlBQVk7SUFDbEJDLElBQUksRUFBRSxtQkFBbUI7SUFDekJDLE1BQU0sRUFBRSxNQUFNO0lBQ2RDLE9BQU8sRUFBRTtNQUNQLGNBQWMsRUFBRSxtQ0FBbUM7TUFDbkQsZ0JBQWdCLEVBQUVULFNBQVMsQ0FBQ1U7SUFDOUI7RUFDRixDQUFDO0VBRUQsT0FBTzFDLFlBQVksQ0FBQzJDLE9BQU8sQ0FBQ04sWUFBWSxFQUFFTCxTQUFTLENBQUM7QUFDdEQ7QUFFQVksTUFBTSxDQUFDQyxPQUFPLEdBQUc7RUFDZmhCLGFBQWEsRUFBRUEsYUFBYTtFQUM1QjFCLGdCQUFnQixFQUFFQTtBQUNwQixDQUFDIiwiaWdub3JlTGlzdCI6W119
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Parse Server authentication adapter for Keycloak.
5
+ *
6
+ * @class KeycloakAdapter
7
+ * @param {Object} options - The adapter configuration options.
8
+ * @param {Object} options.config - The Keycloak configuration object, typically loaded from a JSON file.
9
+ * @param {String} options.config.auth-server-url - The Keycloak authentication server URL.
10
+ * @param {String} options.config.realm - The Keycloak realm name.
11
+ * @param {String} options.config.client-id - The Keycloak client ID.
12
+ *
13
+ * @param {Object} authData - The authentication data provided by the client.
14
+ * @param {String} authData.access_token - The Keycloak access token retrieved during client authentication.
15
+ * @param {String} authData.id - The user ID retrieved from Keycloak during client authentication.
16
+ * @param {Array} [authData.roles] - The roles assigned to the user in Keycloak (optional).
17
+ * @param {Array} [authData.groups] - The groups assigned to the user in Keycloak (optional).
18
+ *
19
+ * @description
20
+ * ## Parse Server Configuration
21
+ * To configure Parse Server for Keycloak authentication, use the following structure:
22
+ * ```javascript
23
+ * {
24
+ * "auth": {
25
+ * "keycloak": {
26
+ * "config": require('./auth/keycloak.json')
27
+ * }
28
+ * }
29
+ * }
30
+ * ```
31
+ * Ensure the `keycloak.json` configuration file is generated from Keycloak's setup guide and includes:
32
+ * - `auth-server-url`: The Keycloak authentication server URL.
33
+ * - `realm`: The Keycloak realm name.
34
+ * - `client-id`: The Keycloak client ID.
35
+ *
36
+ * ## Auth Data
37
+ * The adapter requires the following `authData` fields:
38
+ * - `access_token`: The Keycloak access token retrieved during client authentication.
39
+ * - `id`: The user ID retrieved from Keycloak during client authentication.
40
+ * - `roles` (optional): The roles assigned to the user in Keycloak.
41
+ * - `groups` (optional): The groups assigned to the user in Keycloak.
42
+ *
43
+ * ## Auth Payload Example
44
+ * ### Example Auth Data
45
+ * ```json
46
+ * {
47
+ * "keycloak": {
48
+ * "access_token": "an authorized Keycloak access token for the user",
49
+ * "id": "user's Keycloak ID as a string",
50
+ * "roles": ["admin", "user"],
51
+ * "groups": ["group1", "group2"]
52
+ * }
53
+ * }
54
+ * ```
55
+ *
56
+ * ## Notes
57
+ * - Parse Server validates the provided `authData` by making a `userinfo` call to Keycloak and ensures the attributes match those returned by Keycloak.
58
+ *
59
+ * ## Keycloak Configuration
60
+ * To configure Keycloak, copy the JSON configuration file generated from Keycloak's setup guide:
61
+ * - [Keycloak Securing Apps Documentation](https://www.keycloak.org/docs/latest/securing_apps/index.html#_javascript_adapter)
62
+ *
63
+ * Place the configuration file on your server, for example:
64
+ * - `auth/keycloak.json`
65
+ *
66
+ * For more information on Keycloak authentication, see:
67
+ * - [Securing Apps Documentation](https://www.keycloak.org/docs/latest/securing_apps/)
68
+ * - [Server Administration Documentation](https://www.keycloak.org/docs/latest/server_admin/)
69
+ */
70
+
71
+ const {
72
+ Parse
73
+ } = require('parse/node');
74
+ const httpsRequest = require('./httpsRequest');
75
+ const arraysEqual = (_arr1, _arr2) => {
76
+ if (!Array.isArray(_arr1) || !Array.isArray(_arr2) || _arr1.length !== _arr2.length) {
77
+ return false;
78
+ }
79
+ var arr1 = _arr1.concat().sort();
80
+ var arr2 = _arr2.concat().sort();
81
+ for (var i = 0; i < arr1.length; i++) {
82
+ if (arr1[i] !== arr2[i]) {
83
+ return false;
84
+ }
85
+ }
86
+ return true;
87
+ };
88
+ const handleAuth = async ({
89
+ access_token,
90
+ id,
91
+ roles,
92
+ groups
93
+ } = {}, {
94
+ config
95
+ } = {}) => {
96
+ if (!(access_token && id)) {
97
+ throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Missing access token and/or User id');
98
+ }
99
+ if (!config || !(config['auth-server-url'] && config['realm'])) {
100
+ throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Missing keycloak configuration');
101
+ }
102
+ try {
103
+ const response = await httpsRequest.get({
104
+ host: config['auth-server-url'],
105
+ path: `/realms/${config['realm']}/protocol/openid-connect/userinfo`,
106
+ headers: {
107
+ Authorization: 'Bearer ' + access_token
108
+ }
109
+ });
110
+ if (response && response.data && response.data.sub == id && arraysEqual(response.data.roles, roles) && arraysEqual(response.data.groups, groups)) {
111
+ return;
112
+ }
113
+ throw new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'Invalid authentication');
114
+ } catch (e) {
115
+ if (e instanceof Parse.Error) {
116
+ throw e;
117
+ }
118
+ const error = JSON.parse(e.text);
119
+ if (error.error_description) {
120
+ throw new Parse.Error(Parse.Error.HOSTING_ERROR, error.error_description);
121
+ } else {
122
+ throw new Parse.Error(Parse.Error.HOSTING_ERROR, 'Could not connect to the authentication server');
123
+ }
124
+ }
125
+ };
126
+
127
+ /*
128
+ @param {Object} authData: the client provided authData
129
+ @param {string} authData.access_token: the access_token retrieved from client authentication in Keycloak
130
+ @param {string} authData.id: the id retrieved from client authentication in Keycloak
131
+ @param {Array} authData.roles: the roles retrieved from client authentication in Keycloak
132
+ @param {Array} authData.groups: the groups retrieved from client authentication in Keycloak
133
+ @param {Object} options: additional options
134
+ @param {Object} options.config: the config object passed during Parse Server instantiation
135
+ */
136
+ function validateAuthData(authData, options = {}) {
137
+ return handleAuth(authData, options);
138
+ }
139
+
140
+ // Returns a promise that fulfills if this app id is valid.
141
+ function validateAppId() {
142
+ return Promise.resolve();
143
+ }
144
+ module.exports = {
145
+ validateAppId,
146
+ validateAuthData
147
+ };
148
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJQYXJzZSIsInJlcXVpcmUiLCJodHRwc1JlcXVlc3QiLCJhcnJheXNFcXVhbCIsIl9hcnIxIiwiX2FycjIiLCJBcnJheSIsImlzQXJyYXkiLCJsZW5ndGgiLCJhcnIxIiwiY29uY2F0Iiwic29ydCIsImFycjIiLCJpIiwiaGFuZGxlQXV0aCIsImFjY2Vzc190b2tlbiIsImlkIiwicm9sZXMiLCJncm91cHMiLCJjb25maWciLCJFcnJvciIsIk9CSkVDVF9OT1RfRk9VTkQiLCJyZXNwb25zZSIsImdldCIsImhvc3QiLCJwYXRoIiwiaGVhZGVycyIsIkF1dGhvcml6YXRpb24iLCJkYXRhIiwic3ViIiwiZSIsImVycm9yIiwiSlNPTiIsInBhcnNlIiwidGV4dCIsImVycm9yX2Rlc2NyaXB0aW9uIiwiSE9TVElOR19FUlJPUiIsInZhbGlkYXRlQXV0aERhdGEiLCJhdXRoRGF0YSIsIm9wdGlvbnMiLCJ2YWxpZGF0ZUFwcElkIiwiUHJvbWlzZSIsInJlc29sdmUiLCJtb2R1bGUiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL0FkYXB0ZXJzL0F1dGgva2V5Y2xvYWsuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBQYXJzZSBTZXJ2ZXIgYXV0aGVudGljYXRpb24gYWRhcHRlciBmb3IgS2V5Y2xvYWsuXG4gKlxuICogQGNsYXNzIEtleWNsb2FrQWRhcHRlclxuICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBUaGUgYWRhcHRlciBjb25maWd1cmF0aW9uIG9wdGlvbnMuXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucy5jb25maWcgLSBUaGUgS2V5Y2xvYWsgY29uZmlndXJhdGlvbiBvYmplY3QsIHR5cGljYWxseSBsb2FkZWQgZnJvbSBhIEpTT04gZmlsZS5cbiAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLmNvbmZpZy5hdXRoLXNlcnZlci11cmwgLSBUaGUgS2V5Y2xvYWsgYXV0aGVudGljYXRpb24gc2VydmVyIFVSTC5cbiAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLmNvbmZpZy5yZWFsbSAtIFRoZSBLZXljbG9hayByZWFsbSBuYW1lLlxuICogQHBhcmFtIHtTdHJpbmd9IG9wdGlvbnMuY29uZmlnLmNsaWVudC1pZCAtIFRoZSBLZXljbG9hayBjbGllbnQgSUQuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGF1dGhEYXRhIC0gVGhlIGF1dGhlbnRpY2F0aW9uIGRhdGEgcHJvdmlkZWQgYnkgdGhlIGNsaWVudC5cbiAqIEBwYXJhbSB7U3RyaW5nfSBhdXRoRGF0YS5hY2Nlc3NfdG9rZW4gLSBUaGUgS2V5Y2xvYWsgYWNjZXNzIHRva2VuIHJldHJpZXZlZCBkdXJpbmcgY2xpZW50IGF1dGhlbnRpY2F0aW9uLlxuICogQHBhcmFtIHtTdHJpbmd9IGF1dGhEYXRhLmlkIC0gVGhlIHVzZXIgSUQgcmV0cmlldmVkIGZyb20gS2V5Y2xvYWsgZHVyaW5nIGNsaWVudCBhdXRoZW50aWNhdGlvbi5cbiAqIEBwYXJhbSB7QXJyYXl9IFthdXRoRGF0YS5yb2xlc10gLSBUaGUgcm9sZXMgYXNzaWduZWQgdG8gdGhlIHVzZXIgaW4gS2V5Y2xvYWsgKG9wdGlvbmFsKS5cbiAqIEBwYXJhbSB7QXJyYXl9IFthdXRoRGF0YS5ncm91cHNdIC0gVGhlIGdyb3VwcyBhc3NpZ25lZCB0byB0aGUgdXNlciBpbiBLZXljbG9hayAob3B0aW9uYWwpLlxuICpcbiAqIEBkZXNjcmlwdGlvblxuICogIyMgUGFyc2UgU2VydmVyIENvbmZpZ3VyYXRpb25cbiAqIFRvIGNvbmZpZ3VyZSBQYXJzZSBTZXJ2ZXIgZm9yIEtleWNsb2FrIGF1dGhlbnRpY2F0aW9uLCB1c2UgdGhlIGZvbGxvd2luZyBzdHJ1Y3R1cmU6XG4gKiBgYGBqYXZhc2NyaXB0XG4gKiB7XG4gKiAgIFwiYXV0aFwiOiB7XG4gKiAgICAgXCJrZXljbG9ha1wiOiB7XG4gKiAgICAgICBcImNvbmZpZ1wiOiByZXF1aXJlKCcuL2F1dGgva2V5Y2xvYWsuanNvbicpXG4gKiAgICAgfVxuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqIEVuc3VyZSB0aGUgYGtleWNsb2FrLmpzb25gIGNvbmZpZ3VyYXRpb24gZmlsZSBpcyBnZW5lcmF0ZWQgZnJvbSBLZXljbG9haydzIHNldHVwIGd1aWRlIGFuZCBpbmNsdWRlczpcbiAqIC0gYGF1dGgtc2VydmVyLXVybGA6IFRoZSBLZXljbG9hayBhdXRoZW50aWNhdGlvbiBzZXJ2ZXIgVVJMLlxuICogLSBgcmVhbG1gOiBUaGUgS2V5Y2xvYWsgcmVhbG0gbmFtZS5cbiAqIC0gYGNsaWVudC1pZGA6IFRoZSBLZXljbG9hayBjbGllbnQgSUQuXG4gKlxuICogIyMgQXV0aCBEYXRhXG4gKiBUaGUgYWRhcHRlciByZXF1aXJlcyB0aGUgZm9sbG93aW5nIGBhdXRoRGF0YWAgZmllbGRzOlxuICogLSBgYWNjZXNzX3Rva2VuYDogVGhlIEtleWNsb2FrIGFjY2VzcyB0b2tlbiByZXRyaWV2ZWQgZHVyaW5nIGNsaWVudCBhdXRoZW50aWNhdGlvbi5cbiAqIC0gYGlkYDogVGhlIHVzZXIgSUQgcmV0cmlldmVkIGZyb20gS2V5Y2xvYWsgZHVyaW5nIGNsaWVudCBhdXRoZW50aWNhdGlvbi5cbiAqIC0gYHJvbGVzYCAob3B0aW9uYWwpOiBUaGUgcm9sZXMgYXNzaWduZWQgdG8gdGhlIHVzZXIgaW4gS2V5Y2xvYWsuXG4gKiAtIGBncm91cHNgIChvcHRpb25hbCk6IFRoZSBncm91cHMgYXNzaWduZWQgdG8gdGhlIHVzZXIgaW4gS2V5Y2xvYWsuXG4gKlxuICogIyMgQXV0aCBQYXlsb2FkIEV4YW1wbGVcbiAqICMjIyBFeGFtcGxlIEF1dGggRGF0YVxuICogYGBganNvblxuICoge1xuICogICBcImtleWNsb2FrXCI6IHtcbiAqICAgICBcImFjY2Vzc190b2tlblwiOiBcImFuIGF1dGhvcml6ZWQgS2V5Y2xvYWsgYWNjZXNzIHRva2VuIGZvciB0aGUgdXNlclwiLFxuICogICAgIFwiaWRcIjogXCJ1c2VyJ3MgS2V5Y2xvYWsgSUQgYXMgYSBzdHJpbmdcIixcbiAqICAgICBcInJvbGVzXCI6IFtcImFkbWluXCIsIFwidXNlclwiXSxcbiAqICAgICBcImdyb3Vwc1wiOiBbXCJncm91cDFcIiwgXCJncm91cDJcIl1cbiAqICAgfVxuICogfVxuICogYGBgXG4gKlxuICogIyMgTm90ZXNcbiAqIC0gUGFyc2UgU2VydmVyIHZhbGlkYXRlcyB0aGUgcHJvdmlkZWQgYGF1dGhEYXRhYCBieSBtYWtpbmcgYSBgdXNlcmluZm9gIGNhbGwgdG8gS2V5Y2xvYWsgYW5kIGVuc3VyZXMgdGhlIGF0dHJpYnV0ZXMgbWF0Y2ggdGhvc2UgcmV0dXJuZWQgYnkgS2V5Y2xvYWsuXG4gKlxuICogIyMgS2V5Y2xvYWsgQ29uZmlndXJhdGlvblxuICogVG8gY29uZmlndXJlIEtleWNsb2FrLCBjb3B5IHRoZSBKU09OIGNvbmZpZ3VyYXRpb24gZmlsZSBnZW5lcmF0ZWQgZnJvbSBLZXljbG9haydzIHNldHVwIGd1aWRlOlxuICogLSBbS2V5Y2xvYWsgU2VjdXJpbmcgQXBwcyBEb2N1bWVudGF0aW9uXShodHRwczovL3d3dy5rZXljbG9hay5vcmcvZG9jcy9sYXRlc3Qvc2VjdXJpbmdfYXBwcy9pbmRleC5odG1sI19qYXZhc2NyaXB0X2FkYXB0ZXIpXG4gKlxuICogUGxhY2UgdGhlIGNvbmZpZ3VyYXRpb24gZmlsZSBvbiB5b3VyIHNlcnZlciwgZm9yIGV4YW1wbGU6XG4gKiAtIGBhdXRoL2tleWNsb2FrLmpzb25gXG4gKlxuICogRm9yIG1vcmUgaW5mb3JtYXRpb24gb24gS2V5Y2xvYWsgYXV0aGVudGljYXRpb24sIHNlZTpcbiAqIC0gW1NlY3VyaW5nIEFwcHMgRG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly93d3cua2V5Y2xvYWsub3JnL2RvY3MvbGF0ZXN0L3NlY3VyaW5nX2FwcHMvKVxuICogLSBbU2VydmVyIEFkbWluaXN0cmF0aW9uIERvY3VtZW50YXRpb25dKGh0dHBzOi8vd3d3LmtleWNsb2FrLm9yZy9kb2NzL2xhdGVzdC9zZXJ2ZXJfYWRtaW4vKVxuICovXG5cbmNvbnN0IHsgUGFyc2UgfSA9IHJlcXVpcmUoJ3BhcnNlL25vZGUnKTtcbmNvbnN0IGh0dHBzUmVxdWVzdCA9IHJlcXVpcmUoJy4vaHR0cHNSZXF1ZXN0Jyk7XG5cbmNvbnN0IGFycmF5c0VxdWFsID0gKF9hcnIxLCBfYXJyMikgPT4ge1xuICBpZiAoIUFycmF5LmlzQXJyYXkoX2FycjEpIHx8ICFBcnJheS5pc0FycmF5KF9hcnIyKSB8fCBfYXJyMS5sZW5ndGggIT09IF9hcnIyLmxlbmd0aCkgeyByZXR1cm4gZmFsc2U7IH1cblxuICB2YXIgYXJyMSA9IF9hcnIxLmNvbmNhdCgpLnNvcnQoKTtcbiAgdmFyIGFycjIgPSBfYXJyMi5jb25jYXQoKS5zb3J0KCk7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcnIxLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGFycjFbaV0gIT09IGFycjJbaV0pIHsgcmV0dXJuIGZhbHNlOyB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG5cbmNvbnN0IGhhbmRsZUF1dGggPSBhc3luYyAoeyBhY2Nlc3NfdG9rZW4sIGlkLCByb2xlcywgZ3JvdXBzIH0gPSB7fSwgeyBjb25maWcgfSA9IHt9KSA9PiB7XG4gIGlmICghKGFjY2Vzc190b2tlbiAmJiBpZCkpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ01pc3NpbmcgYWNjZXNzIHRva2VuIGFuZC9vciBVc2VyIGlkJyk7XG4gIH1cbiAgaWYgKCFjb25maWcgfHwgIShjb25maWdbJ2F1dGgtc2VydmVyLXVybCddICYmIGNvbmZpZ1sncmVhbG0nXSkpIHtcbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ01pc3Npbmcga2V5Y2xvYWsgY29uZmlndXJhdGlvbicpO1xuICB9XG4gIHRyeSB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBodHRwc1JlcXVlc3QuZ2V0KHtcbiAgICAgIGhvc3Q6IGNvbmZpZ1snYXV0aC1zZXJ2ZXItdXJsJ10sXG4gICAgICBwYXRoOiBgL3JlYWxtcy8ke2NvbmZpZ1sncmVhbG0nXX0vcHJvdG9jb2wvb3BlbmlkLWNvbm5lY3QvdXNlcmluZm9gLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICBBdXRob3JpemF0aW9uOiAnQmVhcmVyICcgKyBhY2Nlc3NfdG9rZW4sXG4gICAgICB9LFxuICAgIH0pO1xuICAgIGlmIChcbiAgICAgIHJlc3BvbnNlICYmXG4gICAgICByZXNwb25zZS5kYXRhICYmXG4gICAgICByZXNwb25zZS5kYXRhLnN1YiA9PSBpZCAmJlxuICAgICAgYXJyYXlzRXF1YWwocmVzcG9uc2UuZGF0YS5yb2xlcywgcm9sZXMpICYmXG4gICAgICBhcnJheXNFcXVhbChyZXNwb25zZS5kYXRhLmdyb3VwcywgZ3JvdXBzKVxuICAgICkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aHJvdyBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ0ludmFsaWQgYXV0aGVudGljYXRpb24nKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmIChlIGluc3RhbmNlb2YgUGFyc2UuRXJyb3IpIHtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuICAgIGNvbnN0IGVycm9yID0gSlNPTi5wYXJzZShlLnRleHQpO1xuICAgIGlmIChlcnJvci5lcnJvcl9kZXNjcmlwdGlvbikge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLkhPU1RJTkdfRVJST1IsIGVycm9yLmVycm9yX2Rlc2NyaXB0aW9uKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICBQYXJzZS5FcnJvci5IT1NUSU5HX0VSUk9SLFxuICAgICAgICAnQ291bGQgbm90IGNvbm5lY3QgdG8gdGhlIGF1dGhlbnRpY2F0aW9uIHNlcnZlcidcbiAgICAgICk7XG4gICAgfVxuICB9XG59O1xuXG4vKlxuICBAcGFyYW0ge09iamVjdH0gYXV0aERhdGE6IHRoZSBjbGllbnQgcHJvdmlkZWQgYXV0aERhdGFcbiAgQHBhcmFtIHtzdHJpbmd9IGF1dGhEYXRhLmFjY2Vzc190b2tlbjogdGhlIGFjY2Vzc190b2tlbiByZXRyaWV2ZWQgZnJvbSBjbGllbnQgYXV0aGVudGljYXRpb24gaW4gS2V5Y2xvYWtcbiAgQHBhcmFtIHtzdHJpbmd9IGF1dGhEYXRhLmlkOiB0aGUgaWQgcmV0cmlldmVkIGZyb20gY2xpZW50IGF1dGhlbnRpY2F0aW9uIGluIEtleWNsb2FrXG4gIEBwYXJhbSB7QXJyYXl9ICBhdXRoRGF0YS5yb2xlczogdGhlIHJvbGVzIHJldHJpZXZlZCBmcm9tIGNsaWVudCBhdXRoZW50aWNhdGlvbiBpbiBLZXljbG9ha1xuICBAcGFyYW0ge0FycmF5fSAgYXV0aERhdGEuZ3JvdXBzOiB0aGUgZ3JvdXBzIHJldHJpZXZlZCBmcm9tIGNsaWVudCBhdXRoZW50aWNhdGlvbiBpbiBLZXljbG9ha1xuICBAcGFyYW0ge09iamVjdH0gb3B0aW9uczogYWRkaXRpb25hbCBvcHRpb25zXG4gIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zLmNvbmZpZzogdGhlIGNvbmZpZyBvYmplY3QgcGFzc2VkIGR1cmluZyBQYXJzZSBTZXJ2ZXIgaW5zdGFudGlhdGlvblxuKi9cbmZ1bmN0aW9uIHZhbGlkYXRlQXV0aERhdGEoYXV0aERhdGEsIG9wdGlvbnMgPSB7fSkge1xuICByZXR1cm4gaGFuZGxlQXV0aChhdXRoRGF0YSwgb3B0aW9ucyk7XG59XG5cbi8vIFJldHVybnMgYSBwcm9taXNlIHRoYXQgZnVsZmlsbHMgaWYgdGhpcyBhcHAgaWQgaXMgdmFsaWQuXG5mdW5jdGlvbiB2YWxpZGF0ZUFwcElkKCkge1xuICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWxpZGF0ZUFwcElkLFxuICB2YWxpZGF0ZUF1dGhEYXRhLFxufTtcbiJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Parse Server authentication adapter for LDAP.
5
+ *
6
+ * @class LDAP
7
+ * @param {Object} options - The adapter configuration options.
8
+ * @param {String} options.url - The LDAP server URL. Must start with `ldap://` or `ldaps://`.
9
+ * @param {String} options.suffix - The LDAP suffix for user distinguished names (DN).
10
+ * @param {String} [options.dn] - The distinguished name (DN) template for user authentication. Replace `{{id}}` with the username.
11
+ * @param {Object} [options.tlsOptions] - Options for LDAPS TLS connections.
12
+ * @param {String} [options.groupCn] - The common name (CN) of the group to verify user membership.
13
+ * @param {String} [options.groupFilter] - The LDAP search filter for groups, with `{{id}}` replaced by the username.
14
+ *
15
+ * @param {Object} authData - The authentication data provided by the client.
16
+ * @param {String} authData.id - The user's LDAP username.
17
+ * @param {String} authData.password - The user's LDAP password.
18
+ *
19
+ * @description
20
+ * ## Parse Server Configuration
21
+ * To configure Parse Server for LDAP authentication, use the following structure:
22
+ * ```javascript
23
+ * {
24
+ * auth: {
25
+ * ldap: {
26
+ * url: 'ldaps://ldap.example.com',
27
+ * suffix: 'ou=users,dc=example,dc=com',
28
+ * groupCn: 'admins',
29
+ * groupFilter: '(memberUid={{id}})',
30
+ * tlsOptions: {
31
+ * rejectUnauthorized: false
32
+ * }
33
+ * }
34
+ * }
35
+ * }
36
+ * ```
37
+ *
38
+ * ## Authentication Process
39
+ * 1. Validates the provided `authData` using an LDAP bind operation.
40
+ * 2. Optionally, verifies that the user belongs to a specific group by performing an LDAP search using the provided `groupCn` or `groupFilter`.
41
+ *
42
+ * ## Auth Payload
43
+ * The adapter requires the following `authData` fields:
44
+ * - `id`: The user's LDAP username.
45
+ * - `password`: The user's LDAP password.
46
+ *
47
+ * ### Example Auth Payload
48
+ * ```json
49
+ * {
50
+ * "ldap": {
51
+ * "id": "jdoe",
52
+ * "password": "password123"
53
+ * }
54
+ * }
55
+ * ```
56
+ *
57
+ * @example <caption>Configuration Example</caption>
58
+ * // Example Parse Server configuration:
59
+ * const config = {
60
+ * auth: {
61
+ * ldap: {
62
+ * url: 'ldaps://ldap.example.com',
63
+ * suffix: 'ou=users,dc=example,dc=com',
64
+ * groupCn: 'admins',
65
+ * groupFilter: '(memberUid={{id}})',
66
+ * tlsOptions: {
67
+ * rejectUnauthorized: false
68
+ * }
69
+ * }
70
+ * }
71
+ * };
72
+ *
73
+ * @see {@link https://ldap.com/ LDAP Basics}
74
+ * @see {@link https://ldap.com/ldap-filters/ LDAP Filters}
75
+ */
76
+
77
+ const ldapjs = require('ldapjs');
78
+ const Parse = require('parse/node').Parse;
79
+ function validateAuthData(authData, options) {
80
+ if (!optionsAreValid(options)) {
81
+ return new Promise((_, reject) => {
82
+ reject(new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'LDAP auth configuration missing'));
83
+ });
84
+ }
85
+ const clientOptions = options.url.startsWith('ldaps://') ? {
86
+ url: options.url,
87
+ tlsOptions: options.tlsOptions
88
+ } : {
89
+ url: options.url
90
+ };
91
+ const client = ldapjs.createClient(clientOptions);
92
+ const userCn = typeof options.dn === 'string' ? options.dn.replace('{{id}}', authData.id) : `uid=${authData.id},${options.suffix}`;
93
+ return new Promise((resolve, reject) => {
94
+ client.bind(userCn, authData.password, ldapError => {
95
+ delete authData.password;
96
+ if (ldapError) {
97
+ let error;
98
+ switch (ldapError.code) {
99
+ case 49:
100
+ error = new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'LDAP: Wrong username or password');
101
+ break;
102
+ case 'DEPTH_ZERO_SELF_SIGNED_CERT':
103
+ error = new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'LDAPS: Certificate mismatch');
104
+ break;
105
+ default:
106
+ error = new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'LDAP: Somthing went wrong (' + ldapError.code + ')');
107
+ }
108
+ reject(error);
109
+ client.destroy(ldapError);
110
+ return;
111
+ }
112
+ if (typeof options.groupCn === 'string' && typeof options.groupFilter === 'string') {
113
+ searchForGroup(client, options, authData.id, resolve, reject);
114
+ } else {
115
+ client.unbind();
116
+ client.destroy();
117
+ resolve();
118
+ }
119
+ });
120
+ });
121
+ }
122
+ function optionsAreValid(options) {
123
+ return typeof options === 'object' && typeof options.suffix === 'string' && typeof options.url === 'string' && (options.url.startsWith('ldap://') || options.url.startsWith('ldaps://') && typeof options.tlsOptions === 'object');
124
+ }
125
+ function searchForGroup(client, options, id, resolve, reject) {
126
+ const filter = options.groupFilter.replace(/{{id}}/gi, id);
127
+ const opts = {
128
+ scope: 'sub',
129
+ filter: filter
130
+ };
131
+ let found = false;
132
+ client.search(options.suffix, opts, (searchError, res) => {
133
+ if (searchError) {
134
+ client.unbind();
135
+ client.destroy();
136
+ return reject(new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'LDAP group search failed'));
137
+ }
138
+ res.on('searchEntry', entry => {
139
+ if (entry.pojo.attributes.find(obj => obj.type === 'cn').values.includes(options.groupCn)) {
140
+ found = true;
141
+ client.unbind();
142
+ client.destroy();
143
+ return resolve();
144
+ }
145
+ });
146
+ res.on('end', () => {
147
+ if (!found) {
148
+ client.unbind();
149
+ client.destroy();
150
+ return reject(new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'LDAP: User not in group'));
151
+ }
152
+ });
153
+ res.on('error', () => {
154
+ client.unbind();
155
+ client.destroy();
156
+ return reject(new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'LDAP group search failed'));
157
+ });
158
+ });
159
+ }
160
+ function validateAppId() {
161
+ return Promise.resolve();
162
+ }
163
+ module.exports = {
164
+ validateAppId,
165
+ validateAuthData
166
+ };
167
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJsZGFwanMiLCJyZXF1aXJlIiwiUGFyc2UiLCJ2YWxpZGF0ZUF1dGhEYXRhIiwiYXV0aERhdGEiLCJvcHRpb25zIiwib3B0aW9uc0FyZVZhbGlkIiwiUHJvbWlzZSIsIl8iLCJyZWplY3QiLCJFcnJvciIsIklOVEVSTkFMX1NFUlZFUl9FUlJPUiIsImNsaWVudE9wdGlvbnMiLCJ1cmwiLCJzdGFydHNXaXRoIiwidGxzT3B0aW9ucyIsImNsaWVudCIsImNyZWF0ZUNsaWVudCIsInVzZXJDbiIsImRuIiwicmVwbGFjZSIsImlkIiwic3VmZml4IiwicmVzb2x2ZSIsImJpbmQiLCJwYXNzd29yZCIsImxkYXBFcnJvciIsImVycm9yIiwiY29kZSIsIk9CSkVDVF9OT1RfRk9VTkQiLCJkZXN0cm95IiwiZ3JvdXBDbiIsImdyb3VwRmlsdGVyIiwic2VhcmNoRm9yR3JvdXAiLCJ1bmJpbmQiLCJmaWx0ZXIiLCJvcHRzIiwic2NvcGUiLCJmb3VuZCIsInNlYXJjaCIsInNlYXJjaEVycm9yIiwicmVzIiwib24iLCJlbnRyeSIsInBvam8iLCJhdHRyaWJ1dGVzIiwiZmluZCIsIm9iaiIsInR5cGUiLCJ2YWx1ZXMiLCJpbmNsdWRlcyIsInZhbGlkYXRlQXBwSWQiLCJtb2R1bGUiLCJleHBvcnRzIl0sInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL0FkYXB0ZXJzL0F1dGgvbGRhcC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFBhcnNlIFNlcnZlciBhdXRoZW50aWNhdGlvbiBhZGFwdGVyIGZvciBMREFQLlxuICpcbiAqIEBjbGFzcyBMREFQXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyAtIFRoZSBhZGFwdGVyIGNvbmZpZ3VyYXRpb24gb3B0aW9ucy5cbiAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnVybCAtIFRoZSBMREFQIHNlcnZlciBVUkwuIE11c3Qgc3RhcnQgd2l0aCBgbGRhcDovL2Agb3IgYGxkYXBzOi8vYC5cbiAqIEBwYXJhbSB7U3RyaW5nfSBvcHRpb25zLnN1ZmZpeCAtIFRoZSBMREFQIHN1ZmZpeCBmb3IgdXNlciBkaXN0aW5ndWlzaGVkIG5hbWVzIChETikuXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuZG5dIC0gVGhlIGRpc3Rpbmd1aXNoZWQgbmFtZSAoRE4pIHRlbXBsYXRlIGZvciB1c2VyIGF1dGhlbnRpY2F0aW9uLiBSZXBsYWNlIGB7e2lkfX1gIHdpdGggdGhlIHVzZXJuYW1lLlxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zLnRsc09wdGlvbnNdIC0gT3B0aW9ucyBmb3IgTERBUFMgVExTIGNvbm5lY3Rpb25zLlxuICogQHBhcmFtIHtTdHJpbmd9IFtvcHRpb25zLmdyb3VwQ25dIC0gVGhlIGNvbW1vbiBuYW1lIChDTikgb2YgdGhlIGdyb3VwIHRvIHZlcmlmeSB1c2VyIG1lbWJlcnNoaXAuXG4gKiBAcGFyYW0ge1N0cmluZ30gW29wdGlvbnMuZ3JvdXBGaWx0ZXJdIC0gVGhlIExEQVAgc2VhcmNoIGZpbHRlciBmb3IgZ3JvdXBzLCB3aXRoIGB7e2lkfX1gIHJlcGxhY2VkIGJ5IHRoZSB1c2VybmFtZS5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gYXV0aERhdGEgLSBUaGUgYXV0aGVudGljYXRpb24gZGF0YSBwcm92aWRlZCBieSB0aGUgY2xpZW50LlxuICogQHBhcmFtIHtTdHJpbmd9IGF1dGhEYXRhLmlkIC0gVGhlIHVzZXIncyBMREFQIHVzZXJuYW1lLlxuICogQHBhcmFtIHtTdHJpbmd9IGF1dGhEYXRhLnBhc3N3b3JkIC0gVGhlIHVzZXIncyBMREFQIHBhc3N3b3JkLlxuICpcbiAqIEBkZXNjcmlwdGlvblxuICogIyMgUGFyc2UgU2VydmVyIENvbmZpZ3VyYXRpb25cbiAqIFRvIGNvbmZpZ3VyZSBQYXJzZSBTZXJ2ZXIgZm9yIExEQVAgYXV0aGVudGljYXRpb24sIHVzZSB0aGUgZm9sbG93aW5nIHN0cnVjdHVyZTpcbiAqIGBgYGphdmFzY3JpcHRcbiAqIHtcbiAqICAgYXV0aDoge1xuICogICAgIGxkYXA6IHtcbiAqICAgICAgIHVybDogJ2xkYXBzOi8vbGRhcC5leGFtcGxlLmNvbScsXG4gKiAgICAgICBzdWZmaXg6ICdvdT11c2VycyxkYz1leGFtcGxlLGRjPWNvbScsXG4gKiAgICAgICBncm91cENuOiAnYWRtaW5zJyxcbiAqICAgICAgIGdyb3VwRmlsdGVyOiAnKG1lbWJlclVpZD17e2lkfX0pJyxcbiAqICAgICAgIHRsc09wdGlvbnM6IHtcbiAqICAgICAgICAgcmVqZWN0VW5hdXRob3JpemVkOiBmYWxzZVxuICogICAgICAgfVxuICogICAgIH1cbiAqICAgfVxuICogfVxuICogYGBgXG4gKlxuICogIyMgQXV0aGVudGljYXRpb24gUHJvY2Vzc1xuICogMS4gVmFsaWRhdGVzIHRoZSBwcm92aWRlZCBgYXV0aERhdGFgIHVzaW5nIGFuIExEQVAgYmluZCBvcGVyYXRpb24uXG4gKiAyLiBPcHRpb25hbGx5LCB2ZXJpZmllcyB0aGF0IHRoZSB1c2VyIGJlbG9uZ3MgdG8gYSBzcGVjaWZpYyBncm91cCBieSBwZXJmb3JtaW5nIGFuIExEQVAgc2VhcmNoIHVzaW5nIHRoZSBwcm92aWRlZCBgZ3JvdXBDbmAgb3IgYGdyb3VwRmlsdGVyYC5cbiAqXG4gKiAjIyBBdXRoIFBheWxvYWRcbiAqIFRoZSBhZGFwdGVyIHJlcXVpcmVzIHRoZSBmb2xsb3dpbmcgYGF1dGhEYXRhYCBmaWVsZHM6XG4gKiAtIGBpZGA6IFRoZSB1c2VyJ3MgTERBUCB1c2VybmFtZS5cbiAqIC0gYHBhc3N3b3JkYDogVGhlIHVzZXIncyBMREFQIHBhc3N3b3JkLlxuICpcbiAqICMjIyBFeGFtcGxlIEF1dGggUGF5bG9hZFxuICogYGBganNvblxuICoge1xuICogICBcImxkYXBcIjoge1xuICogICAgIFwiaWRcIjogXCJqZG9lXCIsXG4gKiAgICAgXCJwYXNzd29yZFwiOiBcInBhc3N3b3JkMTIzXCJcbiAqICAgfVxuICogfVxuICogYGBgXG4gKlxuICogQGV4YW1wbGUgPGNhcHRpb24+Q29uZmlndXJhdGlvbiBFeGFtcGxlPC9jYXB0aW9uPlxuICogLy8gRXhhbXBsZSBQYXJzZSBTZXJ2ZXIgY29uZmlndXJhdGlvbjpcbiAqIGNvbnN0IGNvbmZpZyA9IHtcbiAqICAgYXV0aDoge1xuICogICAgIGxkYXA6IHtcbiAqICAgICAgIHVybDogJ2xkYXBzOi8vbGRhcC5leGFtcGxlLmNvbScsXG4gKiAgICAgICBzdWZmaXg6ICdvdT11c2VycyxkYz1leGFtcGxlLGRjPWNvbScsXG4gKiAgICAgICBncm91cENuOiAnYWRtaW5zJyxcbiAqICAgICAgIGdyb3VwRmlsdGVyOiAnKG1lbWJlclVpZD17e2lkfX0pJyxcbiAqICAgICAgIHRsc09wdGlvbnM6IHtcbiAqICAgICAgICAgcmVqZWN0VW5hdXRob3JpemVkOiBmYWxzZVxuICogICAgICAgfVxuICogICAgIH1cbiAqICAgfVxuICogfTtcbiAqXG4gKiBAc2VlIHtAbGluayBodHRwczovL2xkYXAuY29tLyBMREFQIEJhc2ljc31cbiAqIEBzZWUge0BsaW5rIGh0dHBzOi8vbGRhcC5jb20vbGRhcC1maWx0ZXJzLyBMREFQIEZpbHRlcnN9XG4gKi9cblxuXG5jb25zdCBsZGFwanMgPSByZXF1aXJlKCdsZGFwanMnKTtcbmNvbnN0IFBhcnNlID0gcmVxdWlyZSgncGFyc2Uvbm9kZScpLlBhcnNlO1xuXG5mdW5jdGlvbiB2YWxpZGF0ZUF1dGhEYXRhKGF1dGhEYXRhLCBvcHRpb25zKSB7XG4gIGlmICghb3B0aW9uc0FyZVZhbGlkKG9wdGlvbnMpKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChfLCByZWplY3QpID0+IHtcbiAgICAgIHJlamVjdChuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuSU5URVJOQUxfU0VSVkVSX0VSUk9SLCAnTERBUCBhdXRoIGNvbmZpZ3VyYXRpb24gbWlzc2luZycpKTtcbiAgICB9KTtcbiAgfVxuICBjb25zdCBjbGllbnRPcHRpb25zID0gb3B0aW9ucy51cmwuc3RhcnRzV2l0aCgnbGRhcHM6Ly8nKVxuICAgID8geyB1cmw6IG9wdGlvbnMudXJsLCB0bHNPcHRpb25zOiBvcHRpb25zLnRsc09wdGlvbnMgfVxuICAgIDogeyB1cmw6IG9wdGlvbnMudXJsIH07XG5cbiAgY29uc3QgY2xpZW50ID0gbGRhcGpzLmNyZWF0ZUNsaWVudChjbGllbnRPcHRpb25zKTtcbiAgY29uc3QgdXNlckNuID1cbiAgICB0eXBlb2Ygb3B0aW9ucy5kbiA9PT0gJ3N0cmluZydcbiAgICAgID8gb3B0aW9ucy5kbi5yZXBsYWNlKCd7e2lkfX0nLCBhdXRoRGF0YS5pZClcbiAgICAgIDogYHVpZD0ke2F1dGhEYXRhLmlkfSwke29wdGlvbnMuc3VmZml4fWA7XG5cbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBjbGllbnQuYmluZCh1c2VyQ24sIGF1dGhEYXRhLnBhc3N3b3JkLCBsZGFwRXJyb3IgPT4ge1xuICAgICAgZGVsZXRlIGF1dGhEYXRhLnBhc3N3b3JkO1xuICAgICAgaWYgKGxkYXBFcnJvcikge1xuICAgICAgICBsZXQgZXJyb3I7XG4gICAgICAgIHN3aXRjaCAobGRhcEVycm9yLmNvZGUpIHtcbiAgICAgICAgICBjYXNlIDQ5OlxuICAgICAgICAgICAgZXJyb3IgPSBuZXcgUGFyc2UuRXJyb3IoXG4gICAgICAgICAgICAgIFBhcnNlLkVycm9yLk9CSkVDVF9OT1RfRk9VTkQsXG4gICAgICAgICAgICAgICdMREFQOiBXcm9uZyB1c2VybmFtZSBvciBwYXNzd29yZCdcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICdERVBUSF9aRVJPX1NFTEZfU0lHTkVEX0NFUlQnOlxuICAgICAgICAgICAgZXJyb3IgPSBuZXcgUGFyc2UuRXJyb3IoUGFyc2UuRXJyb3IuT0JKRUNUX05PVF9GT1VORCwgJ0xEQVBTOiBDZXJ0aWZpY2F0ZSBtaXNtYXRjaCcpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGVycm9yID0gbmV3IFBhcnNlLkVycm9yKFxuICAgICAgICAgICAgICBQYXJzZS5FcnJvci5PQkpFQ1RfTk9UX0ZPVU5ELFxuICAgICAgICAgICAgICAnTERBUDogU29tdGhpbmcgd2VudCB3cm9uZyAoJyArIGxkYXBFcnJvci5jb2RlICsgJyknXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgIGNsaWVudC5kZXN0cm95KGxkYXBFcnJvcik7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmdyb3VwQ24gPT09ICdzdHJpbmcnICYmIHR5cGVvZiBvcHRpb25zLmdyb3VwRmlsdGVyID09PSAnc3RyaW5nJykge1xuICAgICAgICBzZWFyY2hGb3JHcm91cChjbGllbnQsIG9wdGlvbnMsIGF1dGhEYXRhLmlkLCByZXNvbHZlLCByZWplY3QpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2xpZW50LnVuYmluZCgpO1xuICAgICAgICBjbGllbnQuZGVzdHJveSgpO1xuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBvcHRpb25zQXJlVmFsaWQob3B0aW9ucykge1xuICByZXR1cm4gKFxuICAgIHR5cGVvZiBvcHRpb25zID09PSAnb2JqZWN0JyAmJlxuICAgIHR5cGVvZiBvcHRpb25zLnN1ZmZpeCA9PT0gJ3N0cmluZycgJiZcbiAgICB0eXBlb2Ygb3B0aW9ucy51cmwgPT09ICdzdHJpbmcnICYmXG4gICAgKG9wdGlvbnMudXJsLnN0YXJ0c1dpdGgoJ2xkYXA6Ly8nKSB8fFxuICAgICAgKG9wdGlvbnMudXJsLnN0YXJ0c1dpdGgoJ2xkYXBzOi8vJykgJiYgdHlwZW9mIG9wdGlvbnMudGxzT3B0aW9ucyA9PT0gJ29iamVjdCcpKVxuICApO1xufVxuXG5mdW5jdGlvbiBzZWFyY2hGb3JHcm91cChjbGllbnQsIG9wdGlvbnMsIGlkLCByZXNvbHZlLCByZWplY3QpIHtcbiAgY29uc3QgZmlsdGVyID0gb3B0aW9ucy5ncm91cEZpbHRlci5yZXBsYWNlKC97e2lkfX0vZ2ksIGlkKTtcbiAgY29uc3Qgb3B0cyA9IHtcbiAgICBzY29wZTogJ3N1YicsXG4gICAgZmlsdGVyOiBmaWx0ZXIsXG4gIH07XG4gIGxldCBmb3VuZCA9IGZhbHNlO1xuICBjbGllbnQuc2VhcmNoKG9wdGlvbnMuc3VmZml4LCBvcHRzLCAoc2VhcmNoRXJyb3IsIHJlcykgPT4ge1xuICAgIGlmIChzZWFyY2hFcnJvcikge1xuICAgICAgY2xpZW50LnVuYmluZCgpO1xuICAgICAgY2xpZW50LmRlc3Ryb3koKTtcbiAgICAgIHJldHVybiByZWplY3QobmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUiwgJ0xEQVAgZ3JvdXAgc2VhcmNoIGZhaWxlZCcpKTtcbiAgICB9XG4gICAgcmVzLm9uKCdzZWFyY2hFbnRyeScsIGVudHJ5ID0+IHtcbiAgICAgIGlmIChlbnRyeS5wb2pvLmF0dHJpYnV0ZXMuZmluZChvYmogPT4gb2JqLnR5cGUgPT09ICdjbicpLnZhbHVlcy5pbmNsdWRlcyhvcHRpb25zLmdyb3VwQ24pKSB7XG4gICAgICAgIGZvdW5kID0gdHJ1ZTtcbiAgICAgICAgY2xpZW50LnVuYmluZCgpO1xuICAgICAgICBjbGllbnQuZGVzdHJveSgpO1xuICAgICAgICByZXR1cm4gcmVzb2x2ZSgpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJlcy5vbignZW5kJywgKCkgPT4ge1xuICAgICAgaWYgKCFmb3VuZCkge1xuICAgICAgICBjbGllbnQudW5iaW5kKCk7XG4gICAgICAgIGNsaWVudC5kZXN0cm95KCk7XG4gICAgICAgIHJldHVybiByZWplY3QoXG4gICAgICAgICAgbmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUiwgJ0xEQVA6IFVzZXIgbm90IGluIGdyb3VwJylcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXMub24oJ2Vycm9yJywgKCkgPT4ge1xuICAgICAgY2xpZW50LnVuYmluZCgpO1xuICAgICAgY2xpZW50LmRlc3Ryb3koKTtcbiAgICAgIHJldHVybiByZWplY3QobmV3IFBhcnNlLkVycm9yKFBhcnNlLkVycm9yLklOVEVSTkFMX1NFUlZFUl9FUlJPUiwgJ0xEQVAgZ3JvdXAgc2VhcmNoIGZhaWxlZCcpKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlQXBwSWQoKSB7XG4gIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIHZhbGlkYXRlQXBwSWQsXG4gIHZhbGlkYXRlQXV0aERhdGEsXG59O1xuIl0sIm1hcHBpbmdzIjoiOztBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUdBLE1BQU1BLE1BQU0sR0FBR0MsT0FBTyxDQUFDLFFBQVEsQ0FBQztBQUNoQyxNQUFNQyxLQUFLLEdBQUdELE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQ0MsS0FBSztBQUV6QyxTQUFTQyxnQkFBZ0JBLENBQUNDLFFBQVEsRUFBRUMsT0FBTyxFQUFFO0VBQzNDLElBQUksQ0FBQ0MsZUFBZSxDQUFDRCxPQUFPLENBQUMsRUFBRTtJQUM3QixPQUFPLElBQUlFLE9BQU8sQ0FBQyxDQUFD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