@joystick.js/db-canary 0.0.0-canary.2209
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.build/getFilesToBuild.js +26 -0
- package/.build/getPlatformSafeFilePath.js +6 -0
- package/.build/getPlatformSafePath.js +6 -0
- package/.build/index.js +88 -0
- package/.build/isWindows.js +3 -0
- package/API_KEY +1 -0
- package/README.md +1821 -0
- package/data/data.mdb +0 -0
- package/data/lock.mdb +0 -0
- package/dist/client/database.js +1 -0
- package/dist/client/index.js +1 -0
- package/dist/server/cluster/index.js +1 -0
- package/dist/server/cluster/master.js +20 -0
- package/dist/server/cluster/worker.js +1 -0
- package/dist/server/index.js +1 -0
- package/dist/server/lib/api_key_manager.js +9 -0
- package/dist/server/lib/auth_manager.js +1 -0
- package/dist/server/lib/auto_index_manager.js +1 -0
- package/dist/server/lib/backup_manager.js +1 -0
- package/dist/server/lib/connection_manager.js +1 -0
- package/dist/server/lib/disk_utils.js +2 -0
- package/dist/server/lib/http_server.js +405 -0
- package/dist/server/lib/index_manager.js +1 -0
- package/dist/server/lib/load_settings.js +1 -0
- package/dist/server/lib/logger.js +1 -0
- package/dist/server/lib/op_types.js +1 -0
- package/dist/server/lib/operation_dispatcher.js +1 -0
- package/dist/server/lib/operations/admin.js +1 -0
- package/dist/server/lib/operations/bulk_write.js +1 -0
- package/dist/server/lib/operations/create_index.js +1 -0
- package/dist/server/lib/operations/delete_one.js +1 -0
- package/dist/server/lib/operations/drop_index.js +1 -0
- package/dist/server/lib/operations/find.js +1 -0
- package/dist/server/lib/operations/find_one.js +1 -0
- package/dist/server/lib/operations/get_indexes.js +1 -0
- package/dist/server/lib/operations/insert_one.js +1 -0
- package/dist/server/lib/operations/update_one.js +1 -0
- package/dist/server/lib/performance_monitor.js +1 -0
- package/dist/server/lib/query_engine.js +1 -0
- package/dist/server/lib/recovery_manager.js +1 -0
- package/dist/server/lib/replication_manager.js +1 -0
- package/dist/server/lib/safe_json_parse.js +1 -0
- package/dist/server/lib/send_response.js +1 -0
- package/dist/server/lib/tcp_protocol.js +1 -0
- package/dist/server/lib/write_forwarder.js +1 -0
- package/dist/server/lib/write_queue.js +1 -0
- package/increment_version.js +3 -0
- package/logs/.013e15b54597d05db4b4b53ecc37b10c92a72927-audit.json +20 -0
- package/logs/.02de550a67ea0f5961faa2dfd458a4d06f59ebd1-audit.json +20 -0
- package/logs/.03494ba24eb3c72214b4068a77d54b8993bee651-audit.json +20 -0
- package/logs/.06309ec60b339be1259a7993dd09c732f8907fbc-audit.json +20 -0
- package/logs/.0663a04dcfa17285661e5e1b8cfa51f41523b210-audit.json +20 -0
- package/logs/.0f06e6c4c9b824622729e13927587479e5060391-audit.json +20 -0
- package/logs/.16ccf58682ecb22b3e3ec63f0da1b7fe9be56528-audit.json +20 -0
- package/logs/.1fa1a5d02f496474b1ab473524c65c984146a9ad-audit.json +20 -0
- package/logs/.2223c0ae3bea6f0d62c62b1d319cc8634856abb7-audit.json +20 -0
- package/logs/.23dc79ffda3e083665e6f5993f59397adcbf4a46-audit.json +20 -0
- package/logs/.28104f49b03906b189eefd1cd462cb46c3c0af22-audit.json +20 -0
- package/logs/.29cdbf13808abe6a0ce70ee2f2efdd680ce3fd8e-audit.json +20 -0
- package/logs/.2a9889afd071f77f41f5170d08703a0afca866b7-audit.json +20 -0
- package/logs/.2acec3d1940a2bbed487528b703ee5948959a599-audit.json +20 -0
- package/logs/.2fb60ff326338c02bfedbcd0e936444e4a216750-audit.json +20 -0
- package/logs/.318fc7a19530d76a345f030f7cad00dda15300e7-audit.json +20 -0
- package/logs/.3cf27043e19085f908cedc7701e6d013463208ee-audit.json +25 -0
- package/logs/.3d90d785415817fc443402843b7c95f8371adc9b-audit.json +20 -0
- package/logs/.4074bca620375f72966fc52dfd439577727671e5-audit.json +20 -0
- package/logs/.40eecf018417ea80a70ea8ec7a3cc9406bc6334b-audit.json +20 -0
- package/logs/.50e974f1ef7c365fca6a1251b2e2c2252914cb5e-audit.json +20 -0
- package/logs/.52cb7d9e4223cf26ba36006ac26b949a97c7923c-audit.json +20 -0
- package/logs/.54befcdb84c15aad980705a31bcc9f555c3577ab-audit.json +20 -0
- package/logs/.57dfb70e22eddb84db2e3c0ceeefac5c0b9baffa-audit.json +20 -0
- package/logs/.5f0b24705a1eaad4eca4968f2d86f91b3f9be683-audit.json +20 -0
- package/logs/.61ba98fdda7db58576b382fee07904e5db1169d6-audit.json +20 -0
- package/logs/.6235017727ef6b199d569a99d6aa8c8e80a1b475-audit.json +20 -0
- package/logs/.63db16193699219489d218a1ddea5dde3750cae4-audit.json +20 -0
- package/logs/.64fb67dfe14149c9eef728d79bf30a54da809c60-audit.json +20 -0
- package/logs/.669137453368987c1f311b5345342527afb54e50-audit.json +20 -0
- package/logs/.7a71f8c89ea28ae266d356aeff6306e876a30fbb-audit.json +20 -0
- package/logs/.7afbaa90fe9dc3a7d682676f9bb79f9a1b1fd9a6-audit.json +20 -0
- package/logs/.7ca29e322cd05327035de850099e7610864f2347-audit.json +20 -0
- package/logs/.83335ab3347e449dae03455a110aaf7f120d4802-audit.json +20 -0
- package/logs/.8c2487b5fd445d2c8e5c483c80b9fa99bbf1ca58-audit.json +20 -0
- package/logs/.8c8b9dc386922c9f3b4c13251af7052aac1d24c0-audit.json +20 -0
- package/logs/.8d6155d94640c4863301ae0fee5e4e7372a21446-audit.json +20 -0
- package/logs/.944a3119a243deea7c8270d5d9e582bb1d0eaa10-audit.json +20 -0
- package/logs/.9816a845c30fb2909f3b26a23eeb3538ebcad5db-audit.json +20 -0
- package/logs/.9dc08784e38b865488177c26d4af5934555e0323-audit.json +20 -0
- package/logs/.9dd27d2e0e454ac0a37600206d1cac5493b0d7ee-audit.json +20 -0
- package/logs/.a3d486feeac7654c59b547de96600e8849a06d4f-audit.json +20 -0
- package/logs/.a5b811f4def22250f86cc18870d7c4573625df22-audit.json +20 -0
- package/logs/.a61648eb5f830e0b6f508ac35e4f8f629d2ad4c7-audit.json +20 -0
- package/logs/.a89016d507045771b4b5a65656944a9c0f1e528b-audit.json +20 -0
- package/logs/.a99bee160a1c590be959af46bacc02724803f691-audit.json +20 -0
- package/logs/.ada7906d6243fd7da802f03d86c4ae5dd9df6236-audit.json +20 -0
- package/logs/.b518339ee942143b6af983af167f5bbb6983b4de-audit.json +20 -0
- package/logs/.b51b124b166d53c9519017856ea610d61d65fabe-audit.json +20 -0
- package/logs/.b7a6aee19f58e55633d5e4a3709041c47dfff975-audit.json +20 -0
- package/logs/.bd7a8a6ba9c55d557a4867ab53f02e3ec2e1553d-audit.json +20 -0
- package/logs/.c1435dafe453b169d6392b25065f3cf4ab6fbb21-audit.json +20 -0
- package/logs/.c17e1ce043109f77dc2f0e2aa290a9d1ed842c03-audit.json +20 -0
- package/logs/.ca62637ce9540e5a38a2fbedb2115febb6ad308a-audit.json +15 -0
- package/logs/.ccee67b9c176967f8977071409a41f5cb5cd6ad4-audit.json +20 -0
- package/logs/.db24043417ea79a6f14cd947476399e53930b48d-audit.json +20 -0
- package/logs/.e0f12acccb57829f5f33712bb2e2607ecd808147-audit.json +20 -0
- package/logs/.e9b6cc33d0bbd2e644c4e2bf44d177f850016557-audit.json +20 -0
- package/logs/.f15291d434808e3bdca7963ccd2e73893be027e6-audit.json +20 -0
- package/logs/.f4bdf9e21ef84f8a3fae3ffb32bbc39275991351-audit.json +15 -0
- package/logs/.fbac3aefac1e81b4230df5aa50667cb90d51024f-audit.json +20 -0
- package/logs/.fcfd495c0a9169db243f4a4f21878ee02b76413c-audit.json +20 -0
- package/logs/admin-2025-09-12.log +580 -0
- package/logs/admin-2025-09-15.log +283 -0
- package/logs/admin-error-2025-09-12.log +22 -0
- package/logs/admin-error-2025-09-15.log +10 -0
- package/logs/api_key_manager-2025-09-12.log +658 -0
- package/logs/api_key_manager-2025-09-15.log +295 -0
- package/logs/api_key_manager-error-2025-09-12.log +0 -0
- package/logs/api_key_manager-error-2025-09-15.log +0 -0
- package/logs/auth_manager-2025-09-12.log +4432 -0
- package/logs/auth_manager-2025-09-15.log +2000 -0
- package/logs/auth_manager-error-2025-09-12.log +11 -0
- package/logs/auth_manager-error-2025-09-15.log +5 -0
- package/logs/auto_index_manager-2025-09-12.log +84 -0
- package/logs/auto_index_manager-2025-09-15.log +45 -0
- package/logs/auto_index_manager-error-2025-09-12.log +6 -0
- package/logs/auto_index_manager-error-2025-09-15.log +0 -0
- package/logs/backup_manager-2025-09-12.log +198 -0
- package/logs/backup_manager-2025-09-15.log +90 -0
- package/logs/backup_manager-error-2025-09-12.log +198 -0
- package/logs/backup_manager-error-2025-09-15.log +90 -0
- package/logs/bulk_write-2025-09-12.log +66 -0
- package/logs/bulk_write-2025-09-15.log +38 -0
- package/logs/bulk_write-error-2025-09-12.log +0 -0
- package/logs/bulk_write-error-2025-09-15.log +0 -0
- package/logs/connection_manager-2025-09-12.log +2412 -0
- package/logs/connection_manager-2025-09-15.log +1132 -0
- package/logs/connection_manager-error-2025-09-12.log +0 -0
- package/logs/connection_manager-error-2025-09-15.log +0 -0
- package/logs/create_index-2025-09-12.log +302 -0
- package/logs/create_index-2025-09-15.log +158 -0
- package/logs/create_index-error-2025-09-12.log +30 -0
- package/logs/create_index-error-2025-09-15.log +13 -0
- package/logs/delete_one-2025-09-12.log +73 -0
- package/logs/delete_one-2025-09-15.log +43 -0
- package/logs/delete_one-error-2025-09-12.log +0 -0
- package/logs/delete_one-error-2025-09-15.log +0 -0
- package/logs/disk_utils-2025-09-12.log +4954 -0
- package/logs/disk_utils-2025-09-15.log +2446 -0
- package/logs/disk_utils-error-2025-09-12.log +0 -0
- package/logs/disk_utils-error-2025-09-15.log +0 -0
- package/logs/drop_index-2025-09-12.log +41 -0
- package/logs/drop_index-2025-09-15.log +23 -0
- package/logs/drop_index-error-2025-09-12.log +11 -0
- package/logs/drop_index-error-2025-09-15.log +5 -0
- package/logs/find-2025-09-12.log +1050 -0
- package/logs/find-2025-09-15.log +592 -0
- package/logs/find-error-2025-09-12.log +1 -0
- package/logs/find-error-2025-09-15.log +0 -0
- package/logs/find_one-2025-09-12.log +425 -0
- package/logs/find_one-2025-09-15.log +264 -0
- package/logs/find_one-error-2025-09-12.log +5 -0
- package/logs/find_one-error-2025-09-15.log +0 -0
- package/logs/get_indexes-2025-09-12.log +84 -0
- package/logs/get_indexes-2025-09-15.log +56 -0
- package/logs/get_indexes-error-2025-09-12.log +6 -0
- package/logs/get_indexes-error-2025-09-15.log +0 -0
- package/logs/http_server-2025-09-12.log +2772 -0
- package/logs/http_server-2025-09-15.log +1276 -0
- package/logs/http_server-error-2025-09-12.log +212 -0
- package/logs/http_server-error-2025-09-15.log +44 -0
- package/logs/index_manager-2025-09-12.log +5031 -0
- package/logs/index_manager-2025-09-15.log +2909 -0
- package/logs/index_manager-error-2025-09-12.log +80 -0
- package/logs/index_manager-error-2025-09-15.log +38 -0
- package/logs/insert_one-2025-09-12.log +2181 -0
- package/logs/insert_one-2025-09-15.log +1293 -0
- package/logs/insert_one-error-2025-09-12.log +0 -0
- package/logs/insert_one-error-2025-09-15.log +0 -0
- package/logs/master-2025-09-12.log +1882 -0
- package/logs/master-2025-09-15.log +910 -0
- package/logs/master-error-2025-09-12.log +80 -0
- package/logs/master-error-2025-09-15.log +0 -0
- package/logs/operation_dispatcher-2025-09-12.log +751 -0
- package/logs/operation_dispatcher-2025-09-15.log +359 -0
- package/logs/operation_dispatcher-error-2025-09-12.log +33 -0
- package/logs/operation_dispatcher-error-2025-09-15.log +11 -0
- package/logs/performance_monitor-2025-09-12.log +14889 -0
- package/logs/performance_monitor-2025-09-15.log +6803 -0
- package/logs/performance_monitor-error-2025-09-12.log +0 -0
- package/logs/performance_monitor-error-2025-09-15.log +0 -0
- package/logs/query_engine-2025-09-12.log +5310 -0
- package/logs/query_engine-2025-09-15.log +2639 -0
- package/logs/query_engine-error-2025-09-12.log +0 -0
- package/logs/query_engine-error-2025-09-15.log +0 -0
- package/logs/recovery_manager-2025-09-12.log +462 -0
- package/logs/recovery_manager-2025-09-15.log +210 -0
- package/logs/recovery_manager-error-2025-09-12.log +22 -0
- package/logs/recovery_manager-error-2025-09-15.log +10 -0
- package/logs/replication-2025-09-12.log +1923 -0
- package/logs/replication-2025-09-15.log +917 -0
- package/logs/replication-error-2025-09-12.log +33 -0
- package/logs/replication-error-2025-09-15.log +15 -0
- package/logs/server-2025-09-12.log +2601 -0
- package/logs/server-2025-09-15.log +1191 -0
- package/logs/server-error-2025-09-12.log +0 -0
- package/logs/server-error-2025-09-15.log +0 -0
- package/logs/tcp_protocol-2025-09-12.log +22 -0
- package/logs/tcp_protocol-2025-09-15.log +10 -0
- package/logs/tcp_protocol-error-2025-09-12.log +22 -0
- package/logs/tcp_protocol-error-2025-09-15.log +10 -0
- package/logs/test-2025-09-12.log +0 -0
- package/logs/test-2025-09-15.log +0 -0
- package/logs/test-error-2025-09-12.log +0 -0
- package/logs/test-error-2025-09-15.log +0 -0
- package/logs/update_one-2025-09-12.log +173 -0
- package/logs/update_one-2025-09-15.log +118 -0
- package/logs/update_one-error-2025-09-12.log +0 -0
- package/logs/update_one-error-2025-09-15.log +0 -0
- package/logs/worker-2025-09-12.log +1457 -0
- package/logs/worker-2025-09-15.log +695 -0
- package/logs/worker-error-2025-09-12.log +0 -0
- package/logs/worker-error-2025-09-15.log +0 -0
- package/logs/write_forwarder-2025-09-12.log +1956 -0
- package/logs/write_forwarder-2025-09-15.log +932 -0
- package/logs/write_forwarder-error-2025-09-12.log +66 -0
- package/logs/write_forwarder-error-2025-09-15.log +30 -0
- package/logs/write_queue-2025-09-12.log +612 -0
- package/logs/write_queue-2025-09-15.log +301 -0
- package/logs/write_queue-error-2025-09-12.log +184 -0
- package/logs/write_queue-error-2025-09-15.log +83 -0
- package/package.json +48 -0
- package/prompts/01-core-infrastructure.md +56 -0
- package/prompts/02-secondary-indexing.md +65 -0
- package/prompts/03-write-serialization.md +63 -0
- package/prompts/04-enhanced-authentication.md +75 -0
- package/prompts/05-comprehensive-admin-operations.md +75 -0
- package/prompts/06-backup-and-restore-system.md +106 -0
- package/prompts/07-production-safety-features.md +107 -0
- package/prompts/08-tcp-client-library.md +121 -0
- package/prompts/09-api-method-chaining.md +134 -0
- package/prompts/10-automatic-index-creation.md +223 -0
- package/prompts/11-operation-naming-consistency.md +268 -0
- package/prompts/12-tcp-replication-system.md +333 -0
- package/prompts/13-master-read-write-operations.md +57 -0
- package/prompts/14-index-upsert-operations.md +68 -0
- package/prompts/15-client-api-return-types.md +81 -0
- package/prompts/16-server-setup-ui.md +97 -0
- package/prompts/17-emergency-password-change.md +108 -0
- package/prompts/18-joystick-framework-integration.md +116 -0
- package/prompts/19-api-key-authentication-system.md +137 -0
- package/prompts/20-configurable-server-port.md +105 -0
- package/prompts/21-multi-database-support.md +161 -0
- package/prompts/FULL_TEXT_SEARCH.md +293 -0
- package/prompts/PROMPTS.md +158 -0
- package/prompts/README.md +221 -0
- package/prompts/TYPESCRIPT_GENERATION.md +179 -0
- package/src/client/database.js +166 -0
- package/src/client/index.js +752 -0
- package/src/server/cluster/index.js +53 -0
- package/src/server/cluster/master.js +774 -0
- package/src/server/cluster/worker.js +537 -0
- package/src/server/index.js +540 -0
- package/src/server/lib/api_key_manager.js +473 -0
- package/src/server/lib/auth_manager.js +375 -0
- package/src/server/lib/auto_index_manager.js +681 -0
- package/src/server/lib/backup_manager.js +650 -0
- package/src/server/lib/connection_manager.js +218 -0
- package/src/server/lib/disk_utils.js +118 -0
- package/src/server/lib/http_server.js +1165 -0
- package/src/server/lib/index_manager.js +756 -0
- package/src/server/lib/load_settings.js +143 -0
- package/src/server/lib/logger.js +135 -0
- package/src/server/lib/op_types.js +29 -0
- package/src/server/lib/operation_dispatcher.js +268 -0
- package/src/server/lib/operations/admin.js +808 -0
- package/src/server/lib/operations/bulk_write.js +367 -0
- package/src/server/lib/operations/create_index.js +68 -0
- package/src/server/lib/operations/delete_one.js +114 -0
- package/src/server/lib/operations/drop_index.js +58 -0
- package/src/server/lib/operations/find.js +340 -0
- package/src/server/lib/operations/find_one.js +319 -0
- package/src/server/lib/operations/get_indexes.js +52 -0
- package/src/server/lib/operations/insert_one.js +113 -0
- package/src/server/lib/operations/update_one.js +225 -0
- package/src/server/lib/performance_monitor.js +313 -0
- package/src/server/lib/query_engine.js +243 -0
- package/src/server/lib/recovery_manager.js +388 -0
- package/src/server/lib/replication_manager.js +727 -0
- package/src/server/lib/safe_json_parse.js +21 -0
- package/src/server/lib/send_response.js +47 -0
- package/src/server/lib/tcp_protocol.js +130 -0
- package/src/server/lib/write_forwarder.js +636 -0
- package/src/server/lib/write_queue.js +335 -0
- package/test_data/data.mdb +0 -0
- package/test_data/lock.mdb +0 -0
- package/tests/client/index.test.js +1232 -0
- package/tests/server/cluster/cluster.test.js +248 -0
- package/tests/server/cluster/master_read_write_operations.test.js +577 -0
- package/tests/server/index.test.js +651 -0
- package/tests/server/integration/authentication_integration.test.js +294 -0
- package/tests/server/integration/auto_indexing_integration.test.js +268 -0
- package/tests/server/integration/backup_integration.test.js +513 -0
- package/tests/server/integration/indexing_integration.test.js +126 -0
- package/tests/server/integration/production_safety_integration.test.js +358 -0
- package/tests/server/integration/replication_integration.test.js +227 -0
- package/tests/server/integration/write_serialization_integration.test.js +246 -0
- package/tests/server/lib/api_key_manager.test.js +516 -0
- package/tests/server/lib/auth_manager.test.js +317 -0
- package/tests/server/lib/auto_index_manager.test.js +275 -0
- package/tests/server/lib/backup_manager.test.js +238 -0
- package/tests/server/lib/connection_manager.test.js +221 -0
- package/tests/server/lib/disk_utils.test.js +63 -0
- package/tests/server/lib/http_server.test.js +389 -0
- package/tests/server/lib/index_manager.test.js +301 -0
- package/tests/server/lib/load_settings.test.js +107 -0
- package/tests/server/lib/load_settings_port_config.test.js +243 -0
- package/tests/server/lib/logger.test.js +282 -0
- package/tests/server/lib/operations/admin.test.js +638 -0
- package/tests/server/lib/operations/bulk_write.test.js +128 -0
- package/tests/server/lib/operations/create_index.test.js +138 -0
- package/tests/server/lib/operations/delete_one.test.js +52 -0
- package/tests/server/lib/operations/drop_index.test.js +72 -0
- package/tests/server/lib/operations/find.test.js +93 -0
- package/tests/server/lib/operations/find_one.test.js +91 -0
- package/tests/server/lib/operations/get_indexes.test.js +87 -0
- package/tests/server/lib/operations/insert_one.test.js +42 -0
- package/tests/server/lib/operations/update_one.test.js +89 -0
- package/tests/server/lib/performance_monitor.test.js +185 -0
- package/tests/server/lib/query_engine.test.js +46 -0
- package/tests/server/lib/recovery_manager.test.js +414 -0
- package/tests/server/lib/replication_manager.test.js +202 -0
- package/tests/server/lib/safe_json_parse.test.js +45 -0
- package/tests/server/lib/send_response.test.js +155 -0
- package/tests/server/lib/tcp_protocol.test.js +169 -0
- package/tests/server/lib/write_forwarder.test.js +258 -0
- package/tests/server/lib/write_queue.test.js +255 -0
- package/tsconfig.json +30 -0
- package/types/client/index.d.ts +447 -0
- package/types/server/cluster/index.d.ts +28 -0
- package/types/server/cluster/master.d.ts +115 -0
- package/types/server/cluster/worker.d.ts +1 -0
- package/types/server/lib/auth_manager.d.ts +13 -0
- package/types/server/lib/backup_manager.d.ts +43 -0
- package/types/server/lib/connection_manager.d.ts +15 -0
- package/types/server/lib/disk_utils.d.ts +3 -0
- package/types/server/lib/index_manager.d.ts +24 -0
- package/types/server/lib/load_settings.d.ts +4 -0
- package/types/server/lib/logger.d.ts +44 -0
- package/types/server/lib/op_types.d.ts +6 -0
- package/types/server/lib/performance_monitor.d.ts +68 -0
- package/types/server/lib/query_engine.d.ts +10 -0
- package/types/server/lib/safe_json_parse.d.ts +7 -0
- package/types/server/lib/send_response.d.ts +3 -0
- package/types/server/lib/tcp_protocol.d.ts +12 -0
- package/types/server/lib/write_queue.d.ts +2 -0
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Authentication manager with rate limiting, IP whitelisting, and secure password handling.
|
|
3
|
+
*
|
|
4
|
+
* Provides comprehensive authentication services including password generation, verification,
|
|
5
|
+
* rate limiting with exponential backoff, failed attempt tracking, and secure settings management.
|
|
6
|
+
* Handles authentication setup, IP-based security controls, and persistent state management.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { readFileSync, writeFileSync, existsSync, unlinkSync } from 'fs';
|
|
10
|
+
import bcrypt from 'bcrypt';
|
|
11
|
+
import crypto from 'crypto';
|
|
12
|
+
import create_logger from './logger.js';
|
|
13
|
+
|
|
14
|
+
const { create_context_logger } = create_logger('auth_manager');
|
|
15
|
+
const log = create_context_logger();
|
|
16
|
+
|
|
17
|
+
import { load_settings as load_joystick_settings, get_settings as get_joystick_settings, has_settings } from './load_settings.js';
|
|
18
|
+
|
|
19
|
+
/** @type {number} BCrypt salt rounds for password hashing */
|
|
20
|
+
const SALT_ROUNDS = 12;
|
|
21
|
+
|
|
22
|
+
/** @type {number} Rate limiting window in milliseconds (1 minute) */
|
|
23
|
+
const RATE_LIMIT_WINDOW = 60 * 1000;
|
|
24
|
+
|
|
25
|
+
/** @type {number} Maximum failed attempts before rate limiting */
|
|
26
|
+
const MAX_FAILED_ATTEMPTS = 5;
|
|
27
|
+
|
|
28
|
+
/** @type {number} Base backoff duration in milliseconds */
|
|
29
|
+
const BACKOFF_BASE = 1000;
|
|
30
|
+
|
|
31
|
+
/** @type {number} Backoff multiplier for exponential backoff */
|
|
32
|
+
const BACKOFF_MULTIPLIER = 2;
|
|
33
|
+
|
|
34
|
+
/** @type {Object|null} Cached settings data */
|
|
35
|
+
let settings_data = null;
|
|
36
|
+
|
|
37
|
+
/** @type {Map<string, Array<number>>} Map of IP addresses to failed attempt timestamps */
|
|
38
|
+
let failed_attempts = new Map();
|
|
39
|
+
|
|
40
|
+
/** @type {Map<string, Object>} Map of IP addresses to rate limit information */
|
|
41
|
+
let rate_limits = new Map();
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Generates a cryptographically secure random password.
|
|
45
|
+
* @returns {string} 32-character hexadecimal password
|
|
46
|
+
*/
|
|
47
|
+
const generate_secure_password = () => {
|
|
48
|
+
return crypto.randomBytes(16).toString('hex');
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Loads settings data from environment variable and initializes authentication state.
|
|
53
|
+
* @returns {Object|null} Loaded settings data or null if not available
|
|
54
|
+
* @throws {Error} When environment variable contains invalid JSON
|
|
55
|
+
*/
|
|
56
|
+
const load_settings_data = () => {
|
|
57
|
+
try {
|
|
58
|
+
if (!has_settings()) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const parsed_data = load_joystick_settings();
|
|
63
|
+
settings_data = parsed_data;
|
|
64
|
+
|
|
65
|
+
if (parsed_data.authentication && parsed_data.authentication.failed_attempts) {
|
|
66
|
+
failed_attempts = new Map(Object.entries(parsed_data.authentication.failed_attempts));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (parsed_data.authentication && parsed_data.authentication.rate_limits) {
|
|
70
|
+
rate_limits = new Map(Object.entries(parsed_data.authentication.rate_limits));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
log.info('Settings data loaded successfully from environment variable');
|
|
74
|
+
return settings_data;
|
|
75
|
+
} catch (error) {
|
|
76
|
+
log.error('Failed to load settings data', { error: error.message });
|
|
77
|
+
throw new Error(`Failed to load settings data: ${error.message}`);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Updates the JOYSTICK_DB_SETTINGS environment variable with current authentication state.
|
|
83
|
+
* NOTE: This updates the environment variable for the current process only.
|
|
84
|
+
* @throws {Error} When settings data is null or JSON serialization fails
|
|
85
|
+
*/
|
|
86
|
+
const save_settings_data = () => {
|
|
87
|
+
try {
|
|
88
|
+
if (!settings_data) {
|
|
89
|
+
throw new Error('No settings data to save');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// NOTE: Update authentication section with current failed attempts and rate limits.
|
|
93
|
+
if (!settings_data.authentication) {
|
|
94
|
+
settings_data.authentication = {};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
settings_data.authentication.failed_attempts = Object.fromEntries(failed_attempts);
|
|
98
|
+
settings_data.authentication.rate_limits = Object.fromEntries(rate_limits);
|
|
99
|
+
|
|
100
|
+
// NOTE: Update the environment variable with the new settings.
|
|
101
|
+
process.env.JOYSTICK_DB_SETTINGS = JSON.stringify(settings_data);
|
|
102
|
+
|
|
103
|
+
log.info('Settings data saved successfully to environment variable');
|
|
104
|
+
} catch (error) {
|
|
105
|
+
log.error('Failed to save settings data', { error: error.message });
|
|
106
|
+
throw new Error(`Failed to save settings data: ${error.message}`);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Checks if an IP address is whitelisted (localhost addresses).
|
|
112
|
+
* Whitelisting is disabled during tests to allow rate limiting testing.
|
|
113
|
+
* @param {string} ip - IP address to check
|
|
114
|
+
* @returns {boolean} True if IP is whitelisted
|
|
115
|
+
*/
|
|
116
|
+
const is_ip_whitelisted = (ip) => {
|
|
117
|
+
// NOTE: Disable IP whitelisting during tests to allow rate limiting testing.
|
|
118
|
+
if (process.env.NODE_ENV === 'test') {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const whitelisted_ips = ['127.0.0.1', '::1', 'localhost'];
|
|
123
|
+
return whitelisted_ips.includes(ip);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Extracts client IP address from socket connection.
|
|
128
|
+
* @param {net.Socket} socket - Socket connection
|
|
129
|
+
* @returns {string} Client IP address or localhost fallback
|
|
130
|
+
*/
|
|
131
|
+
const get_client_ip = (socket) => {
|
|
132
|
+
return socket.remoteAddress || '127.0.0.1';
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Checks if an IP address is currently rate limited.
|
|
137
|
+
* Implements exponential backoff based on failed attempt count.
|
|
138
|
+
* @param {string} ip - IP address to check
|
|
139
|
+
* @returns {boolean} True if IP is rate limited
|
|
140
|
+
*/
|
|
141
|
+
const is_rate_limited = (ip) => {
|
|
142
|
+
if (is_ip_whitelisted(ip)) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const now = Date.now();
|
|
147
|
+
const attempts = failed_attempts.get(ip) || [];
|
|
148
|
+
|
|
149
|
+
const recent_attempts = attempts.filter(timestamp => now - timestamp < RATE_LIMIT_WINDOW);
|
|
150
|
+
|
|
151
|
+
if (recent_attempts.length >= MAX_FAILED_ATTEMPTS) {
|
|
152
|
+
const rate_limit_info = rate_limits.get(ip);
|
|
153
|
+
if (rate_limit_info && now < rate_limit_info.expires_at) {
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const backoff_duration = Math.min(
|
|
158
|
+
BACKOFF_BASE * Math.pow(BACKOFF_MULTIPLIER, Math.floor(recent_attempts.length / MAX_FAILED_ATTEMPTS)),
|
|
159
|
+
30 * 60 * 1000
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
rate_limits.set(ip, {
|
|
163
|
+
expires_at: now + backoff_duration,
|
|
164
|
+
attempts: recent_attempts.length
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
save_settings_data();
|
|
168
|
+
|
|
169
|
+
log.warn('IP rate limited', {
|
|
170
|
+
ip,
|
|
171
|
+
attempts: recent_attempts.length,
|
|
172
|
+
backoff_duration_ms: backoff_duration
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return false;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Records a failed authentication attempt for an IP address.
|
|
183
|
+
* @param {string} ip - IP address that failed authentication
|
|
184
|
+
*/
|
|
185
|
+
const record_failed_attempt = (ip) => {
|
|
186
|
+
if (is_ip_whitelisted(ip)) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const now = Date.now();
|
|
191
|
+
const attempts = failed_attempts.get(ip) || [];
|
|
192
|
+
attempts.push(now);
|
|
193
|
+
|
|
194
|
+
const recent_attempts = attempts.filter(timestamp => now - timestamp < RATE_LIMIT_WINDOW);
|
|
195
|
+
failed_attempts.set(ip, recent_attempts);
|
|
196
|
+
|
|
197
|
+
log.warn('Failed authentication attempt recorded', {
|
|
198
|
+
ip,
|
|
199
|
+
total_recent_attempts: recent_attempts.length
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
save_settings_data();
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Clears failed attempts and rate limits for an IP address after successful authentication.
|
|
207
|
+
* @param {string} ip - IP address to clear
|
|
208
|
+
*/
|
|
209
|
+
const clear_failed_attempts = (ip) => {
|
|
210
|
+
failed_attempts.delete(ip);
|
|
211
|
+
rate_limits.delete(ip);
|
|
212
|
+
save_settings_data();
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Sets up authentication by generating a secure password and saving configuration.
|
|
217
|
+
* @returns {string} Generated password (only shown once)
|
|
218
|
+
* @throws {Error} When authentication is already configured
|
|
219
|
+
*/
|
|
220
|
+
const setup_authentication = () => {
|
|
221
|
+
// NOTE: Load existing settings or create new ones.
|
|
222
|
+
if (!settings_data) {
|
|
223
|
+
load_settings_data();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (!settings_data) {
|
|
227
|
+
// NOTE: Create default settings structure.
|
|
228
|
+
settings_data = {
|
|
229
|
+
port: 1983,
|
|
230
|
+
cluster: true,
|
|
231
|
+
worker_count: 2,
|
|
232
|
+
authentication: {},
|
|
233
|
+
backup: { enabled: false },
|
|
234
|
+
replication: { enabled: false, role: "primary" },
|
|
235
|
+
auto_indexing: { enabled: true, threshold: 100 },
|
|
236
|
+
performance: {
|
|
237
|
+
monitoring_enabled: true,
|
|
238
|
+
log_slow_queries: true,
|
|
239
|
+
slow_query_threshold_ms: 1000
|
|
240
|
+
},
|
|
241
|
+
logging: { level: "info", structured: true }
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (settings_data.authentication && settings_data.authentication.password_hash) {
|
|
246
|
+
throw new Error('Authentication already configured. Update JOYSTICK_DB_SETTINGS environment variable to reconfigure.');
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const password = generate_secure_password();
|
|
250
|
+
const password_hash = bcrypt.hashSync(password, SALT_ROUNDS);
|
|
251
|
+
const now = new Date().toISOString();
|
|
252
|
+
|
|
253
|
+
settings_data.authentication = {
|
|
254
|
+
password_hash,
|
|
255
|
+
created_at: now,
|
|
256
|
+
last_updated: now,
|
|
257
|
+
failed_attempts: {},
|
|
258
|
+
rate_limits: {}
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
save_settings_data();
|
|
262
|
+
|
|
263
|
+
log.info('Authentication setup completed', {
|
|
264
|
+
created_at: now
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
return password;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Verifies a password against the stored hash with rate limiting and timing attack protection.
|
|
272
|
+
* @param {string} password - Password to verify
|
|
273
|
+
* @param {string} ip - Client IP address for rate limiting
|
|
274
|
+
* @returns {Promise<boolean>} True if password is valid
|
|
275
|
+
* @throws {Error} When authentication not configured or rate limited
|
|
276
|
+
*/
|
|
277
|
+
const verify_password = async (password, ip) => {
|
|
278
|
+
if (!settings_data) {
|
|
279
|
+
try {
|
|
280
|
+
load_settings_data();
|
|
281
|
+
} catch (error) {
|
|
282
|
+
// NOTE: If loading fails, settings_data remains null.
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
if (!settings_data || !settings_data.authentication || !settings_data.authentication.password_hash) {
|
|
287
|
+
throw new Error('Authentication not configured. Run setup first.');
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (is_rate_limited(ip)) {
|
|
291
|
+
throw new Error('Too many failed attempts. Please try again later.');
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const start_time = Date.now();
|
|
295
|
+
|
|
296
|
+
try {
|
|
297
|
+
const is_valid = await bcrypt.compare(password, settings_data.authentication.password_hash);
|
|
298
|
+
|
|
299
|
+
const verification_time = Date.now() - start_time;
|
|
300
|
+
const min_time = 100;
|
|
301
|
+
if (verification_time < min_time) {
|
|
302
|
+
await new Promise(resolve => setTimeout(resolve, min_time - verification_time));
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (is_valid) {
|
|
306
|
+
clear_failed_attempts(ip);
|
|
307
|
+
log.info('Password verification successful', { ip });
|
|
308
|
+
return true;
|
|
309
|
+
} else {
|
|
310
|
+
record_failed_attempt(ip);
|
|
311
|
+
log.warn('Password verification failed', { ip });
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
} catch (error) {
|
|
315
|
+
record_failed_attempt(ip);
|
|
316
|
+
log.error('Password verification error', { ip, error: error.message });
|
|
317
|
+
throw error;
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Gets authentication statistics and status information.
|
|
323
|
+
* @returns {Object} Authentication statistics
|
|
324
|
+
* @returns {boolean} returns.configured - Whether authentication is configured
|
|
325
|
+
* @returns {number} returns.failed_attempts_count - Number of IPs with failed attempts
|
|
326
|
+
* @returns {number} returns.rate_limited_ips - Number of rate limited IPs
|
|
327
|
+
* @returns {string|null} returns.created_at - Authentication creation timestamp
|
|
328
|
+
* @returns {string|null} returns.last_updated - Last update timestamp
|
|
329
|
+
*/
|
|
330
|
+
const get_auth_stats = () => {
|
|
331
|
+
const auth_configured = !!(settings_data && settings_data.authentication && settings_data.authentication.password_hash);
|
|
332
|
+
return {
|
|
333
|
+
configured: auth_configured,
|
|
334
|
+
failed_attempts_count: failed_attempts.size,
|
|
335
|
+
rate_limited_ips: rate_limits.size,
|
|
336
|
+
created_at: settings_data?.authentication?.created_at || null,
|
|
337
|
+
last_updated: settings_data?.authentication?.last_updated || null
|
|
338
|
+
};
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Initializes the authentication manager by loading existing settings.
|
|
343
|
+
*/
|
|
344
|
+
const initialize_auth_manager = () => {
|
|
345
|
+
try {
|
|
346
|
+
load_settings_data();
|
|
347
|
+
} catch (error) {
|
|
348
|
+
log.warn('Could not load settings data on startup', { error: error.message });
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Resets authentication state (used for testing).
|
|
354
|
+
* Clears both in-memory state and environment variable.
|
|
355
|
+
*/
|
|
356
|
+
const reset_auth_state = () => {
|
|
357
|
+
settings_data = null;
|
|
358
|
+
failed_attempts = new Map();
|
|
359
|
+
rate_limits = new Map();
|
|
360
|
+
|
|
361
|
+
// NOTE: Clear the environment variable to ensure clean test state.
|
|
362
|
+
if (process.env.JOYSTICK_DB_SETTINGS) {
|
|
363
|
+
delete process.env.JOYSTICK_DB_SETTINGS;
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
export {
|
|
368
|
+
setup_authentication,
|
|
369
|
+
verify_password,
|
|
370
|
+
get_client_ip,
|
|
371
|
+
is_rate_limited,
|
|
372
|
+
get_auth_stats,
|
|
373
|
+
initialize_auth_manager,
|
|
374
|
+
reset_auth_state
|
|
375
|
+
};
|