@universis/janitor 1.6.3 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +3 -3
  2. package/dist/index.d.ts +213 -7
  3. package/dist/index.esm.js +896 -0
  4. package/dist/index.esm.js.map +1 -0
  5. package/dist/index.js +909 -9
  6. package/dist/index.js.map +1 -1
  7. package/package.json +40 -20
  8. package/src/HttpBearerStategy.js +134 -0
  9. package/src/HttpBearerStrategy.d.ts +4 -0
  10. package/src/RedisClientStore.js +1 -1
  11. package/src/ScopeAccessConfiguration.d.ts +23 -1
  12. package/src/ScopeAccessConfiguration.js +38 -8
  13. package/src/index.d.ts +1 -1
  14. package/src/index.js +1 -1
  15. package/.gitlab-ci.yml +0 -29
  16. package/dist/OAuth2ClientService.d.ts +0 -98
  17. package/dist/OAuth2ClientService.js +0 -251
  18. package/dist/OAuth2ClientService.js.map +0 -1
  19. package/dist/RateLimitService.d.ts +0 -4
  20. package/dist/RateLimitService.js +0 -102
  21. package/dist/RateLimitService.js.map +0 -1
  22. package/dist/RedisClientStore.d.ts +0 -5
  23. package/dist/RedisClientStore.js +0 -122
  24. package/dist/RedisClientStore.js.map +0 -1
  25. package/dist/RemoteAddressValidator.d.ts +0 -10
  26. package/dist/RemoteAddressValidator.js +0 -89
  27. package/dist/RemoteAddressValidator.js.map +0 -1
  28. package/dist/ScopeAccessConfiguration.d.ts +0 -65
  29. package/dist/ScopeAccessConfiguration.js +0 -160
  30. package/dist/ScopeAccessConfiguration.js.map +0 -1
  31. package/dist/SpeedLimitService.d.ts +0 -4
  32. package/dist/SpeedLimitService.js +0 -113
  33. package/dist/SpeedLimitService.js.map +0 -1
  34. package/dist/polyfills.js +0 -11
  35. package/dist/polyfills.js.map +0 -1
  36. package/dist/validateScope.d.ts +0 -2
  37. package/dist/validateScope.js +0 -23
  38. package/dist/validateScope.js.map +0 -1
  39. package/src/polyfills.js +0 -10
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["require","_RateLimitService","Object","keys","forEach","key","exports","defineProperty","enumerable","get","_SpeedLimitService","_RedisClientStore","_ScopeAccessConfiguration","_validateScope","_OAuth2ClientService","_RemoteAddressValidator"],"sources":["../src/index.js"],"sourcesContent":["import './polyfills';\nexport * from './RateLimitService';\nexport * from './SpeedLimitService';\nexport * from './RedisClientStore';\nexport * from './ScopeAccessConfiguration';\nexport * from './validateScope';\nexport * from './OAuth2ClientService';\nexport * from './RemoteAddressValidator';\n"],"mappings":"2EAAAA,OAAA;AACA,IAAAC,iBAAA,GAAAD,OAAA,uBAAAE,MAAA,CAAAC,IAAA,CAAAF,iBAAA,EAAAG,OAAA,WAAAC,GAAA,OAAAA,GAAA,kBAAAA,GAAA,8BAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAJ,iBAAA,CAAAI,GAAA,UAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA,IAAAG,UAAA,QAAAC,GAAA,WAAAA,CAAA,UAAAR,iBAAA,CAAAI,GAAA;AACA,IAAAK,kBAAA,GAAAV,OAAA,wBAAAE,MAAA,CAAAC,IAAA,CAAAO,kBAAA,EAAAN,OAAA,WAAAC,GAAA,OAAAA,GAAA,kBAAAA,GAAA,8BAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAK,kBAAA,CAAAL,GAAA,UAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA,IAAAG,UAAA,QAAAC,GAAA,WAAAA,CAAA,UAAAC,kBAAA,CAAAL,GAAA;AACA,IAAAM,iBAAA,GAAAX,OAAA,uBAAAE,MAAA,CAAAC,IAAA,CAAAQ,iBAAA,EAAAP,OAAA,WAAAC,GAAA,OAAAA,GAAA,kBAAAA,GAAA,8BAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAM,iBAAA,CAAAN,GAAA,UAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA,IAAAG,UAAA,QAAAC,GAAA,WAAAA,CAAA,UAAAE,iBAAA,CAAAN,GAAA;AACA,IAAAO,yBAAA,GAAAZ,OAAA,+BAAAE,MAAA,CAAAC,IAAA,CAAAS,yBAAA,EAAAR,OAAA,WAAAC,GAAA,OAAAA,GAAA,kBAAAA,GAAA,8BAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAO,yBAAA,CAAAP,GAAA,UAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA,IAAAG,UAAA,QAAAC,GAAA,WAAAA,CAAA,UAAAG,yBAAA,CAAAP,GAAA;AACA,IAAAQ,cAAA,GAAAb,OAAA,oBAAAE,MAAA,CAAAC,IAAA,CAAAU,cAAA,EAAAT,OAAA,WAAAC,GAAA,OAAAA,GAAA,kBAAAA,GAAA,8BAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAQ,cAAA,CAAAR,GAAA,UAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA,IAAAG,UAAA,QAAAC,GAAA,WAAAA,CAAA,UAAAI,cAAA,CAAAR,GAAA;AACA,IAAAS,oBAAA,GAAAd,OAAA,0BAAAE,MAAA,CAAAC,IAAA,CAAAW,oBAAA,EAAAV,OAAA,WAAAC,GAAA,OAAAA,GAAA,kBAAAA,GAAA,8BAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAS,oBAAA,CAAAT,GAAA,UAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA,IAAAG,UAAA,QAAAC,GAAA,WAAAA,CAAA,UAAAK,oBAAA,CAAAT,GAAA;AACA,IAAAU,uBAAA,GAAAf,OAAA,6BAAAE,MAAA,CAAAC,IAAA,CAAAY,uBAAA,EAAAX,OAAA,WAAAC,GAAA,OAAAA,GAAA,kBAAAA,GAAA,8BAAAA,GAAA,IAAAC,OAAA,IAAAA,OAAA,CAAAD,GAAA,MAAAU,uBAAA,CAAAV,GAAA,UAAAH,MAAA,CAAAK,cAAA,CAAAD,OAAA,EAAAD,GAAA,IAAAG,UAAA,QAAAC,GAAA,WAAAA,CAAA,UAAAM,uBAAA,CAAAV,GAAA"}
1
+ {"version":3,"file":"index.js","sources":["../src/RateLimitService.js","../src/SpeedLimitService.js","../src/RedisClientStore.js","../src/ScopeAccessConfiguration.js","../src/validateScope.js","../src/OAuth2ClientService.js","../src/RemoteAddressValidator.js"],"sourcesContent":["import { ApplicationService, TraceUtils } from '@themost/common';\nimport { rateLimit } from 'express-rate-limit';\nimport express from 'express';\nimport path from 'path';\n\nexport class RateLimitService extends ApplicationService {\n /**\n * @param {import('@themost/express').ExpressDataApplication} app \n */\n constructor(app) {\n super(app);\n app.serviceRouter.subscribe(serviceRouter => {\n if (serviceRouter == null) {\n return;\n }\n try {\n const addRouter = express.Router();\n let serviceConfiguration = app.getConfiguration().getSourceAt('settings/universis/janitor/rateLimit') || {\n profiles: [],\n paths: []\n };\n if (serviceConfiguration.extends) {\n // get additional configuration\n const configurationPath = app.getConfiguration().getConfigurationPath();\n const extendsPath = path.resolve(configurationPath, serviceConfiguration.extends);\n TraceUtils.log(`@universis/janitor#RateLimitService will try to extend service configuration from ${extendsPath}`);\n serviceConfiguration = require(extendsPath);\n }\n const pathsArray = serviceConfiguration.paths || [];\n const profilesArray = serviceConfiguration.profiles || [];\n // create maps\n const paths = new Map(pathsArray);\n const profiles = new Map(profilesArray);\n if (paths.size === 0) {\n TraceUtils.warn('@universis/janitor#RateLimitService is being started but the collection of paths is empty.');\n }\n // get proxy address forwarding option\n let proxyAddressForwarding = app.getConfiguration().getSourceAt('settings/universis/api/proxyAddressForwarding');\n if (typeof proxyAddressForwarding !== 'boolean') {\n proxyAddressForwarding = false;\n }\n paths.forEach((value, path) => {\n let profile;\n // get profile\n if (value.profile) {\n profile = profiles.get(value.profile);\n } else {\n // or options defined inline\n profile = value\n }\n if (profile != null) {\n const rateLimitOptions = Object.assign({\n windowMs: 5 * 60 * 1000, // 5 minutes\n limit: 50, // 50 requests\n legacyHeaders: true // send headers\n }, profile, {\n keyGenerator: (req) => {\n let remoteAddress;\n if (proxyAddressForwarding) {\n // get proxy headers or remote address\n remoteAddress = req.headers['x-real-ip'] || req.headers['x-forwarded-for'] || (req.connection ? req.connection.remoteAddress : req.socket.remoteAddress);\n } else {\n // get remote address\n remoteAddress = (req.connection ? req.connection.remoteAddress : req.socket.remoteAddress);\n }\n return `${path}:${remoteAddress}`;\n }\n });\n if (typeof rateLimitOptions.store === 'string') {\n // load store\n const store = rateLimitOptions.store.split('#');\n let StoreClass;\n if (store.length === 2) {\n const storeModule = require(store[0]);\n if (Object.prototype.hasOwnProperty.call(storeModule, store[1])) {\n StoreClass = storeModule[store[1]];\n rateLimitOptions.store = new StoreClass(this, rateLimitOptions);\n } else {\n throw new Error(`${store} cannot be found or is inaccessible`);\n }\n } else {\n StoreClass = require(store[0]);\n // create store\n rateLimitOptions.store = new StoreClass(this, rateLimitOptions);\n }\n }\n addRouter.use(path, rateLimit(rateLimitOptions));\n }\n });\n if (addRouter.stack.length) {\n serviceRouter.stack.unshift.apply(serviceRouter.stack, addRouter.stack);\n }\n } catch (err) {\n TraceUtils.error('An error occurred while validating rate limit configuration.');\n TraceUtils.error(err);\n TraceUtils.warn('Rate limit service is inactive due to an error occured while loading configuration.')\n }\n });\n }\n\n}","import { ApplicationService, TraceUtils } from '@themost/common';\nimport slowDown from 'express-slow-down';\nimport express from 'express';\nimport path from 'path';\n\nexport class SpeedLimitService extends ApplicationService {\n constructor(app) {\n super(app);\n\n app.serviceRouter.subscribe(serviceRouter => {\n if (serviceRouter == null) {\n return;\n }\n try {\n const addRouter = express.Router();\n let serviceConfiguration = app.getConfiguration().getSourceAt('settings/universis/janitor/speedLimit') || {\n profiles: [],\n paths: []\n };\n if (serviceConfiguration.extends) {\n // get additional configuration\n const configurationPath = app.getConfiguration().getConfigurationPath();\n const extendsPath = path.resolve(configurationPath, serviceConfiguration.extends);\n TraceUtils.log(`@universis/janitor#SpeedLimitService will try to extend service configuration from ${extendsPath}`);\n serviceConfiguration = require(extendsPath);\n }\n const pathsArray = serviceConfiguration.paths || [];\n const profilesArray = serviceConfiguration.profiles || [];\n // create maps\n const paths = new Map(pathsArray);\n const profiles = new Map(profilesArray);\n if (paths.size === 0) {\n TraceUtils.warn('@universis/janitor#SpeedLimitService is being started but the collection of paths is empty.');\n }\n // get proxy address forwarding option\n let proxyAddressForwarding = app.getConfiguration().getSourceAt('settings/universis/api/proxyAddressForwarding');\n if (typeof proxyAddressForwarding !== 'boolean') {\n proxyAddressForwarding = false;\n }\n paths.forEach((value, path) => {\n let profile;\n // get profile\n if (value.profile) {\n profile = profiles.get(value.profile);\n } else {\n // or options defined inline\n profile = value\n }\n if (profile != null) {\n const slowDownOptions = Object.assign({\n windowMs: 5 * 60 * 1000, // 5 minutes\n delayAfter: 20, // 20 requests\n delayMs: 500, // 500 ms\n maxDelayMs: 10000 // 10 seconds\n }, profile, {\n keyGenerator: (req) => {\n let remoteAddress;\n if (proxyAddressForwarding) {\n // get proxy headers or remote address\n remoteAddress = req.headers['x-real-ip'] || req.headers['x-forwarded-for'] || (req.connection ? req.connection.remoteAddress : req.socket.remoteAddress);\n } else {\n // get remote address\n remoteAddress = (req.connection ? req.connection.remoteAddress : req.socket.remoteAddress);\n }\n return `${path}:${remoteAddress}`;\n }\n });\n if (Array.isArray(slowDownOptions.randomDelayMs)) {\n slowDownOptions.delayMs = () => {\n const delayMs = Math.floor(Math.random() * (slowDownOptions.randomDelayMs[1] - slowDownOptions.randomDelayMs[0] + 1) + slowDownOptions.randomDelayMs[0]);\n return delayMs;\n }\n }\n if (Array.isArray(slowDownOptions.randomMaxDelayMs)) {\n slowDownOptions.maxDelayMs = () => {\n const maxDelayMs = Math.floor(Math.random() * (slowDownOptions.randomMaxDelayMs[1] - slowDownOptions.randomMaxDelayMs[0] + 1) + slowDownOptions.randomMaxDelayMs[0]);\n return maxDelayMs;\n }\n }\n if (typeof slowDownOptions.store === 'string') {\n // load store\n const store = slowDownOptions.store.split('#');\n let StoreClass;\n if (store.length === 2) {\n const storeModule = require(store[0]);\n if (Object.prototype.hasOwnProperty.call(storeModule, store[1])) {\n StoreClass = storeModule[store[1]];\n slowDownOptions.store = new StoreClass(this, slowDownOptions);\n } else {\n throw new Error(`${store} cannot be found or is inaccessible`);\n }\n } else {\n StoreClass = require(store[0]);\n // create store\n slowDownOptions.store = new StoreClass(this, slowDownOptions);\n }\n }\n addRouter.use(path, slowDown(slowDownOptions));\n }\n });\n if (addRouter.stack.length) {\n serviceRouter.stack.unshift.apply(serviceRouter.stack, addRouter.stack);\n }\n } catch (err) {\n TraceUtils.error('An error occurred while validating speed limit configuration.');\n TraceUtils.error(err);\n TraceUtils.warn('Speed limit service is inactive due to an error occured while loading configuration.')\n }\n });\n }\n\n}","import { TraceUtils } from '@themost/common';\nimport { RedisStore } from 'rate-limit-redis';\nimport { Redis } from 'ioredis';\nimport '@themost/promise-sequence';\n\nlet superLoadIncrementScript;\nlet superLoadGetScript;\n\nfunction noLoadGetScript() {\n //\n}\n\nfunction noLoadIncrementScript() {\n //\n}\n\nif (RedisStore.prototype.loadIncrementScript.name === 'loadIncrementScript') {\n // get super method for future use\n superLoadIncrementScript = RedisStore.prototype.loadIncrementScript;\n RedisStore.prototype.loadIncrementScript = noLoadIncrementScript;\n}\n\nif (RedisStore.prototype.loadGetScript.name === 'loadGetScript') {\n // get super method\n superLoadGetScript = RedisStore.prototype.loadGetScript;\n RedisStore.prototype.loadGetScript = noLoadGetScript;\n}\n\nclass RedisClientStore extends RedisStore {\n\n /**\n * @type {import('redis').RedisClientType}\n */\n client;\n\n /**\n * \n * @param {import('@themost/common').ApplicationService} service\n * @param {{windowMs: number}} options\n */\n constructor(service, options) {\n super({\n /**\n * @param {...string} args\n * @returns {Promise<*>}\n */\n sendCommand: function () {\n const args = Array.from(arguments);\n const [command] = args.splice(0, 1);\n const self = this;\n if (command === 'SCRIPT') {\n const connectOptions = service.getApplication().getConfiguration().getSourceAt('settings/redis/options') || {\n host: '127.0.0.1',\n port: 6379\n };\n const client = new Redis(connectOptions);\n return client.call(command, args).catch((error) => {\n if (error instanceof TypeError && error.message === 'Invalid argument type') {\n TraceUtils.warn('RedisClientStore: Invalid argument type: ' + JSON.stringify(args));\n }\n return Promise.reject(error);\n }).finally(() => {\n if (client.isOpen) {\n client.disconnect().catch((errDisconnect) => {\n TraceUtils.error(errDisconnect);\n });\n }\n });\n }\n if (self.client == null) {\n const connectOptions = service.getApplication().getConfiguration().getSourceAt('settings/redis/options') || {\n host: '127.0.0.1',\n port: 6379\n };\n self.client = new Redis(connectOptions);\n }\n if (self.client.isOpen) {\n return self.client.call(command, args).catch((error) => {\n if (error instanceof TypeError && error.message === 'Invalid argument type') {\n TraceUtils.warn('RedisClientStore: Invalid argument type: ' + JSON.stringify(args));\n }\n return Promise.reject(error);\n });\n }\n // send load script commands once\n return (() => {\n if (self.incrementScriptSha == null) {\n return this.postInit();\n }\n return Promise.resolve();\n })().then(() => {\n // send command \n args[0] = self.incrementScriptSha;\n return self.client.call(command, args).catch((error) => {\n if (error instanceof TypeError && error.message === 'Invalid argument type') {\n TraceUtils.warn('RedisClientStore: Invalid argument type: ' + JSON.stringify(args));\n }\n return Promise.reject(error);\n });\n });\n }\n });\n this.init(options);\n TraceUtils.debug('RedisClientStore: Starting up and loading increment and get scripts.');\n void this.postInit().then(() => {\n TraceUtils.debug('RedisClientStore: Successfully loaded increment and get scripts.');\n }).catch((err) => {\n TraceUtils.error('RedisClientStore: Failed to load increment and get scripts.');\n TraceUtils.error(err);\n });\n }\n async postInit() {\n const [incrementScriptSha, getScriptSha] = await Promise.sequence([\n () => superLoadIncrementScript.call(this),\n () => superLoadGetScript.call(this)\n ]);\n this.incrementScriptSha = incrementScriptSha;\n this.getScriptSha = getScriptSha;\n }\n\n}\n\nexport {\n RedisClientStore\n}","\nimport {ConfigurationStrategy, Args, ApplicationService} from '@themost/common';\nimport path from 'path';\nimport url from 'url';\n\nconst HTTP_METHOD_REGEXP = /^\\b(POST|PUT|PATCH|DELETE)\\b$/i;\n\nclass ScopeString {\n constructor(str) {\n this.value = str;\n }\n toString() {\n return this.value;\n }\n /**\n * Splits a comma-separated or space-separated scope string e.g. \"profile email\" or \"profile,email\"\n *\n * Important note: https://www.rfc-editor.org/rfc/rfc6749#section-3.3 defines the regular expression of access token scopes\n * which is a space separated string. Several OAuth2 servers use a comma-separated list instead.\n *\n * The operation will try to use both implementations by excluding comma ',' from access token regular expressions\n * @returns {Array<string>}\n */\n split() {\n // the default regular expression includes comma /([\\x21\\x23-\\x5B\\x5D-\\x7E]+)/g\n // the modified regular expression excludes comma /x2C /([\\x21\\x23-\\x2B\\x2D-\\x5B\\x5D-\\x7E]+)/g\n const re = /([\\x21\\x23-\\x2B\\x2D-\\x5B\\x5D-\\x7E]+)/g\n const results = [];\n let match = re.exec(this.value);\n while(match !== null) {\n results.push(match[0]);\n match = re.exec(this.value);\n }\n return results;\n }\n}\n\nclass ScopeAccessConfiguration extends ConfigurationStrategy {\n /**\n * @param {import('@themost/common').ConfigurationBase} configuration\n */\n constructor(configuration) {\n super(configuration);\n let elements = [];\n // define property\n Object.defineProperty(this, 'elements', {\n get: () => {\n return elements;\n },\n enumerable: true\n });\n }\n\n /**\n * @param {Request} req\n * @returns Promise<ScopeAccessConfigurationElement>\n */\n verify(req) {\n return new Promise((resolve, reject) => {\n try {\n // validate request context\n Args.notNull(req.context,'Context');\n // validate request context user\n Args.notNull(req.context.user,'User');\n if (req.context.user.authenticationScope && req.context.user.authenticationScope.length>0) {\n // get original url\n let reqUrl = url.parse(req.originalUrl).pathname;\n // get user context scopes as array e.g, ['students', 'students:read']\n let reqScopes = new ScopeString(req.context.user.authenticationScope).split();\n // get user access based on HTTP method e.g. GET -> read access\n let reqAccess = HTTP_METHOD_REGEXP.test(req.method) ? 'write' : 'read';\n // first phase: find element by resource and scope\n let result = this.elements.find(x => {\n // filter element by access level\n return new RegExp( \"^\" + x.resource, 'i').test(reqUrl)\n // and scopes\n && x.scope.find(y => {\n // search user scopes (validate wildcard scope)\n return y === \"*\" || reqScopes.indexOf(y)>=0;\n });\n });\n // second phase: check access level\n if (result == null) {\n return resolve();\n }\n // if access is missing or access is not an array\n if (Array.isArray(result.access) === false) {\n // the requested access is not allowed because the access is not defined\n return resolve();\n }\n // if the requested access is not in the access array\n if (result.access.indexOf(reqAccess) < 0) {\n // the requested access is not allowed because the access levels do not match\n return resolve();\n }\n // otherwise, return result\n return resolve(result);\n }\n return resolve();\n }\n catch(err) {\n return reject(err);\n }\n\n });\n }\n\n}\n\n/**\n * @class\n */\nclass DefaultScopeAccessConfiguration extends ScopeAccessConfiguration {\n /**\n * @param {import('@themost/common').ConfigurationBase} configuration\n */\n constructor(configuration) {\n super(configuration);\n let defaults = [];\n // load scope access from configuration resource\n try {\n /**\n * @type {Array<ScopeAccessConfigurationElement>}\n */\n defaults = require(path.resolve(configuration.getConfigurationPath(), 'scope.access.json'));\n }\n catch(err) {\n // if an error occurred other than module not found (there are no default access policies)\n if (err.code !== 'MODULE_NOT_FOUND') {\n // throw error\n throw err;\n }\n // otherwise continue\n }\n this.elements.push.apply(this.elements, defaults);\n }\n}\n\nclass EnableScopeAccessConfiguration extends ApplicationService {\n /**\n * @param {import('@themost/express').ExpressDataApplication|import('@themost/common').ApplicationBase} app \n */\n constructor(app) {\n super(app);\n // register scope access configuration\n app.getConfiguration().useStrategy(ScopeAccessConfiguration, DefaultScopeAccessConfiguration);\n }\n}\n\n\n/**\n * @class\n */\nclass ExtendScopeAccessConfiguration extends ApplicationService {\n /**\n * @param {import('@themost/express').ExpressDataApplication|import('@themost/common').ApplicationBase} app\n */\n constructor(app) {\n super(app);\n // Get the additional scope access extensions from the configuration\n const scopeAccessExtensions = app.getConfiguration().settings.universis?.janitor?.scopeAccess.imports;\n if (app && app.container && scopeAccessExtensions != null) {\n app.container.subscribe((container) => {\n if (container) {\n const scopeAccess = app.getConfiguration().getStrategy(function ScopeAccessConfiguration() { });\n if (scopeAccess != null) {\n for (const scopeAccessExtension of scopeAccessExtensions) {\n try {\n const elements = require(path.resolve(app.getConfiguration().getConfigurationPath(), scopeAccessExtension));\n if (elements) {\n // add extra scope access elements\n scopeAccess.elements.unshift(...elements);\n }\n }\n catch(err) {\n // if an error occurred other than module not found (there are no default access policies)\n if (err.code !== 'MODULE_NOT_FOUND') {\n // throw error\n throw err;\n }\n }\n }\n }\n }\n });\n }\n }\n}\n\nexport {\n ScopeString,\n ScopeAccessConfiguration,\n DefaultScopeAccessConfiguration,\n EnableScopeAccessConfiguration,\n ExtendScopeAccessConfiguration\n}\n","import { ScopeAccessConfiguration } from './ScopeAccessConfiguration';\nimport {HttpForbiddenError} from '@themost/common';\n\nfunction validateScope() {\n return (req, res, next) => {\n /**\n * @type {ScopeAccessConfiguration}\n */\n let scopeAccessConfiguration = req.context.getApplication().getConfiguration().getStrategy(ScopeAccessConfiguration);\n if (typeof scopeAccessConfiguration === 'undefined') {\n return next(new Error('Invalid application configuration. Scope access configuration strategy is missing or is in accessible.'));\n }\n scopeAccessConfiguration.verify(req).then(value => {\n if (value) {\n return next();\n }\n return next(new HttpForbiddenError('Access denied due to authorization scopes.'))\n }).catch(reason => {\n return next(reason);\n });\n };\n}\n\nexport {\n validateScope\n}\n","import {Request} from 'superagent'\nimport {URL} from 'url';\nimport {ApplicationService, DataError, HttpError} from '@themost/common';\n\nfunction responseHander(resolve, reject) {\n return function (err, response) {\n if (err) {\n /**\n * @type {import('superagent').Response}\n */\n const response = err.response\n if (response && response.headers['content-type'] === 'application/json') {\n // get body\n const clientError = response.body;\n const error = new HttpError(response.status);\n return reject(Object.assign(error, {\n clientError\n }));\n }\n return reject(err);\n }\n if (response.status === 204 && response.headers['content-type'] === 'application/json') {\n return resolve(null);\n }\n return resolve(response.body);\n };\n}\n\n/**\n * @class\n */\nclass OAuth2ClientService extends ApplicationService {\n /**\n * @param {import('@themost/express').ExpressDataApplication} app\n */\n constructor(app) {\n super(app);\n /**\n * @name OAuth2ClientService#settings\n * @type {{server_uri:string,token_uri?:string}}\n */\n Object.defineProperty(this, 'settings', {\n writable: false,\n value: app.getConfiguration().getSourceAt('settings/auth'),\n enumerable: false,\n configurable: false\n });\n }\n\n /**\n * Gets keycloak server root\n * @returns {string}\n */\n getServer() {\n return this.settings.server_uri;\n }\n\n /**\n * Gets keycloak server root\n * @returns {string}\n */\n getAdminRoot() {\n return this.settings.admin_uri;\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Gets user's profile by calling OAuth2 server profile endpoint\n * @param {ExpressDataContext} context\n * @param {string} token\n */\n getUserInfo(token) {\n return new Promise((resolve, reject) => {\n const userinfo_uri = this.settings.userinfo_uri ? new URL(this.settings.userinfo_uri, this.getServer()) : new URL('me', this.getServer());\n return new Request('GET', userinfo_uri)\n .set({\n 'Authorization': `Bearer ${token}`,\n 'Accept': 'application/json'\n })\n .query({\n 'access_token':token\n }).end(responseHander(resolve, reject));\n });\n }\n\n // noinspection JSUnusedGlobalSymbols\n /**\n * Gets the token info of the current context\n * @param {ExpressDataContext} context\n */\n getContextTokenInfo(context) {\n if (context.user == null) {\n return Promise.reject(new Error('Context user may not be null'));\n }\n if (context.user.authenticationType !== 'Bearer') {\n return Promise.reject(new Error('Invalid context authentication type'));\n }\n if (context.user.authenticationToken == null) {\n return Promise.reject(new Error('Context authentication data may not be null'));\n }\n return this.getTokenInfo(context, context.user.authenticationToken);\n }\n /**\n * Gets token info by calling OAuth2 server endpoint\n * @param {ExpressDataContext} _context\n * @param {string} token\n */\n getTokenInfo(_context, token) {\n return new Promise((resolve, reject) => {\n const introspection_uri = this.settings.introspection_uri ? new URL(this.settings.introspection_uri, this.getServer()) : new URL('tokeninfo', this.getServer());\n return new Request('POST', introspection_uri)\n .auth(this.settings.client_id, this.settings.client_secret)\n .set('Accept', 'application/json')\n .type('form')\n .send({\n 'token_type_hint': 'access_token',\n 'token': token,\n }).end(responseHander(resolve, reject));\n });\n }\n\n /**\n * @param {AuthorizeUser} authorizeUser\n */\n authorize(authorizeUser) {\n const tokenURL = this.settings.token_uri ? new URL(this.settings.token_uri) : new URL('authorize', this.getServer());\n return new Promise((resolve, reject)=> {\n return new Request('POST', tokenURL)\n .type('form')\n .send(authorizeUser).end(responseHander(resolve, reject));\n });\n }\n\n /**\n * Gets a user by name\n * @param {*} user_id \n * @param {AdminMethodOptions} options \n */\n getUserById(user_id, options) {\n return new Promise((resolve, reject) => {\n return new Request('GET', new URL(`users/${user_id}`, this.getAdminRoot()))\n .set('Authorization', `Bearer ${options.access_token}`)\n .end(responseHander(resolve, reject));\n });\n }\n\n /**\n * Gets a user by name\n * @param {string} username \n * @param {AdminMethodOptions} options \n */\n getUser(username, options) {\n return new Promise((resolve, reject)=> {\n return new Request('GET', new URL('users', this.getAdminRoot()))\n .set('Authorization', `Bearer ${options.access_token}`)\n .query({\n '$filter': `name eq '${username}'`\n })\n .end(responseHander(resolve, reject));\n });\n }\n\n /**\n * Gets a user by email address\n * @param {string} email \n * @param {AdminMethodOptions} options \n */\n getUserByEmail(email, options) {\n return new Promise((resolve, reject)=> {\n return new Request('GET', new URL('users', this.getAdminRoot()))\n .set('Authorization', `Bearer ${options.access_token}`)\n .query({\n '$filter': `alternateName eq '${email}'`\n })\n .end(responseHander(resolve, reject));\n });\n }\n\n /**\n * Updates an existing user\n * @param {*} user \n * @param {AdminMethodOptions} options \n */\n updateUser(user, options) {\n return new Promise((resolve, reject)=> {\n if (user.id == null) {\n return reject(new DataError('E_IDENTIFIER', 'User may not be empty at this context.', null, 'User', 'id'));\n }\n const request = new Request('PUT', new URL(`users/${user.id}`, this.getAdminRoot()));\n return request.set('Authorization', `Bearer ${options.access_token}`)\n .set('Content-Type', 'application/json')\n .send(user)\n .end(responseHander(resolve, reject));\n });\n }\n\n /**\n * Creates a new user\n * @param {*} user \n * @param {AdminMethodOptions} options \n */\n createUser(user, options) {\n return new Promise((resolve, reject)=> {\n const request = new Request('POST', new URL('users', this.getAdminRoot()));\n return request.set('Authorization', `Bearer ${options.access_token}`)\n .set('Content-Type', 'application/json')\n .send(Object.assign({}, user, {\n $state: 1 // for create\n }))\n .end(responseHander(resolve, reject));\n });\n }\n\n /**\n * Deletes a user\n * @param {{id: any}} user \n * @param {AdminMethodOptions} options \n */\n deleteUser(user, options) {\n return new Promise((resolve, reject)=> {\n if (user.id == null) {\n return reject(new DataError('E_IDENTIFIER', 'User may not be empty at this context.', null, 'User', 'id'));\n }\n const request = new Request('DELETE', new URL(`users/${user.id}`, this.getAdminRoot()));\n return request.set('Authorization', `Bearer ${options.access_token}`)\n .end(responseHander(resolve, reject));\n });\n }\n\n /**\n * @param {boolean=} force \n * @returns {*}\n */\n getWellKnownConfiguration(force) {\n if (force) {\n this.well_known_configuration = null;\n }\n if (this.well_known_configuration) {\n return Promise.resolve(this.well_known_configuration);\n }\n return new Promise((resolve, reject) => {\n const well_known_configuration_uri = this.settings.well_known_configuration_uri ? new URL(this.settings.well_known_configuration_uri, this.getServer()) : new URL('.well-known/openid-configuration', this.getServer());\n return new Request('GET', well_known_configuration_uri)\n .end(responseHander(resolve, reject));\n }).then((configuration) => {\n this.well_known_configuration = configuration;\n return configuration;\n });\n }\n}\n\nexport {\n OAuth2ClientService\n}\n\n","import { ApplicationService, HttpForbiddenError, TraceUtils } from '@themost/common';\nimport express from 'express';\nimport jwt from 'jsonwebtoken';\n\nclass HttpRemoteAddrForbiddenError extends HttpForbiddenError {\n constructor() {\n super('Access is denied due to remote address conflict. The client network has been changed or cannot be determined.');\n this.statusCode = 403.6;\n }\n \n}\n\nclass RemoteAddressValidator extends ApplicationService {\n constructor(app) {\n super(app);\n\n // get proxy address forwarding option\n let proxyAddressForwarding = app.getConfiguration().getSourceAt('settings/universis/api/proxyAddressForwarding');\n if (typeof proxyAddressForwarding !== 'boolean') {\n proxyAddressForwarding = false;\n }\n this.proxyAddressForwarding = proxyAddressForwarding;\n // get token claim name\n this.claim = app.getConfiguration().getSourceAt('settings/universis/janitor/remoteAddress/claim') || 'remoteAddress';\n\n app.serviceRouter.subscribe((serviceRouter) => {\n if (serviceRouter == null) {\n return;\n }\n const addRouter = express.Router();\n addRouter.use((req, res, next) => {\n void this.validateRemoteAddress(req).then((value) => {\n if (value === false) {\n return next(new HttpRemoteAddrForbiddenError());\n }\n return next();\n }).catch((err) => {\n return next(err);\n });\n });\n // insert router at the beginning of serviceRouter.stack\n serviceRouter.stack.unshift.apply(serviceRouter.stack, addRouter.stack);\n });\n }\n\n /**\n * Gets remote address from request\n * @param {import('express').Request} req \n * @returns \n */\n getRemoteAddress(req) {\n let remoteAddress;\n if (this.proxyAddressForwarding) {\n // get proxy headers or remote address\n remoteAddress = req.headers['x-real-ip'] || req.headers['x-forwarded-for'] || (req.connection ? req.connection.remoteAddress : req.socket.remoteAddress);\n } else {\n remoteAddress = req.connection ? req.connection.remoteAddress : req.socket.remoteAddress;\n }\n return remoteAddress;\n }\n\n /**\n * Validates token remote address with request remote address\n * @param {import('express').Request} req \n * @returns {Promise<boolean>}\n */\n async validateRemoteAddress(req) {\n const authenticationToken = req.context?.user?.authenticationToken;\n if (authenticationToken != null) {\n const access_token = jwt.decode(authenticationToken);\n const remoteAddress = access_token[this.claim];\n if (remoteAddress == null) {\n TraceUtils.warn(`Remote address validation failed. Expected a valid remote address claimed by using \"${this.claim}\" attribute but got none.`);\n return false;\n }\n // get context remote address\n const requestRemoteAddress = this.getRemoteAddress(req);\n if (remoteAddress !== requestRemoteAddress) {\n TraceUtils.warn(`Remote address validation failed. Expected remote address is ${remoteAddress || 'Uknown'} but request remote address is ${requestRemoteAddress}`);\n return false;\n }\n return true;\n }\n TraceUtils.warn('Remote address validation cannot be completed because authentication token is not available.');\n return false;\n }\n\n}\n\nexport {\n HttpRemoteAddrForbiddenError,\n RemoteAddressValidator\n}\n"],"names":["RateLimitService","ApplicationService","constructor","app","serviceRouter","subscribe","addRouter","express","Router","serviceConfiguration","getConfiguration","getSourceAt","profiles","paths","extends","configurationPath","getConfigurationPath","extendsPath","path","resolve","TraceUtils","log","require","pathsArray","profilesArray","Map","size","warn","proxyAddressForwarding","forEach","value","profile","get","rateLimitOptions","Object","assign","windowMs","limit","legacyHeaders","keyGenerator","req","remoteAddress","headers","connection","socket","store","split","StoreClass","length","storeModule","prototype","hasOwnProperty","call","Error","use","rateLimit","stack","unshift","apply","err","error","SpeedLimitService","slowDownOptions","delayAfter","delayMs","maxDelayMs","Array","isArray","randomDelayMs","Math","floor","random","randomMaxDelayMs","slowDown","superLoadIncrementScript","superLoadGetScript","noLoadGetScript","noLoadIncrementScript","RedisStore","loadIncrementScript","name","loadGetScript","RedisClientStore","service","options","sendCommand","args","from","arguments","command","splice","self","connectOptions","getApplication","host","port","client","Redis","catch","TypeError","message","JSON","stringify","Promise","reject","finally","isOpen","disconnect","errDisconnect","incrementScriptSha","postInit","then","_defineProperty","init","debug","getScriptSha","sequence","HTTP_METHOD_REGEXP","ScopeString","str","toString","re","results","match","exec","push","ScopeAccessConfiguration","ConfigurationStrategy","configuration","elements","defineProperty","enumerable","verify","Args","notNull","context","user","authenticationScope","reqUrl","url","parse","originalUrl","pathname","reqScopes","reqAccess","test","method","result","find","x","RegExp","resource","scope","y","indexOf","access","DefaultScopeAccessConfiguration","defaults","code","EnableScopeAccessConfiguration","useStrategy","ExtendScopeAccessConfiguration","scopeAccessExtensions","settings","universis","janitor","scopeAccess","imports","container","getStrategy","scopeAccessExtension","validateScope","res","next","scopeAccessConfiguration","HttpForbiddenError","reason","responseHander","response","clientError","body","HttpError","status","OAuth2ClientService","writable","configurable","getServer","server_uri","getAdminRoot","admin_uri","getUserInfo","token","userinfo_uri","URL","Request","set","query","end","getContextTokenInfo","authenticationType","authenticationToken","getTokenInfo","_context","introspection_uri","auth","client_id","client_secret","type","send","authorize","authorizeUser","tokenURL","token_uri","getUserById","user_id","access_token","getUser","username","getUserByEmail","email","updateUser","id","DataError","request","createUser","$state","deleteUser","getWellKnownConfiguration","force","well_known_configuration","well_known_configuration_uri","HttpRemoteAddrForbiddenError","statusCode","RemoteAddressValidator","claim","validateRemoteAddress","getRemoteAddress","jwt","decode","requestRemoteAddress"],"mappings":";;;;;;;;;;;;;;;AAKO,MAAMA,gBAAgB,SAASC,yBAAkB,CAAC;AACrD;AACJ;AACA;EACIC,WAAWA,CAACC,GAAG,EAAE;IACb,KAAK,CAACA,GAAG,CAAC;AACVA,IAAAA,GAAG,CAACC,aAAa,CAACC,SAAS,CAAC,CAAAD,aAAa,KAAI;MACzC,IAAIA,aAAa,IAAI,IAAI,EAAE;AACvB,QAAA;AACJ;MACA,IAAI;AACA,QAAA,MAAME,SAAS,GAAGC,OAAO,CAACC,MAAM,EAAE;AAClC,QAAA,IAAIC,oBAAoB,GAAGN,GAAG,CAACO,gBAAgB,EAAE,CAACC,WAAW,CAAC,sCAAsC,CAAC,IAAI;AACrGC,UAAAA,QAAQ,EAAE,EAAE;AACZC,UAAAA,KAAK,EAAE;SACV;QACD,IAAIJ,oBAAoB,CAACK,OAAO,EAAE;AAC9B;UACA,MAAMC,iBAAiB,GAAGZ,GAAG,CAACO,gBAAgB,EAAE,CAACM,oBAAoB,EAAE;UACvE,MAAMC,WAAW,GAAGC,IAAI,CAACC,OAAO,CAACJ,iBAAiB,EAAEN,oBAAoB,CAACK,OAAO,CAAC;AACjFM,UAAAA,iBAAU,CAACC,GAAG,CAAC,CAAqFJ,kFAAAA,EAAAA,WAAW,EAAE,CAAC;AAClHR,UAAAA,oBAAoB,GAAGa,OAAO,CAACL,WAAW,CAAC;AAC/C;AACA,QAAA,MAAMM,UAAU,GAAGd,oBAAoB,CAACI,KAAK,IAAI,EAAE;AACnD,QAAA,MAAMW,aAAa,GAAGf,oBAAoB,CAACG,QAAQ,IAAI,EAAE;AACzD;AACA,QAAA,MAAMC,KAAK,GAAG,IAAIY,GAAG,CAACF,UAAU,CAAC;AACjC,QAAA,MAAMX,QAAQ,GAAG,IAAIa,GAAG,CAACD,aAAa,CAAC;AACvC,QAAA,IAAIX,KAAK,CAACa,IAAI,KAAK,CAAC,EAAE;AAClBN,UAAAA,iBAAU,CAACO,IAAI,CAAC,4FAA4F,CAAC;AACjH;AACA;QACA,IAAIC,sBAAsB,GAAGzB,GAAG,CAACO,gBAAgB,EAAE,CAACC,WAAW,CAAC,+CAA+C,CAAC;AAChH,QAAA,IAAI,OAAOiB,sBAAsB,KAAK,SAAS,EAAE;AAC7CA,UAAAA,sBAAsB,GAAG,KAAK;AAClC;AACAf,QAAAA,KAAK,CAACgB,OAAO,CAAC,CAACC,KAAK,EAAEZ,IAAI,KAAK;AAC3B,UAAA,IAAIa,OAAO;AACX;UACA,IAAID,KAAK,CAACC,OAAO,EAAE;YACfA,OAAO,GAAGnB,QAAQ,CAACoB,GAAG,CAACF,KAAK,CAACC,OAAO,CAAC;AACzC,WAAC,MAAM;AACH;AACAA,YAAAA,OAAO,GAAGD,KAAK;AACnB;UACA,IAAIC,OAAO,IAAI,IAAI,EAAE;AACjB,YAAA,MAAME,gBAAgB,GAAGC,MAAM,CAACC,MAAM,CAAC;AACnCC,cAAAA,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI;cACvBC,KAAK,EAAE,EAAE;cACTC,aAAa,EAAE,IAAI;aACtB,EAAEP,OAAO,EAAE;cACRQ,YAAY,EAAEA,CAACC,GAAG,KAAK;AACnB,gBAAA,IAAIC,aAAa;AACjB,gBAAA,IAAIb,sBAAsB,EAAE;AACxB;AACAa,kBAAAA,aAAa,GAAGD,GAAG,CAACE,OAAO,CAAC,WAAW,CAAC,IAAIF,GAAG,CAACE,OAAO,CAAC,iBAAiB,CAAC,KAAKF,GAAG,CAACG,UAAU,GAAGH,GAAG,CAACG,UAAU,CAACF,aAAa,GAAGD,GAAG,CAACI,MAAM,CAACH,aAAa,CAAC;AAC5J,iBAAC,MAAM;AACH;AACAA,kBAAAA,aAAa,GAAID,GAAG,CAACG,UAAU,GAAGH,GAAG,CAACG,UAAU,CAACF,aAAa,GAAGD,GAAG,CAACI,MAAM,CAACH,aAAc;AAC9F;AACA,gBAAA,OAAO,CAAGvB,EAAAA,IAAI,CAAIuB,CAAAA,EAAAA,aAAa,CAAE,CAAA;AACrC;AACJ,aAAC,CAAC;AACF,YAAA,IAAI,OAAOR,gBAAgB,CAACY,KAAK,KAAK,QAAQ,EAAE;AAC5C;cACA,MAAMA,KAAK,GAAGZ,gBAAgB,CAACY,KAAK,CAACC,KAAK,CAAC,GAAG,CAAC;AAC/C,cAAA,IAAIC,UAAU;AACd,cAAA,IAAIF,KAAK,CAACG,MAAM,KAAK,CAAC,EAAE;gBACpB,MAAMC,WAAW,GAAG3B,OAAO,CAACuB,KAAK,CAAC,CAAC,CAAC,CAAC;AACrC,gBAAA,IAAIX,MAAM,CAACgB,SAAS,CAACC,cAAc,CAACC,IAAI,CAACH,WAAW,EAAEJ,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;AAC7DE,kBAAAA,UAAU,GAAGE,WAAW,CAACJ,KAAK,CAAC,CAAC,CAAC,CAAC;kBAClCZ,gBAAgB,CAACY,KAAK,GAAG,IAAIE,UAAU,CAAC,IAAI,EAAEd,gBAAgB,CAAC;AACnE,iBAAC,MAAM;AACH,kBAAA,MAAM,IAAIoB,KAAK,CAAC,CAAGR,EAAAA,KAAK,qCAAqC,CAAC;AAClE;AACJ,eAAC,MAAM;AACHE,gBAAAA,UAAU,GAAGzB,OAAO,CAACuB,KAAK,CAAC,CAAC,CAAC,CAAC;AAC9B;gBACAZ,gBAAgB,CAACY,KAAK,GAAG,IAAIE,UAAU,CAAC,IAAI,EAAEd,gBAAgB,CAAC;AACnE;AACJ;YACA3B,SAAS,CAACgD,GAAG,CAACpC,IAAI,EAAEqC,0BAAS,CAACtB,gBAAgB,CAAC,CAAC;AACpD;AACJ,SAAC,CAAC;AACF,QAAA,IAAI3B,SAAS,CAACkD,KAAK,CAACR,MAAM,EAAE;AACxB5C,UAAAA,aAAa,CAACoD,KAAK,CAACC,OAAO,CAACC,KAAK,CAACtD,aAAa,CAACoD,KAAK,EAAElD,SAAS,CAACkD,KAAK,CAAC;AAC3E;OACH,CAAC,OAAOG,GAAG,EAAE;AACVvC,QAAAA,iBAAU,CAACwC,KAAK,CAAC,8DAA8D,CAAC;AAChFxC,QAAAA,iBAAU,CAACwC,KAAK,CAACD,GAAG,CAAC;AACrBvC,QAAAA,iBAAU,CAACO,IAAI,CAAC,qFAAqF,CAAC;AAC1G;AACJ,KAAC,CAAC;AACN;;AAEJ;;AC/FO,MAAMkC,iBAAiB,SAAS5D,yBAAkB,CAAC;EACtDC,WAAWA,CAACC,GAAG,EAAE;IACb,KAAK,CAACA,GAAG,CAAC;;AAEVA,IAAAA,GAAG,CAACC,aAAa,CAACC,SAAS,CAAC,CAAAD,aAAa,KAAI;MACzC,IAAIA,aAAa,IAAI,IAAI,EAAE;AACvB,QAAA;AACJ;MACA,IAAI;AACA,QAAA,MAAME,SAAS,GAAGC,OAAO,CAACC,MAAM,EAAE;AAClC,QAAA,IAAIC,oBAAoB,GAAGN,GAAG,CAACO,gBAAgB,EAAE,CAACC,WAAW,CAAC,uCAAuC,CAAC,IAAI;AACtGC,UAAAA,QAAQ,EAAE,EAAE;AACZC,UAAAA,KAAK,EAAE;SACV;QACD,IAAIJ,oBAAoB,CAACK,OAAO,EAAE;AAC9B;UACA,MAAMC,iBAAiB,GAAGZ,GAAG,CAACO,gBAAgB,EAAE,CAACM,oBAAoB,EAAE;UACvE,MAAMC,WAAW,GAAGC,IAAI,CAACC,OAAO,CAACJ,iBAAiB,EAAEN,oBAAoB,CAACK,OAAO,CAAC;AACjFM,UAAAA,iBAAU,CAACC,GAAG,CAAC,CAAsFJ,mFAAAA,EAAAA,WAAW,EAAE,CAAC;AACnHR,UAAAA,oBAAoB,GAAGa,OAAO,CAACL,WAAW,CAAC;AAC/C;AACA,QAAA,MAAMM,UAAU,GAAGd,oBAAoB,CAACI,KAAK,IAAI,EAAE;AACnD,QAAA,MAAMW,aAAa,GAAGf,oBAAoB,CAACG,QAAQ,IAAI,EAAE;AACzD;AACA,QAAA,MAAMC,KAAK,GAAG,IAAIY,GAAG,CAACF,UAAU,CAAC;AACjC,QAAA,MAAMX,QAAQ,GAAG,IAAIa,GAAG,CAACD,aAAa,CAAC;AACvC,QAAA,IAAIX,KAAK,CAACa,IAAI,KAAK,CAAC,EAAE;AAClBN,UAAAA,iBAAU,CAACO,IAAI,CAAC,6FAA6F,CAAC;AAClH;AACA;QACA,IAAIC,sBAAsB,GAAGzB,GAAG,CAACO,gBAAgB,EAAE,CAACC,WAAW,CAAC,+CAA+C,CAAC;AAChH,QAAA,IAAI,OAAOiB,sBAAsB,KAAK,SAAS,EAAE;AAC7CA,UAAAA,sBAAsB,GAAG,KAAK;AAClC;AACAf,QAAAA,KAAK,CAACgB,OAAO,CAAC,CAACC,KAAK,EAAEZ,IAAI,KAAK;AAC3B,UAAA,IAAIa,OAAO;AACX;UACA,IAAID,KAAK,CAACC,OAAO,EAAE;YACfA,OAAO,GAAGnB,QAAQ,CAACoB,GAAG,CAACF,KAAK,CAACC,OAAO,CAAC;AACzC,WAAC,MAAM;AACH;AACAA,YAAAA,OAAO,GAAGD,KAAK;AACnB;UACA,IAAIC,OAAO,IAAI,IAAI,EAAE;AACjB,YAAA,MAAM+B,eAAe,GAAG5B,MAAM,CAACC,MAAM,CAAC;AAClCC,cAAAA,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI;cACvB2B,UAAU,EAAE,EAAE;cACdC,OAAO,EAAE,GAAG;cACZC,UAAU,EAAE,KAAK;aACpB,EAAElC,OAAO,EAAE;cACRQ,YAAY,EAAEA,CAACC,GAAG,KAAK;AACnB,gBAAA,IAAIC,aAAa;AACjB,gBAAA,IAAIb,sBAAsB,EAAE;AACxB;AACAa,kBAAAA,aAAa,GAAGD,GAAG,CAACE,OAAO,CAAC,WAAW,CAAC,IAAIF,GAAG,CAACE,OAAO,CAAC,iBAAiB,CAAC,KAAKF,GAAG,CAACG,UAAU,GAAGH,GAAG,CAACG,UAAU,CAACF,aAAa,GAAGD,GAAG,CAACI,MAAM,CAACH,aAAa,CAAC;AAC5J,iBAAC,MAAM;AACH;AACAA,kBAAAA,aAAa,GAAID,GAAG,CAACG,UAAU,GAAGH,GAAG,CAACG,UAAU,CAACF,aAAa,GAAGD,GAAG,CAACI,MAAM,CAACH,aAAc;AAC9F;AACA,gBAAA,OAAO,CAAGvB,EAAAA,IAAI,CAAIuB,CAAAA,EAAAA,aAAa,CAAE,CAAA;AACrC;AACJ,aAAC,CAAC;YACF,IAAIyB,KAAK,CAACC,OAAO,CAACL,eAAe,CAACM,aAAa,CAAC,EAAE;cAC9CN,eAAe,CAACE,OAAO,GAAG,MAAM;AAC5B,gBAAA,MAAMA,OAAO,GAAGK,IAAI,CAACC,KAAK,CAACD,IAAI,CAACE,MAAM,EAAE,IAAIT,eAAe,CAACM,aAAa,CAAC,CAAC,CAAC,GAAGN,eAAe,CAACM,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAGN,eAAe,CAACM,aAAa,CAAC,CAAC,CAAC,CAAC;AACxJ,gBAAA,OAAOJ,OAAO;eACjB;AACL;YACA,IAAIE,KAAK,CAACC,OAAO,CAACL,eAAe,CAACU,gBAAgB,CAAC,EAAE;cACjDV,eAAe,CAACG,UAAU,GAAG,MAAM;AAC/B,gBAAA,MAAMA,UAAU,GAAGI,IAAI,CAACC,KAAK,CAACD,IAAI,CAACE,MAAM,EAAE,IAAIT,eAAe,CAACU,gBAAgB,CAAC,CAAC,CAAC,GAAGV,eAAe,CAACU,gBAAgB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAGV,eAAe,CAACU,gBAAgB,CAAC,CAAC,CAAC,CAAC;AACpK,gBAAA,OAAOP,UAAU;eACpB;AACL;AACA,YAAA,IAAI,OAAOH,eAAe,CAACjB,KAAK,KAAK,QAAQ,EAAE;AAC3C;cACA,MAAMA,KAAK,GAAGiB,eAAe,CAACjB,KAAK,CAACC,KAAK,CAAC,GAAG,CAAC;AAC9C,cAAA,IAAIC,UAAU;AACd,cAAA,IAAIF,KAAK,CAACG,MAAM,KAAK,CAAC,EAAE;gBACpB,MAAMC,WAAW,GAAG3B,OAAO,CAACuB,KAAK,CAAC,CAAC,CAAC,CAAC;AACrC,gBAAA,IAAIX,MAAM,CAACgB,SAAS,CAACC,cAAc,CAACC,IAAI,CAACH,WAAW,EAAEJ,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;AAC7DE,kBAAAA,UAAU,GAAGE,WAAW,CAACJ,KAAK,CAAC,CAAC,CAAC,CAAC;kBAClCiB,eAAe,CAACjB,KAAK,GAAG,IAAIE,UAAU,CAAC,IAAI,EAAEe,eAAe,CAAC;AACjE,iBAAC,MAAM;AACH,kBAAA,MAAM,IAAIT,KAAK,CAAC,CAAGR,EAAAA,KAAK,qCAAqC,CAAC;AAClE;AACJ,eAAC,MAAM;AACHE,gBAAAA,UAAU,GAAGzB,OAAO,CAACuB,KAAK,CAAC,CAAC,CAAC,CAAC;AAC9B;gBACAiB,eAAe,CAACjB,KAAK,GAAG,IAAIE,UAAU,CAAC,IAAI,EAAEe,eAAe,CAAC;AACjE;AACJ;YACAxD,SAAS,CAACgD,GAAG,CAACpC,IAAI,EAAEuD,QAAQ,CAACX,eAAe,CAAC,CAAC;AAClD;AACJ,SAAC,CAAC;AACF,QAAA,IAAIxD,SAAS,CAACkD,KAAK,CAACR,MAAM,EAAE;AACxB5C,UAAAA,aAAa,CAACoD,KAAK,CAACC,OAAO,CAACC,KAAK,CAACtD,aAAa,CAACoD,KAAK,EAAElD,SAAS,CAACkD,KAAK,CAAC;AAC3E;OACH,CAAC,OAAOG,GAAG,EAAE;AACVvC,QAAAA,iBAAU,CAACwC,KAAK,CAAC,+DAA+D,CAAC;AACjFxC,QAAAA,iBAAU,CAACwC,KAAK,CAACD,GAAG,CAAC;AACrBvC,QAAAA,iBAAU,CAACO,IAAI,CAAC,sFAAsF,CAAC;AAC3G;AACJ,KAAC,CAAC;AACN;;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;AC1GA,IAAI+C,wBAAwB;AAC5B,IAAIC,kBAAkB;;AAEtB,SAASC,eAAeA,GAAG;;AACvB;AAAA;AAGJ,SAASC,qBAAqBA,GAAG;;AAC7B;AAAA;AAGJ,IAAIC,yBAAU,CAAC5B,SAAS,CAAC6B,mBAAmB,CAACC,IAAI,KAAK,qBAAqB,EAAE;AACzE;AACAN,EAAAA,wBAAwB,GAAGI,yBAAU,CAAC5B,SAAS,CAAC6B,mBAAmB;AACnED,EAAAA,yBAAU,CAAC5B,SAAS,CAAC6B,mBAAmB,GAAGF,qBAAqB;AACpE;;AAEA,IAAIC,yBAAU,CAAC5B,SAAS,CAAC+B,aAAa,CAACD,IAAI,KAAK,eAAe,EAAE;AAC7D;AACAL,EAAAA,kBAAkB,GAAGG,yBAAU,CAAC5B,SAAS,CAAC+B,aAAa;AACvDH,EAAAA,yBAAU,CAAC5B,SAAS,CAAC+B,aAAa,GAAGL,eAAe;AACxD;;AAEA,MAAMM,gBAAgB,SAASJ,yBAAU,CAAC;;;;;;;AAOtC;AACJ;AACA;AACA;AACA;AACI5E,EAAAA,WAAWA,CAACiF,OAAO,EAAEC,OAAO,EAAE;AAC1B,IAAA,KAAK,CAAC;AACF;AACZ;AACA;AACA;MACYC,WAAW,EAAE,YAAY;AACrB,QAAA,MAAMC,IAAI,GAAGpB,KAAK,CAACqB,IAAI,CAACC,SAAS,CAAC;QAClC,MAAM,CAACC,OAAO,CAAC,GAAGH,IAAI,CAACI,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;QACnC,MAAMC,IAAI,GAAG,IAAI;QACjB,IAAIF,OAAO,KAAK,QAAQ,EAAE;AACtB,UAAA,MAAMG,cAAc,GAAGT,OAAO,CAACU,cAAc,EAAE,CAACnF,gBAAgB,EAAE,CAACC,WAAW,CAAC,wBAAwB,CAAC,IAAI;AACxGmF,YAAAA,IAAI,EAAE,WAAW;AACjBC,YAAAA,IAAI,EAAE;WACT;AACD,UAAA,MAAMC,MAAM,GAAG,IAAIC,aAAK,CAACL,cAAc,CAAC;AACxC,UAAA,OAAOI,MAAM,CAAC5C,IAAI,CAACqC,OAAO,EAAEH,IAAI,CAAC,CAACY,KAAK,CAAC,CAACtC,KAAK,KAAK;YAC/C,IAAIA,KAAK,YAAYuC,SAAS,IAAIvC,KAAK,CAACwC,OAAO,KAAK,uBAAuB,EAAE;cACzEhF,iBAAU,CAACO,IAAI,CAAC,2CAA2C,GAAG0E,IAAI,CAACC,SAAS,CAAChB,IAAI,CAAC,CAAC;AACvF;AACA,YAAA,OAAOiB,OAAO,CAACC,MAAM,CAAC5C,KAAK,CAAC;AAChC,WAAC,CAAC,CAAC6C,OAAO,CAAC,MAAM;YACb,IAAIT,MAAM,CAACU,MAAM,EAAE;cACfV,MAAM,CAACW,UAAU,EAAE,CAACT,KAAK,CAAC,CAACU,aAAa,KAAK;AACzCxF,gBAAAA,iBAAU,CAACwC,KAAK,CAACgD,aAAa,CAAC;AACnC,eAAC,CAAC;AACN;AACJ,WAAC,CAAC;AACN;AACA,QAAA,IAAIjB,IAAI,CAACK,MAAM,IAAI,IAAI,EAAE;AACrB,UAAA,MAAMJ,cAAc,GAAGT,OAAO,CAACU,cAAc,EAAE,CAACnF,gBAAgB,EAAE,CAACC,WAAW,CAAC,wBAAwB,CAAC,IAAI;AACxGmF,YAAAA,IAAI,EAAE,WAAW;AACjBC,YAAAA,IAAI,EAAE;WACT;AACDJ,UAAAA,IAAI,CAACK,MAAM,GAAG,IAAIC,aAAK,CAACL,cAAc,CAAC;AAC3C;AACA,QAAA,IAAID,IAAI,CAACK,MAAM,CAACU,MAAM,EAAE;AACpB,UAAA,OAAOf,IAAI,CAACK,MAAM,CAAC5C,IAAI,CAACqC,OAAO,EAAEH,IAAI,CAAC,CAACY,KAAK,CAAC,CAACtC,KAAK,KAAK;YACpD,IAAIA,KAAK,YAAYuC,SAAS,IAAIvC,KAAK,CAACwC,OAAO,KAAK,uBAAuB,EAAE;cACzEhF,iBAAU,CAACO,IAAI,CAAC,2CAA2C,GAAG0E,IAAI,CAACC,SAAS,CAAChB,IAAI,CAAC,CAAC;AACvF;AACA,YAAA,OAAOiB,OAAO,CAACC,MAAM,CAAC5C,KAAK,CAAC;AAChC,WAAC,CAAC;AACN;AACA;AACA,QAAA,OAAO,CAAC,MAAM;AACV,UAAA,IAAI+B,IAAI,CAACkB,kBAAkB,IAAI,IAAI,EAAE;AACjC,YAAA,OAAO,IAAI,CAACC,QAAQ,EAAE;AAC1B;AACA,UAAA,OAAOP,OAAO,CAACpF,OAAO,EAAE;AAC5B,SAAC,GAAG,CAAC4F,IAAI,CAAC,MAAM;AACZ;AACAzB,UAAAA,IAAI,CAAC,CAAC,CAAC,GAAGK,IAAI,CAACkB,kBAAkB;AACjC,UAAA,OAAOlB,IAAI,CAACK,MAAM,CAAC5C,IAAI,CAACqC,OAAO,EAAEH,IAAI,CAAC,CAACY,KAAK,CAAC,CAACtC,KAAK,KAAK;YACpD,IAAIA,KAAK,YAAYuC,SAAS,IAAIvC,KAAK,CAACwC,OAAO,KAAK,uBAAuB,EAAE;cACzEhF,iBAAU,CAACO,IAAI,CAAC,2CAA2C,GAAG0E,IAAI,CAACC,SAAS,CAAChB,IAAI,CAAC,CAAC;AACvF;AACA,YAAA,OAAOiB,OAAO,CAACC,MAAM,CAAC5C,KAAK,CAAC;AAChC,WAAC,CAAC;AACN,SAAC,CAAC;AACN;KACH,CAAC,CAAC;AAtEX;AACA,OAFIoD,eAAA,CAAA,IAAA,EAAA,QAAA,EAAA,MAAA,CAAA,CAwEI,IAAI,CAACC,IAAI,CAAC7B,OAAO,CAAC,CAClBhE,iBAAU,CAAC8F,KAAK,CAAC,sEAAsE,CAAC;IACxF,KAAK,IAAI,CAACJ,QAAQ,EAAE,CAACC,IAAI,CAAC,MAAM;AAC5B3F,MAAAA,iBAAU,CAAC8F,KAAK,CAAC,kEAAkE,CAAC;AACxF,KAAC,CAAC,CAAChB,KAAK,CAAC,CAACvC,GAAG,KAAK;AACdvC,MAAAA,iBAAU,CAACwC,KAAK,CAAC,6DAA6D,CAAC;AAC/ExC,MAAAA,iBAAU,CAACwC,KAAK,CAACD,GAAG,CAAC;AACzB,KAAC,CAAC;AACN;EACA,MAAMmD,QAAQA,GAAG;IACb,MAAM,CAACD,kBAAkB,EAAEM,YAAY,CAAC,GAAG,MAAMZ,OAAO,CAACa,QAAQ,CAAC;AAC9D,IAAA,MAAM1C,wBAAwB,CAACtB,IAAI,CAAC,IAAI,CAAC;AACzC,IAAA,MAAMuB,kBAAkB,CAACvB,IAAI,CAAC,IAAI,CAAC;KACrC;IACF,IAAI,CAACyD,kBAAkB,GAAGA,kBAAkB;IAC5C,IAAI,CAACM,YAAY,GAAGA,YAAY;AACpC;;AAEJ;;ACnHA,MAAME,kBAAkB,GAAG,gCAAgC;;AAE3D,MAAMC,WAAW,CAAC;EACdpH,WAAWA,CAACqH,GAAG,EAAE;IACb,IAAI,CAACzF,KAAK,GAAGyF,GAAG;AACpB;AACAC,EAAAA,QAAQA,GAAG;IACP,OAAO,IAAI,CAAC1F,KAAK;AACrB;AACA;AACJ;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACIgB,EAAAA,KAAKA,GAAG;AACJ;AACA;IACA,MAAM2E,EAAE,GAAG,uCAAuC;IAClD,MAAMC,OAAO,GAAG,EAAE;IAClB,IAAIC,KAAK,GAAGF,EAAE,CAACG,IAAI,CAAC,IAAI,CAAC9F,KAAK,CAAC;IAC/B,OAAM6F,KAAK,KAAK,IAAI,EAAE;AAClBD,MAAAA,OAAO,CAACG,IAAI,CAACF,KAAK,CAAC,CAAC,CAAC,CAAC;MACtBA,KAAK,GAAGF,EAAE,CAACG,IAAI,CAAC,IAAI,CAAC9F,KAAK,CAAC;AAC/B;AACA,IAAA,OAAO4F,OAAO;AAClB;AACJ;;AAEA,MAAMI,wBAAwB,SAASC,4BAAqB,CAAC;AACzD;AACJ;AACA;EACI7H,WAAWA,CAAC8H,aAAa,EAAE;IACvB,KAAK,CAACA,aAAa,CAAC;IACpB,IAAIC,QAAQ,GAAG,EAAE;AACjB;AACA/F,IAAAA,MAAM,CAACgG,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE;MACpClG,GAAG,EAAEA,MAAM;AACP,QAAA,OAAOiG,QAAQ;OAClB;AACDE,MAAAA,UAAU,EAAE;AAChB,KAAC,CAAC;AACN;;AAEA;AACJ;AACA;AACA;EACIC,MAAMA,CAAC5F,GAAG,EAAE;AACR,IAAA,OAAO,IAAI+D,OAAO,CAAC,CAACpF,OAAO,EAAEqF,MAAM,KAAK;MACpC,IAAI;AACA;QACA6B,WAAI,CAACC,OAAO,CAAC9F,GAAG,CAAC+F,OAAO,EAAC,SAAS,CAAC;AACnC;QACAF,WAAI,CAACC,OAAO,CAAC9F,GAAG,CAAC+F,OAAO,CAACC,IAAI,EAAC,MAAM,CAAC;AACrC,QAAA,IAAIhG,GAAG,CAAC+F,OAAO,CAACC,IAAI,CAACC,mBAAmB,IAAIjG,GAAG,CAAC+F,OAAO,CAACC,IAAI,CAACC,mBAAmB,CAACzF,MAAM,GAAC,CAAC,EAAE;AACvF;UACA,IAAI0F,MAAM,GAAGC,GAAG,CAACC,KAAK,CAACpG,GAAG,CAACqG,WAAW,CAAC,CAACC,QAAQ;AAChD;AACA,UAAA,IAAIC,SAAS,GAAG,IAAIzB,WAAW,CAAC9E,GAAG,CAAC+F,OAAO,CAACC,IAAI,CAACC,mBAAmB,CAAC,CAAC3F,KAAK,EAAE;AAC7E;AACA,UAAA,IAAIkG,SAAS,GAAG3B,kBAAkB,CAAC4B,IAAI,CAACzG,GAAG,CAAC0G,MAAM,CAAC,GAAG,OAAO,GAAG,MAAM;AACtE;UACA,IAAIC,MAAM,GAAG,IAAI,CAAClB,QAAQ,CAACmB,IAAI,CAAC,CAAAC,CAAC,KAAI;AACjC;AACA,YAAA,OAAO,IAAIC,MAAM,CAAE,GAAG,GAAGD,CAAC,CAACE,QAAQ,EAAE,GAAG,CAAC,CAACN,IAAI,CAACP,MAAM;AACjD;eACGW,CAAC,CAACG,KAAK,CAACJ,IAAI,CAAC,CAAAK,CAAC,KAAI;AACjB;cACA,OAAOA,CAAC,KAAK,GAAG,IAAIV,SAAS,CAACW,OAAO,CAACD,CAAC,CAAC,IAAE,CAAC;AAC/C,aAAC,CAAC;AACV,WAAC,CAAC;AACF;UACA,IAAIN,MAAM,IAAI,IAAI,EAAE;YAChB,OAAOhI,OAAO,EAAE;AACpB;AACA;UACA,IAAI+C,KAAK,CAACC,OAAO,CAACgF,MAAM,CAACQ,MAAM,CAAC,KAAK,KAAK,EAAE;AACxC;YACA,OAAOxI,OAAO,EAAE;AACpB;AACA;UACA,IAAIgI,MAAM,CAACQ,MAAM,CAACD,OAAO,CAACV,SAAS,CAAC,GAAG,CAAC,EAAE;AACtC;YACA,OAAO7H,OAAO,EAAE;AACpB;AACA;UACA,OAAOA,OAAO,CAACgI,MAAM,CAAC;AAC1B;QACA,OAAOhI,OAAO,EAAE;AACpB;AACA,MAAA,OAAMwC,GAAG,EAAE;QACP,OAAO6C,MAAM,CAAC7C,GAAG,CAAC;AACtB;;AAEJ,KAAC,CAAC;AACN;;AAEJ;;AAEA;AACA;AACA;AACA,MAAMiG,+BAA+B,SAAS9B,wBAAwB,CAAC;AACnE;AACJ;AACA;EACI5H,WAAWA,CAAC8H,aAAa,EAAE;IACxB,KAAK,CAACA,aAAa,CAAC;IACnB,IAAI6B,QAAQ,GAAG,EAAE;AAClB;IACC,IAAI;AACA;AACZ;AACA;AACYA,MAAAA,QAAQ,GAAGvI,OAAO,CAACJ,IAAI,CAACC,OAAO,CAAC6G,aAAa,CAAChH,oBAAoB,EAAE,EAAE,mBAAmB,CAAC,CAAC;AAC/F;AACA,IAAA,OAAM2C,GAAG,EAAE;AACP;AACA,MAAA,IAAIA,GAAG,CAACmG,IAAI,KAAK,kBAAkB,EAAE;AACjC;AACA,QAAA,MAAMnG,GAAG;AACb;AACA;AACJ;AACA,IAAA,IAAI,CAACsE,QAAQ,CAACJ,IAAI,CAACnE,KAAK,CAAC,IAAI,CAACuE,QAAQ,EAAE4B,QAAQ,CAAC;AACrD;AACJ;;AAEA,MAAME,8BAA8B,SAAS9J,yBAAkB,CAAC;AAC5D;AACJ;AACA;EACIC,WAAWA,CAACC,GAAG,EAAE;IACb,KAAK,CAACA,GAAG,CAAC;AACV;IACAA,GAAG,CAACO,gBAAgB,EAAE,CAACsJ,WAAW,CAAClC,wBAAwB,EAAE8B,+BAA+B,CAAC;AACjG;AACJ;;;AAGA;AACA;AACA;AACA,MAAMK,8BAA8B,SAAShK,yBAAkB,CAAC;AAC5D;AACJ;AACA;EACIC,WAAWA,CAACC,GAAG,EAAE;IACb,KAAK,CAACA,GAAG,CAAC;AACV;AACA,IAAA,MAAM+J,qBAAqB,GAAG/J,GAAG,CAACO,gBAAgB,EAAE,CAACyJ,QAAQ,CAACC,SAAS,EAAEC,OAAO,EAAEC,WAAW,CAACC,OAAO;IACrG,IAAIpK,GAAG,IAAIA,GAAG,CAACqK,SAAS,IAAIN,qBAAqB,IAAI,IAAI,EAAE;AACvD/J,MAAAA,GAAG,CAACqK,SAAS,CAACnK,SAAS,CAAC,CAACmK,SAAS,KAAK;AACnC,QAAA,IAAIA,SAAS,EAAE;AACX,UAAA,MAAMF,WAAW,GAAGnK,GAAG,CAACO,gBAAgB,EAAE,CAAC+J,WAAW,CAAC,SAAS3C,wBAAwBA,GAAG,EAAG,CAAC;UAC/F,IAAIwC,WAAW,IAAI,IAAI,EAAE;AACrB,YAAA,KAAK,MAAMI,oBAAoB,IAAIR,qBAAqB,EAAE;cACtD,IAAI;gBACA,MAAMjC,QAAQ,GAAG3G,OAAO,CAACJ,IAAI,CAACC,OAAO,CAAChB,GAAG,CAACO,gBAAgB,EAAE,CAACM,oBAAoB,EAAE,EAAE0J,oBAAoB,CAAC,CAAC;AAC3G,gBAAA,IAAIzC,QAAQ,EAAE;AACV;AACAqC,kBAAAA,WAAW,CAACrC,QAAQ,CAACxE,OAAO,CAAC,GAAGwE,QAAQ,CAAC;AAC7C;AACJ;AACA,cAAA,OAAMtE,GAAG,EAAE;AACP;AACA,gBAAA,IAAIA,GAAG,CAACmG,IAAI,KAAK,kBAAkB,EAAE;AACjC;AACA,kBAAA,MAAMnG,GAAG;AACb;AACJ;AACJ;AACJ;AACJ;AACJ,OAAC,CAAC;AACN;AACJ;AACJ;;ACxLA,SAASgH,aAAaA,GAAG;AACrB,EAAA,OAAO,CAACnI,GAAG,EAAEoI,GAAG,EAAEC,IAAI,KAAK;AACvB;AACR;AACA;AACQ,IAAA,IAAIC,wBAAwB,GAAGtI,GAAG,CAAC+F,OAAO,CAAC1C,cAAc,EAAE,CAACnF,gBAAgB,EAAE,CAAC+J,WAAW,CAAC3C,wBAAwB,CAAC;AACpH,IAAA,IAAI,OAAOgD,wBAAwB,KAAK,WAAW,EAAE;AACjD,MAAA,OAAOD,IAAI,CAAC,IAAIxH,KAAK,CAAC,wGAAwG,CAAC,CAAC;AACpI;IACAyH,wBAAwB,CAAC1C,MAAM,CAAC5F,GAAG,CAAC,CAACuE,IAAI,CAAC,CAAAjF,KAAK,KAAI;AAC/C,MAAA,IAAIA,KAAK,EAAE;QACP,OAAO+I,IAAI,EAAE;AACjB;AACA,MAAA,OAAOA,IAAI,CAAC,IAAIE,yBAAkB,CAAC,4CAA4C,CAAC,CAAC;AACrF,KAAC,CAAC,CAAC7E,KAAK,CAAC,CAAA8E,MAAM,KAAI;MACf,OAAOH,IAAI,CAACG,MAAM,CAAC;AACvB,KAAC,CAAC;GACL;AACL;;ACjBA,SAASC,cAAcA,CAAC9J,OAAO,EAAEqF,MAAM,EAAE;AACrC,EAAA,OAAO,UAAU7C,GAAG,EAAEuH,QAAQ,EAAE;AAC5B,IAAA,IAAIvH,GAAG,EAAE;AACL;AACZ;AACA;AACY,MAAA,MAAMuH,QAAQ,GAAGvH,GAAG,CAACuH,QAAQ;MAC7B,IAAIA,QAAQ,IAAIA,QAAQ,CAACxI,OAAO,CAAC,cAAc,CAAC,KAAK,kBAAkB,EAAE;AACrE;AACA,QAAA,MAAMyI,WAAW,GAAGD,QAAQ,CAACE,IAAI;QACjC,MAAMxH,KAAK,GAAG,IAAIyH,gBAAS,CAACH,QAAQ,CAACI,MAAM,CAAC;AAC5C,QAAA,OAAO9E,MAAM,CAACtE,MAAM,CAACC,MAAM,CAACyB,KAAK,EAAE;AAC/BuH,UAAAA;AACJ,SAAC,CAAC,CAAC;AACP;MACA,OAAO3E,MAAM,CAAC7C,GAAG,CAAC;AACtB;AACA,IAAA,IAAIuH,QAAQ,CAACI,MAAM,KAAK,GAAG,IAAIJ,QAAQ,CAACxI,OAAO,CAAC,cAAc,CAAC,KAAK,kBAAkB,EAAE;MACpF,OAAOvB,OAAO,CAAC,IAAI,CAAC;AACxB;AACA,IAAA,OAAOA,OAAO,CAAC+J,QAAQ,CAACE,IAAI,CAAC;GAChC;AACL;;AAEA;AACA;AACA;AACA,MAAMG,mBAAmB,SAAStL,yBAAkB,CAAC;AACjD;AACJ;AACA;EACIC,WAAWA,CAACC,GAAG,EAAE;IACb,KAAK,CAACA,GAAG,CAAC;AACV;AACR;AACA;AACA;AACS+B,IAAAA,MAAM,CAACgG,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE;AACrCsD,MAAAA,QAAQ,EAAE,KAAK;MACf1J,KAAK,EAAE3B,GAAG,CAACO,gBAAgB,EAAE,CAACC,WAAW,CAAC,eAAe,CAAC;AAC1DwH,MAAAA,UAAU,EAAE,KAAK;AACjBsD,MAAAA,YAAY,EAAE;AAClB,KAAC,CAAC;AACN;;AAEA;AACJ;AACA;AACA;AACKC,EAAAA,SAASA,GAAG;AACT,IAAA,OAAO,IAAI,CAACvB,QAAQ,CAACwB,UAAU;AACnC;;AAEA;AACJ;AACA;AACA;AACKC,EAAAA,YAAYA,GAAG;AACZ,IAAA,OAAO,IAAI,CAACzB,QAAQ,CAAC0B,SAAS;AAClC;;AAEA;AACA;AACJ;AACA;AACA;AACA;EACIC,WAAWA,CAACC,KAAK,EAAE;AACf,IAAA,OAAO,IAAIxF,OAAO,CAAC,CAACpF,OAAO,EAAEqF,MAAM,KAAK;AACpC,MAAA,MAAMwF,YAAY,GAAG,IAAI,CAAC7B,QAAQ,CAAC6B,YAAY,GAAG,IAAIC,OAAG,CAAC,IAAI,CAAC9B,QAAQ,CAAC6B,YAAY,EAAE,IAAI,CAACN,SAAS,EAAE,CAAC,GAAG,IAAIO,OAAG,CAAC,IAAI,EAAE,IAAI,CAACP,SAAS,EAAE,CAAC;AACzI,MAAA,OAAO,IAAIQ,kBAAO,CAAC,KAAK,EAAEF,YAAY,CAAC;AAClCG,MAAAA,GAAG,CAAC;QACD,eAAe,EAAE,CAAUJ,OAAAA,EAAAA,KAAK,CAAE,CAAA;AAClC,QAAA,QAAQ,EAAE;AACd,OAAC,CAAC;AACDK,MAAAA,KAAK,CAAC;AACH,QAAA,cAAc,EAACL;OAClB,CAAC,CAACM,GAAG,CAACpB,cAAc,CAAC9J,OAAO,EAAEqF,MAAM,CAAC,CAAC;AAC/C,KAAC,CAAC;AACN;;AAEA;AACA;AACJ;AACA;AACA;EACI8F,mBAAmBA,CAAC/D,OAAO,EAAE;AACzB,IAAA,IAAIA,OAAO,CAACC,IAAI,IAAI,IAAI,EAAE;MACtB,OAAOjC,OAAO,CAACC,MAAM,CAAC,IAAInD,KAAK,CAAC,8BAA8B,CAAC,CAAC;AACpE;AACA,IAAA,IAAIkF,OAAO,CAACC,IAAI,CAAC+D,kBAAkB,KAAK,QAAQ,EAAE;MAC9C,OAAOhG,OAAO,CAACC,MAAM,CAAC,IAAInD,KAAK,CAAC,qCAAqC,CAAC,CAAC;AAC3E;AACA,IAAA,IAAIkF,OAAO,CAACC,IAAI,CAACgE,mBAAmB,IAAI,IAAI,EAAE;MAC1C,OAAOjG,OAAO,CAACC,MAAM,CAAC,IAAInD,KAAK,CAAC,6CAA6C,CAAC,CAAC;AACnF;IACA,OAAO,IAAI,CAACoJ,YAAY,CAAClE,OAAO,EAAEA,OAAO,CAACC,IAAI,CAACgE,mBAAmB,CAAC;AACvE;AACA;AACJ;AACA;AACA;AACA;AACIC,EAAAA,YAAYA,CAACC,QAAQ,EAAEX,KAAK,EAAE;AAC1B,IAAA,OAAO,IAAIxF,OAAO,CAAC,CAACpF,OAAO,EAAEqF,MAAM,KAAK;AACpC,MAAA,MAAMmG,iBAAiB,GAAG,IAAI,CAACxC,QAAQ,CAACwC,iBAAiB,GAAG,IAAIV,OAAG,CAAC,IAAI,CAAC9B,QAAQ,CAACwC,iBAAiB,EAAE,IAAI,CAACjB,SAAS,EAAE,CAAC,GAAG,IAAIO,OAAG,CAAC,WAAW,EAAE,IAAI,CAACP,SAAS,EAAE,CAAC;AAC/J,MAAA,OAAO,IAAIQ,kBAAO,CAAC,MAAM,EAAES,iBAAiB,CAAC;AACxCC,MAAAA,IAAI,CAAC,IAAI,CAACzC,QAAQ,CAAC0C,SAAS,EAAE,IAAI,CAAC1C,QAAQ,CAAC2C,aAAa,CAAC;AAC1DX,MAAAA,GAAG,CAAC,QAAQ,EAAE,kBAAkB,CAAC;MACjCY,IAAI,CAAC,MAAM,CAAC;AACZC,MAAAA,IAAI,CAAC;AACF,QAAA,iBAAiB,EAAE,cAAc;AACjC,QAAA,OAAO,EAAEjB;OACZ,CAAC,CAACM,GAAG,CAACpB,cAAc,CAAC9J,OAAO,EAAEqF,MAAM,CAAC,CAAC;AAC/C,KAAC,CAAC;AACN;;AAEA;AACJ;AACA;EACKyG,SAASA,CAACC,aAAa,EAAE;AACtB,IAAA,MAAMC,QAAQ,GAAG,IAAI,CAAChD,QAAQ,CAACiD,SAAS,GAAG,IAAInB,OAAG,CAAC,IAAI,CAAC9B,QAAQ,CAACiD,SAAS,CAAC,GAAG,IAAInB,OAAG,CAAC,WAAW,EAAE,IAAI,CAACP,SAAS,EAAE,CAAC;AACpH,IAAA,OAAO,IAAInF,OAAO,CAAC,CAACpF,OAAO,EAAEqF,MAAM,KAAI;AACnC,MAAA,OAAO,IAAI0F,kBAAO,CAAC,MAAM,EAAEiB,QAAQ,CAAC;MAC/BJ,IAAI,CAAC,MAAM,CAAC;AACZC,MAAAA,IAAI,CAACE,aAAa,CAAC,CAACb,GAAG,CAACpB,cAAc,CAAC9J,OAAO,EAAEqF,MAAM,CAAC,CAAC;AACjE,KAAC,CAAC;AACN;;AAEA;AACJ;AACA;AACA;AACA;AACK6G,EAAAA,WAAWA,CAACC,OAAO,EAAElI,OAAO,EAAE;AAC3B,IAAA,OAAO,IAAImB,OAAO,CAAC,CAACpF,OAAO,EAAEqF,MAAM,KAAK;AACpC,MAAA,OAAO,IAAI0F,kBAAO,CAAC,KAAK,EAAE,IAAID,OAAG,CAAC,CAAA,MAAA,EAASqB,OAAO,CAAA,CAAE,EAAE,IAAI,CAAC1B,YAAY,EAAE,CAAC,CAAC;MACtEO,GAAG,CAAC,eAAe,EAAE,CAAA,OAAA,EAAU/G,OAAO,CAACmI,YAAY,EAAE,CAAC;AACtDlB,MAAAA,GAAG,CAACpB,cAAc,CAAC9J,OAAO,EAAEqF,MAAM,CAAC,CAAC;AAC7C,KAAC,CAAC;AACN;;AAEA;AACJ;AACA;AACA;AACA;AACIgH,EAAAA,OAAOA,CAACC,QAAQ,EAAErI,OAAO,EAAE;AACvB,IAAA,OAAO,IAAImB,OAAO,CAAC,CAACpF,OAAO,EAAEqF,MAAM,KAAI;AACnC,MAAA,OAAO,IAAI0F,kBAAO,CAAC,KAAK,EAAE,IAAID,OAAG,CAAC,OAAO,EAAE,IAAI,CAACL,YAAY,EAAE,CAAC,CAAC;MAC3DO,GAAG,CAAC,eAAe,EAAE,CAAA,OAAA,EAAU/G,OAAO,CAACmI,YAAY,EAAE,CAAC;AACtDnB,MAAAA,KAAK,CAAC;QACH,SAAS,EAAE,YAAYqB,QAAQ,CAAA,CAAA;AACnC,OAAC,CAAC;AACDpB,MAAAA,GAAG,CAACpB,cAAc,CAAC9J,OAAO,EAAEqF,MAAM,CAAC,CAAC;AAC7C,KAAC,CAAC;AACN;;AAEA;AACJ;AACA;AACA;AACA;AACKkH,EAAAA,cAAcA,CAACC,KAAK,EAAEvI,OAAO,EAAE;AAC5B,IAAA,OAAO,IAAImB,OAAO,CAAC,CAACpF,OAAO,EAAEqF,MAAM,KAAI;AACnC,MAAA,OAAO,IAAI0F,kBAAO,CAAC,KAAK,EAAE,IAAID,OAAG,CAAC,OAAO,EAAE,IAAI,CAACL,YAAY,EAAE,CAAC,CAAC;MAC3DO,GAAG,CAAC,eAAe,EAAE,CAAA,OAAA,EAAU/G,OAAO,CAACmI,YAAY,EAAE,CAAC;AACtDnB,MAAAA,KAAK,CAAC;QACH,SAAS,EAAE,qBAAqBuB,KAAK,CAAA,CAAA;AACzC,OAAC,CAAC;AACDtB,MAAAA,GAAG,CAACpB,cAAc,CAAC9J,OAAO,EAAEqF,MAAM,CAAC,CAAC;AAC7C,KAAC,CAAC;AACN;;AAEA;AACJ;AACA;AACA;AACA;AACKoH,EAAAA,UAAUA,CAACpF,IAAI,EAAEpD,OAAO,EAAE;AACvB,IAAA,OAAO,IAAImB,OAAO,CAAC,CAACpF,OAAO,EAAEqF,MAAM,KAAI;AACnC,MAAA,IAAIgC,IAAI,CAACqF,EAAE,IAAI,IAAI,EAAE;AACjB,QAAA,OAAOrH,MAAM,CAAC,IAAIsH,gBAAS,CAAC,cAAc,EAAE,wCAAwC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;AAC9G;MACA,MAAMC,OAAO,GAAG,IAAI7B,kBAAO,CAAC,KAAK,EAAE,IAAID,OAAG,CAAC,CAAA,MAAA,EAASzD,IAAI,CAACqF,EAAE,EAAE,EAAE,IAAI,CAACjC,YAAY,EAAE,CAAC,CAAC;MACpF,OAAOmC,OAAO,CAAC5B,GAAG,CAAC,eAAe,EAAE,CAAA,OAAA,EAAU/G,OAAO,CAACmI,YAAY,CAAA,CAAE,CAAC;AAChEpB,MAAAA,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC;MACvCa,IAAI,CAACxE,IAAI,CAAC;AACV6D,MAAAA,GAAG,CAACpB,cAAc,CAAC9J,OAAO,EAAEqF,MAAM,CAAC,CAAC;AAC7C,KAAC,CAAC;AACN;;AAEA;AACJ;AACA;AACA;AACA;AACKwH,EAAAA,UAAUA,CAACxF,IAAI,EAAEpD,OAAO,EAAE;AACvB,IAAA,OAAO,IAAImB,OAAO,CAAC,CAACpF,OAAO,EAAEqF,MAAM,KAAI;AACnC,MAAA,MAAMuH,OAAO,GAAG,IAAI7B,kBAAO,CAAC,MAAM,EAAE,IAAID,OAAG,CAAC,OAAO,EAAE,IAAI,CAACL,YAAY,EAAE,CAAC,CAAC;MAC1E,OAAOmC,OAAO,CAAC5B,GAAG,CAAC,eAAe,EAAE,CAAA,OAAA,EAAU/G,OAAO,CAACmI,YAAY,CAAA,CAAE,CAAC;AAChEpB,MAAAA,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC;MACvCa,IAAI,CAAC9K,MAAM,CAACC,MAAM,CAAC,EAAE,EAAEqG,IAAI,EAAE;QAC1ByF,MAAM,EAAE,CAAC;AACb,OAAC,CAAC,CAAC;AACF5B,MAAAA,GAAG,CAACpB,cAAc,CAAC9J,OAAO,EAAEqF,MAAM,CAAC,CAAC;AAC7C,KAAC,CAAC;AACN;;AAEA;AACJ;AACA;AACA;AACA;AACK0H,EAAAA,UAAUA,CAAC1F,IAAI,EAAEpD,OAAO,EAAE;AACvB,IAAA,OAAO,IAAImB,OAAO,CAAC,CAACpF,OAAO,EAAEqF,MAAM,KAAI;AACnC,MAAA,IAAIgC,IAAI,CAACqF,EAAE,IAAI,IAAI,EAAE;AACjB,QAAA,OAAOrH,MAAM,CAAC,IAAIsH,gBAAS,CAAC,cAAc,EAAE,wCAAwC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;AAC9G;MACA,MAAMC,OAAO,GAAG,IAAI7B,kBAAO,CAAC,QAAQ,EAAE,IAAID,OAAG,CAAC,CAAA,MAAA,EAASzD,IAAI,CAACqF,EAAE,EAAE,EAAE,IAAI,CAACjC,YAAY,EAAE,CAAC,CAAC;MACvF,OAAOmC,OAAO,CAAC5B,GAAG,CAAC,eAAe,EAAE,CAAA,OAAA,EAAU/G,OAAO,CAACmI,YAAY,CAAA,CAAE,CAAC;AAChElB,MAAAA,GAAG,CAACpB,cAAc,CAAC9J,OAAO,EAAEqF,MAAM,CAAC,CAAC;AAC7C,KAAC,CAAC;AACN;;AAEA;AACJ;AACA;AACA;EACI2H,yBAAyBA,CAACC,KAAK,EAAE;AAC7B,IAAA,IAAIA,KAAK,EAAE;MACP,IAAI,CAACC,wBAAwB,GAAG,IAAI;AACxC;IACA,IAAI,IAAI,CAACA,wBAAwB,EAAE;AAC/B,MAAA,OAAO9H,OAAO,CAACpF,OAAO,CAAC,IAAI,CAACkN,wBAAwB,CAAC;AACzD;AACA,IAAA,OAAO,IAAI9H,OAAO,CAAC,CAACpF,OAAO,EAAEqF,MAAM,KAAK;AACpC,MAAA,MAAM8H,4BAA4B,GAAG,IAAI,CAACnE,QAAQ,CAACmE,4BAA4B,GAAG,IAAIrC,OAAG,CAAC,IAAI,CAAC9B,QAAQ,CAACmE,4BAA4B,EAAE,IAAI,CAAC5C,SAAS,EAAE,CAAC,GAAG,IAAIO,OAAG,CAAC,kCAAkC,EAAE,IAAI,CAACP,SAAS,EAAE,CAAC;AACvN,MAAA,OAAO,IAAIQ,kBAAO,CAAC,KAAK,EAAEoC,4BAA4B,CAAC;AAClDjC,MAAAA,GAAG,CAACpB,cAAc,CAAC9J,OAAO,EAAEqF,MAAM,CAAC,CAAC;AAC7C,KAAC,CAAC,CAACO,IAAI,CAAC,CAACiB,aAAa,KAAK;MACvB,IAAI,CAACqG,wBAAwB,GAAGrG,aAAa;AAC7C,MAAA,OAAOA,aAAa;AACxB,KAAC,CAAC;AACN;AACJ;;ACrPA,MAAMuG,4BAA4B,SAASxD,yBAAkB,CAAC;AAC1D7K,EAAAA,WAAWA,GAAG;IACV,KAAK,CAAC,+GAA+G,CAAC;IACtH,IAAI,CAACsO,UAAU,GAAG,KAAK;AAC3B;;AAEJ;;AAEA,MAAMC,sBAAsB,SAASxO,yBAAkB,CAAC;EACtDC,WAAWA,CAACC,GAAG,EAAE;IACf,KAAK,CAACA,GAAG,CAAC;;AAEV;IACA,IAAIyB,sBAAsB,GAAGzB,GAAG,CAACO,gBAAgB,EAAE,CAACC,WAAW,CAAC,+CAA+C,CAAC;AAChH,IAAA,IAAI,OAAOiB,sBAAsB,KAAK,SAAS,EAAE;AAC7CA,MAAAA,sBAAsB,GAAG,KAAK;AAClC;IACA,IAAI,CAACA,sBAAsB,GAAGA,sBAAsB;AACpD;AACA,IAAA,IAAI,CAAC8M,KAAK,GAAGvO,GAAG,CAACO,gBAAgB,EAAE,CAACC,WAAW,CAAC,gDAAgD,CAAC,IAAI,eAAe;;AAEpHR,IAAAA,GAAG,CAACC,aAAa,CAACC,SAAS,CAAC,CAACD,aAAa,KAAK;MAC3C,IAAIA,aAAa,IAAI,IAAI,EAAE;AACvB,QAAA;AACJ;AACA,MAAA,MAAME,SAAS,GAAGC,OAAO,CAACC,MAAM,EAAE;MAClCF,SAAS,CAACgD,GAAG,CAAC,CAACd,GAAG,EAAEoI,GAAG,EAAEC,IAAI,KAAK;QAC9B,KAAK,IAAI,CAAC8D,qBAAqB,CAACnM,GAAG,CAAC,CAACuE,IAAI,CAAC,CAACjF,KAAK,KAAK;UACjD,IAAIA,KAAK,KAAK,KAAK,EAAE;AACjB,YAAA,OAAO+I,IAAI,CAAC,IAAI0D,4BAA4B,EAAE,CAAC;AACnD;UACA,OAAO1D,IAAI,EAAE;AACjB,SAAC,CAAC,CAAC3E,KAAK,CAAC,CAACvC,GAAG,KAAK;UACd,OAAOkH,IAAI,CAAClH,GAAG,CAAC;AACpB,SAAC,CAAC;AACN,OAAC,CAAC;AACF;AACAvD,MAAAA,aAAa,CAACoD,KAAK,CAACC,OAAO,CAACC,KAAK,CAACtD,aAAa,CAACoD,KAAK,EAAElD,SAAS,CAACkD,KAAK,CAAC;AAC3E,KAAC,CAAC;AACJ;;AAEA;AACF;AACA;AACA;AACA;EACEoL,gBAAgBA,CAACpM,GAAG,EAAE;AACpB,IAAA,IAAIC,aAAa;IACjB,IAAI,IAAI,CAACb,sBAAsB,EAAE;AAC7B;AACAa,MAAAA,aAAa,GAAGD,GAAG,CAACE,OAAO,CAAC,WAAW,CAAC,IAAIF,GAAG,CAACE,OAAO,CAAC,iBAAiB,CAAC,KAAKF,GAAG,CAACG,UAAU,GAAGH,GAAG,CAACG,UAAU,CAACF,aAAa,GAAGD,GAAG,CAACI,MAAM,CAACH,aAAa,CAAC;AAC5J,KAAC,MAAM;AACHA,MAAAA,aAAa,GAAGD,GAAG,CAACG,UAAU,GAAGH,GAAG,CAACG,UAAU,CAACF,aAAa,GAAGD,GAAG,CAACI,MAAM,CAACH,aAAa;AAC5F;AACA,IAAA,OAAOA,aAAa;AACtB;;AAEA;AACF;AACA;AACA;AACA;EACE,MAAMkM,qBAAqBA,CAACnM,GAAG,EAAE;IAC/B,MAAMgK,mBAAmB,GAAGhK,GAAG,CAAC+F,OAAO,EAAEC,IAAI,EAAEgE,mBAAmB;IAClE,IAAIA,mBAAmB,IAAI,IAAI,EAAE;AAC7B,MAAA,MAAMe,YAAY,GAAGsB,GAAG,CAACC,MAAM,CAACtC,mBAAmB,CAAC;AACpD,MAAA,MAAM/J,aAAa,GAAG8K,YAAY,CAAC,IAAI,CAACmB,KAAK,CAAC;MAC9C,IAAIjM,aAAa,IAAI,IAAI,EAAE;QACvBrB,iBAAU,CAACO,IAAI,CAAC,CAAA,oFAAA,EAAuF,IAAI,CAAC+M,KAAK,2BAA2B,CAAC;AAC7I,QAAA,OAAO,KAAK;AAChB;AACA;AACA,MAAA,MAAMK,oBAAoB,GAAG,IAAI,CAACH,gBAAgB,CAACpM,GAAG,CAAC;MACvD,IAAIC,aAAa,KAAKsM,oBAAoB,EAAE;QACxC3N,iBAAU,CAACO,IAAI,CAAC,CAAgEc,6DAAAA,EAAAA,aAAa,IAAI,QAAQ,CAAA,+BAAA,EAAkCsM,oBAAoB,CAAA,CAAE,CAAC;AAClK,QAAA,OAAO,KAAK;AAChB;AACA,MAAA,OAAO,IAAI;AACf;AACA3N,IAAAA,iBAAU,CAACO,IAAI,CAAC,8FAA8F,CAAC;AAC/G,IAAA,OAAO,KAAK;AACd;;AAEF;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,19 +1,20 @@
1
1
  {
2
2
  "name": "@universis/janitor",
3
- "version": "1.6.3",
4
- "description": "Universis api plugin for rate limiting requests",
3
+ "version": "1.9.0",
4
+ "description": "Universis api plugin for handling user authorization and rate limiting",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "engines": {
8
8
  "node": ">=14"
9
9
  },
10
10
  "scripts": {
11
- "test": "jasmine",
12
- "build": "rimraf dist && babel src --out-dir dist --copy-files --source-maps"
11
+ "test": "jest",
12
+ "lint": "eslint",
13
+ "build": "rimraf dist && rollup --config rollup.config.cjs"
13
14
  },
14
15
  "repository": {
15
16
  "type": "git",
16
- "url": "git+https://gitlab.com/universis/rate-limit.git"
17
+ "url": "git+https://gitlab.com/universis/janitor.git"
17
18
  },
18
19
  "keywords": [
19
20
  "universis",
@@ -26,40 +27,59 @@
26
27
  "author": "",
27
28
  "license": "LGPL-3.0-or-later",
28
29
  "bugs": {
29
- "url": "https://gitlab.com/universis/rate-limit/issues"
30
+ "url": "https://gitlab.com/universis/janitor/issues"
30
31
  },
31
32
  "dependencies": {
33
+ "@themost/promise-sequence": "^1.0.2",
32
34
  "express-rate-limit": "^7.1.1",
33
35
  "express-slow-down": "^1.6.0",
34
36
  "ioredis": "^5.3.2",
35
37
  "jsonwebtoken": "^9.0.2",
36
- "rate-limit-redis": "^4.2.0",
37
- "superagent": "^8.1.2"
38
+ "passport-http-bearer": "^1.0.1",
39
+ "rate-limit-redis": "^4.2.1",
40
+ "superagent": "^10.2.1"
38
41
  },
39
42
  "peerDependencies": {
40
43
  "@themost/common": "^2",
41
44
  "@themost/data": "^2",
45
+ "@themost/express": "^1 || ^2",
42
46
  "@themost/query": "^2",
43
47
  "@themost/xml": "^2",
44
- "@themost/express": "^1"
48
+ "express": "^4 || ^5",
49
+ "core-js": "^2 || ^3"
45
50
  },
46
51
  "devDependencies": {
47
- "@babel/cli": "^7.21.0",
48
- "@babel/core": "^7.21.4",
49
- "@babel/eslint-parser": "^7.21.3",
52
+ "@babel/core": "^7.26.10",
53
+ "@babel/eslint-parser": "^7.26.10",
54
+ "@babel/plugin-proposal-class-properties": "^7.18.6",
50
55
  "@babel/plugin-proposal-decorators": "^7.21.0",
51
- "@babel/preset-env": "^7.21.4",
52
- "@babel/register": "^7.21.0",
53
- "@rollup/plugin-babel": "^6.0.3",
54
- "@types/express": "^4.17.6",
56
+ "@babel/preset-env": "^7.26.9",
57
+ "@rollup/plugin-babel": "^6.0.4",
58
+ "@themost/common": "^2.11.1",
59
+ "@themost/data": "^2.18.8",
60
+ "@themost/express": "^2.4.0",
61
+ "@themost/query": "^2.14.13",
62
+ "@themost/sqlite": "^2.10.1",
63
+ "@themost/web": "^2.8.1",
64
+ "@themost/xml": "^2.5.2",
65
+ "@types/express": "^5.0.2",
55
66
  "@types/ioredis": "^5.0.0",
56
- "@types/jasmine": "^3.5.10",
67
+ "@types/jest": "^29.5.14",
68
+ "@types/passport": "^1.0.17",
69
+ "@types/passport-http-bearer": "^1.0.41",
70
+ "@types/supertest": "^6.0.3",
71
+ "@universis/keycloak": "^3.1.2",
57
72
  "dotenv": "^8.2.0",
58
73
  "eslint": "^8.39.0",
59
- "jasmine": "^4.6.0",
60
- "jasmine-spec-reporter": "^5.0.2",
74
+ "eslint-plugin-jest": "^28.12.0",
75
+ "express": "^5.1.0",
76
+ "jest": "^29.7.0",
77
+ "passport": "^0.7.0",
61
78
  "rimraf": "3.0.2",
79
+ "rollup": "^4.41.1",
80
+ "rollup-plugin-dts": "^6.2.1",
81
+ "supertest": "^7.1.1",
62
82
  "typescript": "^5.0.4"
63
83
  },
64
- "homepage": "https://gitlab.com/universis/rate-limit#readme"
84
+ "homepage": "https://gitlab.com/universis/janitor#readme"
65
85
  }
@@ -0,0 +1,134 @@
1
+ import { HttpError, HttpForbiddenError } from '@themost/common';
2
+ import BearerStrategy from 'passport-http-bearer';
3
+
4
+ class HttpBearerTokenRequired extends HttpError {
5
+ constructor() {
6
+ super(499, 'A token is required to fulfill the request.');
7
+ this.code = 'E_TOKEN_REQUIRED';
8
+ this.title = 'Token Required';
9
+ }
10
+ }
11
+
12
+ class HttpBearerTokenNotFound extends HttpError {
13
+ constructor() {
14
+ super(498, 'Token was not found.');
15
+ this.code = 'E_TOKEN_NOT_FOUND';
16
+ this.title = 'Invalid token';
17
+ }
18
+ }
19
+
20
+ class HttpBearerTokenExpired extends HttpError {
21
+ constructor() {
22
+ super(498, 'Token was expired or is in invalid state.');
23
+ this.code = 'E_TOKEN_EXPIRED';
24
+ this.title = 'Invalid token';
25
+ }
26
+ }
27
+
28
+ class HttpAccountDisabled extends HttpForbiddenError {
29
+ constructor() {
30
+ super('Access is denied. User account is disabled.');
31
+ this.code = 'E_ACCOUNT_DISABLED';
32
+ this.statusCode = 403.2;
33
+ this.title = 'Disabled account';
34
+ }
35
+ }
36
+
37
+ class HttpBearerStrategy extends BearerStrategy {
38
+ constructor() {
39
+ super({
40
+ passReqToCallback: true
41
+ },
42
+ /**
43
+ * @param {Request} req
44
+ * @param {string} token
45
+ * @param {Function} done
46
+ */
47
+ function(req, token, done) {
48
+ /**
49
+ * Gets OAuth2 client services
50
+ * @type {import('./OAuth2ClientService').OAuth2ClientService}
51
+ */
52
+ let client = req.context.getApplication().getStrategy(function OAuth2ClientService() {});
53
+ // if client cannot be found
54
+ if (client == null) {
55
+ // throw configuration error
56
+ return done(new Error('Invalid application configuration. OAuth2 client service cannot be found.'))
57
+ }
58
+ if (token == null) {
59
+ // throw 499 Token Required error
60
+ return done(new HttpBearerTokenRequired());
61
+ }
62
+ // get token info
63
+ client.getTokenInfo(req.context, token).then(info => {
64
+ if (info == null) {
65
+ // the specified token cannot be found - 498 invalid token with specific code
66
+ return done(new HttpBearerTokenNotFound());
67
+ }
68
+ // if the given token is not active throw token expired - 498 invalid token with specific code
69
+ if (!info.active) {
70
+ return done(new HttpBearerTokenExpired());
71
+ }
72
+ // find user from token info
73
+ return (function () {
74
+ /**
75
+ * @type {import('./services/user-provisioning-mapper-service').UserProvisioningMapperService}
76
+ */
77
+ const mapper = req.context.getA$1pplication().getService(function UserProvisioningMapperService() {});
78
+ if (mapper == null) {
79
+ return req.context.model('User').where('name').equal(info.username).silent().getItem();
80
+ }
81
+ return mapper.getUser(req.context, info);
82
+ })().then((user) => {
83
+ // check if userProvisioning service is installed and try to find related user only if user not found
84
+ if (user == null) {
85
+ /**
86
+ * @type {import('./services/user-provisioning-service').UserProvisioningService}
87
+ */
88
+ const service = req.context.getApplication().getService(function UserProvisioningService() {});
89
+ if (service == null) {
90
+ return user;
91
+ }
92
+ return service.validateUser(req.context, info);
93
+ }
94
+ return user;
95
+ }).then( user => {
96
+ // user cannot be found and of course cannot be authenticated (throw forbidden error)
97
+ if (user == null) {
98
+ // write access log for forbidden
99
+ return done(new HttpForbiddenError());
100
+ }
101
+ // check if user has enabled attribute
102
+ if (Object.prototype.hasOwnProperty.call(user, 'enabled') && !user.enabled) {
103
+ //if user.enabled is off throw forbidden error
104
+ return done(new HttpAccountDisabled('Access is denied. User account is disabled.'));
105
+ }
106
+ // otherwise return user data
107
+ return done(null, {
108
+ 'name': user.name,
109
+ 'authenticationProviderKey': user.id,
110
+ 'authenticationType':'Bearer',
111
+ 'authenticationToken': token,
112
+ 'authenticationScope': info.scope
113
+ });
114
+ });
115
+ }).catch(err => {
116
+ // end log token info request with error
117
+ if (err && err.statusCode === 404) {
118
+ // revert 404 not found returned by auth server to 498 invalid token
119
+ return done(new HttpBearerTokenNotFound());
120
+ }
121
+ // otherwise continue with error
122
+ return done(err);
123
+ });
124
+ });
125
+ }
126
+ }
127
+
128
+ export {
129
+ HttpAccountDisabled,
130
+ HttpBearerTokenExpired,
131
+ HttpBearerTokenNotFound,
132
+ HttpBearerTokenRequired,
133
+ HttpBearerStrategy
134
+ }
@@ -0,0 +1,4 @@
1
+ import { Strategy } from 'passport';
2
+ export declare class HttpBearerStrategy extends Strategy {
3
+ constructor();
4
+ }
@@ -1,5 +1,5 @@
1
1
  import { TraceUtils } from '@themost/common';
2
- import RedisStore from 'rate-limit-redis';
2
+ import { RedisStore } from 'rate-limit-redis';
3
3
  import { Redis } from 'ioredis';
4
4
  import '@themost/promise-sequence';
5
5
 
@@ -6,13 +6,27 @@
6
6
  * Use of this source code is governed by an LGPL 3.0 license that can be
7
7
  * found in the LICENSE file at https://universis.io/license
8
8
  */
9
- import {ConfigurationBase, ConfigurationStrategy} from '@themost/common';
9
+ import {ApplicationBase, ApplicationService, ConfigurationBase, ConfigurationStrategy} from '@themost/common';
10
10
 
11
11
  export declare class ScopeString {
12
12
  constructor(str: string);
13
13
  split(): string[];
14
14
  }
15
15
 
16
+ export declare interface UniversisConfigurationSection {
17
+ universis: {
18
+ [k: string]: any;
19
+ }
20
+ }
21
+
22
+ export declare interface ScopeAccessConfigurationSection {
23
+ janitor: {
24
+ scopeAccess: {
25
+ imports: string[]
26
+ }
27
+ }
28
+ }
29
+
16
30
  /**
17
31
  * Declares a configuration element for managing scope-based permissions on server resources
18
32
  */
@@ -63,3 +77,11 @@ export declare class DefaultScopeAccessConfiguration extends ScopeAccessConfigur
63
77
  verify(req: Request): Promise<ScopeAccessConfigurationElement>;
64
78
 
65
79
  }
80
+
81
+ export declare class EnableScopeAccessConfiguration extends ApplicationService {
82
+ constructor(app: ApplicationBase);
83
+ }
84
+
85
+ export declare class ExtendScopeAccessConfiguration extends ApplicationService {
86
+ constructor(app: ApplicationBase);
87
+ }
@@ -1,3 +1,4 @@
1
+
1
2
  import {ConfigurationStrategy, Args, ApplicationService} from '@themost/common';
2
3
  import path from 'path';
3
4
  import url from 'url';
@@ -68,17 +69,31 @@ class ScopeAccessConfiguration extends ConfigurationStrategy {
68
69
  let reqScopes = new ScopeString(req.context.user.authenticationScope).split();
69
70
  // get user access based on HTTP method e.g. GET -> read access
70
71
  let reqAccess = HTTP_METHOD_REGEXP.test(req.method) ? 'write' : 'read';
72
+ // first phase: find element by resource and scope
71
73
  let result = this.elements.find(x => {
72
74
  // filter element by access level
73
- return x.access.indexOf(reqAccess)>=0
74
- // resource path
75
- && new RegExp( '^' + x.resource, 'i').test(reqUrl)
75
+ return new RegExp( "^" + x.resource, 'i').test(reqUrl)
76
76
  // and scopes
77
77
  && x.scope.find(y => {
78
78
  // search user scopes (validate wildcard scope)
79
- return y === '*' || reqScopes.indexOf(y)>=0;
79
+ return y === "*" || reqScopes.indexOf(y)>=0;
80
80
  });
81
81
  });
82
+ // second phase: check access level
83
+ if (result == null) {
84
+ return resolve();
85
+ }
86
+ // if access is missing or access is not an array
87
+ if (Array.isArray(result.access) === false) {
88
+ // the requested access is not allowed because the access is not defined
89
+ return resolve();
90
+ }
91
+ // if the requested access is not in the access array
92
+ if (result.access.indexOf(reqAccess) < 0) {
93
+ // the requested access is not allowed because the access levels do not match
94
+ return resolve();
95
+ }
96
+ // otherwise, return result
82
97
  return resolve(result);
83
98
  }
84
99
  return resolve();
@@ -121,15 +136,29 @@ class DefaultScopeAccessConfiguration extends ScopeAccessConfiguration {
121
136
  }
122
137
  }
123
138
 
139
+ class EnableScopeAccessConfiguration extends ApplicationService {
140
+ /**
141
+ * @param {import('@themost/express').ExpressDataApplication|import('@themost/common').ApplicationBase} app
142
+ */
143
+ constructor(app) {
144
+ super(app);
145
+ // register scope access configuration
146
+ app.getConfiguration().useStrategy(ScopeAccessConfiguration, DefaultScopeAccessConfiguration);
147
+ }
148
+ }
149
+
124
150
 
125
151
  /**
126
152
  * @class
127
153
  */
128
154
  class ExtendScopeAccessConfiguration extends ApplicationService {
155
+ /**
156
+ * @param {import('@themost/express').ExpressDataApplication|import('@themost/common').ApplicationBase} app
157
+ */
129
158
  constructor(app) {
130
159
  super(app);
131
160
  // Get the additional scope access extensions from the configuration
132
- const scopeAccessExtensions = app.getConfiguration().settings.universis?.janitor?.scopeAccess["imports"];
161
+ const scopeAccessExtensions = app.getConfiguration().settings.universis?.janitor?.scopeAccess.imports;
133
162
  if (app && app.container && scopeAccessExtensions != null) {
134
163
  app.container.subscribe((container) => {
135
164
  if (container) {
@@ -137,10 +166,10 @@ class ExtendScopeAccessConfiguration extends ApplicationService {
137
166
  if (scopeAccess != null) {
138
167
  for (const scopeAccessExtension of scopeAccessExtensions) {
139
168
  try {
140
- const element = require(path.resolve(app.getConfiguration().getConfigurationPath(), scopeAccessExtension));
141
- if (element) {
169
+ const elements = require(path.resolve(app.getConfiguration().getConfigurationPath(), scopeAccessExtension));
170
+ if (elements) {
142
171
  // add extra scope access elements
143
- scopeAccess.elements.push.apply(scopeAccess.elements, element);
172
+ scopeAccess.elements.unshift(...elements);
144
173
  }
145
174
  }
146
175
  catch(err) {
@@ -162,5 +191,6 @@ export {
162
191
  ScopeString,
163
192
  ScopeAccessConfiguration,
164
193
  DefaultScopeAccessConfiguration,
194
+ EnableScopeAccessConfiguration,
165
195
  ExtendScopeAccessConfiguration
166
196
  }
package/src/index.d.ts CHANGED
@@ -4,4 +4,4 @@ export * from './RedisClientStore';
4
4
  export * from './ScopeAccessConfiguration';
5
5
  export * from './validateScope';
6
6
  export * from './OAuth2ClientService';
7
- export * from './RemoteAddressValidator';
7
+ export * from './RemoteAddressValidator';
package/src/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import './polyfills';
1
+ import 'core-js/stable/string/replace-all';
2
2
  export * from './RateLimitService';
3
3
  export * from './SpeedLimitService';
4
4
  export * from './RedisClientStore';
package/.gitlab-ci.yml DELETED
@@ -1,29 +0,0 @@
1
- image: node:14
2
-
3
- stages:
4
- - releases
5
- - deploy
6
-
7
- npm_publish:
8
- stage: releases
9
- rules:
10
- - if: $CI_PROJECT_NAMESPACE == "universis" && $CI_COMMIT_REF_PROTECTED == "true" && $CI_COMMIT_TAG =~ /^v(\d+.)(\d+.)(\d+)$/
11
- script:
12
- - npm i
13
- - npm run build
14
- - echo //registry.npmjs.org/:_authToken=$NPM_TOKEN > .npmrc
15
- - npm publish --access=public
16
- - rm .npmrc
17
-
18
- pages:
19
- stage: deploy
20
- script:
21
- - mkdir .public
22
- - cp -r * .public
23
- - mv .public public
24
- artifacts:
25
- paths:
26
- - public
27
- rules:
28
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
29
-