@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,651 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import sinon from 'sinon';
|
|
3
|
+
import net from 'net';
|
|
4
|
+
import { encode as encode_messagepack } from 'msgpackr';
|
|
5
|
+
import { parse_data, check_op_type, create_server } from '../../src/server/index.js';
|
|
6
|
+
import op_types from '../../src/server/lib/op_types.js';
|
|
7
|
+
import { load_settings, get_settings } from '../../src/server/lib/load_settings.js';
|
|
8
|
+
import { reset_auth_state } from '../../src/server/lib/auth_manager.js';
|
|
9
|
+
|
|
10
|
+
test.beforeEach(() => {
|
|
11
|
+
// Reset auth state and clean up environment variables
|
|
12
|
+
reset_auth_state();
|
|
13
|
+
delete process.env.JOYSTICK_DB_SETTINGS;
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test.afterEach(() => {
|
|
17
|
+
// Clean up environment variables after each test
|
|
18
|
+
reset_auth_state();
|
|
19
|
+
delete process.env.JOYSTICK_DB_SETTINGS;
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('setup operation creates authentication and returns password', async (t) => {
|
|
23
|
+
const { setup } = await import('../../src/server/index.js');
|
|
24
|
+
|
|
25
|
+
let response_data = null;
|
|
26
|
+
const mock_socket = {
|
|
27
|
+
write: (data) => {
|
|
28
|
+
response_data = data;
|
|
29
|
+
},
|
|
30
|
+
end: sinon.stub()
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
await setup(mock_socket, {});
|
|
34
|
+
|
|
35
|
+
// Verify authentication environment variable was created
|
|
36
|
+
t.true(process.env.JOYSTICK_DB_SETTINGS !== undefined);
|
|
37
|
+
|
|
38
|
+
// Verify response was sent
|
|
39
|
+
t.truthy(response_data);
|
|
40
|
+
|
|
41
|
+
// Parse the response to check structure
|
|
42
|
+
const response_string = response_data.toString();
|
|
43
|
+
t.true(response_string.includes('Authentication setup completed'));
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('setup operation handles already configured authentication', async (t) => {
|
|
47
|
+
const { setup } = await import('../../src/server/index.js');
|
|
48
|
+
const { setup_authentication } = await import('../../src/server/lib/auth_manager.js');
|
|
49
|
+
|
|
50
|
+
// Setup authentication first
|
|
51
|
+
setup_authentication();
|
|
52
|
+
|
|
53
|
+
let response_data = null;
|
|
54
|
+
const mock_socket = {
|
|
55
|
+
write: (data) => {
|
|
56
|
+
response_data = data;
|
|
57
|
+
},
|
|
58
|
+
end: sinon.stub()
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
await setup(mock_socket, {});
|
|
62
|
+
|
|
63
|
+
// Verify error response was sent
|
|
64
|
+
t.truthy(response_data);
|
|
65
|
+
|
|
66
|
+
const response_string = response_data.toString();
|
|
67
|
+
t.true(response_string.includes('Authentication already configured'));
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test('authentication operation requires password in data', async (t) => {
|
|
71
|
+
const { authentication } = await import('../../src/server/index.js');
|
|
72
|
+
|
|
73
|
+
let response_data = null;
|
|
74
|
+
const mock_socket = {
|
|
75
|
+
id: 'test-socket',
|
|
76
|
+
write: (data) => {
|
|
77
|
+
response_data = data;
|
|
78
|
+
},
|
|
79
|
+
end: sinon.stub()
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
await authentication(mock_socket, {});
|
|
83
|
+
|
|
84
|
+
// Verify error response was sent and socket was closed
|
|
85
|
+
t.truthy(response_data);
|
|
86
|
+
t.true(mock_socket.end.calledOnce);
|
|
87
|
+
|
|
88
|
+
const response_string = response_data.toString();
|
|
89
|
+
t.true(response_string.includes('Authentication operation requires password to be set in data'));
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
test('authentication operation succeeds with correct password', async (t) => {
|
|
93
|
+
const { authentication } = await import('../../src/server/index.js');
|
|
94
|
+
const { setup_authentication } = await import('../../src/server/lib/auth_manager.js');
|
|
95
|
+
|
|
96
|
+
// Setup authentication first
|
|
97
|
+
const password = setup_authentication();
|
|
98
|
+
|
|
99
|
+
let response_data = null;
|
|
100
|
+
const mock_socket = {
|
|
101
|
+
id: 'test-socket',
|
|
102
|
+
remoteAddress: '127.0.0.1',
|
|
103
|
+
write: (data) => {
|
|
104
|
+
response_data = data;
|
|
105
|
+
},
|
|
106
|
+
end: sinon.stub()
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
await authentication(mock_socket, { password });
|
|
110
|
+
|
|
111
|
+
// Verify success response was sent and socket was NOT closed
|
|
112
|
+
t.truthy(response_data);
|
|
113
|
+
t.false(mock_socket.end.called);
|
|
114
|
+
|
|
115
|
+
const response_string = response_data.toString();
|
|
116
|
+
t.true(response_string.includes('Authentication successful'));
|
|
117
|
+
t.true(response_string.includes('1.0.0'));
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test('authentication operation fails with incorrect password', async (t) => {
|
|
121
|
+
const { authentication } = await import('../../src/server/index.js');
|
|
122
|
+
const { setup_authentication } = await import('../../src/server/lib/auth_manager.js');
|
|
123
|
+
|
|
124
|
+
// Setup authentication first
|
|
125
|
+
setup_authentication();
|
|
126
|
+
|
|
127
|
+
let response_data = null;
|
|
128
|
+
const mock_socket = {
|
|
129
|
+
id: 'test-socket',
|
|
130
|
+
remoteAddress: '192.168.1.100',
|
|
131
|
+
write: (data) => {
|
|
132
|
+
response_data = data;
|
|
133
|
+
},
|
|
134
|
+
end: sinon.stub()
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
await authentication(mock_socket, { password: 'wrong_password' });
|
|
138
|
+
|
|
139
|
+
// Verify error response was sent and socket was closed
|
|
140
|
+
t.truthy(response_data);
|
|
141
|
+
t.true(mock_socket.end.calledOnce);
|
|
142
|
+
|
|
143
|
+
const response_string = response_data.toString();
|
|
144
|
+
t.true(response_string.includes('Authentication failed'));
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test('authentication operation handles rate limiting', async (t) => {
|
|
148
|
+
const { authentication } = await import('../../src/server/index.js');
|
|
149
|
+
const { setup_authentication } = await import('../../src/server/lib/auth_manager.js');
|
|
150
|
+
|
|
151
|
+
// Setup authentication first
|
|
152
|
+
setup_authentication();
|
|
153
|
+
|
|
154
|
+
let response_data = null;
|
|
155
|
+
const mock_socket = {
|
|
156
|
+
id: 'test-socket',
|
|
157
|
+
remoteAddress: '192.168.1.100',
|
|
158
|
+
write: (data) => {
|
|
159
|
+
response_data = data;
|
|
160
|
+
},
|
|
161
|
+
end: sinon.stub()
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// Make 5 failed attempts to trigger rate limiting
|
|
165
|
+
for (let i = 0; i < 5; i++) {
|
|
166
|
+
await authentication(mock_socket, { password: 'wrong_password' });
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Reset for the rate limited attempt
|
|
170
|
+
response_data = null;
|
|
171
|
+
mock_socket.end.resetHistory();
|
|
172
|
+
|
|
173
|
+
// 6th attempt should be rate limited
|
|
174
|
+
await authentication(mock_socket, { password: 'wrong_password' });
|
|
175
|
+
|
|
176
|
+
// Verify rate limiting error response was sent and socket was closed
|
|
177
|
+
t.truthy(response_data);
|
|
178
|
+
t.true(mock_socket.end.calledOnce);
|
|
179
|
+
|
|
180
|
+
const response_string = response_data.toString();
|
|
181
|
+
t.true(response_string.includes('Too many failed attempts'));
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test('parse_data processes valid messagepack with JSON data', (t = {}) => {
|
|
185
|
+
const json_data = { name: "test", value: 123 };
|
|
186
|
+
const json_string = JSON.stringify(json_data);
|
|
187
|
+
const messagepack_data = encode_messagepack(json_string);
|
|
188
|
+
const raw_data = Buffer.from(messagepack_data);
|
|
189
|
+
|
|
190
|
+
const result = parse_data(raw_data);
|
|
191
|
+
|
|
192
|
+
t.deepEqual(result, json_data);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
test('check_op_type returns true for valid operation types', (t = {}) => {
|
|
196
|
+
op_types.forEach((op_type) => {
|
|
197
|
+
const result = check_op_type(op_type);
|
|
198
|
+
t.true(result, `Expected ${op_type} to be valid`);
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
test('check_op_type validates setup operation type', (t = {}) => {
|
|
203
|
+
const result = check_op_type('setup');
|
|
204
|
+
t.true(result);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test('check_op_type validates authentication operation type', (t = {}) => {
|
|
208
|
+
const result = check_op_type('authentication');
|
|
209
|
+
t.true(result);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test('check_op_type returns false for invalid operation types', (t = {}) => {
|
|
213
|
+
const invalid_op_types = [
|
|
214
|
+
"invalid_op",
|
|
215
|
+
"unknown",
|
|
216
|
+
"select",
|
|
217
|
+
"create",
|
|
218
|
+
"drop",
|
|
219
|
+
"alter",
|
|
220
|
+
"FIND_ONE",
|
|
221
|
+
"Authentication",
|
|
222
|
+
"ping_test"
|
|
223
|
+
];
|
|
224
|
+
|
|
225
|
+
invalid_op_types.forEach((op_type) => {
|
|
226
|
+
const result = check_op_type(op_type);
|
|
227
|
+
t.false(result, `Expected ${op_type} to be invalid`);
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
test('check_op_type throws error when no op_type is provided', (t = {}) => {
|
|
232
|
+
const error = t.throws(() => {
|
|
233
|
+
check_op_type();
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
t.is(error.message, 'Must pass an op type for operation.');
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
test('check_op_type throws error when empty string is provided', (t = {}) => {
|
|
240
|
+
const error = t.throws(() => {
|
|
241
|
+
check_op_type('');
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
t.is(error.message, 'Must pass an op type for operation.');
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
test('check_op_type throws error when null is provided', (t = {}) => {
|
|
248
|
+
const error = t.throws(() => {
|
|
249
|
+
check_op_type(null);
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
t.is(error.message, 'Must pass an op type for operation.');
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
test('check_op_type throws error when undefined is provided', (t = {}) => {
|
|
256
|
+
const error = t.throws(() => {
|
|
257
|
+
check_op_type(undefined);
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
t.is(error.message, 'Must pass an op type for operation.');
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test('check_op_type handles non-string input types', (t = {}) => {
|
|
264
|
+
const non_string_inputs = [
|
|
265
|
+
123,
|
|
266
|
+
true,
|
|
267
|
+
{},
|
|
268
|
+
[],
|
|
269
|
+
Symbol('test')
|
|
270
|
+
];
|
|
271
|
+
|
|
272
|
+
non_string_inputs.forEach((input) => {
|
|
273
|
+
const result = check_op_type(input);
|
|
274
|
+
t.false(result, `Expected ${typeof input} input to be invalid`);
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
test('parse_data processes messagepack with array JSON', (t = {}) => {
|
|
279
|
+
const json_data = [1, 2, 3, "test"];
|
|
280
|
+
const json_string = JSON.stringify(json_data);
|
|
281
|
+
const messagepack_data = encode_messagepack(json_string);
|
|
282
|
+
const raw_data = Buffer.from(messagepack_data);
|
|
283
|
+
|
|
284
|
+
const result = parse_data(raw_data);
|
|
285
|
+
|
|
286
|
+
t.deepEqual(result, json_data);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
test('parse_data processes messagepack with primitive JSON values', (t = {}) => {
|
|
290
|
+
const test_cases = [
|
|
291
|
+
{ input: true, expected: true },
|
|
292
|
+
{ input: false, expected: false },
|
|
293
|
+
{ input: null, expected: null },
|
|
294
|
+
{ input: 42, expected: 42 },
|
|
295
|
+
{ input: "hello", expected: "hello" }
|
|
296
|
+
];
|
|
297
|
+
|
|
298
|
+
test_cases.forEach(({ input, expected }) => {
|
|
299
|
+
const json_string = JSON.stringify(input);
|
|
300
|
+
const messagepack_data = encode_messagepack(json_string);
|
|
301
|
+
const raw_data = Buffer.from(messagepack_data);
|
|
302
|
+
|
|
303
|
+
const result = parse_data(raw_data);
|
|
304
|
+
|
|
305
|
+
t.is(result, expected);
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
test('parse_data returns null for messagepack with invalid JSON', (t = {}) => {
|
|
310
|
+
const invalid_json = '{"name": "test", "value":}';
|
|
311
|
+
const messagepack_data = encode_messagepack(invalid_json);
|
|
312
|
+
const raw_data = Buffer.from(messagepack_data);
|
|
313
|
+
|
|
314
|
+
const result = parse_data(raw_data);
|
|
315
|
+
|
|
316
|
+
t.is(result, null);
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
test('parse_data returns null for messagepack with empty string', (t = {}) => {
|
|
320
|
+
const empty_string = '';
|
|
321
|
+
const messagepack_data = encode_messagepack(empty_string);
|
|
322
|
+
const raw_data = Buffer.from(messagepack_data);
|
|
323
|
+
|
|
324
|
+
const result = parse_data(raw_data);
|
|
325
|
+
|
|
326
|
+
t.is(result, null);
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
test('parse_data processes complex nested JSON objects', (t = {}) => {
|
|
330
|
+
const complex_data = {
|
|
331
|
+
user: {
|
|
332
|
+
id: 1,
|
|
333
|
+
name: "John Doe",
|
|
334
|
+
preferences: {
|
|
335
|
+
theme: "dark",
|
|
336
|
+
notifications: true
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
items: [
|
|
340
|
+
{ id: 1, name: "Item 1" },
|
|
341
|
+
{ id: 2, name: "Item 2" }
|
|
342
|
+
]
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
const json_string = JSON.stringify(complex_data);
|
|
346
|
+
const messagepack_data = encode_messagepack(json_string);
|
|
347
|
+
const raw_data = Buffer.from(messagepack_data);
|
|
348
|
+
|
|
349
|
+
const result = parse_data(raw_data);
|
|
350
|
+
|
|
351
|
+
t.deepEqual(result, complex_data);
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
test('parse_data processes buffer input as raw_data', (t = {}) => {
|
|
355
|
+
const json_data = { message: "test" };
|
|
356
|
+
const json_string = JSON.stringify(json_data);
|
|
357
|
+
const messagepack_data = encode_messagepack(json_string);
|
|
358
|
+
const raw_data_buffer = Buffer.from(messagepack_data);
|
|
359
|
+
|
|
360
|
+
const result = parse_data(raw_data_buffer);
|
|
361
|
+
|
|
362
|
+
t.deepEqual(result, json_data);
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
test('parse_data handles messagepack with JSON containing special characters', (t = {}) => {
|
|
366
|
+
const json_data = {
|
|
367
|
+
message: "Hello \"world\" with 'quotes' and \n newlines",
|
|
368
|
+
unicode: "🚀 Unicode test 中文",
|
|
369
|
+
escaped: "Line 1\nLine 2\tTabbed"
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
const json_string = JSON.stringify(json_data);
|
|
373
|
+
const messagepack_data = encode_messagepack(json_string);
|
|
374
|
+
const raw_data = Buffer.from(messagepack_data);
|
|
375
|
+
|
|
376
|
+
const result = parse_data(raw_data);
|
|
377
|
+
|
|
378
|
+
t.deepEqual(result, json_data);
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
test('admin operation requires authentication', (t) => {
|
|
382
|
+
const mock_socket = {
|
|
383
|
+
id: 'unauthenticated-socket',
|
|
384
|
+
write: sinon.stub(),
|
|
385
|
+
end: sinon.stub()
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
const send_error_stub = sinon.stub();
|
|
389
|
+
|
|
390
|
+
const authenticated_clients = new Set();
|
|
391
|
+
|
|
392
|
+
const check_authentication = (socket) => {
|
|
393
|
+
return authenticated_clients.has(socket.id);
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
const is_authenticated = check_authentication(mock_socket);
|
|
397
|
+
|
|
398
|
+
t.false(is_authenticated);
|
|
399
|
+
|
|
400
|
+
if (!is_authenticated) {
|
|
401
|
+
send_error_stub(mock_socket, { message: 'Authentication required' });
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
t.true(send_error_stub.calledOnce);
|
|
405
|
+
t.true(send_error_stub.calledWith(mock_socket, { message: 'Authentication required' }));
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
test('admin operation returns server information structure', (t) => {
|
|
409
|
+
const mock_db = {
|
|
410
|
+
getStats: () => ({ pages: 100, entries: 50 }),
|
|
411
|
+
getRange: () => [
|
|
412
|
+
{ key: 'users:1' },
|
|
413
|
+
{ key: 'users:2' },
|
|
414
|
+
{ key: 'posts:1' },
|
|
415
|
+
{ key: 'posts:2' },
|
|
416
|
+
{ key: 'posts:3' }
|
|
417
|
+
]
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
const mock_settings = {
|
|
421
|
+
port: 1983,
|
|
422
|
+
cluster: true
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
const collections = new Map();
|
|
426
|
+
let total_documents = 0;
|
|
427
|
+
|
|
428
|
+
for (const { key } of mock_db.getRange()) {
|
|
429
|
+
if (typeof key === 'string' && key.includes(':')) {
|
|
430
|
+
const collection_name = key.split(':')[0];
|
|
431
|
+
collections.set(collection_name, (collections.get(collection_name) || 0) + 1);
|
|
432
|
+
total_documents++;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
const admin_info = {
|
|
437
|
+
server: {
|
|
438
|
+
uptime: process.uptime(),
|
|
439
|
+
memory_usage: process.memoryUsage(),
|
|
440
|
+
node_version: process.version,
|
|
441
|
+
platform: process.platform,
|
|
442
|
+
pid: process.pid
|
|
443
|
+
},
|
|
444
|
+
database: {
|
|
445
|
+
total_documents,
|
|
446
|
+
collections: Object.fromEntries(collections),
|
|
447
|
+
stats: mock_db.getStats()
|
|
448
|
+
},
|
|
449
|
+
authentication: {
|
|
450
|
+
authenticated_clients: 0
|
|
451
|
+
},
|
|
452
|
+
settings: {
|
|
453
|
+
port: mock_settings.port || 1983,
|
|
454
|
+
cluster_enabled: !!mock_settings.cluster
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
t.is(typeof admin_info.server.uptime, 'number');
|
|
459
|
+
t.is(typeof admin_info.server.memory_usage, 'object');
|
|
460
|
+
t.is(typeof admin_info.server.node_version, 'string');
|
|
461
|
+
t.is(typeof admin_info.server.platform, 'string');
|
|
462
|
+
t.is(typeof admin_info.server.pid, 'number');
|
|
463
|
+
t.is(admin_info.database.total_documents, 5);
|
|
464
|
+
t.deepEqual(admin_info.database.collections, { users: 2, posts: 3 });
|
|
465
|
+
t.deepEqual(admin_info.database.stats, { pages: 100, entries: 50 });
|
|
466
|
+
t.is(admin_info.authentication.authenticated_clients, 0);
|
|
467
|
+
t.is(admin_info.settings.port, 1983);
|
|
468
|
+
t.true(admin_info.settings.cluster_enabled);
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
test('admin operation handles database without getStats method', (t) => {
|
|
472
|
+
const mock_db = {
|
|
473
|
+
getRange: () => [
|
|
474
|
+
{ key: 'users:1' },
|
|
475
|
+
{ key: 'posts:1' }
|
|
476
|
+
]
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
const stats = mock_db.getStats ? mock_db.getStats() : {};
|
|
480
|
+
const collections = new Map();
|
|
481
|
+
let total_documents = 0;
|
|
482
|
+
|
|
483
|
+
for (const { key } of mock_db.getRange()) {
|
|
484
|
+
if (typeof key === 'string' && key.includes(':')) {
|
|
485
|
+
const collection_name = key.split(':')[0];
|
|
486
|
+
collections.set(collection_name, (collections.get(collection_name) || 0) + 1);
|
|
487
|
+
total_documents++;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
t.deepEqual(stats, {});
|
|
492
|
+
t.is(total_documents, 2);
|
|
493
|
+
t.deepEqual(Object.fromEntries(collections), { users: 1, posts: 1 });
|
|
494
|
+
});
|
|
495
|
+
|
|
496
|
+
test('admin operation counts authenticated clients correctly', (t) => {
|
|
497
|
+
const authenticated_clients = new Set(['socket1', 'socket2', 'socket3']);
|
|
498
|
+
|
|
499
|
+
const admin_info = {
|
|
500
|
+
authentication: {
|
|
501
|
+
authenticated_clients: authenticated_clients.size
|
|
502
|
+
}
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
t.is(admin_info.authentication.authenticated_clients, 3);
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
test('reload operation requires authentication', (t) => {
|
|
509
|
+
const mock_socket = {
|
|
510
|
+
id: 'unauthenticated-socket',
|
|
511
|
+
write: sinon.stub(),
|
|
512
|
+
end: sinon.stub()
|
|
513
|
+
};
|
|
514
|
+
|
|
515
|
+
const send_error_stub = sinon.stub();
|
|
516
|
+
|
|
517
|
+
const authenticated_clients = new Set();
|
|
518
|
+
|
|
519
|
+
const check_authentication = (socket) => {
|
|
520
|
+
return authenticated_clients.has(socket.id);
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
const is_authenticated = check_authentication(mock_socket);
|
|
524
|
+
|
|
525
|
+
t.false(is_authenticated);
|
|
526
|
+
|
|
527
|
+
if (!is_authenticated) {
|
|
528
|
+
send_error_stub(mock_socket, { message: 'Authentication required' });
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
t.true(send_error_stub.calledOnce);
|
|
532
|
+
t.true(send_error_stub.calledWith(mock_socket, { message: 'Authentication required' }));
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
test('reload operation detects configuration changes', (t) => {
|
|
536
|
+
const old_settings = {
|
|
537
|
+
port: 1983,
|
|
538
|
+
authentication: { password_hash: 'old-hash' },
|
|
539
|
+
cluster: false
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
const new_settings = {
|
|
543
|
+
port: 2000,
|
|
544
|
+
authentication: { password_hash: 'new-hash' },
|
|
545
|
+
cluster: true
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
const reload_info = {
|
|
549
|
+
status: 'success',
|
|
550
|
+
message: 'Configuration reloaded successfully',
|
|
551
|
+
changes: {
|
|
552
|
+
port_changed: old_settings.port !== new_settings.port,
|
|
553
|
+
authentication_changed: old_settings.authentication?.password_hash !== new_settings.authentication?.password_hash,
|
|
554
|
+
cluster_changed: old_settings.cluster !== new_settings.cluster
|
|
555
|
+
},
|
|
556
|
+
timestamp: new Date().toISOString()
|
|
557
|
+
};
|
|
558
|
+
|
|
559
|
+
t.is(reload_info.status, 'success');
|
|
560
|
+
t.is(reload_info.message, 'Configuration reloaded successfully');
|
|
561
|
+
t.true(reload_info.changes.port_changed);
|
|
562
|
+
t.true(reload_info.changes.authentication_changed);
|
|
563
|
+
t.true(reload_info.changes.cluster_changed);
|
|
564
|
+
t.is(typeof reload_info.timestamp, 'string');
|
|
565
|
+
});
|
|
566
|
+
|
|
567
|
+
test('reload operation detects no changes when settings are identical', (t) => {
|
|
568
|
+
const old_settings = {
|
|
569
|
+
port: 1983,
|
|
570
|
+
authentication: { password_hash: 'same-hash' },
|
|
571
|
+
cluster: true
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
const new_settings = {
|
|
575
|
+
port: 1983,
|
|
576
|
+
authentication: { password_hash: 'same-hash' },
|
|
577
|
+
cluster: true
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
const reload_info = {
|
|
581
|
+
status: 'success',
|
|
582
|
+
message: 'Configuration reloaded successfully',
|
|
583
|
+
changes: {
|
|
584
|
+
port_changed: old_settings.port !== new_settings.port,
|
|
585
|
+
authentication_changed: old_settings.authentication?.password_hash !== new_settings.authentication?.password_hash,
|
|
586
|
+
cluster_changed: old_settings.cluster !== new_settings.cluster
|
|
587
|
+
},
|
|
588
|
+
timestamp: new Date().toISOString()
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
t.is(reload_info.status, 'success');
|
|
592
|
+
t.false(reload_info.changes.port_changed);
|
|
593
|
+
t.false(reload_info.changes.authentication_changed);
|
|
594
|
+
t.false(reload_info.changes.cluster_changed);
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
test('reload operation handles missing authentication in old settings', (t) => {
|
|
598
|
+
const old_settings = {
|
|
599
|
+
port: 1983,
|
|
600
|
+
cluster: false
|
|
601
|
+
};
|
|
602
|
+
|
|
603
|
+
const new_settings = {
|
|
604
|
+
port: 1983,
|
|
605
|
+
authentication: { password_hash: 'new-hash' },
|
|
606
|
+
cluster: false
|
|
607
|
+
};
|
|
608
|
+
|
|
609
|
+
const reload_info = {
|
|
610
|
+
status: 'success',
|
|
611
|
+
message: 'Configuration reloaded successfully',
|
|
612
|
+
changes: {
|
|
613
|
+
port_changed: old_settings.port !== new_settings.port,
|
|
614
|
+
authentication_changed: old_settings.authentication?.password_hash !== new_settings.authentication?.password_hash,
|
|
615
|
+
cluster_changed: old_settings.cluster !== new_settings.cluster
|
|
616
|
+
},
|
|
617
|
+
timestamp: new Date().toISOString()
|
|
618
|
+
};
|
|
619
|
+
|
|
620
|
+
t.false(reload_info.changes.port_changed);
|
|
621
|
+
t.true(reload_info.changes.authentication_changed);
|
|
622
|
+
t.false(reload_info.changes.cluster_changed);
|
|
623
|
+
});
|
|
624
|
+
|
|
625
|
+
test('reload operation handles missing authentication in new settings', (t) => {
|
|
626
|
+
const old_settings = {
|
|
627
|
+
port: 1983,
|
|
628
|
+
authentication: { password_hash: 'old-hash' },
|
|
629
|
+
cluster: false
|
|
630
|
+
};
|
|
631
|
+
|
|
632
|
+
const new_settings = {
|
|
633
|
+
port: 1983,
|
|
634
|
+
cluster: false
|
|
635
|
+
};
|
|
636
|
+
|
|
637
|
+
const reload_info = {
|
|
638
|
+
status: 'success',
|
|
639
|
+
message: 'Configuration reloaded successfully',
|
|
640
|
+
changes: {
|
|
641
|
+
port_changed: old_settings.port !== new_settings.port,
|
|
642
|
+
authentication_changed: old_settings.authentication?.password_hash !== new_settings.authentication?.password_hash,
|
|
643
|
+
cluster_changed: old_settings.cluster !== new_settings.cluster
|
|
644
|
+
},
|
|
645
|
+
timestamp: new Date().toISOString()
|
|
646
|
+
};
|
|
647
|
+
|
|
648
|
+
t.false(reload_info.changes.port_changed);
|
|
649
|
+
t.true(reload_info.changes.authentication_changed);
|
|
650
|
+
t.false(reload_info.changes.cluster_changed);
|
|
651
|
+
});
|