@harperfast/harper 5.0.0-alpha.10 → 5.0.0-beta.1

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 (444) hide show
  1. package/bin/BinObjects.js +17 -0
  2. package/bin/cliOperations.js +157 -0
  3. package/bin/copyDb.ts +280 -0
  4. package/bin/harper.js +156 -0
  5. package/bin/install.js +15 -0
  6. package/bin/lite.js +5 -0
  7. package/bin/restart.js +201 -0
  8. package/bin/run.js +409 -0
  9. package/bin/status.js +65 -0
  10. package/bin/stop.js +22 -0
  11. package/bin/upgrade.js +134 -0
  12. package/components/Application.ts +646 -0
  13. package/components/ApplicationScope.ts +49 -0
  14. package/components/Component.ts +53 -0
  15. package/components/ComponentV1.ts +342 -0
  16. package/components/DEFAULT_CONFIG.ts +18 -0
  17. package/components/EntryHandler.ts +227 -0
  18. package/components/Logger.ts +14 -0
  19. package/components/OptionsWatcher.ts +354 -0
  20. package/components/PluginModule.ts +6 -0
  21. package/components/Scope.ts +329 -0
  22. package/components/componentLoader.ts +529 -0
  23. package/components/deriveCommonPatternBase.ts +31 -0
  24. package/components/deriveGlobOptions.ts +44 -0
  25. package/components/deriveURLPath.ts +57 -0
  26. package/components/operations.js +658 -0
  27. package/components/operationsValidation.js +246 -0
  28. package/components/packageComponent.ts +39 -0
  29. package/components/requestRestart.ts +26 -0
  30. package/components/resolveBaseURLPath.ts +38 -0
  31. package/components/status/ComponentStatus.ts +110 -0
  32. package/components/status/ComponentStatusRegistry.ts +251 -0
  33. package/components/status/api.ts +153 -0
  34. package/components/status/crossThread.ts +405 -0
  35. package/components/status/errors.ts +152 -0
  36. package/components/status/index.ts +44 -0
  37. package/components/status/internal.ts +65 -0
  38. package/components/status/registry.ts +12 -0
  39. package/components/status/types.ts +96 -0
  40. package/config/RootConfigWatcher.ts +59 -0
  41. package/config/configHelpers.ts +11 -0
  42. package/config/configUtils.js +967 -0
  43. package/config/harperConfigEnvVars.ts +641 -0
  44. package/dataLayer/CreateAttributeObject.js +25 -0
  45. package/dataLayer/CreateTableObject.js +11 -0
  46. package/dataLayer/DataLayerObjects.js +43 -0
  47. package/dataLayer/DeleteBeforeObject.js +22 -0
  48. package/dataLayer/DeleteObject.js +25 -0
  49. package/dataLayer/DropAttributeObject.js +11 -0
  50. package/dataLayer/GetBackupObject.js +22 -0
  51. package/dataLayer/InsertObject.js +24 -0
  52. package/dataLayer/ReadAuditLogObject.js +24 -0
  53. package/dataLayer/SQLSearch.js +1335 -0
  54. package/dataLayer/SearchByConditionsObject.js +61 -0
  55. package/dataLayer/SearchByHashObject.js +21 -0
  56. package/dataLayer/SearchObject.js +45 -0
  57. package/dataLayer/SqlSearchObject.js +14 -0
  58. package/dataLayer/UpdateObject.js +23 -0
  59. package/dataLayer/UpsertObject.js +23 -0
  60. package/dataLayer/bulkLoad.js +813 -0
  61. package/dataLayer/dataObjects/BulkLoadObjects.js +27 -0
  62. package/dataLayer/dataObjects/UpsertObject.js +23 -0
  63. package/dataLayer/delete.js +164 -0
  64. package/dataLayer/export.js +381 -0
  65. package/dataLayer/getBackup.js +40 -0
  66. package/dataLayer/harperBridge/BridgeMethods.js +81 -0
  67. package/dataLayer/harperBridge/ResourceBridge.ts +633 -0
  68. package/dataLayer/harperBridge/bridgeUtility/insertUpdateReturnObj.js +28 -0
  69. package/dataLayer/harperBridge/bridgeUtility/insertUpdateValidate.js +88 -0
  70. package/dataLayer/harperBridge/harperBridge.js +21 -0
  71. package/dataLayer/harperBridge/lmdbBridge/LMDBBridge.js +119 -0
  72. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/DeleteAuditLogsBeforeResults.js +19 -0
  73. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateAttribute.js +112 -0
  74. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateRecords.js +67 -0
  75. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateSchema.js +31 -0
  76. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbCreateTable.js +94 -0
  77. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDeleteAuditLogsBefore.js +98 -0
  78. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDeleteRecords.js +89 -0
  79. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropAttribute.js +109 -0
  80. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropSchema.js +107 -0
  81. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbDropTable.js +137 -0
  82. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbFlush.js +35 -0
  83. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetBackup.js +111 -0
  84. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetDataByHash.js +28 -0
  85. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbGetDataByValue.js +29 -0
  86. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbReadAuditLog.js +207 -0
  87. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByConditions.js +156 -0
  88. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByHash.js +21 -0
  89. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbSearchByValue.js +30 -0
  90. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbTransaction.js +19 -0
  91. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbUpdateRecords.js +64 -0
  92. package/dataLayer/harperBridge/lmdbBridge/lmdbMethods/lmdbUpsertRecords.js +70 -0
  93. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBCreateAttributeObject.js +22 -0
  94. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBDeleteTransactionObject.js +23 -0
  95. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBInsertTransactionObject.js +22 -0
  96. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBTransactionObject.js +23 -0
  97. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBUpdateTransactionObject.js +24 -0
  98. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/LMDBUpsertTransactionObject.js +24 -0
  99. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/TableSizeObject.js +25 -0
  100. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/initializeHashSearch.js +21 -0
  101. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/initializePaths.js +157 -0
  102. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbCheckForNewAttributes.js +94 -0
  103. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbCreateTransactionsAuditEnvironment.js +39 -0
  104. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbGetTableSize.js +34 -0
  105. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbProcessRows.js +100 -0
  106. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbSearch.js +371 -0
  107. package/dataLayer/harperBridge/lmdbBridge/lmdbUtility/lmdbWriteTransaction.js +109 -0
  108. package/dataLayer/hdbInfoController.js +254 -0
  109. package/dataLayer/insert.js +266 -0
  110. package/dataLayer/readAuditLog.js +59 -0
  111. package/dataLayer/schema.js +366 -0
  112. package/dataLayer/schemaDescribe.js +289 -0
  113. package/dataLayer/search.js +60 -0
  114. package/dataLayer/transaction.js +17 -0
  115. package/dataLayer/update.js +124 -0
  116. package/dist/components/Logger.d.ts +12 -0
  117. package/dist/components/Logger.js +3 -0
  118. package/dist/components/Logger.js.map +1 -0
  119. package/dist/components/Scope.d.ts +14 -4
  120. package/dist/components/Scope.js +18 -10
  121. package/dist/components/Scope.js.map +1 -1
  122. package/dist/components/componentLoader.js +16 -9
  123. package/dist/components/componentLoader.js.map +1 -1
  124. package/dist/components/operations.js +2 -2
  125. package/dist/components/operations.js.map +1 -1
  126. package/dist/config/configUtils.d.ts +1 -1
  127. package/dist/config/configUtils.js +1 -1
  128. package/dist/config/configUtils.js.map +1 -1
  129. package/dist/dataLayer/CreateTableObject.d.ts +2 -2
  130. package/dist/dataLayer/CreateTableObject.js +2 -2
  131. package/dist/dataLayer/CreateTableObject.js.map +1 -1
  132. package/dist/dataLayer/delete.d.ts +1 -1
  133. package/dist/dataLayer/schema.js +6 -5
  134. package/dist/dataLayer/schema.js.map +1 -1
  135. package/dist/dataLayer/schemaDescribe.js +1 -1
  136. package/dist/dataLayer/schemaDescribe.js.map +1 -1
  137. package/dist/index.d.ts +1 -1
  138. package/dist/index.js +2 -0
  139. package/dist/index.js.map +1 -1
  140. package/dist/resources/DatabaseTransaction.d.ts +1 -1
  141. package/dist/resources/IterableEventQueue.d.ts +1 -1
  142. package/dist/resources/LMDBTransaction.d.ts +5 -1
  143. package/dist/resources/Resource.d.ts +1 -1
  144. package/dist/resources/RocksIndexStore.d.ts +3 -3
  145. package/dist/resources/RocksTransactionLogStore.d.ts +6 -3
  146. package/dist/resources/Table.d.ts +15 -6
  147. package/dist/resources/Table.js +4 -1
  148. package/dist/resources/Table.js.map +1 -1
  149. package/dist/resources/analytics/read.js +32 -22
  150. package/dist/resources/analytics/read.js.map +1 -1
  151. package/dist/resources/analytics/write.js +3 -6
  152. package/dist/resources/analytics/write.js.map +1 -1
  153. package/dist/resources/auditStore.d.ts +3 -3
  154. package/dist/resources/blob.d.ts +25 -2
  155. package/dist/resources/databases.d.ts +12 -2
  156. package/dist/resources/databases.js +22 -19
  157. package/dist/resources/databases.js.map +1 -1
  158. package/dist/resources/search.js +11 -5
  159. package/dist/resources/search.js.map +1 -1
  160. package/dist/resources/transaction.d.ts +2 -1
  161. package/dist/security/auth.js +1 -1
  162. package/dist/security/auth.js.map +1 -1
  163. package/dist/security/cryptoHash.d.ts +2 -2
  164. package/dist/security/jsLoader.js +243 -66
  165. package/dist/security/jsLoader.js.map +1 -1
  166. package/dist/security/keys.js +4 -5
  167. package/dist/security/keys.js.map +1 -1
  168. package/dist/security/user.js +3 -3
  169. package/dist/security/user.js.map +1 -1
  170. package/dist/server/REST.js +16 -2
  171. package/dist/server/REST.js.map +1 -1
  172. package/dist/server/Server.d.ts +2 -1
  173. package/dist/server/Server.js.map +1 -1
  174. package/dist/server/fastifyRoutes/plugins/hdbCore.d.ts +6 -1
  175. package/dist/server/fastifyRoutes.js +2 -0
  176. package/dist/server/fastifyRoutes.js.map +1 -1
  177. package/dist/server/http.js +12 -6
  178. package/dist/server/http.js.map +1 -1
  179. package/dist/server/jobs/JobObject.d.ts +3 -3
  180. package/dist/server/loadRootComponents.js +1 -0
  181. package/dist/server/loadRootComponents.js.map +1 -1
  182. package/dist/server/operationsServer.js +3 -1
  183. package/dist/server/operationsServer.js.map +1 -1
  184. package/dist/server/serverHelpers/JSONStream.d.ts +3 -3
  185. package/dist/server/serverHelpers/Request.d.ts +5 -5
  186. package/dist/server/serverHelpers/requestTimePlugin.d.ts +1 -1
  187. package/dist/server/threads/manageThreads.d.ts +2 -2
  188. package/dist/server/threads/manageThreads.js +50 -35
  189. package/dist/server/threads/manageThreads.js.map +1 -1
  190. package/dist/server/threads/socketRouter.d.ts +1 -1
  191. package/dist/sqlTranslator/deleteTranslator.d.ts +1 -1
  192. package/dist/utility/AWS/AWSConnector.d.ts +3 -2
  193. package/dist/utility/common_utils.d.ts +3 -3
  194. package/dist/utility/environment/systemInformation.d.ts +1 -0
  195. package/dist/utility/functions/date/dateFunctions.d.ts +11 -11
  196. package/dist/utility/globalSchema.d.ts +1 -1
  197. package/dist/utility/hdbTerms.d.ts +3 -0
  198. package/dist/utility/hdbTerms.js +3 -0
  199. package/dist/utility/hdbTerms.js.map +1 -1
  200. package/dist/utility/installation.d.ts +2 -4
  201. package/dist/utility/installation.js.map +1 -1
  202. package/dist/utility/lmdb/commonUtility.d.ts +1 -0
  203. package/dist/utility/lmdb/deleteUtility.d.ts +1 -0
  204. package/dist/utility/lmdb/environmentUtility.d.ts +1 -0
  205. package/dist/utility/lmdb/searchUtility.d.ts +2 -1
  206. package/dist/utility/lmdb/writeUtility.d.ts +1 -0
  207. package/dist/utility/logging/harper_logger.d.ts +6 -6
  208. package/dist/utility/processManagement/processManagement.d.ts +1 -1
  209. package/dist/utility/processManagement/servicesConfig.d.ts +12 -6
  210. package/dist/validation/common_validators.d.ts +4 -3
  211. package/dist/validation/configValidator.d.ts +3 -2
  212. package/index.d.ts +56 -0
  213. package/index.js +41 -0
  214. package/json/systemSchema.json +373 -0
  215. package/launchServiceScripts/launchHarperDB.js +3 -0
  216. package/launchServiceScripts/utility/checkNodeVersion.js +15 -0
  217. package/package.json +21 -3
  218. package/resources/DatabaseTransaction.ts +378 -0
  219. package/resources/ErrorResource.ts +57 -0
  220. package/resources/IterableEventQueue.ts +94 -0
  221. package/resources/LMDBTransaction.ts +349 -0
  222. package/resources/RecordEncoder.ts +702 -0
  223. package/resources/RequestTarget.ts +134 -0
  224. package/resources/Resource.ts +789 -0
  225. package/resources/ResourceInterface.ts +221 -0
  226. package/resources/ResourceInterfaceV2.ts +53 -0
  227. package/resources/ResourceV2.ts +67 -0
  228. package/resources/Resources.ts +162 -0
  229. package/resources/RocksIndexStore.ts +70 -0
  230. package/resources/RocksTransactionLogStore.ts +352 -0
  231. package/resources/Table.ts +4527 -0
  232. package/resources/analytics/hostnames.ts +72 -0
  233. package/resources/analytics/metadata.ts +10 -0
  234. package/resources/analytics/read.ts +252 -0
  235. package/resources/analytics/write.ts +803 -0
  236. package/resources/auditStore.ts +556 -0
  237. package/resources/blob.ts +1268 -0
  238. package/resources/crdt.ts +125 -0
  239. package/resources/dataLoader.ts +527 -0
  240. package/resources/databases.ts +1290 -0
  241. package/resources/graphql.ts +221 -0
  242. package/resources/indexes/HierarchicalNavigableSmallWorld.ts +638 -0
  243. package/resources/indexes/customIndexes.ts +7 -0
  244. package/resources/indexes/vector.ts +38 -0
  245. package/resources/jsResource.ts +86 -0
  246. package/resources/loadEnv.ts +22 -0
  247. package/resources/login.ts +18 -0
  248. package/resources/openApi.ts +409 -0
  249. package/resources/registrationDeprecated.ts +8 -0
  250. package/resources/replayLogs.ts +136 -0
  251. package/resources/roles.ts +98 -0
  252. package/resources/search.ts +1301 -0
  253. package/resources/tracked.ts +584 -0
  254. package/resources/transaction.ts +89 -0
  255. package/resources/transactionBroadcast.ts +258 -0
  256. package/security/auth.ts +376 -0
  257. package/security/certificateVerification/certificateVerificationSource.ts +84 -0
  258. package/security/certificateVerification/configValidation.ts +107 -0
  259. package/security/certificateVerification/crlVerification.ts +623 -0
  260. package/security/certificateVerification/index.ts +121 -0
  261. package/security/certificateVerification/ocspVerification.ts +148 -0
  262. package/security/certificateVerification/pkijs-ed25519-patch.ts +188 -0
  263. package/security/certificateVerification/types.ts +128 -0
  264. package/security/certificateVerification/verificationConfig.ts +138 -0
  265. package/security/certificateVerification/verificationUtils.ts +447 -0
  266. package/security/cryptoHash.js +42 -0
  267. package/security/data_objects/PermissionAttributeResponseObject.js +15 -0
  268. package/security/data_objects/PermissionResponseObject.js +115 -0
  269. package/security/data_objects/PermissionTableResponseObject.js +20 -0
  270. package/security/fastifyAuth.js +169 -0
  271. package/security/impersonation.ts +160 -0
  272. package/security/jsLoader.ts +716 -0
  273. package/security/keys.js +948 -0
  274. package/security/permissionsTranslator.js +300 -0
  275. package/security/role.js +218 -0
  276. package/security/tokenAuthentication.ts +228 -0
  277. package/security/user.ts +449 -0
  278. package/server/DurableSubscriptionsSession.ts +503 -0
  279. package/server/REST.ts +407 -0
  280. package/server/Server.ts +89 -0
  281. package/server/fastifyRoutes/helpers/getCORSOptions.js +36 -0
  282. package/server/fastifyRoutes/helpers/getHeaderTimeoutConfig.js +15 -0
  283. package/server/fastifyRoutes/helpers/getServerOptions.js +33 -0
  284. package/server/fastifyRoutes/plugins/hdbCore.js +39 -0
  285. package/server/fastifyRoutes.ts +205 -0
  286. package/server/graphqlQuerying.ts +700 -0
  287. package/server/http.ts +640 -0
  288. package/server/itc/serverHandlers.js +161 -0
  289. package/server/itc/utility/ITCEventObject.js +10 -0
  290. package/server/jobs/JobObject.js +24 -0
  291. package/server/jobs/jobProcess.js +69 -0
  292. package/server/jobs/jobRunner.js +162 -0
  293. package/server/jobs/jobs.js +304 -0
  294. package/server/loadRootComponents.js +44 -0
  295. package/server/mqtt.ts +485 -0
  296. package/server/nodeName.ts +75 -0
  297. package/server/operationsServer.ts +313 -0
  298. package/server/serverHelpers/Headers.ts +108 -0
  299. package/server/serverHelpers/JSONStream.ts +269 -0
  300. package/server/serverHelpers/OperationFunctionObject.ts +13 -0
  301. package/server/serverHelpers/Request.ts +158 -0
  302. package/server/serverHelpers/contentTypes.ts +637 -0
  303. package/server/serverHelpers/requestTimePlugin.js +57 -0
  304. package/server/serverHelpers/serverHandlers.js +148 -0
  305. package/server/serverHelpers/serverUtilities.ts +473 -0
  306. package/server/serverRegistry.ts +8 -0
  307. package/server/static.ts +187 -0
  308. package/server/status/definitions.ts +37 -0
  309. package/server/status/index.ts +125 -0
  310. package/server/storageReclamation.ts +93 -0
  311. package/server/threads/itc.js +89 -0
  312. package/server/threads/manageThreads.js +594 -0
  313. package/server/threads/socketRouter.ts +360 -0
  314. package/server/threads/threadServer.js +279 -0
  315. package/server/throttle.ts +73 -0
  316. package/sqlTranslator/SelectValidator.js +330 -0
  317. package/sqlTranslator/alasqlFunctionImporter.js +62 -0
  318. package/sqlTranslator/deleteTranslator.js +67 -0
  319. package/sqlTranslator/index.js +242 -0
  320. package/sqlTranslator/sql_statement_bucket.js +472 -0
  321. package/static/defaultConfig.yaml +3 -0
  322. package/studio/web/HDBDogOnly.svg +78 -0
  323. package/studio/web/assets/PPRadioGrotesk-Bold-DDaUYG8E.woff +0 -0
  324. package/studio/web/assets/fa-brands-400-CEJbCg16.woff +0 -0
  325. package/studio/web/assets/fa-brands-400-CSYNqBb_.ttf +0 -0
  326. package/studio/web/assets/fa-brands-400-DnkPfk3o.eot +0 -0
  327. package/studio/web/assets/fa-brands-400-UxlILjvJ.woff2 +0 -0
  328. package/studio/web/assets/fa-brands-400-cH1MgKbP.svg +3717 -0
  329. package/studio/web/assets/fa-regular-400-BhTwtT8w.eot +0 -0
  330. package/studio/web/assets/fa-regular-400-D1vz6WBx.ttf +0 -0
  331. package/studio/web/assets/fa-regular-400-DFnMcJPd.woff +0 -0
  332. package/studio/web/assets/fa-regular-400-DGzu1beS.woff2 +0 -0
  333. package/studio/web/assets/fa-regular-400-gwj8Pxq-.svg +801 -0
  334. package/studio/web/assets/fa-solid-900-B4ZZ7kfP.svg +5034 -0
  335. package/studio/web/assets/fa-solid-900-B6Axprfb.eot +0 -0
  336. package/studio/web/assets/fa-solid-900-BUswJgRo.woff2 +0 -0
  337. package/studio/web/assets/fa-solid-900-DOXgCApm.woff +0 -0
  338. package/studio/web/assets/fa-solid-900-mxuxnBEa.ttf +0 -0
  339. package/studio/web/assets/index-BTgXJX9d.js +235 -0
  340. package/studio/web/assets/index-BTgXJX9d.js.map +1 -0
  341. package/studio/web/assets/index-C-GXfcup.js +37 -0
  342. package/studio/web/assets/index-C-GXfcup.js.map +1 -0
  343. package/studio/web/assets/index-PFlNdimM.js +2 -0
  344. package/studio/web/assets/index-PFlNdimM.js.map +1 -0
  345. package/studio/web/assets/index-Y2g_iFpU.css +1 -0
  346. package/studio/web/assets/index-jiPwkrsB.css +1 -0
  347. package/studio/web/assets/index.lazy-C3TJZJ4o.js +266 -0
  348. package/studio/web/assets/index.lazy-C3TJZJ4o.js.map +1 -0
  349. package/studio/web/assets/profiler-DotzgiCJ.js +2 -0
  350. package/studio/web/assets/profiler-DotzgiCJ.js.map +1 -0
  351. package/studio/web/assets/react-redux-VxUEx_mU.js +6 -0
  352. package/studio/web/assets/react-redux-VxUEx_mU.js.map +1 -0
  353. package/studio/web/assets/startRecording-B_9J9Csd.js +3 -0
  354. package/studio/web/assets/startRecording-B_9J9Csd.js.map +1 -0
  355. package/studio/web/fabric-signup-background.webp +0 -0
  356. package/studio/web/fabric-signup-text.png +0 -0
  357. package/studio/web/favicon_purple.png +0 -0
  358. package/studio/web/github-icon.svg +15 -0
  359. package/studio/web/harper-fabric_black.png +0 -0
  360. package/studio/web/harper-fabric_white.png +0 -0
  361. package/studio/web/harper-studio_white.png +0 -0
  362. package/studio/web/index.html +16 -0
  363. package/studio/web/running.css +148 -0
  364. package/studio/web/running.html +147 -0
  365. package/studio/web/running.js +111 -0
  366. package/upgrade/UpgradeObjects.js +13 -0
  367. package/upgrade/directives/directivesController.js +90 -0
  368. package/upgrade/directivesManager.js +139 -0
  369. package/upgrade/upgradePrompt.js +124 -0
  370. package/upgrade/upgradeUtilities.js +28 -0
  371. package/utility/AWS/AWSConnector.js +29 -0
  372. package/utility/OperationFunctionCaller.js +63 -0
  373. package/utility/assignCmdEnvVariables.js +62 -0
  374. package/utility/common_utils.js +867 -0
  375. package/utility/environment/environmentManager.js +208 -0
  376. package/utility/environment/systemInformation.js +355 -0
  377. package/utility/errors/commonErrors.js +267 -0
  378. package/utility/errors/hdbError.js +146 -0
  379. package/utility/functions/date/dateFunctions.js +65 -0
  380. package/utility/functions/geo.js +355 -0
  381. package/utility/functions/sql/alaSQLExtension.js +104 -0
  382. package/utility/globalSchema.js +35 -0
  383. package/utility/hdbTerms.ts +819 -0
  384. package/utility/install/checkJWTTokensExist.js +62 -0
  385. package/utility/install/harperdb.conf +15 -0
  386. package/utility/install/harperdb.service +14 -0
  387. package/utility/install/installer.js +635 -0
  388. package/utility/installation.ts +30 -0
  389. package/utility/lmdb/DBIDefinition.js +20 -0
  390. package/utility/lmdb/DeleteRecordsResponseObject.js +25 -0
  391. package/utility/lmdb/InsertRecordsResponseObject.js +22 -0
  392. package/utility/lmdb/OpenDBIObject.js +31 -0
  393. package/utility/lmdb/OpenEnvironmentObject.js +41 -0
  394. package/utility/lmdb/UpdateRecordsResponseObject.js +25 -0
  395. package/utility/lmdb/UpsertRecordsResponseObject.js +22 -0
  396. package/utility/lmdb/cleanLMDBMap.js +65 -0
  397. package/utility/lmdb/commonUtility.js +119 -0
  398. package/utility/lmdb/deleteUtility.js +128 -0
  399. package/utility/lmdb/environmentUtility.js +477 -0
  400. package/utility/lmdb/searchCursorFunctions.js +187 -0
  401. package/utility/lmdb/searchUtility.js +918 -0
  402. package/utility/lmdb/terms.js +57 -0
  403. package/utility/lmdb/writeUtility.js +407 -0
  404. package/utility/logging/harper_logger.js +876 -0
  405. package/utility/logging/logRotator.js +157 -0
  406. package/utility/logging/logger.ts +24 -0
  407. package/utility/logging/readLog.js +355 -0
  408. package/utility/logging/transactionLog.js +57 -0
  409. package/utility/mount_hdb.js +59 -0
  410. package/utility/npmUtilities.js +102 -0
  411. package/utility/operationPermissions.ts +112 -0
  412. package/utility/operation_authorization.js +836 -0
  413. package/utility/packageUtils.js +55 -0
  414. package/utility/password.ts +99 -0
  415. package/utility/processManagement/processManagement.js +187 -0
  416. package/utility/processManagement/servicesConfig.js +56 -0
  417. package/utility/scripts/restartHdb.js +24 -0
  418. package/utility/scripts/user_data.sh +13 -0
  419. package/utility/signalling.js +36 -0
  420. package/utility/terms/certificates.js +81 -0
  421. package/utility/when.ts +20 -0
  422. package/v1.d.ts +39 -0
  423. package/v1.js +41 -0
  424. package/v2.d.ts +39 -0
  425. package/v2.js +41 -0
  426. package/validation/bulkDeleteValidator.js +24 -0
  427. package/validation/check_permissions.js +19 -0
  428. package/validation/common_validators.js +95 -0
  429. package/validation/configValidator.js +331 -0
  430. package/validation/deleteValidator.js +15 -0
  431. package/validation/fileLoadValidator.js +153 -0
  432. package/validation/insertValidator.js +40 -0
  433. package/validation/installValidator.js +37 -0
  434. package/validation/readLogValidator.js +64 -0
  435. package/validation/role_validation.js +320 -0
  436. package/validation/schemaMetadataValidator.js +42 -0
  437. package/validation/searchValidator.js +166 -0
  438. package/validation/statusValidator.ts +66 -0
  439. package/validation/transactionLogValidator.js +33 -0
  440. package/validation/user_validation.js +55 -0
  441. package/validation/validationWrapper.js +105 -0
  442. package/dist/resources/analytics/profile.d.ts +0 -2
  443. package/dist/resources/analytics/profile.js +0 -144
  444. package/dist/resources/analytics/profile.js.map +0 -1
@@ -0,0 +1,258 @@
1
+ import { warn } from '../utility/logging/harper_logger.js';
2
+ import { IterableEventQueue } from './IterableEventQueue.ts';
3
+ import { keyArrayToString } from './Resources.ts';
4
+ import type { Id } from './ResourceInterface.ts';
5
+
6
+ const allSubscriptions = Object.create(null); // using it as a map that doesn't change much
7
+ const allSameThreadSubscriptions = Object.create(null); // using it as a map that doesn't change much
8
+ /**
9
+ * This module/function is responsible for the main work of tracking subscriptions and listening for new transactions
10
+ * that have occurred on any thread, and then reading through the transaction log to notify listeners. This is
11
+ * responsible for cleanup of subscriptions as well.
12
+ * @param table
13
+ * @param key
14
+ * @param listener
15
+ * @param startTime
16
+ * @param options
17
+ */
18
+ export function addSubscription(table, key, listener?: (key) => any, startTime?: number, options?: any) {
19
+ const path = table.primaryStore.path;
20
+ const tableId = table.primaryStore.tableId;
21
+ // set up the subscriptions map. We want to just use a single map (per table) for efficient delegation
22
+ // (rather than having every subscriber filter every transaction)
23
+ let databaseSubscriptions;
24
+ if (options?.crossThreads === false) {
25
+ // we are only listening for commits on our own thread, so we use a separate subscriber and sequencer tracker
26
+ databaseSubscriptions = allSameThreadSubscriptions[path] || (allSameThreadSubscriptions[path] = []);
27
+ listenToCommits(table.primaryStore, table.auditStore);
28
+ } else {
29
+ databaseSubscriptions = allSubscriptions[path] || (allSubscriptions[path] = []);
30
+ const auditStore = table.auditStore;
31
+ if (!auditStore.hasSubscriptionCommitListener) {
32
+ let auditLogIterator;
33
+ if (auditStore.reusableIterable) {
34
+ // with rocksdb-js iterator we can and should not specify a start time so we just start at the end of the txn log
35
+ // and still match older version numbers that may commit in the future. But we have to start
36
+ // immediately so we are at the right position
37
+ auditLogIterator = auditStore.getRange({});
38
+ }
39
+ auditStore.hasSubscriptionCommitListener = true;
40
+ auditStore.on('committed', () => {
41
+ notifyFromTransactionData(databaseSubscriptions, auditLogIterator);
42
+ });
43
+ }
44
+ }
45
+ databaseSubscriptions.auditStore = table.auditStore;
46
+ if (databaseSubscriptions.lastTxnTime == null) {
47
+ databaseSubscriptions.lastTxnTime = Date.now();
48
+ }
49
+ if (options?.scope === 'full-database') {
50
+ return;
51
+ }
52
+ let tableSubscriptions = databaseSubscriptions[tableId];
53
+ if (!tableSubscriptions) {
54
+ tableSubscriptions = databaseSubscriptions[tableId] = new Map();
55
+ tableSubscriptions.envs = databaseSubscriptions;
56
+ tableSubscriptions.tableId = tableId;
57
+ tableSubscriptions.store = table.primaryStore;
58
+ }
59
+
60
+ key = keyArrayToString(key);
61
+ const subscription = new Subscription(listener);
62
+ subscription.startTime = startTime;
63
+ let subscriptions: any[] = tableSubscriptions.get(key);
64
+
65
+ if (subscriptions) subscriptions.push(subscription);
66
+ else {
67
+ tableSubscriptions.set(key, (subscriptions = [subscription]));
68
+ subscriptions.tables = tableSubscriptions;
69
+ subscriptions.key = key;
70
+ }
71
+ subscription.subscriptions = subscriptions;
72
+ return subscription;
73
+ }
74
+
75
+ /**
76
+ * This is the class that is returned from subscribe calls and provide the interface to set a callback, end the
77
+ * subscription and get the initial state.
78
+ */
79
+ class Subscription extends IterableEventQueue {
80
+ listener: (recordId: Id, auditEntry: any, localTime: number, beginTxn: boolean) => void;
81
+ subscriptions: [];
82
+ startTime?: number;
83
+ includeDescendants?: boolean;
84
+ supportsTransactions?: boolean;
85
+ onlyChildren?: boolean;
86
+ constructor(listener) {
87
+ super();
88
+ this.listener = listener;
89
+ this.on('close', () => this.end());
90
+ }
91
+ end() {
92
+ // cleanup
93
+ if (!this.subscriptions) return;
94
+ this.subscriptions.splice(this.subscriptions.indexOf(this), 1);
95
+ if (this.subscriptions.length === 0) {
96
+ const tableSubscriptions = this.subscriptions.tables;
97
+ if (tableSubscriptions) {
98
+ // TODO: Handle cleanup of wildcard
99
+ const key = this.subscriptions.key;
100
+ tableSubscriptions.delete(key);
101
+ if (tableSubscriptions.size === 0) {
102
+ const envSubscriptions = tableSubscriptions.envs;
103
+ const dbi = tableSubscriptions.dbi;
104
+ delete envSubscriptions[dbi];
105
+ }
106
+ }
107
+ }
108
+ this.subscriptions = null;
109
+ }
110
+ toJSON() {
111
+ return { name: 'subscription' };
112
+ }
113
+ }
114
+ const ACTIONS_OF_INTEREST = ['put', 'patch', 'delete', 'message', 'invalidate'];
115
+ function notifyFromTransactionData(subscriptions, auditLogIterable) {
116
+ if (!subscriptions) return; // if no subscriptions to this env path, don't need to read anything
117
+ const auditStore = subscriptions.auditStore;
118
+ auditStore.resetReadTxn?.();
119
+ nextTransaction(subscriptions.auditStore);
120
+ let subscribersWithTxns;
121
+ if (!auditLogIterable) {
122
+ // rocksdb will pass this in, but with lmdb, we have to re-create the iterable
123
+ auditLogIterable = auditStore.getRange({
124
+ start: subscriptions.lastTxnTime,
125
+ exclusiveStart: true,
126
+ });
127
+ }
128
+ for (const auditRecord of auditLogIterable) {
129
+ const timestamp: number = auditRecord.localTime ?? auditRecord.version;
130
+ subscriptions.lastTxnTime = timestamp;
131
+ if (!ACTIONS_OF_INTEREST.includes(auditRecord.type)) continue;
132
+ const tableSubscriptions = subscriptions[auditRecord.tableId];
133
+ if (!tableSubscriptions) continue;
134
+ const recordId = auditRecord.recordId;
135
+ // TODO: How to handle invalidation
136
+ let matchingKey = keyArrayToString(recordId);
137
+ let ancestorLevel = 0;
138
+ do {
139
+ // we iterate through the key hierarchy, notifying all subscribers for each key,
140
+ // so for an id like resource/foo/bar, we notify subscribers for resource/foo/bar, resource/foo/, resource/foo, resource/, and resource
141
+ // this allows for efficient subscriptions to children ids/topics
142
+ const keySubscriptions = tableSubscriptions.get(matchingKey);
143
+ if (keySubscriptions) {
144
+ for (const subscription of keySubscriptions) {
145
+ if (
146
+ ancestorLevel > 0 && // only ancestors if the subscription is for ancestors (and apply onlyChildren filtering as necessary)
147
+ !(subscription.includeDescendants && !(subscription.onlyChildren && ancestorLevel > 1))
148
+ )
149
+ continue;
150
+ if (subscription.startTime >= timestamp) {
151
+ continue;
152
+ }
153
+ try {
154
+ let beginTxn;
155
+ if (subscription.supportsTransactions && subscription.txnInProgress !== auditRecord.version) {
156
+ // if the subscriber supports transactions, we mark this as the beginning of a new transaction
157
+ // tracking the subscription so that we can delimit the transaction on next transaction
158
+ // (with a beginTxn flag, which may be on an endTxn event)
159
+ beginTxn = true;
160
+ if (!subscription.txnInProgress) {
161
+ // if first txn for subscriber of this cycle, add to the transactional subscribers that we are tracking
162
+ if (!subscribersWithTxns) subscribersWithTxns = [subscription];
163
+ else subscribersWithTxns.push(subscription);
164
+ }
165
+ // the version defines the extent of a transaction, all audit records with the same version
166
+ // are part of the same transaction, and when the version changes, we know it is a new
167
+ // transaction
168
+ subscription.txnInProgress = auditRecord.version;
169
+ }
170
+ subscription.listener(recordId, auditRecord, timestamp, beginTxn);
171
+ } catch (error) {
172
+ warn(error);
173
+ }
174
+ }
175
+ }
176
+ if (matchingKey == null) break;
177
+ const lastSlash = matchingKey.lastIndexOf?.('/', matchingKey.length - 2);
178
+ if (lastSlash !== matchingKey.length - 1) {
179
+ ancestorLevel++; // don't increase the ancestor level for this going from resource/ to resource
180
+ }
181
+ if (lastSlash > -1) {
182
+ matchingKey = matchingKey.slice(0, lastSlash + 1);
183
+ } else matchingKey = null;
184
+ } while (true);
185
+ }
186
+ if (subscribersWithTxns) {
187
+ // any subscribers with open transactions need to have an event to indicate that their transaction has been ended
188
+ for (const subscription of subscribersWithTxns) {
189
+ subscription.txnInProgress = null; // clean up
190
+ subscription.listener(null, { type: 'end_txn' }, subscriptions.lastTxnTime, true);
191
+ }
192
+ }
193
+ }
194
+ /**
195
+ * Interface with database to listen for commits and traverse the audit log only on the same thread.
196
+ * @param primaryStore
197
+ * @param auditStore
198
+ */
199
+ export function listenToCommits(primaryStore, auditStore) {
200
+ const store = auditStore || primaryStore;
201
+ const path = primaryStore.path;
202
+ const lmdbEnv = store.env;
203
+ if (!lmdbEnv.hasAfterCommitListener) {
204
+ lmdbEnv.hasAfterCommitListener = true;
205
+ store.on('aftercommit', (logEntries) => {
206
+ const subscriptions = allSameThreadSubscriptions[path]; // there is a different set of subscribers for same-thread subscriptions
207
+ if (!subscriptions) return;
208
+ // With RocksTransactionLog, we actually have direct access to the list of log entries:
209
+ if (Array.isArray(logEntries)) {
210
+ return notifyFromTransactionData(subscriptions, logEntries);
211
+ }
212
+ // we want each thread to do this mutually exclusively so that we don't have multiple threads trying to process the same data (the intended purpose of crossThreads=false)
213
+ const acquiredLock = () => {
214
+ // we have the lock, so we can now read the last sequence/local write time and continue to read the audit log from there
215
+ if (!store.threadLocalWrites)
216
+ // initiate the shared buffer if needed
217
+ store.threadLocalWrites = new Float64Array(
218
+ store.getUserSharedBuffer('last-thread-local-write', new ArrayBuffer(8))
219
+ );
220
+ subscriptions.txnTime = store.threadLocalWrites[0] || Date.now(); // start from last one
221
+ try {
222
+ notifyFromTransactionData(subscriptions);
223
+ } finally {
224
+ store.threadLocalWrites[0] = subscriptions.lastTxnTime; // update shared buffer
225
+ store.unlock('thread-local-writes'); // and release the lock
226
+ }
227
+ };
228
+ // try to get lock or wait for it
229
+ if (!store.tryLock('thread-local-writes', acquiredLock)) return;
230
+ acquiredLock();
231
+ });
232
+ }
233
+ }
234
+ function nextTransaction(auditStore) {
235
+ auditStore.nextTransaction?.resolve();
236
+ let nextResolve;
237
+ auditStore.nextTransaction = new Promise((resolve) => {
238
+ nextResolve = resolve;
239
+ });
240
+ auditStore.nextTransaction.resolve = nextResolve;
241
+ }
242
+
243
+ export function whenNextTransaction(auditStore) {
244
+ if (!auditStore.nextTransaction) {
245
+ addSubscription(
246
+ {
247
+ primaryStore: auditStore,
248
+ auditStore,
249
+ },
250
+ null,
251
+ null,
252
+ 0,
253
+ { scope: 'full-database' }
254
+ );
255
+ nextTransaction(auditStore);
256
+ }
257
+ return auditStore.nextTransaction;
258
+ }
@@ -0,0 +1,376 @@
1
+ import { getSuperUser } from './user.ts';
2
+ import { server } from '../server/Server.ts';
3
+ import { resources } from '../resources/Resources.ts';
4
+ import { validateOperationToken, validateRefreshToken } from './tokenAuthentication.ts';
5
+ import { table } from '../resources/databases.ts';
6
+ import { v4 as uuid } from 'uuid';
7
+ import * as env from '../utility/environment/environmentManager.js';
8
+ import { CONFIG_PARAMS, AUTH_AUDIT_STATUS, AUTH_AUDIT_TYPES } from '../utility/hdbTerms.ts';
9
+ import harperLogger from '../utility/logging/harper_logger.js';
10
+ const { forComponent, AuthAuditLog } = harperLogger;
11
+ import serverHandlers from '../server/itc/serverHandlers.js';
12
+ const { user } = serverHandlers;
13
+ import { Headers } from '../server/serverHelpers/Headers.ts';
14
+ import { convertToMS } from '../utility/common_utils.js';
15
+ import { verifyCertificate } from './certificateVerification/index.ts';
16
+ import { serializeMessage } from '../server/serverHelpers/contentTypes.ts';
17
+ const authLogger = forComponent('authentication');
18
+ const { debug } = authLogger;
19
+ const authEventLog = authLogger.withTag('auth-event');
20
+ env.initSync();
21
+
22
+ const appsCorsAccesslist = env.get(CONFIG_PARAMS.HTTP_CORSACCESSLIST);
23
+ const appsCors = env.get(CONFIG_PARAMS.HTTP_CORS);
24
+ const operationsCorsAccesslist = env.get(CONFIG_PARAMS.OPERATIONSAPI_NETWORK_CORSACCESSLIST);
25
+ const operationsCors = env.get(CONFIG_PARAMS.OPERATIONSAPI_NETWORK_CORS);
26
+
27
+ const sessionTable = table({
28
+ table: 'hdb_session',
29
+ database: 'system',
30
+ attributes: [{ name: 'id', isPrimaryKey: true }, { name: 'user' }],
31
+ });
32
+ const ENABLE_SESSIONS = env.get(CONFIG_PARAMS.AUTHENTICATION_ENABLESESSIONS) ?? true;
33
+ // check the environment for a flag to bypass authentication (for testing) since it doesn't necessarily get set on child threads
34
+ let AUTHORIZE_LOCAL =
35
+ process.env.AUTHENTICATION_AUTHORIZELOCAL ??
36
+ env.get(CONFIG_PARAMS.AUTHENTICATION_AUTHORIZELOCAL) ??
37
+ process.env.DEV_MODE;
38
+ const LOG_AUTH_SUCCESSFUL = env.get(CONFIG_PARAMS.LOGGING_AUDITAUTHEVENTS_LOGSUCCESSFUL) ?? false;
39
+ const LOG_AUTH_FAILED = env.get(CONFIG_PARAMS.LOGGING_AUDITAUTHEVENTS_LOGFAILED) ?? false;
40
+
41
+ const DEFAULT_COOKIE_EXPIRES = 'Tue, 01 Oct 8307 19:33:20 GMT';
42
+
43
+ let authorizationCache = new Map();
44
+ server.onInvalidatedUser(() => {
45
+ // TODO: Eventually we probably want to be able to invalidate individual users
46
+ authorizationCache = new Map();
47
+ });
48
+ export function bypassAuth() {
49
+ AUTHORIZE_LOCAL = true;
50
+ }
51
+
52
+ // TODO: Make this not return a promise if it can be fulfilled synchronously (from cache)
53
+ export async function authentication(request, nextHandler) {
54
+ const headers = request.headers.asObject; // we cheat and use the node headers object since it is a little faster
55
+ const authorization = headers.authorization;
56
+ const cookie = headers.cookie;
57
+ let origin = headers.origin;
58
+ let responseHeaders = [];
59
+ try {
60
+ if (origin) {
61
+ const accessList = request.isOperationsServer
62
+ ? operationsCors
63
+ ? operationsCorsAccesslist
64
+ : []
65
+ : appsCors
66
+ ? appsCorsAccesslist
67
+ : [];
68
+ if (accessList.includes(origin) || accessList.includes('*')) {
69
+ if (request.method === 'OPTIONS') {
70
+ const accessControlAllowHeaders =
71
+ env.get(CONFIG_PARAMS.HTTP_CORSACCESSCONTROLALLOWHEADERS) ?? 'Accept, Content-Type, Authorization';
72
+
73
+ // preflight request
74
+ const headers = new Headers([
75
+ ['Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, PATCH, OPTIONS'],
76
+ ['Access-Control-Allow-Headers', accessControlAllowHeaders],
77
+ ['Access-Control-Allow-Origin', origin],
78
+ ]);
79
+ if (ENABLE_SESSIONS) headers.set('Access-Control-Allow-Credentials', 'true');
80
+ return {
81
+ status: 200,
82
+ headers,
83
+ };
84
+ }
85
+ responseHeaders.push('Access-Control-Allow-Origin', origin);
86
+ if (ENABLE_SESSIONS) responseHeaders.push('Access-Control-Allow-Credentials', 'true');
87
+ }
88
+ }
89
+ let sessionId;
90
+ let session;
91
+ if (ENABLE_SESSIONS) {
92
+ // we prefix the cookie name with the origin so that we can partition/separate session/authentications
93
+ // host, to protect against CSRF
94
+ if (!origin) origin = headers.host;
95
+ const cookiePrefix = (origin ? origin.replace(/^https?:\/\//, '').replace(/\W/, '_') + '-' : '') + 'hdb-session=';
96
+ const cookies = cookie?.split(/;\s+/) || [];
97
+ for (const cookie of cookies) {
98
+ if (cookie.startsWith(cookiePrefix)) {
99
+ const end = cookie.indexOf(';');
100
+ sessionId = cookie.slice(cookiePrefix.length, end === -1 ? cookie.length : end);
101
+ session = await sessionTable.get(sessionId);
102
+ break;
103
+ }
104
+ }
105
+ request.session = session ? { ...session } : (session = {});
106
+ }
107
+
108
+ const authAuditLog = (username, status, strategy) => {
109
+ const log = new AuthAuditLog(
110
+ username,
111
+ status,
112
+ AUTH_AUDIT_TYPES.AUTHENTICATION,
113
+ headers['x-forwarded-for'] ?? request.ip,
114
+ request.method,
115
+ request.pathname
116
+ );
117
+ log.auth_strategy = strategy;
118
+ if (sessionId) log.session_id = sessionId;
119
+ if (headers['referer']) log.referer = headers['referer'];
120
+ if (headers['origin']) log.origin = headers['origin'];
121
+
122
+ if (status === AUTH_AUDIT_STATUS.SUCCESS) authEventLog.info?.(log);
123
+ else authEventLog.error?.(log);
124
+ };
125
+
126
+ if (
127
+ !request.authorized &&
128
+ request.mtlsConfig &&
129
+ request.peerCertificate.subject &&
130
+ request?._nodeRequest?.socket?.authorizationError
131
+ )
132
+ authEventLog.error?.('Authorization error:', request._nodeRequest.socket.authorizationError);
133
+
134
+ if (request.mtlsConfig && request.authorized && request.peerCertificate.subject) {
135
+ const verificationResult = await verifyCertificate(request.peerCertificate, request.mtlsConfig);
136
+ if (!verificationResult.valid) {
137
+ authEventLog.error?.(
138
+ 'Certificate verification failed:',
139
+ verificationResult.status,
140
+ 'for',
141
+ request.peerCertificate.subject.CN
142
+ );
143
+ return applyResponseHeaders({
144
+ status: 401,
145
+ body: serializeMessage({ error: 'Certificate revoked or verification failed' }, request),
146
+ });
147
+ }
148
+
149
+ // Alternative behavior: Instead of returning 401 above, we could just not set the user
150
+ // and let authentication fall through to other methods (Basic auth, etc.):
151
+ // if (verificationResult.valid) {
152
+ // // Only extract user from certificate if verification passed
153
+ // let username = ...
154
+ // }
155
+
156
+ let username = request.mtlsConfig.user;
157
+ if (username !== null) {
158
+ // null means no user is defined from certificate, need regular authentication as well
159
+ if (username === undefined || username === 'Common Name' || username === 'CN')
160
+ username = request.peerCertificate.subject.CN;
161
+ request.user = await server.getUser(username, null, request);
162
+ authAuditLog(username, AUTH_AUDIT_STATUS.SUCCESS, 'mTLS');
163
+ } else {
164
+ debug('HTTPS/WSS mTLS authorized connection (mTLS did not authorize a user)', 'from', request.ip);
165
+ }
166
+ }
167
+
168
+ let newUser;
169
+ if (request.user) {
170
+ // already authenticated
171
+ } else if (authorization) {
172
+ const cachedUser = authorizationCache.get(authorization);
173
+ if (cachedUser?.role) {
174
+ // Shallow-clone so verifyPerms's `role.permission = fullRolePerms` reassignment
175
+ // doesn't mutate the cache entry (defense-in-depth; operations and other
176
+ // meta-permission fields are now preserved through translation in permissionsTranslator).
177
+ newUser = { ...cachedUser, role: { ...cachedUser.role, permission: { ...cachedUser.role.permission } } };
178
+ } else if (cachedUser) {
179
+ newUser = cachedUser;
180
+ }
181
+ if (!newUser) {
182
+ const spaceIndex = authorization.indexOf(' ');
183
+ const strategy = authorization.slice(0, spaceIndex);
184
+ const credentials = authorization.slice(spaceIndex + 1);
185
+ let username, password;
186
+ try {
187
+ switch (strategy) {
188
+ case 'Basic':
189
+ const decoded = atob(credentials);
190
+ const colonIndex = decoded.indexOf(':');
191
+ username = decoded.slice(0, colonIndex);
192
+ password = decoded.slice(colonIndex + 1);
193
+ // legacy support for passing in blank username and password to indicate no auth
194
+ newUser = username || password ? await server.getUser(username, password, request) : null;
195
+ break;
196
+ case 'Bearer':
197
+ try {
198
+ newUser = await validateOperationToken(credentials);
199
+ } catch (error) {
200
+ if (error.message === 'invalid token') {
201
+ // see if they provided a refresh token; we can allow that and pass it on to operations API
202
+ try {
203
+ await validateRefreshToken(credentials);
204
+ return applyResponseHeaders({
205
+ // we explicitly declare we don't want to handle this because the operations
206
+ // API has its own logic for handling this
207
+ status: -1,
208
+ });
209
+ } catch {
210
+ throw error;
211
+ }
212
+ }
213
+ }
214
+ break;
215
+ }
216
+ } catch (err) {
217
+ if (LOG_AUTH_FAILED) {
218
+ const failedAttempt = authorizationCache.get(credentials);
219
+ if (!failedAttempt) {
220
+ authorizationCache.set(credentials, credentials);
221
+ authAuditLog(username, AUTH_AUDIT_STATUS.FAILURE, strategy);
222
+ }
223
+ }
224
+
225
+ return applyResponseHeaders({
226
+ status: 401,
227
+ body: serializeMessage({ error: err.message }, request),
228
+ });
229
+ }
230
+
231
+ authorizationCache.set(authorization, newUser);
232
+ if (LOG_AUTH_SUCCESSFUL) authAuditLog(newUser.username, AUTH_AUDIT_STATUS.SUCCESS, strategy);
233
+ // Shallow-clone so verifyPerms's `role.permission = fullRolePerms` reassignment
234
+ // doesn't mutate the just-stored cache entry (defense-in-depth).
235
+ if (newUser?.role) {
236
+ newUser = { ...newUser, role: { ...newUser.role, permission: { ...newUser.role.permission } } };
237
+ }
238
+ }
239
+
240
+ request.user = newUser;
241
+ } else if (session?.user) {
242
+ // or should this be cached in the session?
243
+ request.user = await server.getUser(session.user, null, request);
244
+ } else if (
245
+ (AUTHORIZE_LOCAL && (request.ip?.includes('127.0.0.') || request.ip == '::1')) ||
246
+ (request?._nodeRequest?.socket?.server?._pipeName && request.ip === undefined) // allow socket domain
247
+ ) {
248
+ request.user = await getSuperUser();
249
+ }
250
+ if (ENABLE_SESSIONS) {
251
+ request.session.update = function (updatedSession) {
252
+ const expires = env.get(CONFIG_PARAMS.AUTHENTICATION_COOKIE_EXPIRES);
253
+ const useSecure =
254
+ request.protocol === 'https' ||
255
+ headers.host?.startsWith('localhost:') ||
256
+ headers.host?.startsWith('127.0.0.1:') ||
257
+ headers.host?.startsWith('::1');
258
+ if (!sessionId) {
259
+ sessionId = uuid();
260
+ const domains = env.get(CONFIG_PARAMS.AUTHENTICATION_COOKIE_DOMAINS);
261
+ const expiresString = expires
262
+ ? new Date(Date.now() + convertToMS(expires)).toUTCString()
263
+ : DEFAULT_COOKIE_EXPIRES;
264
+ const domain =
265
+ headers.host &&
266
+ domains?.find((domain) => {
267
+ // find a domain that matches the host header
268
+ // the configured cookie domain starts with a dot, that indicates a wildcard, so we need to remove it
269
+ if (domain.startsWith('.')) domain = domain.slice(1);
270
+ // host can have a port, so we need to remove it because we are comparing domain names
271
+ const portStart = headers.host.indexOf(':');
272
+ const host = portStart !== -1 ? headers.host.slice(0, portStart) : headers.host;
273
+ return host.endsWith(domain);
274
+ });
275
+ const cookiePrefix =
276
+ (origin ? origin.replace(/^https?:\/\//, '').replace(/\W/, '_') + '-' : '') + 'hdb-session=';
277
+ // "Secure" can work with localhost/127.0.0.1 in certain browsers.
278
+ // https://github.com/httpwg/http-extensions/issues/2605
279
+ let cookie = `${cookiePrefix}${sessionId}; Path=/; Expires=${expiresString}; HttpOnly`;
280
+ if (domain) {
281
+ cookie += `; Domain=${domain}`;
282
+ }
283
+
284
+ if (useSecure) {
285
+ cookie += `; SameSite=None; Secure`;
286
+ }
287
+ if (responseHeaders) {
288
+ responseHeaders.push('Set-Cookie', cookie);
289
+ } else if (response?.headers?.set) {
290
+ response.headers.set('Set-Cookie', cookie);
291
+ }
292
+ }
293
+ if (useSecure) {
294
+ // Indicate that we have successfully updated a session
295
+ // We make sure this is allowed by CORS so that a client can determine if it has
296
+ // a valid cookie-authenticated session (studio needs this)
297
+ if (responseHeaders) {
298
+ if (origin) responseHeaders.push('Access-Control-Expose-Headers', 'X-Hdb-Session');
299
+ responseHeaders.push('X-Hdb-Session', 'Secure');
300
+ } else if (response?.headers?.set) {
301
+ if (origin) response.headers.set('Access-Control-Expose-Headers', 'X-Hdb-Session');
302
+ response.headers.set('X-Hdb-Session', 'Secure');
303
+ }
304
+ }
305
+ updatedSession.id = sessionId;
306
+ return sessionTable.put(updatedSession, {
307
+ expiresAt: expires ? Date.now() + convertToMS(expires) : undefined,
308
+ });
309
+ };
310
+ request.login = async function (username: string, password: string) {
311
+ const user: any = (request.user = await server.authenticateUser(username, password, request));
312
+ request.session.update({ user: user && (user.getId?.() ?? user.username) });
313
+ };
314
+ }
315
+ const response = await nextHandler(request);
316
+ if (!response) return response;
317
+ if (response.status === 401) {
318
+ if (
319
+ headers['user-agent']?.startsWith('Mozilla') &&
320
+ headers.accept?.startsWith('text/html') &&
321
+ resources.loginPath
322
+ ) {
323
+ // on the web if we have a login page, default to redirecting to it
324
+ response.status = 302;
325
+ response.headers.set('Location', resources.loginPath(request));
326
+ } // the HTTP specified way of indicating HTTP authentication methods supported:
327
+ else response.headers.set('WWW-Authenticate', 'Basic');
328
+ }
329
+ return applyResponseHeaders(response);
330
+ } catch (error) {
331
+ throw applyResponseHeaders(error);
332
+ }
333
+ function applyResponseHeaders(response) {
334
+ const l = responseHeaders.length;
335
+ if (l > 0) {
336
+ let headers = response.headers;
337
+ if (!headers) response.headers = headers = new Headers();
338
+ for (let i = 0; i < l; ) {
339
+ const name = responseHeaders[i++];
340
+ headers.set(name, responseHeaders[i++]);
341
+ }
342
+ }
343
+ responseHeaders = null;
344
+ return response;
345
+ }
346
+ }
347
+ let started;
348
+ export function start({ server, port, securePort }) {
349
+ server.http(authentication, port || securePort ? { port, securePort } : { port: 'all' });
350
+ // keep it cleaned out periodically
351
+ if (!started) {
352
+ started = true;
353
+ setInterval(() => {
354
+ authorizationCache = new Map();
355
+ }, env.get(CONFIG_PARAMS.AUTHENTICATION_CACHETTL)).unref();
356
+ user.addListener(() => {
357
+ authorizationCache = new Map();
358
+ });
359
+ }
360
+ }
361
+ // operations
362
+ export async function login(loginObject) {
363
+ if (!loginObject.baseRequest?.login) throw new Error('No session for login');
364
+ // intercept any attempts to set headers on the standard response object and pass them on to fastify
365
+ loginObject.baseResponse.headers.set = (name, value) => {
366
+ loginObject.fastifyResponse.header(name, value);
367
+ };
368
+ await loginObject.baseRequest.login(loginObject.username, loginObject.password ?? '');
369
+ return 'Login successful';
370
+ }
371
+
372
+ export async function logout(logoutObject) {
373
+ if (!logoutObject.baseRequest.session) throw new Error('No session for logout');
374
+ await logoutObject.baseRequest.session.update({ user: null });
375
+ return 'Logout successful';
376
+ }