From d8cce143ae3eb0cc91e0db87b8a01e8bf01342b3 Mon Sep 17 00:00:00 2001 From: tgstation-server Date: Tue, 21 Jan 2020 16:36:00 +0000 Subject: [PATCH] Deploy code docs to GitHub Pages for Appveyor build 1076 Commit: 5481a096f9132afd0d1aed5010339dddc648acfd --- ..._initial_create_8_designer_8cs_source.html | 9 +- ..._initial_create_8_designer_8cs_source.html | 9 +- ...inimum_security_8_designer_8cs_source.html | 7 +- ...inimum_security_8_designer_8cs_source.html | 9 +- ...ign_key_cleanup_8_designer_8cs_source.html | 9 +- ...ign_key_cleanup_8_designer_8cs_source.html | 9 +- ...le_job_required_8_designer_8cs_source.html | 9 +- ...le_job_required_8_designer_8cs_source.html | 9 +- ...tmerge_comments_8_designer_8cs_source.html | 9 +- ...tmerge_comments_8_designer_8cs_source.html | 7 +- ..._rev_info_index_8_designer_8cs_source.html | 9 +- ..._rev_info_index_8_designer_8cs_source.html | 9 +- _administration_controller_8cs_source.html | 48 +- _api_controller_8cs_source.html | 10 +- _application_8cs_source.html | 87 +- _application_builder_extensions_8cs.html | 10 +- ...ication_builder_extensions_8cs_source.html | 16 +- _assembly_information_provider_8cs.html | 8 +- ...embly_information_provider_8cs_source.html | 16 +- _authentication_context_8cs_source.html | 2 +- ...entication_context_factory_8cs_source.html | 25 +- _basic_watchdog_8cs_source.html | 105 +- _byond_controller_8cs_source.html | 25 +- _byond_manager_8cs_source.html | 39 +- _chat_controller_8cs_source.html | 31 +- _claims_injector_8cs_source.html | 10 +- _comm_context_8cs_source.html | 2 +- _command_factory_8cs_source.html | 25 +- ...chdog_2_i_watchdog_factory_8cs_source.html | 14 +- ...dog_2_reattach_information_8cs_source.html | 14 +- ...atchdog_2_watchdog_factory_8cs_source.html | 40 +- ...chdog_reattach_information_8cs_source.html | 18 +- _configuration_8cs_source.html | 65 +- _configuration_controller_8cs_source.html | 31 +- _console_8cs_source.html | 4 +- _credentials_provider_8cs_source.html | 6 +- _d_b_connection_factory_8cs_source.html | 92 - _database_configuration_8cs.html | 2 +- _database_configuration_8cs_source.html | 4 +- ...l => _database_connection_factory_8cs.html | 13 +- _database_connection_factory_8cs_source.html | 92 + _database_context_8cs.html | 8 +- _database_context_8cs_source.html | 57 +- _database_context_factory_8cs.html | 8 +- _database_context_factory_8cs_source.html | 22 +- _database_seeder_8cs.html | 8 +- _database_seeder_8cs_source.html | 27 +- _dead_session_controller_8cs_source.html | 42 +- _default_i_o_manager_8cs_source.html | 16 +- ...n_time_db_context_factory_helpers_8cs.html | 12 +- ...db_context_factory_helpers_8cs_source.html | 20 +- _dmb_factory_8cs.html | 10 +- _dmb_factory_8cs_source.html | 66 +- _dmb_provider_8cs.html | 8 +- _dmb_provider_8cs_source.html | 34 +- _dream_daemon_controller_8cs_source.html | 37 +- _dream_maker_controller_8cs_source.html | 39 +- _event_consumer_8cs_source.html | 2 +- _experimental_watchdog_8cs_source.html | 116 +- _general_configuration_8cs_source.html | 3 +- _home_controller_8cs_source.html | 39 +- _i_assembly_information_provider_8cs.html | 10 +- ...embly_information_provider_8cs_source.html | 12 +- _i_authentication_context_8cs_source.html | 2 +- _i_byond_executable_lock_8cs_source.html | 2 +- _i_claims_injector_8cs.html | 2 +- _i_claims_injector_8cs_source.html | 4 +- _i_compile_job_consumer_8cs.html | 10 +- _i_compile_job_consumer_8cs_source.html | 10 +- _i_configuration_8cs_source.html | 4 +- _i_console_8cs.html | 2 +- _i_console_8cs_source.html | 2 +- _i_database_connection_factory_8cs.html | 105 + ...atabase_connection_factory_8cs_source.html | 12 +- _i_database_context_8cs.html | 10 +- _i_database_context_8cs_source.html | 38 +- _i_database_context_factory_8cs.html | 10 +- _i_database_context_factory_8cs_source.html | 14 +- _i_database_seeder_8cs.html | 10 +- _i_database_seeder_8cs_source.html | 14 +- _i_dmb_factory_8cs.html | 10 +- _i_dmb_factory_8cs_source.html | 20 +- _i_dmb_provider_8cs.html | 10 +- _i_dmb_provider_8cs_source.html | 16 +- _i_dream_maker_8cs.html | 10 +- _i_dream_maker_8cs_source.html | 10 +- _i_i_o_manager_8cs_source.html | 2 +- _i_identity_cache_8cs.html | 2 +- _i_identity_cache_8cs_source.html | 2 +- _i_instance_8cs_source.html | 17 +- _i_instance_factory_8cs_source.html | 2 +- _i_instance_manager_8cs_source.html | 2 +- _i_job_manager_8cs.html | 10 +- _i_job_manager_8cs_source.html | 21 +- _i_network_prompt_reaper_8cs_source.html | 6 +- _i_platform_identifier_8cs.html | 10 +- _i_platform_identifier_8cs_source.html | 12 +- _i_process_8cs.html | 10 +- _i_process_8cs_source.html | 22 +- _i_process_base_8cs.html | 10 +- _i_process_base_8cs_source.html | 14 +- _i_process_executor_8cs.html | 10 +- _i_process_executor_8cs_source.html | 14 +- _i_reattach_info_handler_8cs_source.html | 2 +- _i_session_controller_8cs_source.html | 31 +- _i_session_controller_factory_8cs_source.html | 11 +- _i_system_identity_8cs.html | 2 +- _i_system_identity_8cs_source.html | 6 +- _i_system_identity_factory_8cs.html | 2 +- _identity_cache_8cs_source.html | 4 +- _identity_cache_object_8cs.html | 2 +- _identity_cache_object_8cs_source.html | 2 +- _instance_controller_8cs_source.html | 61 +- _instance_factory_8cs_source.html | 75 +- _instance_manager_8cs_source.html | 52 +- _instance_manager_test_8cs_source.html | 4 +- _instance_user_controller_8cs_source.html | 29 +- _job_controller_8cs_source.html | 33 +- _job_exception_8cs.html | 10 +- _job_exception_8cs_source.html | 14 +- _job_handler_8cs.html | 10 +- _job_handler_8cs_source.html | 22 +- _job_manager_8cs.html | 8 +- _job_manager_8cs_source.html | 53 +- _json_tracking_context_8cs_source.html | 2 +- _launch_result_8cs_source.html | 4 +- _models_2_reattach_information_8cs.html | 2 +- ...s_2_watchdog_reattach_information_8cs.html | 2 +- _monitor_state_8cs_source.html | 4 +- _my_sql_database_context_8cs.html | 10 +- _my_sql_database_context_8cs_source.html | 28 +- ...ase_context_model_snapshot_8cs_source.html | 9 +- ...ql_design_time_db_context_factory_8cs.html | 10 +- ...gn_time_db_context_factory_8cs_source.html | 19 +- _native_methods_8cs_source.html | 7 +- ...open_api_enum_var_names_extension_8cs.html | 10 +- ...i_enum_var_names_extension_8cs_source.html | 89 + _platform_identifier_8cs.html | 8 +- _platform_identifier_8cs_source.html | 16 +- _posix_byond_installer_8cs_source.html | 6 +- _posix_network_prompt_reaper_8cs_source.html | 6 +- _process_8cs.html | 8 +- _process_8cs_source.html | 49 +- _process_executor_8cs.html | 8 +- _process_executor_8cs_source.html | 26 +- _pull_requests_command_8cs_source.html | 8 +- _reattach_info_handler_8cs_source.html | 24 +- _reattach_information_base_8cs_source.html | 2 +- _release_notes_8_assembly_info_8cs.html | 4 +- ...ease_notes_8_assembly_info_8cs_source.html | 6 +- _repository_controller_8cs_source.html | 48 +- _repository_manager_8cs_source.html | 2 +- _resolving_i_o_manager_8cs_source.html | 2 +- _server_8cs_source.html | 2 +- _server_factory_8cs_source.html | 19 +- _server_side_modifications_8cs_source.html | 2 +- _service_collection_extensions_8cs.html | 10 +- ...vice_collection_extensions_8cs_source.html | 12 +- _session_controller_8cs_source.html | 98 +- _session_controller_factory_8cs_source.html | 70 +- _setup_wizard_8cs_source.html | 54 +- _sql_server_database_context_8cs.html | 10 +- _sql_server_database_context_8cs_source.html | 24 +- ...ase_context_model_snapshot_8cs_source.html | 11 +- ...er_design_time_db_context_factory_8cs.html | 10 +- ...gn_time_db_context_factory_8cs_source.html | 19 +- ...cs.html => _swagger_configuration_8cs.html | 9 +- _swagger_configuration_8cs_source.html | 113 + _task_extensions_8cs.html | 10 +- _task_extensions_8cs_source.html | 12 +- _temporary_dmb_provider_8cs.html | 10 +- _temporary_dmb_provider_8cs_source.html | 22 +- _test_application_8cs_source.html | 25 +- _test_async_delayer_8cs_source.html | 2 +- _test_d_b_connection_factory_8cs_source.html | 93 - ..._test_database_connection_factory_8cs.html | 14 +- ...atabase_connection_factory_8cs_source.html | 93 + _test_database_context_factory_8cs.html | 10 +- ...t_database_context_factory_8cs_source.html | 16 +- _test_experimental_watchdog_8cs_source.html | 18 +- _test_git_hub_client_factory_8cs_source.html | 2 +- _test_job_exception_8cs.html | 10 +- _test_job_exception_8cs_source.html | 12 +- _test_job_handler_8cs.html | 10 +- _test_job_handler_8cs_source.html | 26 +- _test_platform_identifier_8cs.html | 10 +- _test_platform_identifier_8cs_source.html | 12 +- _test_server_factory_8cs_source.html | 15 +- _test_service_collection_extensions_8cs.html | 18 +- ...vice_collection_extensions_8cs_source.html | 26 +- _test_setup_wizard_8cs_source.html | 14 +- _testing_server_8cs_source.html | 2 +- _tgs_authorize_attribute_8cs_source.html | 2 +- _tgs_open_api_filters_8cs_source.html | 103 - ...on_8_server_8_api_8_assembly_info_8cs.html | 4 +- ...rver_8_api_8_assembly_info_8cs_source.html | 6 +- ...ver_8_api_8_tests_8_assembly_info_8cs.html | 4 +- ...pi_8_tests_8_assembly_info_8cs_source.html | 6 +- ..._8_server_8_api_8_tests_8_program_8cs.html | 4 +- ...er_8_api_8_tests_8_program_8cs_source.html | 4 +- ...8_server_8_client_8_assembly_info_8cs.html | 4 +- ...r_8_client_8_assembly_info_8cs_source.html | 6 +- ..._8_client_8_tests_8_assembly_info_8cs.html | 4 +- ...nt_8_tests_8_assembly_info_8cs_source.html | 6 +- ...server_8_client_8_tests_8_program_8cs.html | 4 +- ...8_client_8_tests_8_program_8cs_source.html | 4 +- ...s_2_compiler_2_dream_maker_8cs_source.html | 160 - ...onents_2_deployment_2_dream_maker_8cs.html | 10 +- ...2_deployment_2_dream_maker_8cs_source.html | 157 + ...st_2_components_2_instance_8cs_source.html | 102 +- ..._2_repository_2_repository_8cs_source.html | 29 +- ...n_8_server_8_host_8_assembly_info_8cs.html | 4 +- ...ver_8_host_8_assembly_info_8cs_source.html | 6 +- ..._8_host_8_console_8_assembly_info_8cs.html | 4 +- ..._8_console_8_assembly_info_8cs_source.html | 6 +- ...8_console_8_tests_8_assembly_info_8cs.html | 4 +- ...le_8_tests_8_assembly_info_8cs_source.html | 6 +- ..._host_8_console_8_tests_8_program_8cs.html | 4 +- ..._console_8_tests_8_program_8cs_source.html | 4 +- ...rver_8_host_8_razor_assembly_info_8cs.html | 4 +- ...host_8_razor_assembly_info_8cs_source.html | 4 +- ..._8_host_8_service_8_assembly_info_8cs.html | 4 +- ..._8_service_8_assembly_info_8cs_source.html | 6 +- ...8_service_8_tests_8_assembly_info_8cs.html | 4 +- ...ce_8_tests_8_assembly_info_8cs_source.html | 6 +- ...er_8_host_8_tests_8_assembly_info_8cs.html | 4 +- ...st_8_tests_8_assembly_info_8cs_source.html | 6 +- ...8_server_8_host_8_tests_8_program_8cs.html | 4 +- ...r_8_host_8_tests_8_program_8cs_source.html | 4 +- ...8_host_8_watchdog_8_assembly_info_8cs.html | 4 +- ...8_watchdog_8_assembly_info_8cs_source.html | 6 +- ..._watchdog_8_tests_8_assembly_info_8cs.html | 4 +- ...og_8_tests_8_assembly_info_8cs_source.html | 6 +- ...host_8_watchdog_8_tests_8_program_8cs.html | 4 +- ...watchdog_8_tests_8_program_8cs_source.html | 4 +- ..._8_server_8_tests_8_assembly_info_8cs.html | 4 +- ...er_8_tests_8_assembly_info_8cs_source.html | 6 +- ...tation_8_server_8_tests_8_program_8cs.html | 4 +- ...8_server_8_tests_8_program_8cs_source.html | 4 +- _token_factory_8cs_source.html | 23 +- _updates_configuration_8cs_source.html | 2 +- _user_controller_8cs_source.html | 37 +- _watchdog_8cs_source.html | 2 +- _watchdog_base_8cs_source.html | 110 +- _windows_byond_installer_8cs_source.html | 44 +- ...dows_network_prompt_reaper_8cs_source.html | 39 +- _windows_swappable_dmb_provider_8cs.html | 107 + ...ows_swappable_dmb_provider_8cs_source.html | 111 + _windows_system_identity_8cs.html | 2 +- _windows_system_identity_8cs_source.html | 2 +- _windows_watchdog_8cs.html | 107 + _windows_watchdog_8cs_source.html | 139 + _windows_watchdog_factory_8cs.html | 107 + _windows_watchdog_factory_8cs_source.html | 123 + annotated.html | 357 +- api.html | 8 +- architecture.html | 14 +- class_auto_generated_program.html | 12 +- class_db_context.html | 4 +- class_db_context.png | Bin 1045 -> 1019 bytes class_i_design_time_db_context_factory.html | 6 +- class_i_design_time_db_context_factory.png | Bin 1777 -> 1769 bytes class_i_disposable.html | 26 +- class_i_disposable.png | Bin 25481 -> 25645 bytes class_i_document_filter.html | 4 +- class_i_document_filter.png | Bin 963 -> 946 bytes class_i_hosted_service.html | 6 +- class_i_hosted_service.png | Bin 9021 -> 9082 bytes class_i_open_api_extension.html | 90 + class_i_open_api_extension.png | Bin 0 -> 1086 bytes class_i_operation_filter.html | 4 +- class_i_operation_filter.png | Bin 977 -> 964 bytes class_i_schema_filter.html | 90 + class_i_schema_filter.png | Bin 0 -> 960 bytes ...on_1_1_server_1_1_api_1_1_api_headers.html | 16 +- ...er_1_1_api_1_1_models_1_1_compile_job.html | 4 +- ...api_1_1_models_1_1_configuration_file.html | 4 +- ...rver_1_1_api_1_1_models_1_1_entity_id.html | 2 +- ..._1_1_api_1_1_models_1_1_error_message.html | 2 +- ...erver_1_1_api_1_1_models_1_1_instance.html | 4 +- ..._1_1_api_1_1_models_1_1_instance_user.html | 2 +- ...1_models_1_1_internal_1_1_compile_job.html | 4 +- ...al_1_1_dream_daemon_launch_parameters.html | 12 +- ..._1_internal_1_1_dream_daemon_settings.html | 2 +- ...1_api_1_1_models_1_1_internal_1_1_job.html | 6 +- ..._1_1_internal_1_1_repository_settings.html | 2 +- ...1_1_internal_1_1_revision_information.html | 4 +- ..._api_1_1_models_1_1_internal_1_1_user.html | 8 +- ...ver_1_1_api_1_1_models_1_1_repository.html | 10 +- ...i_1_1_models_1_1_revision_information.html | 2 +- ..._1_1_models_1_1_test_merge_parameters.html | 6 +- ..._1_1_api_1_1_rights_1_1_rights_helper.html | 2 +- ...s_1_1_byond_1_1_byond_executable_lock.html | 2 +- ...ts_1_1_byond_1_1_byond_installer_base.html | 4 +- ...omponents_1_1_byond_1_1_byond_manager.html | 138 +- ...s_1_1_byond_1_1_posix_byond_installer.html | 4 +- ...1_1_byond_1_1_windows_byond_installer.html | 88 +- ...host_1_1_components_1_1_chat_1_1_chat.html | 8 +- ...chat_1_1_commands_1_1_command_factory.html | 70 +- ..._1_commands_1_1_pull_requests_command.html | 14 +- ...ts_1_1_chat_1_1_json_tracking_context.html | 2 +- ..._1_1_compiler_1_1_dmb_factory-members.html | 105 - ...mponents_1_1_compiler_1_1_dmb_factory.html | 836 --- ...omponents_1_1_compiler_1_1_dmb_factory.png | Bin 2710 -> 0 bytes ...ponents_1_1_compiler_1_1_dmb_provider.html | 387 -- ...mponents_1_1_compiler_1_1_dmb_provider.png | Bin 1539 -> 0 bytes ..._1_1_compiler_1_1_dream_maker-members.html | 111 - ...mponents_1_1_compiler_1_1_dream_maker.html | 1331 ----- ...omponents_1_1_compiler_1_1_dream_maker.png | Bin 1255 -> 0 bytes ..._1_compiler_1_1_temporary_dmb_provider.png | Bin 1669 -> 0 bytes ..._1_deployment_1_1_dmb_factory-members.html | 105 + ...onents_1_1_deployment_1_1_dmb_factory.html | 836 +++ ...ponents_1_1_deployment_1_1_dmb_factory.png | Bin 0 -> 2840 bytes ...1_deployment_1_1_dmb_provider-members.html | 24 +- ...nents_1_1_deployment_1_1_dmb_provider.html | 387 ++ ...onents_1_1_deployment_1_1_dmb_provider.png | Bin 0 -> 1660 bytes ..._1_deployment_1_1_dream_maker-members.html | 109 + ...onents_1_1_deployment_1_1_dream_maker.html | 1252 +++++ ...ponents_1_1_deployment_1_1_dream_maker.png | Bin 0 -> 1344 bytes ...nt_1_1_temporary_dmb_provider-members.html | 20 +- ...deployment_1_1_temporary_dmb_provider.html | 148 +- ..._deployment_1_1_temporary_dmb_provider.png | Bin 0 -> 1783 bytes ...indows_swappable_dmb_provider-members.html | 97 + ...nt_1_1_windows_swappable_dmb_provider.html | 487 ++ ...ent_1_1_windows_swappable_dmb_provider.png | Bin 0 -> 1842 bytes ..._1_1_host_1_1_components_1_1_instance.html | 286 +- ...t_1_1_components_1_1_instance_factory.html | 194 +- ...t_1_1_components_1_1_instance_manager.html | 154 +- ...mponents_1_1_interop_1_1_comm_command.html | 4 +- ...mponents_1_1_interop_1_1_comm_context.html | 2 +- ..._components_1_1_interop_1_1_constants.html | 34 +- ...ts_1_1_interop_1_1_json_sub_file_list.html | 6 +- ..._components_1_1_reattach_info_handler.html | 24 +- ...1_repository_1_1_credentials_provider.html | 2 +- ...1_1_repository_1_1_repository-members.html | 55 +- ...ponents_1_1_repository_1_1_repository.html | 124 +- ...1_1_repository_1_1_repository_manager.html | 8 +- ...ts_1_1_static_files_1_1_configuration.html | 240 +- ...1_watchdog_1_1_basic_watchdog-members.html | 41 +- ...nents_1_1_watchdog_1_1_basic_watchdog.html | 445 +- ...onents_1_1_watchdog_1_1_basic_watchdog.png | Bin 4870 -> 5867 bytes ...g_1_1_dead_session_controller-members.html | 7 +- ..._watchdog_1_1_dead_session_controller.html | 175 +- ...1_watchdog_1_1_dead_session_controller.png | Bin 2311 -> 2336 bytes ..._1_watchdog_1_1_experimental_watchdog.html | 164 +- ...onents_1_1_watchdog_1_1_launch_result.html | 8 +- ...onents_1_1_watchdog_1_1_monitor_state.html | 14 +- ...chdog_1_1_posix_network_prompt_reaper.html | 4 +- ...1_1_watchdog_1_1_reattach_information.html | 32 +- ...tchdog_1_1_session_controller-members.html | 9 +- ...s_1_1_watchdog_1_1_session_controller.html | 440 +- ...ts_1_1_watchdog_1_1_session_controller.png | Bin 3103 -> 3128 bytes ...tchdog_1_1_session_controller_factory.html | 168 +- ..._tests_1_1_test_experimental_watchdog.html | 12 +- ...onents_1_1_watchdog_1_1_watchdog_base.html | 407 +- ...ponents_1_1_watchdog_1_1_watchdog_base.png | Bin 5264 -> 6317 bytes ...watchdog_1_1_watchdog_factory-members.html | 19 +- ...nts_1_1_watchdog_1_1_watchdog_factory.html | 333 +- ...ents_1_1_watchdog_1_1_watchdog_factory.png | Bin 1278 -> 2053 bytes ...dog_1_1_watchdog_reattach_information.html | 38 +- ...dog_1_1_windows_network_prompt_reaper.html | 116 +- ...watchdog_1_1_windows_watchdog-members.html | 131 + ...nts_1_1_watchdog_1_1_windows_watchdog.html | 726 +++ ...ents_1_1_watchdog_1_1_windows_watchdog.png | Bin 0 -> 5867 bytes ..._1_1_windows_watchdog_factory-members.html | 97 + ...watchdog_1_1_windows_watchdog_factory.html | 349 ++ ..._watchdog_1_1_windows_watchdog_factory.png | Bin 0 -> 2054 bytes ...ation_1_1_control_panel_configuration.html | 4 +- ...figuration_1_1_database_configuration.html | 24 +- ...ration_1_1_file_logging_configuration.html | 10 +- ...ion_1_1_general_configuration-members.html | 3 +- ...nfiguration_1_1_general_configuration.html | 39 +- ...nfiguration_1_1_updates_configuration.html | 14 +- ...rollers_1_1_administration_controller.html | 146 +- ...st_1_1_controllers_1_1_api_controller.html | 18 +- ..._1_1_controllers_1_1_byond_controller.html | 46 +- ...t_1_1_controllers_1_1_chat_controller.html | 92 +- ...trollers_1_1_configuration_controller.html | 96 +- ...ntrollers_1_1_dream_daemon_controller.html | 102 +- ...ontrollers_1_1_dream_maker_controller.html | 88 +- ...t_1_1_controllers_1_1_home_controller.html | 92 +- ...1_controllers_1_1_instance_controller.html | 174 +- ...trollers_1_1_instance_user_controller.html | 72 +- ...st_1_1_controllers_1_1_job_controller.html | 68 +- ...controllers_1_1_repository_controller.html | 162 +- ..._controllers_1_1_tgs_open_api_filters.html | 244 - ...1_controllers_1_1_tgs_open_api_filters.png | Bin 1411 -> 0 bytes ...t_1_1_controllers_1_1_user_controller.html | 114 +- ...host_1_1_core_1_1_application-members.html | 15 +- ...ver_1_1_host_1_1_core_1_1_application.html | 170 +- ...re_1_1_application_builder_extensions.html | 272 - ...ore_1_1_assembly_information_provider.html | 208 - ...core_1_1_assembly_information_provider.png | Bin 1238 -> 0 bytes ...r_1_1_host_1_1_core_1_1_async_delayer.html | 2 +- ...st_1_1_core_1_1_d_b_connection_factory.png | Bin 1149 -> 0 bytes ...1_1_core_1_1_database_context_factory.html | 211 - ..._1_1_core_1_1_database_context_factory.png | Bin 1214 -> 0 bytes ...er_1_1_host_1_1_core_1_1_job_exception.png | Bin 722 -> 0 bytes ...rver_1_1_host_1_1_core_1_1_job_handler.png | Bin 723 -> 0 bytes ...ver_1_1_host_1_1_core_1_1_job_manager.html | 647 --- ...rver_1_1_host_1_1_core_1_1_job_manager.png | Bin 1622 -> 0 bytes ..._api_enum_var_names_extension-members.html | 13 +- ...1_1_open_api_enum_var_names_extension.html | 291 + ..._1_1_open_api_enum_var_names_extension.png | Bin 0 -> 1087 bytes ...host_1_1_core_1_1_platform_identifier.html | 208 - ..._host_1_1_core_1_1_platform_identifier.png | Bin 1021 -> 0 bytes ...1_1_host_1_1_core_1_1_process-members.html | 100 - ..._server_1_1_host_1_1_core_1_1_process.html | 622 --- ...1_server_1_1_host_1_1_core_1_1_process.png | Bin 1545 -> 0 bytes ..._1_host_1_1_core_1_1_process_executor.html | 366 -- ...1_1_host_1_1_core_1_1_process_executor.png | Bin 1006 -> 0 bytes ...t_1_1_core_1_1_semaphore_slim_context.html | 2 +- ...ost_1_1_core_1_1_setup_wizard-members.html | 4 +- ...er_1_1_host_1_1_core_1_1_setup_wizard.html | 223 +- ...ore_1_1_swagger_configuration-members.html | 92 + ...st_1_1_core_1_1_swagger_configuration.html | 406 ++ ...ost_1_1_core_1_1_swagger_configuration.png | Bin 0 -> 1679 bytes ...1_core_1_1_tests_1_1_test_application.html | 12 +- ...ication_1_1_mock_application_lifetime.html | 12 +- ...est_application_1_1_mock_setup_wizard.html | 2 +- ...tests_1_1_test_d_b_connection_factory.html | 140 - ...sts_1_1_test_database_context_factory.html | 140 - ...on_extensions_1_1_bad_config1-members.html | 86 - ...on_extensions_1_1_bad_config2-members.html | 86 - ...on_extensions_1_1_good_config-members.html | 86 - ..._core_1_1_tests_1_1_test_setup_wizard.html | 10 +- ...1_database_connection_factory-members.html | 8 +- ...abase_1_1_database_connection_factory.html | 40 +- ...tabase_1_1_database_connection_factory.png | Bin 0 -> 1243 bytes ...database_1_1_database_context-members.html | 109 + ...ost_1_1_database_1_1_database_context.html | 945 ++++ ...host_1_1_database_1_1_database_context.png | Bin 0 -> 1675 bytes ..._1_1_database_context_factory-members.html | 88 + ...database_1_1_database_context_factory.html | 209 + ..._database_1_1_database_context_factory.png | Bin 0 -> 1210 bytes ..._database_1_1_database_seeder-members.html | 16 +- ...host_1_1_database_1_1_database_seeder.html | 313 ++ ..._host_1_1_database_1_1_database_seeder.png | Bin 0 -> 1070 bytes ...me_db_context_factory_helpers-members.html | 13 +- ...esign_time_db_context_factory_helpers.html | 66 +- ...esign_time_db_context_factory-members.html | 86 + ...my_sql_design_time_db_context_factory.html | 38 +- ..._my_sql_design_time_db_context_factory.png | Bin 0 -> 1455 bytes ...esign_time_db_context_factory-members.html | 86 + ...server_design_time_db_context_factory.html | 38 +- ..._server_design_time_db_context_factory.png | Bin 0 -> 1485 bytes ...e_1_1_my_sql_database_context-members.html | 110 + ..._database_1_1_my_sql_database_context.html | 298 + ...1_database_1_1_my_sql_database_context.png | Bin 0 -> 1344 bytes ...1_sql_server_database_context-members.html | 110 + ...abase_1_1_sql_server_database_context.html | 294 + ...tabase_1_1_sql_server_database_context.png | Bin 0 -> 1326 bytes ...t_database_connection_factory-members.html | 10 +- ..._1_1_test_database_connection_factory.html | 140 + ...test_database_context_factory-members.html | 10 +- ...sts_1_1_test_database_context_factory.html | 138 + ...pplication_builder_extensions-members.html | 14 +- ...ns_1_1_application_builder_extensions.html | 272 + ...service_collection_extensions-members.html | 8 +- ...ons_1_1_service_collection_extensions.html | 28 +- ...xtensions_1_1_task_extensions-members.html | 10 +- ...st_1_1_extensions_1_1_task_extensions.html | 40 +- ...service_collection_extensions-members.html | 8 +- ..._1_test_service_collection_extensions.html | 28 +- ...on_extensions_1_1_bad_config1-members.html | 86 + ...collection_extensions_1_1_bad_config1.html | 20 +- ...on_extensions_1_1_bad_config2-members.html | 86 + ...collection_extensions_1_1_bad_config2.html | 20 +- ...collection_extensions_1_1_bad_config3.html | 8 +- ...on_extensions_1_1_good_config-members.html | 86 + ...collection_extensions_1_1_good_config.html | 20 +- ...1_server_1_1_host_1_1_i_o_1_1_console.html | 18 +- ..._host_1_1_i_o_1_1_default_i_o_manager.html | 58 +- ...ost_1_1_i_o_1_1_resolving_i_o_manager.html | 10 +- ...st_1_1_jobs_1_1_job_exception-members.html | 12 +- ...r_1_1_host_1_1_jobs_1_1_job_exception.html | 58 +- ...er_1_1_host_1_1_jobs_1_1_job_exception.png | Bin 0 -> 719 bytes ...host_1_1_jobs_1_1_job_handler-members.html | 20 +- ...ver_1_1_host_1_1_jobs_1_1_job_handler.html | 132 +- ...rver_1_1_host_1_1_jobs_1_1_job_handler.png | Bin 0 -> 718 bytes ...host_1_1_jobs_1_1_job_manager-members.html | 32 +- ...ver_1_1_host_1_1_jobs_1_1_job_manager.html | 647 +++ ...rver_1_1_host_1_1_jobs_1_1_job_manager.png | Bin 0 -> 1616 bytes ..._tests_1_1_test_job_exception-members.html | 8 +- ...jobs_1_1_tests_1_1_test_job_exception.html | 20 +- ..._1_tests_1_1_test_job_handler-members.html | 20 +- ...1_jobs_1_1_tests_1_1_test_job_handler.html | 124 +- ...r_1_1_host_1_1_models_1_1_compile_job.html | 4 +- ...1_models_1_1_database_context-members.html | 109 - ..._host_1_1_models_1_1_database_context.html | 937 ---- ...1_host_1_1_models_1_1_database_context.png | Bin 1719 -> 0 bytes ...1_host_1_1_models_1_1_database_seeder.html | 307 -- ..._1_host_1_1_models_1_1_database_seeder.png | Bin 1113 -> 0 bytes ...rver_1_1_host_1_1_models_1_1_instance.html | 4 +- ..._1_server_1_1_host_1_1_models_1_1_job.html | 4 +- ...me_db_context_factory_helpers-members.html | 88 - ...grations_1_1_m_s_add_minimum_security.html | 4 +- ...migrations_1_1_m_s_fix_rev_info_index.html | 4 +- ...1_1_migrations_1_1_m_s_initial_create.html | 4 +- ..._m_s_nullable_and_foreign_key_cleanup.html | 4 +- ...1_1_m_s_reattach_compile_job_required.html | 4 +- ...ons_1_1_m_s_toggle_testmerge_comments.html | 4 +- ...grations_1_1_m_y_add_minimum_security.html | 4 +- ...migrations_1_1_m_y_fix_rev_info_index.html | 4 +- ...1_1_migrations_1_1_m_y_initial_create.html | 4 +- ..._m_y_nullable_and_foreign_key_cleanup.html | 4 +- ...1_1_m_y_reattach_compile_job_required.html | 4 +- ...ons_1_1_m_y_toggle_testmerge_comments.html | 4 +- ...y_sql_database_context_model_snapshot.html | 6 +- ..._my_sql_design_time_db_context_factory.png | Bin 1468 -> 0 bytes ...erver_database_context_model_snapshot.html | 6 +- ...esign_time_db_context_factory-members.html | 86 - ..._server_design_time_db_context_factory.png | Bin 1515 -> 0 bytes ...s_1_1_my_sql_database_context-members.html | 110 - ..._1_models_1_1_my_sql_database_context.html | 298 - ...1_1_models_1_1_my_sql_database_context.png | Bin 1378 -> 0 bytes ...t_1_1_models_1_1_reattach_information.html | 6 +- ..._models_1_1_reattach_information_base.html | 16 +- ...t_1_1_models_1_1_revision_information.html | 4 +- ...1_sql_server_database_context-members.html | 110 - ...odels_1_1_sql_server_database_context.html | 294 - ...models_1_1_sql_server_database_context.png | Bin 1377 -> 0 bytes ...er_1_1_host_1_1_models_1_1_test_merge.html | 2 +- ...els_1_1_watchdog_reattach_information.html | 4 +- ..._1_watchdog_reattach_information_base.html | 2 +- ...r_1_1_host_1_1_native_methods-members.html | 23 +- ..._1_server_1_1_host_1_1_native_methods.html | 161 +- ...ation_1_1_server_1_1_host_1_1_program.html | 2 +- ...1_security_1_1_authentication_context.html | 10 +- ...ty_1_1_authentication_context_factory.html | 54 +- ...host_1_1_security_1_1_claims_injector.html | 14 +- ..._host_1_1_security_1_1_identity_cache.html | 6 +- ..._1_security_1_1_identity_cache_object.html | 8 +- ...ity_1_1_posix_system_identity_factory.html | 8 +- ...1_host_1_1_security_1_1_token_factory.html | 52 +- ..._security_1_1_windows_system_identity.html | 14 +- ...y_1_1_windows_system_identity_factory.html | 8 +- ...tation_1_1_server_1_1_host_1_1_server.html | 2 +- ..._1_server_1_1_host_1_1_server_factory.html | 40 +- ...assembly_information_provider-members.html | 12 +- ...tem_1_1_assembly_information_provider.html | 208 + ...stem_1_1_assembly_information_provider.png | Bin 0 -> 1292 bytes ...ystem_1_1_platform_identifier-members.html | 12 +- ...st_1_1_system_1_1_platform_identifier.html | 208 + ...ost_1_1_system_1_1_platform_identifier.png | Bin 0 -> 1142 bytes ...1_host_1_1_system_1_1_process-members.html | 103 + ...erver_1_1_host_1_1_system_1_1_process.html | 725 +++ ...server_1_1_host_1_1_system_1_1_process.png | Bin 0 -> 1588 bytes ...1_system_1_1_process_executor-members.html | 18 +- ..._host_1_1_system_1_1_process_executor.html | 366 ++ ...1_host_1_1_system_1_1_process_executor.png | Bin 0 -> 1115 bytes ..._1_1_test_platform_identifier-members.html | 8 +- ..._1_tests_1_1_test_platform_identifier.html | 20 +- ...ost_1_1_tests_1_1_test_server_factory.html | 14 +- ...er_1_1_host_1_1_watchdog_1_1_watchdog.html | 2 +- ...r_1_1_tests_1_1_instance_manager_test.html | 2 +- ...1_server_1_1_tests_1_1_testing_server.html | 2 +- classes.html | 198 +- ... dir_009a3598be1715e27911e1588bdd551c.html | 4 +- ... dir_019c6d3af924151b681494cc466be1ac.html | 8 +- dir_02f69155ced6ccca99a24744a5273903.html | 4 + ... dir_0b6a380fe7fc1e1d640d1ac854fc3fb6.html | 8 +- dir_0c9add60ab05c04ed8367ecaedf67c01.html | 6 - dir_0de875c2ee7edd4009e892c5045f7b3a.html | 40 +- dir_103b33cf1ab7043de6f87dfa61afa23f.html | 2 +- ... dir_1083fcf52a7d94a2efffb6ca88246acf.html | 4 +- dir_1302441b003a340c6a16c9bc1b51c94e.html | 12 - dir_1735a2166b4b370abc53b0c1e30953fc.html | 88 + dir_17673f49a14d7d676f5a689a303d906e.html | 90 + dir_177c182c6d1f29bec543c3fdad3072d5.html | 2 +- ... dir_18f2820c1d411453d7d989b812e41820.html | 4 +- ... dir_2553b13cbb871373b0c30fb90d66217c.html | 4 +- ... dir_26764abc66ddba24c5915db53fd68d23.html | 8 +- dir_27a421f75b087b80bd0b7a1dbec733b4.html | 94 + ... dir_2b9d136d9ffdab429a63a74fca28b300.html | 8 +- ... dir_2e39d68cad3f83629c74ea67329dead9.html | 8 +- ... dir_2e67631cb23401d696bcfdbe81f86f0f.html | 8 +- dir_34761767c1c3cd212f9d2f80ea0828a8.html | 8 + dir_38cec1532eaed7aa1de0b599a76e3e80.html | 2 - dir_3a3ab2f663730d5bed7026cf41734e8a.html | 111 + dir_3d220027e29e19c608b6d51ce3029c32.html | 104 + dir_446bdfc1cd19b69c11765b5665ebfd45.html | 2 +- ... dir_48968f849f7ddb061f7130e079fe66a6.html | 8 +- ... dir_4c0c7e2f4fc60f51e2347a2d8dda94ce.html | 4 +- dir_5ae0a4770cfe9bc511dad7df7deabb23.html | 92 + dir_685b5aa2d8a661ab5bc3f68b331887b0.html | 2 +- dir_689f0584ee97ae9ca308532531d9c5d2.html | 2 +- dir_74017a19412e2f90cc6ad11fcac82495.html | 2 +- ... dir_78e87f8f095a8e3bb6ef1faef94cdb78.html | 8 +- dir_7a3fd032a1362a6005a1fc9227a8dd86.html | 4 +- dir_7b7b77fd390505b3ee0b06c896e68c8c.html | 90 + ... dir_87039fa7b841d848ca75981d64237477.html | 8 +- dir_87a4f2035ed18e30422f4b60aebc4381.html | 2 +- ... dir_9257d56e926145e494a5aa5279887044.html | 4 +- ... dir_9aa5991638c9344778d807333cc0bd50.html | 6 +- dir_9e1f926893bfa79d60859df55c4de3e7.html | 88 + ... dir_a3714ab037275c284988fc90b4d045a5.html | 4 +- ... dir_a3831f1c39821b3669f8a3808652203f.html | 4 +- dir_a51095d0142a80f0e979ff5bf5b861be.html | 2 +- ... dir_a8807eef6592489c6a360d587f5b1a66.html | 4 +- dir_af336dd70489e812a924e1a8fba73854.html | 92 + dir_b524b00ec2259c3c83b44909fd47f6e3.html | 2 +- ... dir_b551a02288ef39e099594710382363a0.html | 4 +- ... dir_b87cbb2c60cf682b61fbfcceb9bced43.html | 4 +- ... dir_b92573f47b933d7a3661c26d1af2098b.html | 8 +- ... dir_be9f3ed3485a880e3213506a311823d1.html | 8 +- dir_bf23e1e49f40264f2966f02ed35d8142.html | 2 +- dir_c2c4d4ee47e55233c6ea5db8b96422c6.html | 12 - dir_c50f9bd139317d744e2ee08ea9a734cc.html | 2 +- ... dir_c5f98c05147bcbba78e71856485f5049.html | 4 +- ... dir_d8a279f7113e0073f6cd65dd050c1475.html | 4 +- dir_e0c1bccb03249d93bc42ac0968ce43fd.html | 2 +- ... dir_e2f0549e5ba528b36fd9348e214a8e4f.html | 12 +- ... dir_e97d380c3eebaf0856a4ec180d749620.html | 8 +- ... dir_ea36b5ab01ad6e8b607438a02ae91964.html | 8 +- dir_ed78ff3b0fc4a7f5234cdb0b34617476.html | 8 + dir_f0581cdd528a911f791df57d0f438bcb.html | 2 +- ... dir_f88948f9bde0555374e8a59a663bdfc9.html | 4 +- ... dir_fab1362e86740a2c573ef875dd474a67.html | 8 +- dir_fb12273b841438c2f2c9b5bc5398c636.html | 2 +- files.html | 395 +- functions.html | 38 +- functions_b.html | 11 +- functions_c.html | 96 +- functions_d.html | 66 +- functions_e.html | 7 +- functions_enum.html | 3 + functions_f.html | 4 +- functions_func.html | 16 +- functions_func_c.html | 56 +- functions_func_d.html | 26 +- functions_func_f.html | 4 +- functions_func_g.html | 22 +- functions_func_h.html | 8 + functions_func_i.html | 6 +- functions_func_j.html | 10 +- functions_func_k.html | 7 +- functions_func_l.html | 12 +- functions_func_m.html | 9 +- functions_func_o.html | 12 +- functions_func_p.html | 12 +- functions_func_r.html | 28 +- functions_func_s.html | 41 +- functions_func_t.html | 32 +- functions_func_u.html | 18 +- functions_func_v.html | 2 +- functions_func_w.html | 23 +- functions_g.html | 28 +- functions_h.html | 10 +- functions_i.html | 37 +- functions_j.html | 30 +- functions_k.html | 7 +- functions_l.html | 41 +- functions_m.html | 11 +- functions_n.html | 12 +- functions_o.html | 20 +- functions_p.html | 36 +- functions_prop.html | 1 + functions_prop_b.html | 3 + functions_prop_c.html | 18 +- functions_prop_d.html | 19 +- functions_prop_g.html | 3 + functions_prop_i.html | 16 +- functions_prop_j.html | 7 +- functions_prop_l.html | 9 +- functions_prop_n.html | 4 +- functions_prop_o.html | 4 +- functions_prop_p.html | 10 +- functions_prop_r.html | 14 +- functions_prop_s.html | 16 +- functions_prop_t.html | 2 +- functions_prop_u.html | 7 +- functions_prop_w.html | 4 +- functions_r.html | 48 +- functions_s.html | 83 +- functions_t.html | 49 +- functions_u.html | 25 +- functions_v.html | 2 +- functions_vars.html | 11 +- functions_vars_b.html | 8 +- functions_vars_c.html | 26 +- functions_vars_d.html | 21 +- functions_vars_e.html | 7 +- functions_vars_g.html | 3 +- functions_vars_h.html | 2 +- functions_vars_i.html | 11 +- functions_vars_j.html | 5 +- functions_vars_l.html | 16 +- functions_vars_n.html | 4 +- functions_vars_o.html | 4 +- functions_vars_p.html | 10 +- functions_vars_r.html | 4 +- functions_vars_s.html | 24 +- functions_vars_t.html | 4 +- functions_vars_w.html | 2 +- functions_w.html | 29 +- hierarchy.html | 437 +- ...1_1_byond_1_1_i_byond_executable_lock.html | 10 +- ...nents_1_1_byond_1_1_i_byond_installer.html | 8 +- ...ponents_1_1_byond_1_1_i_byond_manager.html | 2 +- ...st_1_1_components_1_1_chat_1_1_i_chat.html | 8 +- ...omponents_1_1_chat_1_1_i_chat_factory.html | 2 +- ...1_1_chat_1_1_i_custom_command_handler.html | 1 + ..._1_1_chat_1_1_i_custom_command_handler.png | Bin 2698 -> 3539 bytes ..._1_1_chat_1_1_i_json_tracking_context.html | 2 +- ..._1_compiler_1_1_i_compile_job_consumer.png | Bin 2302 -> 0 bytes ...ponents_1_1_compiler_1_1_i_dmb_factory.png | Bin 1251 -> 0 bytes ...ponents_1_1_compiler_1_1_i_dream_maker.png | Bin 1259 -> 0 bytes ...nt_1_1_i_compile_job_consumer-members.html | 8 +- ...deployment_1_1_i_compile_job_consumer.html | 42 +- ..._deployment_1_1_i_compile_job_consumer.png | Bin 0 -> 2454 bytes ..._deployment_1_1_i_dmb_factory-members.html | 16 +- ...ents_1_1_deployment_1_1_i_dmb_factory.html | 112 +- ...nents_1_1_deployment_1_1_i_dmb_factory.png | Bin 0 -> 1319 bytes ...deployment_1_1_i_dmb_provider-members.html | 16 +- ...nts_1_1_deployment_1_1_i_dmb_provider.html | 99 +- ...ents_1_1_deployment_1_1_i_dmb_provider.png | Bin 0 -> 3073 bytes ..._deployment_1_1_i_dream_maker-members.html | 8 +- ...ents_1_1_deployment_1_1_i_dream_maker.html | 34 +- ...nents_1_1_deployment_1_1_i_dream_maker.png | Bin 0 -> 1352 bytes ...host_1_1_components_1_1_i_dmb_provider.png | Bin 2278 -> 0 bytes ...t_1_1_components_1_1_i_event_consumer.html | 3 +- ...st_1_1_components_1_1_i_event_consumer.png | Bin 4960 -> 5954 bytes ..._1_host_1_1_components_1_1_i_instance.html | 42 +- ...1_1_components_1_1_i_instance_factory.html | 2 +- ...1_1_components_1_1_i_instance_manager.html | 2 +- ...onents_1_1_interop_1_1_i_comm_context.html | 2 +- ...repository_1_1_i_credentials_provider.html | 2 +- ...nents_1_1_repository_1_1_i_repository.html | 6 +- ..._watchdog_1_1_i_network_prompt_reaper.html | 6 +- ..._watchdog_1_1_i_reattach_info_handler.html | 4 +- ...hdog_1_1_i_session_controller-members.html | 11 +- ...1_1_watchdog_1_1_i_session_controller.html | 139 +- ..._1_1_watchdog_1_1_i_session_controller.png | Bin 3139 -> 3165 bytes ...hdog_1_1_i_session_controller_factory.html | 18 +- ...omponents_1_1_watchdog_1_1_i_watchdog.html | 5 +- ...components_1_1_watchdog_1_1_i_watchdog.png | Bin 4253 -> 5208 bytes ...tchdog_1_1_i_watchdog_factory-members.html | 2 +- ...s_1_1_watchdog_1_1_i_watchdog_factory.html | 28 +- ...ts_1_1_watchdog_1_1_i_watchdog_factory.png | Bin 1282 -> 2056 bytes ...r_1_1_host_1_1_core_1_1_i_application.html | 4 +- ...re_1_1_i_assembly_information_provider.png | Bin 1245 -> 0 bytes ...1_1_host_1_1_core_1_1_i_async_delayer.html | 2 +- ..._1_1_core_1_1_i_d_b_connection_factory.png | Bin 1155 -> 0 bytes ...1_core_1_1_i_database_context_factory.html | 143 - ..._1_core_1_1_i_database_context_factory.png | Bin 1216 -> 0 bytes ...1_1_core_1_1_i_git_hub_client_factory.html | 2 +- ...er_1_1_host_1_1_core_1_1_i_job_manager.png | Bin 1206 -> 0 bytes ...ost_1_1_core_1_1_i_platform_identifier.png | Bin 1029 -> 0 bytes ...erver_1_1_host_1_1_core_1_1_i_process.html | 287 - ...server_1_1_host_1_1_core_1_1_i_process.png | Bin 1551 -> 0 bytes ..._1_1_host_1_1_core_1_1_i_process_base.html | 176 - ...r_1_1_host_1_1_core_1_1_i_process_base.png | Bin 4025 -> 0 bytes ...1_host_1_1_core_1_1_i_process_executor.png | Bin 1013 -> 0 bytes ...1_host_1_1_core_1_1_i_restart_handler.html | 3 +- ..._1_host_1_1_core_1_1_i_restart_handler.png | Bin 3525 -> 4517 bytes ..._1_host_1_1_core_1_1_i_server_control.html | 8 +- ..._1_1_host_1_1_core_1_1_i_setup_wizard.html | 2 +- ...i_database_connection_factory-members.html | 8 +- ...ase_1_1_i_database_connection_factory.html | 42 +- ...base_1_1_i_database_connection_factory.png | Bin 0 -> 1245 bytes ...tabase_1_1_i_database_context-members.html | 101 + ...t_1_1_database_1_1_i_database_context.html | 320 +- ...st_1_1_database_1_1_i_database_context.png | Bin 0 -> 1264 bytes ..._1_i_database_context_factory-members.html | 8 +- ...tabase_1_1_i_database_context_factory.html | 143 + ...atabase_1_1_i_database_context_factory.png | Bin 0 -> 1214 bytes ...atabase_1_1_i_database_seeder-members.html | 10 +- ...st_1_1_database_1_1_i_database_seeder.html | 62 +- ...ost_1_1_database_1_1_i_database_seeder.png | Bin 0 -> 1075 bytes ...server_1_1_host_1_1_i_o_1_1_i_console.html | 32 +- ...er_1_1_host_1_1_i_o_1_1_i_i_o_manager.html | 42 +- ..._1_host_1_1_i_o_1_1_i_symlink_factory.html | 2 +- ...1_1_i_o_1_1_i_synchronous_i_o_manager.html | 8 +- ..._server_1_1_host_1_1_i_server_factory.html | 2 +- ...st_1_1_jobs_1_1_i_job_manager-members.html | 14 +- ...r_1_1_host_1_1_jobs_1_1_i_job_manager.html | 90 +- ...er_1_1_host_1_1_jobs_1_1_i_job_manager.png | Bin 0 -> 1195 bytes ...models_1_1_i_database_context-members.html | 101 - ...host_1_1_models_1_1_i_database_context.png | Bin 1314 -> 0 bytes ..._host_1_1_models_1_1_i_database_seeder.png | Bin 1121 -> 0 bytes ...security_1_1_i_authentication_context.html | 4 +- ...st_1_1_security_1_1_i_claims_injector.html | 10 +- ...1_1_security_1_1_i_cryptography_suite.html | 8 +- ...ost_1_1_security_1_1_i_identity_cache.html | 18 +- ...st_1_1_security_1_1_i_system_identity.html | 30 +- ...ecurity_1_1_i_system_identity_factory.html | 20 +- ...host_1_1_security_1_1_i_token_factory.html | 4 +- ...assembly_information_provider-members.html | 10 +- ...m_1_1_i_assembly_information_provider.html | 48 +- ...em_1_1_i_assembly_information_provider.png | Bin 0 -> 1298 bytes ...tem_1_1_i_platform_identifier-members.html | 10 +- ..._1_1_system_1_1_i_platform_identifier.html | 46 +- ...t_1_1_system_1_1_i_platform_identifier.png | Bin 0 -> 1144 bytes ...host_1_1_system_1_1_i_process-members.html | 24 +- ...ver_1_1_host_1_1_system_1_1_i_process.html | 293 + ...rver_1_1_host_1_1_system_1_1_i_process.png | Bin 0 -> 1593 bytes ...1_1_system_1_1_i_process_base-members.html | 12 +- ..._1_host_1_1_system_1_1_i_process_base.html | 224 + ...1_1_host_1_1_system_1_1_i_process_base.png | Bin 0 -> 4126 bytes ...system_1_1_i_process_executor-members.html | 10 +- ...ost_1_1_system_1_1_i_process_executor.html | 70 +- ...host_1_1_system_1_1_i_process_executor.png | Bin 0 -> 1120 bytes namespace_tgstation_1_1_server_1_1_host.html | 8 + ...on_1_1_server_1_1_host_1_1_components.html | 5 +- ..._1_host_1_1_components_1_1_deployment.html | 36 +- ..._1_1_host_1_1_components_1_1_watchdog.html | 6 + ...1_1_server_1_1_host_1_1_configuration.html | 2 +- ...n_1_1_server_1_1_host_1_1_controllers.html | 3 - ...gstation_1_1_server_1_1_host_1_1_core.html | 55 +- ..._1_server_1_1_host_1_1_core_1_1_tests.html | 12 - ...tion_1_1_server_1_1_host_1_1_database.html | 122 + ...rver_1_1_host_1_1_database_1_1_design.html | 25 +- ...erver_1_1_host_1_1_database_1_1_tests.html | 92 + ...on_1_1_server_1_1_host_1_1_extensions.html | 103 + ...ver_1_1_host_1_1_extensions_1_1_tests.html | 90 + ...tgstation_1_1_server_1_1_host_1_1_i_o.html | 2 +- ...gstation_1_1_server_1_1_host_1_1_jobs.html | 105 + ..._1_server_1_1_host_1_1_jobs_1_1_tests.html | 92 + ...tation_1_1_server_1_1_host_1_1_models.html | 20 +- ...er_1_1_host_1_1_models_1_1_migrations.html | 7 - ...tion_1_1_server_1_1_host_1_1_security.html | 12 +- ...tation_1_1_server_1_1_host_1_1_system.html | 117 + ..._server_1_1_host_1_1_system_1_1_tests.html | 90 + namespaces.html | 37 +- search/all_1.js | 22 +- search/all_10.js | 22 +- search/all_12.js | 35 +- search/all_13.js | 49 +- search/all_14.js | 66 +- search/all_15.js | 15 +- search/all_16.js | 2 +- search/all_17.js | 23 +- search/all_2.js | 13 +- search/all_3.js | 56 +- search/all_4.js | 47 +- search/all_5.js | 5 +- search/all_6.js | 2 +- search/all_7.js | 18 +- search/all_8.js | 4 +- search/all_9.js | 50 +- search/all_a.js | 14 +- search/all_b.js | 2 +- search/all_c.js | 13 +- search/all_d.js | 9 +- search/all_e.js | 8 +- search/all_f.js | 13 +- search/classes_0.js | 4 +- search/classes_1.js | 6 +- search/classes_10.js | 37 +- search/classes_11.js | 58 +- search/classes_12.js | 44 +- search/classes_13.js | 8 +- search/classes_14.js | 12 +- search/classes_15.html | 30 + search/classes_15.js | 17 + search/classes_3.js | 20 +- search/classes_6.js | 2 +- search/classes_8.js | 30 +- search/classes_9.js | 8 +- search/classes_c.js | 4 +- search/classes_e.js | 13 +- search/classes_f.js | 30 +- search/enums_9.html | 30 + search/enums_9.js | 4 + search/enumvalues_d.js | 1 + search/files_10.js | 35 +- search/files_11.js | 42 +- search/files_12.js | 78 +- search/files_13.js | 64 +- search/files_14.js | 8 +- search/files_15.js | 12 +- search/files_16.html | 30 + search/files_16.js | 17 + search/files_4.js | 4 +- search/files_9.js | 2 +- search/files_f.js | 13 +- search/functions_0.js | 9 +- search/functions_10.js | 13 +- search/functions_11.js | 22 +- search/functions_12.js | 26 +- search/functions_13.js | 12 +- search/functions_14.js | 2 +- search/functions_15.js | 14 +- search/functions_2.js | 26 +- search/functions_3.js | 16 +- search/functions_5.js | 2 +- search/functions_6.js | 14 +- search/functions_7.js | 2 + search/functions_8.js | 4 +- search/functions_9.js | 8 +- search/functions_a.js | 2 +- search/functions_b.js | 6 +- search/functions_c.js | 7 +- search/functions_e.js | 6 +- search/functions_f.js | 9 +- search/namespaces_1.js | 9 +- search/properties_0.js | 2 +- search/properties_1.js | 1 + search/properties_10.js | 8 +- search/properties_11.js | 2 +- search/properties_12.js | 3 +- search/properties_14.js | 2 +- search/properties_2.js | 8 +- search/properties_3.js | 11 +- search/properties_6.js | 1 + search/properties_8.js | 8 +- search/properties_9.js | 3 +- search/properties_a.js | 5 +- search/properties_c.js | 2 +- search/properties_d.js | 2 +- search/properties_e.js | 6 +- search/properties_f.js | 8 +- search/searchdata.js | 6 +- search/variables_0.js | 11 +- search/variables_1.js | 7 +- search/variables_11.js | 4 +- search/variables_12.js | 13 +- search/variables_13.js | 4 +- search/variables_16.js | 4 +- search/variables_2.js | 23 +- search/variables_3.js | 18 +- search/variables_4.js | 5 +- search/variables_6.js | 2 +- search/variables_7.js | 2 +- search/variables_8.js | 6 +- search/variables_9.js | 6 +- search/variables_b.js | 5 +- search/variables_d.js | 4 +- search/variables_e.js | 4 +- search/variables_f.js | 9 +- ..._8_server_8_host_2_program_8cs_source.html | 6 +- swagger.json | 4789 +++++++++++++++++ 933 files changed, 29378 insertions(+), 17974 deletions(-) delete mode 100644 _d_b_connection_factory_8cs_source.html rename _tgs_open_api_filters_8cs.html => _database_connection_factory_8cs.html (79%) create mode 100644 _database_connection_factory_8cs_source.html create mode 100644 _i_database_connection_factory_8cs.html rename _i_d_b_connection_factory_8cs_source.html => _i_database_connection_factory_8cs_source.html (56%) rename _i_d_b_connection_factory_8cs.html => _open_api_enum_var_names_extension_8cs.html (87%) create mode 100644 _open_api_enum_var_names_extension_8cs_source.html rename _d_b_connection_factory_8cs.html => _swagger_configuration_8cs.html (89%) create mode 100644 _swagger_configuration_8cs_source.html delete mode 100644 _test_d_b_connection_factory_8cs_source.html rename _test_d_b_connection_factory_8cs.html => _test_database_connection_factory_8cs.html (80%) create mode 100644 _test_database_connection_factory_8cs_source.html delete mode 100644 _tgs_open_api_filters_8cs_source.html delete mode 100644 _tgstation_8_server_8_host_2_components_2_compiler_2_dream_maker_8cs_source.html rename _tgstation_8_server_8_host_2_components_2_compiler_2_dream_maker_8cs.html => _tgstation_8_server_8_host_2_components_2_deployment_2_dream_maker_8cs.html (87%) create mode 100644 _tgstation_8_server_8_host_2_components_2_deployment_2_dream_maker_8cs_source.html create mode 100644 _windows_swappable_dmb_provider_8cs.html create mode 100644 _windows_swappable_dmb_provider_8cs_source.html create mode 100644 _windows_watchdog_8cs.html create mode 100644 _windows_watchdog_8cs_source.html create mode 100644 _windows_watchdog_factory_8cs.html create mode 100644 _windows_watchdog_factory_8cs_source.html create mode 100644 class_i_open_api_extension.html create mode 100644 class_i_open_api_extension.png create mode 100644 class_i_schema_filter.html create mode 100644 class_i_schema_filter.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_factory-members.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_factory.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_factory.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_provider.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_provider.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dream_maker-members.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dream_maker.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dream_maker.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_temporary_dmb_provider.png create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_dmb_factory-members.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_dmb_factory.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_dmb_factory.png rename class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_provider-members.html => class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_dmb_provider-members.html (53%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_dmb_provider.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_dmb_provider.png create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_dream_maker-members.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_dream_maker.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_dream_maker.png rename class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_temporary_dmb_provider-members.html => class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_temporary_dmb_provider-members.html (55%) rename class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_temporary_dmb_provider.html => class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_temporary_dmb_provider.html (50%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_temporary_dmb_provider.png create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_windows_swappable_dmb_provider-members.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_windows_swappable_dmb_provider.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_windows_swappable_dmb_provider.png create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_windows_watchdog-members.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_windows_watchdog.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_windows_watchdog.png create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_windows_watchdog_factory-members.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_windows_watchdog_factory.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_windows_watchdog_factory.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_tgs_open_api_filters.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_tgs_open_api_filters.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_application_builder_extensions.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_assembly_information_provider.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_assembly_information_provider.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_d_b_connection_factory.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_database_context_factory.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_database_context_factory.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_job_exception.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_job_handler.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_job_manager.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_job_manager.png rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_database_context_factory-members.html => class_tgstation_1_1_server_1_1_host_1_1_core_1_1_open_api_enum_var_names_extension-members.html (65%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_open_api_enum_var_names_extension.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_open_api_enum_var_names_extension.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_platform_identifier.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_platform_identifier.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_process-members.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_process.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_process.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_process_executor.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_process_executor.png create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_swagger_configuration-members.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_swagger_configuration.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_swagger_configuration.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_d_b_connection_factory.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_database_context_factory.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_service_collection_extensions_1_1_bad_config1-members.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_service_collection_extensions_1_1_bad_config2-members.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_service_collection_extensions_1_1_good_config-members.html rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_d_b_connection_factory-members.html => class_tgstation_1_1_server_1_1_host_1_1_database_1_1_database_connection_factory-members.html (78%) rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_d_b_connection_factory.html => class_tgstation_1_1_server_1_1_host_1_1_database_1_1_database_connection_factory.html (59%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_database_connection_factory.png create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_database_context-members.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_database_context.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_database_context.png create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_database_context_factory-members.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_database_context_factory.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_database_context_factory.png rename class_tgstation_1_1_server_1_1_host_1_1_models_1_1_database_seeder-members.html => class_tgstation_1_1_server_1_1_host_1_1_database_1_1_database_seeder-members.html (62%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_database_seeder.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_database_seeder.png rename class_tgstation_1_1_server_1_1_host_1_1_controllers_1_1_tgs_open_api_filters-members.html => class_tgstation_1_1_server_1_1_host_1_1_database_1_1_design_1_1_design_time_db_context_factory_helpers-members.html (63%) rename class_tgstation_1_1_server_1_1_host_1_1_models_1_1_migrations_1_1_design_time_db_context_factory_helpers.html => class_tgstation_1_1_server_1_1_host_1_1_database_1_1_design_1_1_design_time_db_context_factory_helpers.html (52%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_design_1_1_my_sql_design_time_db_context_factory-members.html rename class_tgstation_1_1_server_1_1_host_1_1_models_1_1_migrations_1_1_my_sql_design_time_db_context_factory.html => class_tgstation_1_1_server_1_1_host_1_1_database_1_1_design_1_1_my_sql_design_time_db_context_factory.html (65%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_design_1_1_my_sql_design_time_db_context_factory.png create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_design_1_1_sql_server_design_time_db_context_factory-members.html rename class_tgstation_1_1_server_1_1_host_1_1_models_1_1_migrations_1_1_sql_server_design_time_db_context_factory.html => class_tgstation_1_1_server_1_1_host_1_1_database_1_1_design_1_1_sql_server_design_time_db_context_factory.html (62%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_design_1_1_sql_server_design_time_db_context_factory.png create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_my_sql_database_context-members.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_my_sql_database_context.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_my_sql_database_context.png create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_sql_server_database_context-members.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_sql_server_database_context.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_sql_server_database_context.png rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_d_b_connection_factory-members.html => class_tgstation_1_1_server_1_1_host_1_1_database_1_1_tests_1_1_test_database_connection_factory-members.html (70%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_tests_1_1_test_database_connection_factory.html rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_database_context_factory-members.html => class_tgstation_1_1_server_1_1_host_1_1_database_1_1_tests_1_1_test_database_context_factory-members.html (70%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_database_1_1_tests_1_1_test_database_context_factory.html rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_application_builder_extensions-members.html => class_tgstation_1_1_server_1_1_host_1_1_extensions_1_1_application_builder_extensions-members.html (60%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_extensions_1_1_application_builder_extensions.html rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_platform_identifier-members.html => class_tgstation_1_1_server_1_1_host_1_1_extensions_1_1_service_collection_extensions-members.html (76%) rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_service_collection_extensions.html => class_tgstation_1_1_server_1_1_host_1_1_extensions_1_1_service_collection_extensions.html (85%) rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_task_extensions-members.html => class_tgstation_1_1_server_1_1_host_1_1_extensions_1_1_task_extensions-members.html (72%) rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_task_extensions.html => class_tgstation_1_1_server_1_1_host_1_1_extensions_1_1_task_extensions.html (81%) rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_service_collection_extensions-members.html => class_tgstation_1_1_server_1_1_host_1_1_extensions_1_1_tests_1_1_test_service_collection_extensions-members.html (76%) rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_service_collection_extensions.html => class_tgstation_1_1_server_1_1_host_1_1_extensions_1_1_tests_1_1_test_service_collection_extensions.html (78%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_extensions_1_1_tests_1_1_test_service_collection_extensions_1_1_bad_config1-members.html rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_service_collection_extensions_1_1_bad_config1.html => class_tgstation_1_1_server_1_1_host_1_1_extensions_1_1_tests_1_1_test_service_collection_extensions_1_1_bad_config1.html (73%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_extensions_1_1_tests_1_1_test_service_collection_extensions_1_1_bad_config2-members.html rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_service_collection_extensions_1_1_bad_config2.html => class_tgstation_1_1_server_1_1_host_1_1_extensions_1_1_tests_1_1_test_service_collection_extensions_1_1_bad_config2.html (71%) rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_service_collection_extensions_1_1_bad_config3.html => class_tgstation_1_1_server_1_1_host_1_1_extensions_1_1_tests_1_1_test_service_collection_extensions_1_1_bad_config3.html (78%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_extensions_1_1_tests_1_1_test_service_collection_extensions_1_1_good_config-members.html rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_service_collection_extensions_1_1_good_config.html => class_tgstation_1_1_server_1_1_host_1_1_extensions_1_1_tests_1_1_test_service_collection_extensions_1_1_good_config.html (72%) rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_job_exception-members.html => class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception-members.html (80%) rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_job_exception.html => class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception.html (76%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_exception.png rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_job_handler-members.html => class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_handler-members.html (67%) rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_job_handler.html => class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_handler.html (63%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_handler.png rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_job_manager-members.html => class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_manager-members.html (61%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_manager.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_job_manager.png rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_job_exception-members.html => class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_tests_1_1_test_job_exception-members.html (85%) rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_job_exception.html => class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_tests_1_1_test_job_exception.html (86%) rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_job_handler-members.html => class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_tests_1_1_test_job_handler-members.html (68%) rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_job_handler.html => class_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_tests_1_1_test_job_handler.html (62%) delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_models_1_1_database_context-members.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_models_1_1_database_context.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_models_1_1_database_context.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_models_1_1_database_seeder.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_models_1_1_database_seeder.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_models_1_1_migrations_1_1_design_time_db_context_factory_helpers-members.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_models_1_1_migrations_1_1_my_sql_design_time_db_context_factory.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_models_1_1_migrations_1_1_sql_server_design_time_db_context_factory-members.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_models_1_1_migrations_1_1_sql_server_design_time_db_context_factory.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_models_1_1_my_sql_database_context-members.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_models_1_1_my_sql_database_context.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_models_1_1_my_sql_database_context.png delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_models_1_1_sql_server_database_context-members.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_models_1_1_sql_server_database_context.html delete mode 100644 class_tgstation_1_1_server_1_1_host_1_1_models_1_1_sql_server_database_context.png rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_assembly_information_provider-members.html => class_tgstation_1_1_server_1_1_host_1_1_system_1_1_assembly_information_provider-members.html (69%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_system_1_1_assembly_information_provider.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_system_1_1_assembly_information_provider.png rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_platform_identifier-members.html => class_tgstation_1_1_server_1_1_host_1_1_system_1_1_platform_identifier-members.html (72%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_system_1_1_platform_identifier.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_system_1_1_platform_identifier.png create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_system_1_1_process-members.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_system_1_1_process.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_system_1_1_process.png rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_process_executor-members.html => class_tgstation_1_1_server_1_1_host_1_1_system_1_1_process_executor-members.html (58%) create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_system_1_1_process_executor.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_system_1_1_process_executor.png rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_service_collection_extensions-members.html => class_tgstation_1_1_server_1_1_host_1_1_system_1_1_tests_1_1_test_platform_identifier-members.html (77%) rename class_tgstation_1_1_server_1_1_host_1_1_core_1_1_tests_1_1_test_platform_identifier.html => class_tgstation_1_1_server_1_1_host_1_1_system_1_1_tests_1_1_test_platform_identifier.html (81%) rename dir_4e036e007444785d010e90b5c9a24acd.html => dir_009a3598be1715e27911e1588bdd551c.html (93%) rename dir_91e2bbee1291fcb0db7e0417b617d01e.html => dir_019c6d3af924151b681494cc466be1ac.html (91%) rename dir_53c056aa6a96f034cca75f793964be6e.html => dir_0b6a380fe7fc1e1d640d1ac854fc3fb6.html (90%) rename dir_b2c89c850c962495793d09ea3a2ee385.html => dir_1083fcf52a7d94a2efffb6ca88246acf.html (94%) create mode 100644 dir_1735a2166b4b370abc53b0c1e30953fc.html create mode 100644 dir_17673f49a14d7d676f5a689a303d906e.html rename dir_3d40f65451d27d8a0fb149ee9a9b554e.html => dir_18f2820c1d411453d7d989b812e41820.html (90%) rename dir_53aae571c66a052729f8e64ccc397130.html => dir_2553b13cbb871373b0c30fb90d66217c.html (93%) rename dir_2b188058b5c65ed53019acbdf1ae90eb.html => dir_26764abc66ddba24c5915db53fd68d23.html (90%) create mode 100644 dir_27a421f75b087b80bd0b7a1dbec733b4.html rename dir_90400719279795a0c5ea912516a4c874.html => dir_2b9d136d9ffdab429a63a74fca28b300.html (90%) rename dir_ec133cefc1442f53ec97e0d7a57cf129.html => dir_2e39d68cad3f83629c74ea67329dead9.html (90%) rename dir_7ae0efc0613c36c848fa310214e0aee3.html => dir_2e67631cb23401d696bcfdbe81f86f0f.html (90%) create mode 100644 dir_3a3ab2f663730d5bed7026cf41734e8a.html create mode 100644 dir_3d220027e29e19c608b6d51ce3029c32.html rename dir_4122b363a9d577bed19bef337e757ff3.html => dir_48968f849f7ddb061f7130e079fe66a6.html (90%) rename dir_d45f494620bc0048ee4a31fa4f7391e1.html => dir_4c0c7e2f4fc60f51e2347a2d8dda94ce.html (93%) create mode 100644 dir_5ae0a4770cfe9bc511dad7df7deabb23.html rename dir_b8a3bd11729740ba378245d2667dd433.html => dir_78e87f8f095a8e3bb6ef1faef94cdb78.html (91%) create mode 100644 dir_7b7b77fd390505b3ee0b06c896e68c8c.html rename dir_0e792d76844bf2d7c79795a56a50ebec.html => dir_87039fa7b841d848ca75981d64237477.html (90%) rename dir_6db5af7fcfa17a34c7abf23e195af4db.html => dir_9257d56e926145e494a5aa5279887044.html (93%) rename dir_69bd2cc774829698c297e262fcc70ea6.html => dir_9aa5991638c9344778d807333cc0bd50.html (89%) create mode 100644 dir_9e1f926893bfa79d60859df55c4de3e7.html rename dir_13bee0ed20ecc83b9bcd4b869b726d42.html => dir_a3714ab037275c284988fc90b4d045a5.html (93%) rename dir_0772f58f5c1b374fac16f9b51948477a.html => dir_a3831f1c39821b3669f8a3808652203f.html (94%) rename dir_fcc41a8faa41492aba200a49fc7d0aed.html => dir_a8807eef6592489c6a360d587f5b1a66.html (92%) create mode 100644 dir_af336dd70489e812a924e1a8fba73854.html rename dir_900257602d294c4a4799e88420919068.html => dir_b551a02288ef39e099594710382363a0.html (94%) rename dir_e928c7e494884ad322b5f6005c2954e1.html => dir_b87cbb2c60cf682b61fbfcceb9bced43.html (93%) rename dir_40138fd4849573e743490d583f6d06d6.html => dir_b92573f47b933d7a3661c26d1af2098b.html (91%) rename dir_18a5e30c14613227f95d12bd9fddc614.html => dir_be9f3ed3485a880e3213506a311823d1.html (90%) rename dir_298f2a364723f4f4cea115538f944a94.html => dir_c5f98c05147bcbba78e71856485f5049.html (94%) rename dir_83a6f600c846cd444f33e44bb9b4f9cb.html => dir_d8a279f7113e0073f6cd65dd050c1475.html (92%) rename dir_b0d0d898ef448ca0a6a170a2896fa60e.html => dir_e2f0549e5ba528b36fd9348e214a8e4f.html (79%) rename dir_c65d377d3c73fb4a07b3637f9c0caf4d.html => dir_e97d380c3eebaf0856a4ec180d749620.html (91%) rename dir_6c8d8f20501e8e412458f542d0998195.html => dir_ea36b5ab01ad6e8b607438a02ae91964.html (91%) rename dir_383ca23c40357ede4cca827b4a365c76.html => dir_f88948f9bde0555374e8a59a663bdfc9.html (92%) rename dir_7a9d035dcfcd6d9c7aa1efef4b6b58a4.html => dir_fab1362e86740a2c573ef875dd474a67.html (90%) delete mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_compile_job_consumer.png delete mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_dmb_factory.png delete mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_dream_maker.png rename interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_compile_job_consumer-members.html => interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_i_compile_job_consumer-members.html (77%) rename interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_compile_job_consumer.html => interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_i_compile_job_consumer.html (69%) create mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_i_compile_job_consumer.png rename interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_dmb_factory-members.html => interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_i_dmb_factory-members.html (60%) rename interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_dmb_factory.html => interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_i_dmb_factory.html (59%) create mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_i_dmb_factory.png rename interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_dmb_provider-members.html => interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_i_dmb_provider-members.html (61%) rename interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_dmb_provider.html => interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_i_dmb_provider.html (59%) create mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_i_dmb_provider.png rename interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_dream_maker-members.html => interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_i_dream_maker-members.html (75%) rename interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_dream_maker.html => interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_i_dream_maker.html (78%) create mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_i_dream_maker.png delete mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_dmb_provider.png delete mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_assembly_information_provider.png delete mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_d_b_connection_factory.png delete mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_database_context_factory.html delete mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_database_context_factory.png delete mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_job_manager.png delete mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_platform_identifier.png delete mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process.html delete mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process.png delete mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process_base.html delete mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process_base.png delete mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process_executor.png rename interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_d_b_connection_factory-members.html => interface_tgstation_1_1_server_1_1_host_1_1_database_1_1_i_database_connection_factory-members.html (78%) rename interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_d_b_connection_factory.html => interface_tgstation_1_1_server_1_1_host_1_1_database_1_1_i_database_connection_factory.html (66%) create mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_database_1_1_i_database_connection_factory.png create mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_database_1_1_i_database_context-members.html rename interface_tgstation_1_1_server_1_1_host_1_1_models_1_1_i_database_context.html => interface_tgstation_1_1_server_1_1_host_1_1_database_1_1_i_database_context.html (50%) create mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_database_1_1_i_database_context.png rename interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_database_context_factory-members.html => interface_tgstation_1_1_server_1_1_host_1_1_database_1_1_i_database_context_factory-members.html (78%) create mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_database_1_1_i_database_context_factory.html create mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_database_1_1_i_database_context_factory.png rename interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_platform_identifier-members.html => interface_tgstation_1_1_server_1_1_host_1_1_database_1_1_i_database_seeder-members.html (76%) rename interface_tgstation_1_1_server_1_1_host_1_1_models_1_1_i_database_seeder.html => interface_tgstation_1_1_server_1_1_host_1_1_database_1_1_i_database_seeder.html (60%) create mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_database_1_1_i_database_seeder.png rename interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_job_manager-members.html => interface_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_i_job_manager-members.html (77%) rename interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_job_manager.html => interface_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_i_job_manager.html (73%) create mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_i_job_manager.png delete mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_models_1_1_i_database_context-members.html delete mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_models_1_1_i_database_context.png delete mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_models_1_1_i_database_seeder.png rename interface_tgstation_1_1_server_1_1_host_1_1_models_1_1_i_database_seeder-members.html => interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_assembly_information_provider-members.html (74%) rename interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_assembly_information_provider.html => interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_assembly_information_provider.html (67%) create mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_assembly_information_provider.png rename interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process_base-members.html => interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_platform_identifier-members.html (75%) rename interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_platform_identifier.html => interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_platform_identifier.html (63%) create mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_platform_identifier.png rename interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process-members.html => interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_process-members.html (52%) create mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_process.html create mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_process.png rename interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_assembly_information_provider-members.html => interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_process_base-members.html (65%) create mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_process_base.html create mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_process_base.png rename interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process_executor-members.html => interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_process_executor-members.html (73%) rename interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process_executor.html => interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_process_executor.html (59%) create mode 100644 interface_tgstation_1_1_server_1_1_host_1_1_system_1_1_i_process_executor.png rename namespace_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler.html => namespace_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment.html (64%) create mode 100644 namespace_tgstation_1_1_server_1_1_host_1_1_database.html rename class_tgstation_1_1_server_1_1_host_1_1_models_1_1_migrations_1_1_my_sql_design_time_db_context_factory-members.html => namespace_tgstation_1_1_server_1_1_host_1_1_database_1_1_design.html (60%) create mode 100644 namespace_tgstation_1_1_server_1_1_host_1_1_database_1_1_tests.html create mode 100644 namespace_tgstation_1_1_server_1_1_host_1_1_extensions.html create mode 100644 namespace_tgstation_1_1_server_1_1_host_1_1_extensions_1_1_tests.html create mode 100644 namespace_tgstation_1_1_server_1_1_host_1_1_jobs.html create mode 100644 namespace_tgstation_1_1_server_1_1_host_1_1_jobs_1_1_tests.html create mode 100644 namespace_tgstation_1_1_server_1_1_host_1_1_system.html create mode 100644 namespace_tgstation_1_1_server_1_1_host_1_1_system_1_1_tests.html create mode 100644 search/classes_15.html create mode 100644 search/classes_15.js create mode 100644 search/enums_9.html create mode 100644 search/enums_9.js create mode 100644 search/files_16.html create mode 100644 search/files_16.js create mode 100644 swagger.json diff --git a/20180906135553___m_s_initial_create_8_designer_8cs_source.html b/20180906135553___m_s_initial_create_8_designer_8cs_source.html index 2cfdb5e28f..47565ff620 100644 --- a/20180906135553___m_s_initial_create_8_designer_8cs_source.html +++ b/20180906135553___m_s_initial_create_8_designer_8cs_source.html @@ -71,10 +71,15 @@ $(function() {
20180906135553_MSInitialCreate.Designer.cs
-Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Metadata;
6 using Microsoft.EntityFrameworkCore.Migrations;
7 using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
8 
10 {
11  [DbContext(typeof(SqlServerDatabaseContext))]
12  [Migration("20180906135553_MSInitialCreate")]
13  partial class MSInitialCreate
14  {
19  protected override void BuildTargetModel(ModelBuilder modelBuilder)
20  {
21 #pragma warning disable 612, 618
22  modelBuilder
23  .HasAnnotation("ProductVersion", "2.1.2-rtm-30932")
24  .HasAnnotation("Relational:MaxIdentifierLength", 128)
25  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
26 
27  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
28  {
29  b.Property<long>("Id")
30  .ValueGeneratedOnAdd()
31  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
32 
33  b.Property<string>("ConnectionString")
34  .IsRequired();
35 
36  b.Property<bool?>("Enabled");
37 
38  b.Property<long>("InstanceId");
39 
40  b.Property<string>("Name")
41  .IsRequired();
42 
43  b.Property<int?>("Provider");
44 
45  b.HasKey("Id");
46 
47  b.HasIndex("InstanceId");
48 
49  b.HasIndex("Name")
50  .IsUnique();
51 
52  b.ToTable("ChatBots");
53  });
54 
55  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
56  {
57  b.Property<long>("Id")
58  .ValueGeneratedOnAdd()
59  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
60 
61  b.Property<long>("ChatSettingsId");
62 
63  b.Property<decimal?>("DiscordChannelId")
64  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
65 
66  b.Property<string>("IrcChannel");
67 
68  b.Property<bool?>("IsAdminChannel")
69  .IsRequired();
70 
71  b.Property<bool?>("IsUpdatesChannel")
72  .IsRequired();
73 
74  b.Property<bool?>("IsWatchdogChannel")
75  .IsRequired();
76 
77  b.Property<string>("Tag");
78 
79  b.HasKey("Id");
80 
81  b.HasIndex("ChatSettingsId", "DiscordChannelId")
82  .IsUnique()
83  .HasFilter("[DiscordChannelId] IS NOT NULL");
84 
85  b.HasIndex("ChatSettingsId", "IrcChannel")
86  .IsUnique()
87  .HasFilter("[IrcChannel] IS NOT NULL");
88 
89  b.ToTable("ChatChannels");
90  });
91 
92  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
93  {
94  b.Property<long>("Id")
95  .ValueGeneratedOnAdd()
96  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
97 
98  b.Property<string>("ByondVersion")
99  .IsRequired();
100 
101  b.Property<Guid?>("DirectoryName");
102 
103  b.Property<string>("DmeName");
104 
105  b.Property<long?>("JobId");
106 
107  b.Property<string>("Output");
108 
109  b.Property<long>("RevisionInformationId");
110 
111  b.HasKey("Id");
112 
113  b.HasIndex("DirectoryName");
114 
115  b.HasIndex("JobId");
116 
117  b.HasIndex("RevisionInformationId");
118 
119  b.ToTable("CompileJobs");
120  });
121 
122  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
123  {
124  b.Property<long>("Id")
125  .ValueGeneratedOnAdd()
126  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
127 
128  b.Property<string>("AccessToken");
129 
130  b.Property<bool?>("AllowWebClient")
131  .IsRequired();
132 
133  b.Property<bool?>("AutoStart")
134  .IsRequired();
135 
136  b.Property<long>("InstanceId");
137 
138  b.Property<int>("PrimaryPort");
139 
140  b.Property<int?>("ProcessId");
141 
142  b.Property<int>("SecondaryPort");
143 
144  b.Property<int>("SecurityLevel");
145 
146  b.Property<bool?>("SoftRestart")
147  .IsRequired();
148 
149  b.Property<bool?>("SoftShutdown")
150  .IsRequired();
151 
152  b.Property<long>("StartupTimeout");
153 
154  b.HasKey("Id");
155 
156  b.HasIndex("InstanceId")
157  .IsUnique();
158 
159  b.ToTable("DreamDaemonSettings");
160  });
161 
162  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
163  {
164  b.Property<long>("Id")
165  .ValueGeneratedOnAdd()
166  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
167 
168  b.Property<int>("ApiValidationPort");
169 
170  b.Property<long>("InstanceId");
171 
172  b.Property<string>("ProjectName");
173 
174  b.HasKey("Id");
175 
176  b.HasIndex("InstanceId")
177  .IsUnique();
178 
179  b.ToTable("DreamMakerSettings");
180  });
181 
182  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
183  {
184  b.Property<long>("Id")
185  .ValueGeneratedOnAdd()
186  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
187 
188  b.Property<long>("AutoUpdateInterval");
189 
190  b.Property<int>("ConfigurationType");
191 
192  b.Property<string>("Name")
193  .IsRequired();
194 
195  b.Property<bool?>("Online")
196  .IsRequired();
197 
198  b.Property<string>("Path")
199  .IsRequired();
200 
201  b.Property<long?>("WatchdogReattachInformationId");
202 
203  b.HasKey("Id");
204 
205  b.HasIndex("Path")
206  .IsUnique();
207 
208  b.HasIndex("WatchdogReattachInformationId");
209 
210  b.ToTable("Instances");
211  });
212 
213  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
214  {
215  b.Property<long>("Id")
216  .ValueGeneratedOnAdd()
217  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
218 
219  b.Property<decimal>("ByondRights")
220  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
221 
222  b.Property<decimal>("ChatBotRights")
223  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
224 
225  b.Property<decimal>("ConfigurationRights")
226  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
227 
228  b.Property<decimal>("DreamDaemonRights")
229  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
230 
231  b.Property<decimal>("DreamMakerRights")
232  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
233 
234  b.Property<long>("InstanceId");
235 
236  b.Property<decimal>("InstanceUserRights")
237  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
238 
239  b.Property<decimal>("RepositoryRights")
240  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
241 
242  b.Property<long?>("UserId")
243  .IsRequired();
244 
245  b.HasKey("Id");
246 
247  b.HasIndex("InstanceId");
248 
249  b.HasIndex("UserId", "InstanceId")
250  .IsUnique();
251 
252  b.ToTable("InstanceUsers");
253  });
254 
255  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
256  {
257  b.Property<long>("Id")
258  .ValueGeneratedOnAdd()
259  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
260 
261  b.Property<decimal?>("CancelRight")
262  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
263 
264  b.Property<decimal?>("CancelRightsType")
265  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
266 
267  b.Property<bool?>("Cancelled")
268  .IsRequired();
269 
270  b.Property<long?>("CancelledById");
271 
272  b.Property<string>("Description")
273  .IsRequired();
274 
275  b.Property<string>("ExceptionDetails");
276 
277  b.Property<long>("InstanceId");
278 
279  b.Property<DateTimeOffset?>("StartedAt")
280  .IsRequired();
281 
282  b.Property<long>("StartedById");
283 
284  b.Property<DateTimeOffset?>("StoppedAt");
285 
286  b.HasKey("Id");
287 
288  b.HasIndex("CancelledById");
289 
290  b.HasIndex("InstanceId");
291 
292  b.HasIndex("StartedById");
293 
294  b.ToTable("Jobs");
295  });
296 
297  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
298  {
299  b.Property<long>("Id")
300  .ValueGeneratedOnAdd()
301  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
302 
303  b.Property<string>("AccessIdentifier")
304  .IsRequired();
305 
306  b.Property<string>("ChatChannelsJson")
307  .IsRequired();
308 
309  b.Property<string>("ChatCommandsJson")
310  .IsRequired();
311 
312  b.Property<long?>("CompileJobId");
313 
314  b.Property<bool>("IsPrimary");
315 
316  b.Property<int>("Port");
317 
318  b.Property<int>("ProcessId");
319 
320  b.Property<int>("RebootState");
321 
322  b.Property<string>("ServerCommandsJson")
323  .IsRequired();
324 
325  b.HasKey("Id");
326 
327  b.HasIndex("CompileJobId");
328 
329  b.ToTable("ReattachInformations");
330  });
331 
332  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
333  {
334  b.Property<long>("Id")
335  .ValueGeneratedOnAdd()
336  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
337 
338  b.Property<string>("AccessToken");
339 
340  b.Property<string>("AccessUser");
341 
342  b.Property<bool?>("AutoUpdatesKeepTestMerges")
343  .IsRequired();
344 
345  b.Property<bool?>("AutoUpdatesSynchronize")
346  .IsRequired();
347 
348  b.Property<string>("CommitterEmail")
349  .IsRequired();
350 
351  b.Property<string>("CommitterName")
352  .IsRequired();
353 
354  b.Property<long>("InstanceId");
355 
356  b.Property<bool?>("PushTestMergeCommits")
357  .IsRequired();
358 
359  b.Property<bool?>("ShowTestMergeCommitters")
360  .IsRequired();
361 
362  b.HasKey("Id");
363 
364  b.HasIndex("InstanceId")
365  .IsUnique();
366 
367  b.ToTable("RepositorySettings");
368  });
369 
370  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
371  {
372  b.Property<long>("Id")
373  .ValueGeneratedOnAdd()
374  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
375 
376  b.Property<long>("RevisionInformationId");
377 
378  b.Property<long>("TestMergeId");
379 
380  b.HasKey("Id");
381 
382  b.HasIndex("RevisionInformationId");
383 
384  b.HasIndex("TestMergeId");
385 
386  b.ToTable("RevInfoTestMerges");
387  });
388 
389  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
390  {
391  b.Property<long>("Id")
392  .ValueGeneratedOnAdd()
393  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
394 
395  b.Property<string>("CommitSha")
396  .IsRequired()
397  .HasMaxLength(40);
398 
399  b.Property<long>("InstanceId");
400 
401  b.Property<string>("OriginCommitSha")
402  .IsRequired()
403  .HasMaxLength(40);
404 
405  b.HasKey("Id");
406 
407  b.HasIndex("CommitSha")
408  .IsUnique();
409 
410  b.HasIndex("InstanceId");
411 
412  b.ToTable("RevisionInformations");
413  });
414 
415  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
416  {
417  b.Property<long>("Id")
418  .ValueGeneratedOnAdd()
419  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
420 
421  b.Property<string>("Author")
422  .IsRequired();
423 
424  b.Property<string>("BodyAtMerge")
425  .IsRequired();
426 
427  b.Property<string>("Comment");
428 
429  b.Property<DateTimeOffset>("MergedAt");
430 
431  b.Property<long>("MergedById");
432 
433  b.Property<int?>("Number")
434  .IsRequired();
435 
436  b.Property<long?>("PrimaryRevisionInformationId");
437 
438  b.Property<string>("PullRequestRevision")
439  .IsRequired();
440 
441  b.Property<string>("TitleAtMerge")
442  .IsRequired();
443 
444  b.Property<string>("Url")
445  .IsRequired();
446 
447  b.HasKey("Id");
448 
449  b.HasIndex("MergedById");
450 
451  b.HasIndex("PrimaryRevisionInformationId")
452  .IsUnique()
453  .HasFilter("[PrimaryRevisionInformationId] IS NOT NULL");
454 
455  b.ToTable("TestMerges");
456  });
457 
458  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
459  {
460  b.Property<long>("Id")
461  .ValueGeneratedOnAdd()
462  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
463 
464  b.Property<decimal>("AdministrationRights")
465  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
466 
467  b.Property<string>("CanonicalName")
468  .IsRequired();
469 
470  b.Property<DateTimeOffset?>("CreatedAt")
471  .IsRequired();
472 
473  b.Property<long?>("CreatedById");
474 
475  b.Property<bool?>("Enabled")
476  .IsRequired();
477 
478  b.Property<decimal>("InstanceManagerRights")
479  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
480 
481  b.Property<DateTimeOffset?>("LastPasswordUpdate");
482 
483  b.Property<string>("Name")
484  .IsRequired();
485 
486  b.Property<string>("PasswordHash");
487 
488  b.Property<string>("SystemIdentifier");
489 
490  b.HasKey("Id");
491 
492  b.HasIndex("CanonicalName")
493  .IsUnique();
494 
495  b.HasIndex("CreatedById");
496 
497  b.ToTable("Users");
498  });
499 
500  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
501  {
502  b.Property<long>("Id")
503  .ValueGeneratedOnAdd()
504  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
505 
506  b.Property<long?>("AlphaId");
507 
508  b.Property<bool>("AlphaIsActive");
509 
510  b.Property<long?>("BravoId");
511 
512  b.HasKey("Id");
513 
514  b.HasIndex("AlphaId");
515 
516  b.HasIndex("BravoId");
517 
518  b.ToTable("WatchdogReattachInformations");
519  });
520 
521  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
522  {
523  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
524  .WithMany("ChatSettings")
525  .HasForeignKey("InstanceId")
526  .OnDelete(DeleteBehavior.Cascade);
527  });
528 
529  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
530  {
531  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
532  .WithMany("Channels")
533  .HasForeignKey("ChatSettingsId")
534  .OnDelete(DeleteBehavior.Cascade);
535  });
536 
537  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
538  {
539  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
540  .WithMany()
541  .HasForeignKey("JobId");
542 
543  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
544  .WithMany("CompileJobs")
545  .HasForeignKey("RevisionInformationId")
546  .OnDelete(DeleteBehavior.Cascade);
547  });
548 
549  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
550  {
551  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
552  .WithOne("DreamDaemonSettings")
553  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
554  .OnDelete(DeleteBehavior.Cascade);
555  });
556 
557  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
558  {
559  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
560  .WithOne("DreamMakerSettings")
561  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
562  .OnDelete(DeleteBehavior.Cascade);
563  });
564 
565  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
566  {
567  b.HasOne("Tgstation.Server.Host.Models.WatchdogReattachInformation", "WatchdogReattachInformation")
568  .WithMany()
569  .HasForeignKey("WatchdogReattachInformationId");
570  });
571 
572  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
573  {
574  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
575  .WithMany("InstanceUsers")
576  .HasForeignKey("InstanceId")
577  .OnDelete(DeleteBehavior.Cascade);
578 
579  b.HasOne("Tgstation.Server.Host.Models.User")
580  .WithMany("InstanceUsers")
581  .HasForeignKey("UserId")
582  .OnDelete(DeleteBehavior.Cascade);
583  });
584 
585  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
586  {
587  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
588  .WithMany()
589  .HasForeignKey("CancelledById");
590 
591  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
592  .WithMany("Jobs")
593  .HasForeignKey("InstanceId")
594  .OnDelete(DeleteBehavior.Cascade);
595 
596  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
597  .WithMany()
598  .HasForeignKey("StartedById")
599  .OnDelete(DeleteBehavior.Cascade);
600  });
601 
602  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
603  {
604  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
605  .WithMany()
606  .HasForeignKey("CompileJobId");
607  });
608 
609  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
610  {
611  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
612  .WithOne("RepositorySettings")
613  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
614  .OnDelete(DeleteBehavior.Cascade);
615  });
616 
617  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
618  {
619  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
620  .WithMany("ActiveTestMerges")
621  .HasForeignKey("RevisionInformationId")
622  .OnDelete(DeleteBehavior.Cascade);
623 
624  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
625  .WithMany("RevisonInformations")
626  .HasForeignKey("TestMergeId")
627  .OnDelete(DeleteBehavior.Cascade);
628  });
629 
630  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
631  {
632  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
633  .WithMany("RevisionInformations")
634  .HasForeignKey("InstanceId")
635  .OnDelete(DeleteBehavior.Cascade);
636  });
637 
638  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
639  {
640  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
641  .WithMany("TestMerges")
642  .HasForeignKey("MergedById")
643  .OnDelete(DeleteBehavior.Restrict);
644 
645  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
646  .WithOne("PrimaryTestMerge")
647  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
648  .OnDelete(DeleteBehavior.SetNull);
649  });
650 
651  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
652  {
653  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
654  .WithMany("CreatedUsers")
655  .HasForeignKey("CreatedById");
656  });
657 
658  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
659  {
660  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
661  .WithMany()
662  .HasForeignKey("AlphaId");
663 
664  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
665  .WithMany()
666  .HasForeignKey("BravoId");
667  });
668 #pragma warning restore 612, 618
669  }
670  }
671 }
+Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Metadata;
6 using Microsoft.EntityFrameworkCore.Migrations;
7 using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
9 
11 {
13  [Migration("20180906135553_MSInitialCreate")]
14  partial class MSInitialCreate
15  {
20  protected override void BuildTargetModel(ModelBuilder modelBuilder)
21  {
22 #pragma warning disable 612, 618
23  modelBuilder
24  .HasAnnotation("ProductVersion", "2.1.2-rtm-30932")
25  .HasAnnotation("Relational:MaxIdentifierLength", 128)
26  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
27 
28  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
29  {
30  b.Property<long>("Id")
31  .ValueGeneratedOnAdd()
32  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
33 
34  b.Property<string>("ConnectionString")
35  .IsRequired();
36 
37  b.Property<bool?>("Enabled");
38 
39  b.Property<long>("InstanceId");
40 
41  b.Property<string>("Name")
42  .IsRequired();
43 
44  b.Property<int?>("Provider");
45 
46  b.HasKey("Id");
47 
48  b.HasIndex("InstanceId");
49 
50  b.HasIndex("Name")
51  .IsUnique();
52 
53  b.ToTable("ChatBots");
54  });
55 
56  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
57  {
58  b.Property<long>("Id")
59  .ValueGeneratedOnAdd()
60  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
61 
62  b.Property<long>("ChatSettingsId");
63 
64  b.Property<decimal?>("DiscordChannelId")
65  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
66 
67  b.Property<string>("IrcChannel");
68 
69  b.Property<bool?>("IsAdminChannel")
70  .IsRequired();
71 
72  b.Property<bool?>("IsUpdatesChannel")
73  .IsRequired();
74 
75  b.Property<bool?>("IsWatchdogChannel")
76  .IsRequired();
77 
78  b.Property<string>("Tag");
79 
80  b.HasKey("Id");
81 
82  b.HasIndex("ChatSettingsId", "DiscordChannelId")
83  .IsUnique()
84  .HasFilter("[DiscordChannelId] IS NOT NULL");
85 
86  b.HasIndex("ChatSettingsId", "IrcChannel")
87  .IsUnique()
88  .HasFilter("[IrcChannel] IS NOT NULL");
89 
90  b.ToTable("ChatChannels");
91  });
92 
93  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
94  {
95  b.Property<long>("Id")
96  .ValueGeneratedOnAdd()
97  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
98 
99  b.Property<string>("ByondVersion")
100  .IsRequired();
101 
102  b.Property<Guid?>("DirectoryName");
103 
104  b.Property<string>("DmeName");
105 
106  b.Property<long?>("JobId");
107 
108  b.Property<string>("Output");
109 
110  b.Property<long>("RevisionInformationId");
111 
112  b.HasKey("Id");
113 
114  b.HasIndex("DirectoryName");
115 
116  b.HasIndex("JobId");
117 
118  b.HasIndex("RevisionInformationId");
119 
120  b.ToTable("CompileJobs");
121  });
122 
123  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
124  {
125  b.Property<long>("Id")
126  .ValueGeneratedOnAdd()
127  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
128 
129  b.Property<string>("AccessToken");
130 
131  b.Property<bool?>("AllowWebClient")
132  .IsRequired();
133 
134  b.Property<bool?>("AutoStart")
135  .IsRequired();
136 
137  b.Property<long>("InstanceId");
138 
139  b.Property<int>("PrimaryPort");
140 
141  b.Property<int?>("ProcessId");
142 
143  b.Property<int>("SecondaryPort");
144 
145  b.Property<int>("SecurityLevel");
146 
147  b.Property<bool?>("SoftRestart")
148  .IsRequired();
149 
150  b.Property<bool?>("SoftShutdown")
151  .IsRequired();
152 
153  b.Property<long>("StartupTimeout");
154 
155  b.HasKey("Id");
156 
157  b.HasIndex("InstanceId")
158  .IsUnique();
159 
160  b.ToTable("DreamDaemonSettings");
161  });
162 
163  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
164  {
165  b.Property<long>("Id")
166  .ValueGeneratedOnAdd()
167  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
168 
169  b.Property<int>("ApiValidationPort");
170 
171  b.Property<long>("InstanceId");
172 
173  b.Property<string>("ProjectName");
174 
175  b.HasKey("Id");
176 
177  b.HasIndex("InstanceId")
178  .IsUnique();
179 
180  b.ToTable("DreamMakerSettings");
181  });
182 
183  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
184  {
185  b.Property<long>("Id")
186  .ValueGeneratedOnAdd()
187  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
188 
189  b.Property<long>("AutoUpdateInterval");
190 
191  b.Property<int>("ConfigurationType");
192 
193  b.Property<string>("Name")
194  .IsRequired();
195 
196  b.Property<bool?>("Online")
197  .IsRequired();
198 
199  b.Property<string>("Path")
200  .IsRequired();
201 
202  b.Property<long?>("WatchdogReattachInformationId");
203 
204  b.HasKey("Id");
205 
206  b.HasIndex("Path")
207  .IsUnique();
208 
209  b.HasIndex("WatchdogReattachInformationId");
210 
211  b.ToTable("Instances");
212  });
213 
214  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
215  {
216  b.Property<long>("Id")
217  .ValueGeneratedOnAdd()
218  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
219 
220  b.Property<decimal>("ByondRights")
221  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
222 
223  b.Property<decimal>("ChatBotRights")
224  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
225 
226  b.Property<decimal>("ConfigurationRights")
227  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
228 
229  b.Property<decimal>("DreamDaemonRights")
230  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
231 
232  b.Property<decimal>("DreamMakerRights")
233  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
234 
235  b.Property<long>("InstanceId");
236 
237  b.Property<decimal>("InstanceUserRights")
238  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
239 
240  b.Property<decimal>("RepositoryRights")
241  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
242 
243  b.Property<long?>("UserId")
244  .IsRequired();
245 
246  b.HasKey("Id");
247 
248  b.HasIndex("InstanceId");
249 
250  b.HasIndex("UserId", "InstanceId")
251  .IsUnique();
252 
253  b.ToTable("InstanceUsers");
254  });
255 
256  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
257  {
258  b.Property<long>("Id")
259  .ValueGeneratedOnAdd()
260  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
261 
262  b.Property<decimal?>("CancelRight")
263  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
264 
265  b.Property<decimal?>("CancelRightsType")
266  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
267 
268  b.Property<bool?>("Cancelled")
269  .IsRequired();
270 
271  b.Property<long?>("CancelledById");
272 
273  b.Property<string>("Description")
274  .IsRequired();
275 
276  b.Property<string>("ExceptionDetails");
277 
278  b.Property<long>("InstanceId");
279 
280  b.Property<DateTimeOffset?>("StartedAt")
281  .IsRequired();
282 
283  b.Property<long>("StartedById");
284 
285  b.Property<DateTimeOffset?>("StoppedAt");
286 
287  b.HasKey("Id");
288 
289  b.HasIndex("CancelledById");
290 
291  b.HasIndex("InstanceId");
292 
293  b.HasIndex("StartedById");
294 
295  b.ToTable("Jobs");
296  });
297 
298  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
299  {
300  b.Property<long>("Id")
301  .ValueGeneratedOnAdd()
302  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
303 
304  b.Property<string>("AccessIdentifier")
305  .IsRequired();
306 
307  b.Property<string>("ChatChannelsJson")
308  .IsRequired();
309 
310  b.Property<string>("ChatCommandsJson")
311  .IsRequired();
312 
313  b.Property<long?>("CompileJobId");
314 
315  b.Property<bool>("IsPrimary");
316 
317  b.Property<int>("Port");
318 
319  b.Property<int>("ProcessId");
320 
321  b.Property<int>("RebootState");
322 
323  b.Property<string>("ServerCommandsJson")
324  .IsRequired();
325 
326  b.HasKey("Id");
327 
328  b.HasIndex("CompileJobId");
329 
330  b.ToTable("ReattachInformations");
331  });
332 
333  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
334  {
335  b.Property<long>("Id")
336  .ValueGeneratedOnAdd()
337  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
338 
339  b.Property<string>("AccessToken");
340 
341  b.Property<string>("AccessUser");
342 
343  b.Property<bool?>("AutoUpdatesKeepTestMerges")
344  .IsRequired();
345 
346  b.Property<bool?>("AutoUpdatesSynchronize")
347  .IsRequired();
348 
349  b.Property<string>("CommitterEmail")
350  .IsRequired();
351 
352  b.Property<string>("CommitterName")
353  .IsRequired();
354 
355  b.Property<long>("InstanceId");
356 
357  b.Property<bool?>("PushTestMergeCommits")
358  .IsRequired();
359 
360  b.Property<bool?>("ShowTestMergeCommitters")
361  .IsRequired();
362 
363  b.HasKey("Id");
364 
365  b.HasIndex("InstanceId")
366  .IsUnique();
367 
368  b.ToTable("RepositorySettings");
369  });
370 
371  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
372  {
373  b.Property<long>("Id")
374  .ValueGeneratedOnAdd()
375  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
376 
377  b.Property<long>("RevisionInformationId");
378 
379  b.Property<long>("TestMergeId");
380 
381  b.HasKey("Id");
382 
383  b.HasIndex("RevisionInformationId");
384 
385  b.HasIndex("TestMergeId");
386 
387  b.ToTable("RevInfoTestMerges");
388  });
389 
390  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
391  {
392  b.Property<long>("Id")
393  .ValueGeneratedOnAdd()
394  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
395 
396  b.Property<string>("CommitSha")
397  .IsRequired()
398  .HasMaxLength(40);
399 
400  b.Property<long>("InstanceId");
401 
402  b.Property<string>("OriginCommitSha")
403  .IsRequired()
404  .HasMaxLength(40);
405 
406  b.HasKey("Id");
407 
408  b.HasIndex("CommitSha")
409  .IsUnique();
410 
411  b.HasIndex("InstanceId");
412 
413  b.ToTable("RevisionInformations");
414  });
415 
416  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
417  {
418  b.Property<long>("Id")
419  .ValueGeneratedOnAdd()
420  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
421 
422  b.Property<string>("Author")
423  .IsRequired();
424 
425  b.Property<string>("BodyAtMerge")
426  .IsRequired();
427 
428  b.Property<string>("Comment");
429 
430  b.Property<DateTimeOffset>("MergedAt");
431 
432  b.Property<long>("MergedById");
433 
434  b.Property<int?>("Number")
435  .IsRequired();
436 
437  b.Property<long?>("PrimaryRevisionInformationId");
438 
439  b.Property<string>("PullRequestRevision")
440  .IsRequired();
441 
442  b.Property<string>("TitleAtMerge")
443  .IsRequired();
444 
445  b.Property<string>("Url")
446  .IsRequired();
447 
448  b.HasKey("Id");
449 
450  b.HasIndex("MergedById");
451 
452  b.HasIndex("PrimaryRevisionInformationId")
453  .IsUnique()
454  .HasFilter("[PrimaryRevisionInformationId] IS NOT NULL");
455 
456  b.ToTable("TestMerges");
457  });
458 
459  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
460  {
461  b.Property<long>("Id")
462  .ValueGeneratedOnAdd()
463  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
464 
465  b.Property<decimal>("AdministrationRights")
466  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
467 
468  b.Property<string>("CanonicalName")
469  .IsRequired();
470 
471  b.Property<DateTimeOffset?>("CreatedAt")
472  .IsRequired();
473 
474  b.Property<long?>("CreatedById");
475 
476  b.Property<bool?>("Enabled")
477  .IsRequired();
478 
479  b.Property<decimal>("InstanceManagerRights")
480  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
481 
482  b.Property<DateTimeOffset?>("LastPasswordUpdate");
483 
484  b.Property<string>("Name")
485  .IsRequired();
486 
487  b.Property<string>("PasswordHash");
488 
489  b.Property<string>("SystemIdentifier");
490 
491  b.HasKey("Id");
492 
493  b.HasIndex("CanonicalName")
494  .IsUnique();
495 
496  b.HasIndex("CreatedById");
497 
498  b.ToTable("Users");
499  });
500 
501  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
502  {
503  b.Property<long>("Id")
504  .ValueGeneratedOnAdd()
505  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
506 
507  b.Property<long?>("AlphaId");
508 
509  b.Property<bool>("AlphaIsActive");
510 
511  b.Property<long?>("BravoId");
512 
513  b.HasKey("Id");
514 
515  b.HasIndex("AlphaId");
516 
517  b.HasIndex("BravoId");
518 
519  b.ToTable("WatchdogReattachInformations");
520  });
521 
522  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
523  {
524  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
525  .WithMany("ChatSettings")
526  .HasForeignKey("InstanceId")
527  .OnDelete(DeleteBehavior.Cascade);
528  });
529 
530  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
531  {
532  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
533  .WithMany("Channels")
534  .HasForeignKey("ChatSettingsId")
535  .OnDelete(DeleteBehavior.Cascade);
536  });
537 
538  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
539  {
540  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
541  .WithMany()
542  .HasForeignKey("JobId");
543 
544  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
545  .WithMany("CompileJobs")
546  .HasForeignKey("RevisionInformationId")
547  .OnDelete(DeleteBehavior.Cascade);
548  });
549 
550  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
551  {
552  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
553  .WithOne("DreamDaemonSettings")
554  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
555  .OnDelete(DeleteBehavior.Cascade);
556  });
557 
558  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
559  {
560  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
561  .WithOne("DreamMakerSettings")
562  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
563  .OnDelete(DeleteBehavior.Cascade);
564  });
565 
566  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
567  {
568  b.HasOne("Tgstation.Server.Host.Models.WatchdogReattachInformation", "WatchdogReattachInformation")
569  .WithMany()
570  .HasForeignKey("WatchdogReattachInformationId");
571  });
572 
573  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
574  {
575  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
576  .WithMany("InstanceUsers")
577  .HasForeignKey("InstanceId")
578  .OnDelete(DeleteBehavior.Cascade);
579 
580  b.HasOne("Tgstation.Server.Host.Models.User")
581  .WithMany("InstanceUsers")
582  .HasForeignKey("UserId")
583  .OnDelete(DeleteBehavior.Cascade);
584  });
585 
586  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
587  {
588  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
589  .WithMany()
590  .HasForeignKey("CancelledById");
591 
592  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
593  .WithMany("Jobs")
594  .HasForeignKey("InstanceId")
595  .OnDelete(DeleteBehavior.Cascade);
596 
597  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
598  .WithMany()
599  .HasForeignKey("StartedById")
600  .OnDelete(DeleteBehavior.Cascade);
601  });
602 
603  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
604  {
605  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
606  .WithMany()
607  .HasForeignKey("CompileJobId");
608  });
609 
610  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
611  {
612  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
613  .WithOne("RepositorySettings")
614  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
615  .OnDelete(DeleteBehavior.Cascade);
616  });
617 
618  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
619  {
620  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
621  .WithMany("ActiveTestMerges")
622  .HasForeignKey("RevisionInformationId")
623  .OnDelete(DeleteBehavior.Cascade);
624 
625  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
626  .WithMany("RevisonInformations")
627  .HasForeignKey("TestMergeId")
628  .OnDelete(DeleteBehavior.Cascade);
629  });
630 
631  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
632  {
633  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
634  .WithMany("RevisionInformations")
635  .HasForeignKey("InstanceId")
636  .OnDelete(DeleteBehavior.Cascade);
637  });
638 
639  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
640  {
641  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
642  .WithMany("TestMerges")
643  .HasForeignKey("MergedById")
644  .OnDelete(DeleteBehavior.Restrict);
645 
646  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
647  .WithOne("PrimaryTestMerge")
648  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
649  .OnDelete(DeleteBehavior.SetNull);
650  });
651 
652  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
653  {
654  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
655  .WithMany("CreatedUsers")
656  .HasForeignKey("CreatedById");
657  });
658 
659  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
660  {
661  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
662  .WithMany()
663  .HasForeignKey("AlphaId");
664 
665  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
666  .WithMany()
667  .HasForeignKey("BravoId");
668  });
669 #pragma warning restore 612, 618
670  }
671  }
672 }
-
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
+
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
+ +
DatabaseContext<TParentContext> for Sqlserver
+ + +
-Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Migrations;
6 
8 {
9  [DbContext(typeof(MySqlDatabaseContext))]
10  [Migration("20180906143029_MYInitialCreate")]
11  partial class MYInitialCreate
12  {
17  protected override void BuildTargetModel(ModelBuilder modelBuilder)
18  {
19 #pragma warning disable 612, 618
20  modelBuilder
21  .HasAnnotation("ProductVersion", "2.1.2-rtm-30932")
22  .HasAnnotation("Relational:MaxIdentifierLength", 64);
23 
24  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
25  {
26  b.Property<long>("Id")
27  .ValueGeneratedOnAdd();
28 
29  b.Property<string>("ConnectionString")
30  .IsRequired();
31 
32  b.Property<bool?>("Enabled");
33 
34  b.Property<long>("InstanceId");
35 
36  b.Property<string>("Name")
37  .IsRequired();
38 
39  b.Property<int?>("Provider");
40 
41  b.HasKey("Id");
42 
43  b.HasIndex("InstanceId");
44 
45  b.HasIndex("Name")
46  .IsUnique();
47 
48  b.ToTable("ChatBots");
49  });
50 
51  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
52  {
53  b.Property<long>("Id")
54  .ValueGeneratedOnAdd();
55 
56  b.Property<long>("ChatSettingsId");
57 
58  b.Property<ulong?>("DiscordChannelId");
59 
60  b.Property<string>("IrcChannel");
61 
62  b.Property<bool?>("IsAdminChannel")
63  .IsRequired();
64 
65  b.Property<bool?>("IsUpdatesChannel")
66  .IsRequired();
67 
68  b.Property<bool?>("IsWatchdogChannel")
69  .IsRequired();
70 
71  b.Property<string>("Tag");
72 
73  b.HasKey("Id");
74 
75  b.HasIndex("ChatSettingsId", "DiscordChannelId")
76  .IsUnique();
77 
78  b.HasIndex("ChatSettingsId", "IrcChannel")
79  .IsUnique();
80 
81  b.ToTable("ChatChannels");
82  });
83 
84  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
85  {
86  b.Property<long>("Id")
87  .ValueGeneratedOnAdd();
88 
89  b.Property<string>("ByondVersion")
90  .IsRequired();
91 
92  b.Property<Guid?>("DirectoryName");
93 
94  b.Property<string>("DmeName");
95 
96  b.Property<long?>("JobId");
97 
98  b.Property<string>("Output");
99 
100  b.Property<long>("RevisionInformationId");
101 
102  b.HasKey("Id");
103 
104  b.HasIndex("DirectoryName");
105 
106  b.HasIndex("JobId");
107 
108  b.HasIndex("RevisionInformationId");
109 
110  b.ToTable("CompileJobs");
111  });
112 
113  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
114  {
115  b.Property<long>("Id")
116  .ValueGeneratedOnAdd();
117 
118  b.Property<string>("AccessToken");
119 
120  b.Property<bool?>("AllowWebClient")
121  .IsRequired();
122 
123  b.Property<bool?>("AutoStart")
124  .IsRequired();
125 
126  b.Property<long>("InstanceId");
127 
128  b.Property<ushort?>("PrimaryPort")
129  .IsRequired();
130 
131  b.Property<int?>("ProcessId");
132 
133  b.Property<ushort?>("SecondaryPort")
134  .IsRequired();
135 
136  b.Property<int>("SecurityLevel");
137 
138  b.Property<bool?>("SoftRestart")
139  .IsRequired();
140 
141  b.Property<bool?>("SoftShutdown")
142  .IsRequired();
143 
144  b.Property<uint?>("StartupTimeout")
145  .IsRequired();
146 
147  b.HasKey("Id");
148 
149  b.HasIndex("InstanceId")
150  .IsUnique();
151 
152  b.ToTable("DreamDaemonSettings");
153  });
154 
155  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
156  {
157  b.Property<long>("Id")
158  .ValueGeneratedOnAdd();
159 
160  b.Property<ushort?>("ApiValidationPort")
161  .IsRequired();
162 
163  b.Property<long>("InstanceId");
164 
165  b.Property<string>("ProjectName");
166 
167  b.HasKey("Id");
168 
169  b.HasIndex("InstanceId")
170  .IsUnique();
171 
172  b.ToTable("DreamMakerSettings");
173  });
174 
175  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
176  {
177  b.Property<long>("Id")
178  .ValueGeneratedOnAdd();
179 
180  b.Property<uint?>("AutoUpdateInterval")
181  .IsRequired();
182 
183  b.Property<int>("ConfigurationType");
184 
185  b.Property<string>("Name")
186  .IsRequired();
187 
188  b.Property<bool?>("Online")
189  .IsRequired();
190 
191  b.Property<string>("Path")
192  .IsRequired();
193 
194  b.Property<long?>("WatchdogReattachInformationId");
195 
196  b.HasKey("Id");
197 
198  b.HasIndex("Path")
199  .IsUnique();
200 
201  b.HasIndex("WatchdogReattachInformationId");
202 
203  b.ToTable("Instances");
204  });
205 
206  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
207  {
208  b.Property<long>("Id")
209  .ValueGeneratedOnAdd();
210 
211  b.Property<ulong>("ByondRights");
212 
213  b.Property<ulong>("ChatBotRights");
214 
215  b.Property<ulong>("ConfigurationRights");
216 
217  b.Property<ulong>("DreamDaemonRights");
218 
219  b.Property<ulong>("DreamMakerRights");
220 
221  b.Property<long>("InstanceId");
222 
223  b.Property<ulong>("InstanceUserRights");
224 
225  b.Property<ulong>("RepositoryRights");
226 
227  b.Property<long?>("UserId")
228  .IsRequired();
229 
230  b.HasKey("Id");
231 
232  b.HasIndex("InstanceId");
233 
234  b.HasIndex("UserId", "InstanceId")
235  .IsUnique();
236 
237  b.ToTable("InstanceUsers");
238  });
239 
240  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
241  {
242  b.Property<long>("Id")
243  .ValueGeneratedOnAdd();
244 
245  b.Property<ulong?>("CancelRight");
246 
247  b.Property<ulong?>("CancelRightsType");
248 
249  b.Property<bool?>("Cancelled")
250  .IsRequired();
251 
252  b.Property<long?>("CancelledById");
253 
254  b.Property<string>("Description")
255  .IsRequired();
256 
257  b.Property<string>("ExceptionDetails");
258 
259  b.Property<long>("InstanceId");
260 
261  b.Property<DateTimeOffset?>("StartedAt")
262  .IsRequired();
263 
264  b.Property<long>("StartedById");
265 
266  b.Property<DateTimeOffset?>("StoppedAt");
267 
268  b.HasKey("Id");
269 
270  b.HasIndex("CancelledById");
271 
272  b.HasIndex("InstanceId");
273 
274  b.HasIndex("StartedById");
275 
276  b.ToTable("Jobs");
277  });
278 
279  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
280  {
281  b.Property<long>("Id")
282  .ValueGeneratedOnAdd();
283 
284  b.Property<string>("AccessIdentifier")
285  .IsRequired();
286 
287  b.Property<string>("ChatChannelsJson")
288  .IsRequired();
289 
290  b.Property<string>("ChatCommandsJson")
291  .IsRequired();
292 
293  b.Property<long?>("CompileJobId");
294 
295  b.Property<bool>("IsPrimary");
296 
297  b.Property<ushort>("Port");
298 
299  b.Property<int>("ProcessId");
300 
301  b.Property<int>("RebootState");
302 
303  b.Property<string>("ServerCommandsJson")
304  .IsRequired();
305 
306  b.HasKey("Id");
307 
308  b.HasIndex("CompileJobId");
309 
310  b.ToTable("ReattachInformations");
311  });
312 
313  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
314  {
315  b.Property<long>("Id")
316  .ValueGeneratedOnAdd();
317 
318  b.Property<string>("AccessToken");
319 
320  b.Property<string>("AccessUser");
321 
322  b.Property<bool?>("AutoUpdatesKeepTestMerges")
323  .IsRequired();
324 
325  b.Property<bool?>("AutoUpdatesSynchronize")
326  .IsRequired();
327 
328  b.Property<string>("CommitterEmail")
329  .IsRequired();
330 
331  b.Property<string>("CommitterName")
332  .IsRequired();
333 
334  b.Property<long>("InstanceId");
335 
336  b.Property<bool?>("PushTestMergeCommits")
337  .IsRequired();
338 
339  b.Property<bool?>("ShowTestMergeCommitters")
340  .IsRequired();
341 
342  b.HasKey("Id");
343 
344  b.HasIndex("InstanceId")
345  .IsUnique();
346 
347  b.ToTable("RepositorySettings");
348  });
349 
350  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
351  {
352  b.Property<long>("Id")
353  .ValueGeneratedOnAdd();
354 
355  b.Property<long>("RevisionInformationId");
356 
357  b.Property<long>("TestMergeId");
358 
359  b.HasKey("Id");
360 
361  b.HasIndex("RevisionInformationId");
362 
363  b.HasIndex("TestMergeId");
364 
365  b.ToTable("RevInfoTestMerges");
366  });
367 
368  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
369  {
370  b.Property<long>("Id")
371  .ValueGeneratedOnAdd();
372 
373  b.Property<string>("CommitSha")
374  .IsRequired()
375  .HasMaxLength(40);
376 
377  b.Property<long>("InstanceId");
378 
379  b.Property<string>("OriginCommitSha")
380  .IsRequired()
381  .HasMaxLength(40);
382 
383  b.HasKey("Id");
384 
385  b.HasIndex("CommitSha")
386  .IsUnique();
387 
388  b.HasIndex("InstanceId");
389 
390  b.ToTable("RevisionInformations");
391  });
392 
393  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
394  {
395  b.Property<long>("Id")
396  .ValueGeneratedOnAdd();
397 
398  b.Property<string>("Author")
399  .IsRequired();
400 
401  b.Property<string>("BodyAtMerge")
402  .IsRequired();
403 
404  b.Property<string>("Comment");
405 
406  b.Property<DateTimeOffset>("MergedAt");
407 
408  b.Property<long>("MergedById");
409 
410  b.Property<int?>("Number")
411  .IsRequired();
412 
413  b.Property<long?>("PrimaryRevisionInformationId");
414 
415  b.Property<string>("PullRequestRevision")
416  .IsRequired();
417 
418  b.Property<string>("TitleAtMerge")
419  .IsRequired();
420 
421  b.Property<string>("Url")
422  .IsRequired();
423 
424  b.HasKey("Id");
425 
426  b.HasIndex("MergedById");
427 
428  b.HasIndex("PrimaryRevisionInformationId")
429  .IsUnique();
430 
431  b.ToTable("TestMerges");
432  });
433 
434  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
435  {
436  b.Property<long>("Id")
437  .ValueGeneratedOnAdd();
438 
439  b.Property<ulong>("AdministrationRights");
440 
441  b.Property<string>("CanonicalName")
442  .IsRequired();
443 
444  b.Property<DateTimeOffset?>("CreatedAt")
445  .IsRequired();
446 
447  b.Property<long?>("CreatedById");
448 
449  b.Property<bool?>("Enabled")
450  .IsRequired();
451 
452  b.Property<ulong>("InstanceManagerRights");
453 
454  b.Property<DateTimeOffset?>("LastPasswordUpdate");
455 
456  b.Property<string>("Name")
457  .IsRequired();
458 
459  b.Property<string>("PasswordHash");
460 
461  b.Property<string>("SystemIdentifier");
462 
463  b.HasKey("Id");
464 
465  b.HasIndex("CanonicalName")
466  .IsUnique();
467 
468  b.HasIndex("CreatedById");
469 
470  b.ToTable("Users");
471  });
472 
473  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
474  {
475  b.Property<long>("Id")
476  .ValueGeneratedOnAdd();
477 
478  b.Property<long?>("AlphaId");
479 
480  b.Property<bool>("AlphaIsActive");
481 
482  b.Property<long?>("BravoId");
483 
484  b.HasKey("Id");
485 
486  b.HasIndex("AlphaId");
487 
488  b.HasIndex("BravoId");
489 
490  b.ToTable("WatchdogReattachInformations");
491  });
492 
493  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
494  {
495  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
496  .WithMany("ChatSettings")
497  .HasForeignKey("InstanceId")
498  .OnDelete(DeleteBehavior.Cascade);
499  });
500 
501  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
502  {
503  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
504  .WithMany("Channels")
505  .HasForeignKey("ChatSettingsId")
506  .OnDelete(DeleteBehavior.Cascade);
507  });
508 
509  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
510  {
511  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
512  .WithMany()
513  .HasForeignKey("JobId");
514 
515  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
516  .WithMany("CompileJobs")
517  .HasForeignKey("RevisionInformationId")
518  .OnDelete(DeleteBehavior.Cascade);
519  });
520 
521  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
522  {
523  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
524  .WithOne("DreamDaemonSettings")
525  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
526  .OnDelete(DeleteBehavior.Cascade);
527  });
528 
529  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
530  {
531  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
532  .WithOne("DreamMakerSettings")
533  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
534  .OnDelete(DeleteBehavior.Cascade);
535  });
536 
537  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
538  {
539  b.HasOne("Tgstation.Server.Host.Models.WatchdogReattachInformation", "WatchdogReattachInformation")
540  .WithMany()
541  .HasForeignKey("WatchdogReattachInformationId");
542  });
543 
544  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
545  {
546  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
547  .WithMany("InstanceUsers")
548  .HasForeignKey("InstanceId")
549  .OnDelete(DeleteBehavior.Cascade);
550 
551  b.HasOne("Tgstation.Server.Host.Models.User")
552  .WithMany("InstanceUsers")
553  .HasForeignKey("UserId")
554  .OnDelete(DeleteBehavior.Cascade);
555  });
556 
557  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
558  {
559  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
560  .WithMany()
561  .HasForeignKey("CancelledById");
562 
563  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
564  .WithMany("Jobs")
565  .HasForeignKey("InstanceId")
566  .OnDelete(DeleteBehavior.Cascade);
567 
568  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
569  .WithMany()
570  .HasForeignKey("StartedById")
571  .OnDelete(DeleteBehavior.Cascade);
572  });
573 
574  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
575  {
576  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
577  .WithMany()
578  .HasForeignKey("CompileJobId");
579  });
580 
581  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
582  {
583  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
584  .WithOne("RepositorySettings")
585  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
586  .OnDelete(DeleteBehavior.Cascade);
587  });
588 
589  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
590  {
591  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
592  .WithMany("ActiveTestMerges")
593  .HasForeignKey("RevisionInformationId")
594  .OnDelete(DeleteBehavior.Cascade);
595 
596  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
597  .WithMany("RevisonInformations")
598  .HasForeignKey("TestMergeId")
599  .OnDelete(DeleteBehavior.Cascade);
600  });
601 
602  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
603  {
604  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
605  .WithMany("RevisionInformations")
606  .HasForeignKey("InstanceId")
607  .OnDelete(DeleteBehavior.Cascade);
608  });
609 
610  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
611  {
612  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
613  .WithMany("TestMerges")
614  .HasForeignKey("MergedById")
615  .OnDelete(DeleteBehavior.Restrict);
616 
617  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
618  .WithOne("PrimaryTestMerge")
619  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
620  .OnDelete(DeleteBehavior.SetNull);
621  });
622 
623  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
624  {
625  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
626  .WithMany("CreatedUsers")
627  .HasForeignKey("CreatedById");
628  });
629 
630  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
631  {
632  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
633  .WithMany()
634  .HasForeignKey("AlphaId");
635 
636  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
637  .WithMany()
638  .HasForeignKey("BravoId");
639  });
640 #pragma warning restore 612, 618
641  }
642  }
643 }
+Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Migrations;
7 
9 {
11  [Migration("20180906143029_MYInitialCreate")]
12  partial class MYInitialCreate
13  {
18  protected override void BuildTargetModel(ModelBuilder modelBuilder)
19  {
20 #pragma warning disable 612, 618
21  modelBuilder
22  .HasAnnotation("ProductVersion", "2.1.2-rtm-30932")
23  .HasAnnotation("Relational:MaxIdentifierLength", 64);
24 
25  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
26  {
27  b.Property<long>("Id")
28  .ValueGeneratedOnAdd();
29 
30  b.Property<string>("ConnectionString")
31  .IsRequired();
32 
33  b.Property<bool?>("Enabled");
34 
35  b.Property<long>("InstanceId");
36 
37  b.Property<string>("Name")
38  .IsRequired();
39 
40  b.Property<int?>("Provider");
41 
42  b.HasKey("Id");
43 
44  b.HasIndex("InstanceId");
45 
46  b.HasIndex("Name")
47  .IsUnique();
48 
49  b.ToTable("ChatBots");
50  });
51 
52  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
53  {
54  b.Property<long>("Id")
55  .ValueGeneratedOnAdd();
56 
57  b.Property<long>("ChatSettingsId");
58 
59  b.Property<ulong?>("DiscordChannelId");
60 
61  b.Property<string>("IrcChannel");
62 
63  b.Property<bool?>("IsAdminChannel")
64  .IsRequired();
65 
66  b.Property<bool?>("IsUpdatesChannel")
67  .IsRequired();
68 
69  b.Property<bool?>("IsWatchdogChannel")
70  .IsRequired();
71 
72  b.Property<string>("Tag");
73 
74  b.HasKey("Id");
75 
76  b.HasIndex("ChatSettingsId", "DiscordChannelId")
77  .IsUnique();
78 
79  b.HasIndex("ChatSettingsId", "IrcChannel")
80  .IsUnique();
81 
82  b.ToTable("ChatChannels");
83  });
84 
85  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
86  {
87  b.Property<long>("Id")
88  .ValueGeneratedOnAdd();
89 
90  b.Property<string>("ByondVersion")
91  .IsRequired();
92 
93  b.Property<Guid?>("DirectoryName");
94 
95  b.Property<string>("DmeName");
96 
97  b.Property<long?>("JobId");
98 
99  b.Property<string>("Output");
100 
101  b.Property<long>("RevisionInformationId");
102 
103  b.HasKey("Id");
104 
105  b.HasIndex("DirectoryName");
106 
107  b.HasIndex("JobId");
108 
109  b.HasIndex("RevisionInformationId");
110 
111  b.ToTable("CompileJobs");
112  });
113 
114  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
115  {
116  b.Property<long>("Id")
117  .ValueGeneratedOnAdd();
118 
119  b.Property<string>("AccessToken");
120 
121  b.Property<bool?>("AllowWebClient")
122  .IsRequired();
123 
124  b.Property<bool?>("AutoStart")
125  .IsRequired();
126 
127  b.Property<long>("InstanceId");
128 
129  b.Property<ushort?>("PrimaryPort")
130  .IsRequired();
131 
132  b.Property<int?>("ProcessId");
133 
134  b.Property<ushort?>("SecondaryPort")
135  .IsRequired();
136 
137  b.Property<int>("SecurityLevel");
138 
139  b.Property<bool?>("SoftRestart")
140  .IsRequired();
141 
142  b.Property<bool?>("SoftShutdown")
143  .IsRequired();
144 
145  b.Property<uint?>("StartupTimeout")
146  .IsRequired();
147 
148  b.HasKey("Id");
149 
150  b.HasIndex("InstanceId")
151  .IsUnique();
152 
153  b.ToTable("DreamDaemonSettings");
154  });
155 
156  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
157  {
158  b.Property<long>("Id")
159  .ValueGeneratedOnAdd();
160 
161  b.Property<ushort?>("ApiValidationPort")
162  .IsRequired();
163 
164  b.Property<long>("InstanceId");
165 
166  b.Property<string>("ProjectName");
167 
168  b.HasKey("Id");
169 
170  b.HasIndex("InstanceId")
171  .IsUnique();
172 
173  b.ToTable("DreamMakerSettings");
174  });
175 
176  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
177  {
178  b.Property<long>("Id")
179  .ValueGeneratedOnAdd();
180 
181  b.Property<uint?>("AutoUpdateInterval")
182  .IsRequired();
183 
184  b.Property<int>("ConfigurationType");
185 
186  b.Property<string>("Name")
187  .IsRequired();
188 
189  b.Property<bool?>("Online")
190  .IsRequired();
191 
192  b.Property<string>("Path")
193  .IsRequired();
194 
195  b.Property<long?>("WatchdogReattachInformationId");
196 
197  b.HasKey("Id");
198 
199  b.HasIndex("Path")
200  .IsUnique();
201 
202  b.HasIndex("WatchdogReattachInformationId");
203 
204  b.ToTable("Instances");
205  });
206 
207  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
208  {
209  b.Property<long>("Id")
210  .ValueGeneratedOnAdd();
211 
212  b.Property<ulong>("ByondRights");
213 
214  b.Property<ulong>("ChatBotRights");
215 
216  b.Property<ulong>("ConfigurationRights");
217 
218  b.Property<ulong>("DreamDaemonRights");
219 
220  b.Property<ulong>("DreamMakerRights");
221 
222  b.Property<long>("InstanceId");
223 
224  b.Property<ulong>("InstanceUserRights");
225 
226  b.Property<ulong>("RepositoryRights");
227 
228  b.Property<long?>("UserId")
229  .IsRequired();
230 
231  b.HasKey("Id");
232 
233  b.HasIndex("InstanceId");
234 
235  b.HasIndex("UserId", "InstanceId")
236  .IsUnique();
237 
238  b.ToTable("InstanceUsers");
239  });
240 
241  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
242  {
243  b.Property<long>("Id")
244  .ValueGeneratedOnAdd();
245 
246  b.Property<ulong?>("CancelRight");
247 
248  b.Property<ulong?>("CancelRightsType");
249 
250  b.Property<bool?>("Cancelled")
251  .IsRequired();
252 
253  b.Property<long?>("CancelledById");
254 
255  b.Property<string>("Description")
256  .IsRequired();
257 
258  b.Property<string>("ExceptionDetails");
259 
260  b.Property<long>("InstanceId");
261 
262  b.Property<DateTimeOffset?>("StartedAt")
263  .IsRequired();
264 
265  b.Property<long>("StartedById");
266 
267  b.Property<DateTimeOffset?>("StoppedAt");
268 
269  b.HasKey("Id");
270 
271  b.HasIndex("CancelledById");
272 
273  b.HasIndex("InstanceId");
274 
275  b.HasIndex("StartedById");
276 
277  b.ToTable("Jobs");
278  });
279 
280  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
281  {
282  b.Property<long>("Id")
283  .ValueGeneratedOnAdd();
284 
285  b.Property<string>("AccessIdentifier")
286  .IsRequired();
287 
288  b.Property<string>("ChatChannelsJson")
289  .IsRequired();
290 
291  b.Property<string>("ChatCommandsJson")
292  .IsRequired();
293 
294  b.Property<long?>("CompileJobId");
295 
296  b.Property<bool>("IsPrimary");
297 
298  b.Property<ushort>("Port");
299 
300  b.Property<int>("ProcessId");
301 
302  b.Property<int>("RebootState");
303 
304  b.Property<string>("ServerCommandsJson")
305  .IsRequired();
306 
307  b.HasKey("Id");
308 
309  b.HasIndex("CompileJobId");
310 
311  b.ToTable("ReattachInformations");
312  });
313 
314  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
315  {
316  b.Property<long>("Id")
317  .ValueGeneratedOnAdd();
318 
319  b.Property<string>("AccessToken");
320 
321  b.Property<string>("AccessUser");
322 
323  b.Property<bool?>("AutoUpdatesKeepTestMerges")
324  .IsRequired();
325 
326  b.Property<bool?>("AutoUpdatesSynchronize")
327  .IsRequired();
328 
329  b.Property<string>("CommitterEmail")
330  .IsRequired();
331 
332  b.Property<string>("CommitterName")
333  .IsRequired();
334 
335  b.Property<long>("InstanceId");
336 
337  b.Property<bool?>("PushTestMergeCommits")
338  .IsRequired();
339 
340  b.Property<bool?>("ShowTestMergeCommitters")
341  .IsRequired();
342 
343  b.HasKey("Id");
344 
345  b.HasIndex("InstanceId")
346  .IsUnique();
347 
348  b.ToTable("RepositorySettings");
349  });
350 
351  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
352  {
353  b.Property<long>("Id")
354  .ValueGeneratedOnAdd();
355 
356  b.Property<long>("RevisionInformationId");
357 
358  b.Property<long>("TestMergeId");
359 
360  b.HasKey("Id");
361 
362  b.HasIndex("RevisionInformationId");
363 
364  b.HasIndex("TestMergeId");
365 
366  b.ToTable("RevInfoTestMerges");
367  });
368 
369  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
370  {
371  b.Property<long>("Id")
372  .ValueGeneratedOnAdd();
373 
374  b.Property<string>("CommitSha")
375  .IsRequired()
376  .HasMaxLength(40);
377 
378  b.Property<long>("InstanceId");
379 
380  b.Property<string>("OriginCommitSha")
381  .IsRequired()
382  .HasMaxLength(40);
383 
384  b.HasKey("Id");
385 
386  b.HasIndex("CommitSha")
387  .IsUnique();
388 
389  b.HasIndex("InstanceId");
390 
391  b.ToTable("RevisionInformations");
392  });
393 
394  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
395  {
396  b.Property<long>("Id")
397  .ValueGeneratedOnAdd();
398 
399  b.Property<string>("Author")
400  .IsRequired();
401 
402  b.Property<string>("BodyAtMerge")
403  .IsRequired();
404 
405  b.Property<string>("Comment");
406 
407  b.Property<DateTimeOffset>("MergedAt");
408 
409  b.Property<long>("MergedById");
410 
411  b.Property<int?>("Number")
412  .IsRequired();
413 
414  b.Property<long?>("PrimaryRevisionInformationId");
415 
416  b.Property<string>("PullRequestRevision")
417  .IsRequired();
418 
419  b.Property<string>("TitleAtMerge")
420  .IsRequired();
421 
422  b.Property<string>("Url")
423  .IsRequired();
424 
425  b.HasKey("Id");
426 
427  b.HasIndex("MergedById");
428 
429  b.HasIndex("PrimaryRevisionInformationId")
430  .IsUnique();
431 
432  b.ToTable("TestMerges");
433  });
434 
435  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
436  {
437  b.Property<long>("Id")
438  .ValueGeneratedOnAdd();
439 
440  b.Property<ulong>("AdministrationRights");
441 
442  b.Property<string>("CanonicalName")
443  .IsRequired();
444 
445  b.Property<DateTimeOffset?>("CreatedAt")
446  .IsRequired();
447 
448  b.Property<long?>("CreatedById");
449 
450  b.Property<bool?>("Enabled")
451  .IsRequired();
452 
453  b.Property<ulong>("InstanceManagerRights");
454 
455  b.Property<DateTimeOffset?>("LastPasswordUpdate");
456 
457  b.Property<string>("Name")
458  .IsRequired();
459 
460  b.Property<string>("PasswordHash");
461 
462  b.Property<string>("SystemIdentifier");
463 
464  b.HasKey("Id");
465 
466  b.HasIndex("CanonicalName")
467  .IsUnique();
468 
469  b.HasIndex("CreatedById");
470 
471  b.ToTable("Users");
472  });
473 
474  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
475  {
476  b.Property<long>("Id")
477  .ValueGeneratedOnAdd();
478 
479  b.Property<long?>("AlphaId");
480 
481  b.Property<bool>("AlphaIsActive");
482 
483  b.Property<long?>("BravoId");
484 
485  b.HasKey("Id");
486 
487  b.HasIndex("AlphaId");
488 
489  b.HasIndex("BravoId");
490 
491  b.ToTable("WatchdogReattachInformations");
492  });
493 
494  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
495  {
496  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
497  .WithMany("ChatSettings")
498  .HasForeignKey("InstanceId")
499  .OnDelete(DeleteBehavior.Cascade);
500  });
501 
502  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
503  {
504  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
505  .WithMany("Channels")
506  .HasForeignKey("ChatSettingsId")
507  .OnDelete(DeleteBehavior.Cascade);
508  });
509 
510  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
511  {
512  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
513  .WithMany()
514  .HasForeignKey("JobId");
515 
516  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
517  .WithMany("CompileJobs")
518  .HasForeignKey("RevisionInformationId")
519  .OnDelete(DeleteBehavior.Cascade);
520  });
521 
522  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
523  {
524  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
525  .WithOne("DreamDaemonSettings")
526  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
527  .OnDelete(DeleteBehavior.Cascade);
528  });
529 
530  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
531  {
532  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
533  .WithOne("DreamMakerSettings")
534  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
535  .OnDelete(DeleteBehavior.Cascade);
536  });
537 
538  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
539  {
540  b.HasOne("Tgstation.Server.Host.Models.WatchdogReattachInformation", "WatchdogReattachInformation")
541  .WithMany()
542  .HasForeignKey("WatchdogReattachInformationId");
543  });
544 
545  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
546  {
547  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
548  .WithMany("InstanceUsers")
549  .HasForeignKey("InstanceId")
550  .OnDelete(DeleteBehavior.Cascade);
551 
552  b.HasOne("Tgstation.Server.Host.Models.User")
553  .WithMany("InstanceUsers")
554  .HasForeignKey("UserId")
555  .OnDelete(DeleteBehavior.Cascade);
556  });
557 
558  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
559  {
560  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
561  .WithMany()
562  .HasForeignKey("CancelledById");
563 
564  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
565  .WithMany("Jobs")
566  .HasForeignKey("InstanceId")
567  .OnDelete(DeleteBehavior.Cascade);
568 
569  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
570  .WithMany()
571  .HasForeignKey("StartedById")
572  .OnDelete(DeleteBehavior.Cascade);
573  });
574 
575  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
576  {
577  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
578  .WithMany()
579  .HasForeignKey("CompileJobId");
580  });
581 
582  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
583  {
584  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
585  .WithOne("RepositorySettings")
586  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
587  .OnDelete(DeleteBehavior.Cascade);
588  });
589 
590  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
591  {
592  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
593  .WithMany("ActiveTestMerges")
594  .HasForeignKey("RevisionInformationId")
595  .OnDelete(DeleteBehavior.Cascade);
596 
597  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
598  .WithMany("RevisonInformations")
599  .HasForeignKey("TestMergeId")
600  .OnDelete(DeleteBehavior.Cascade);
601  });
602 
603  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
604  {
605  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
606  .WithMany("RevisionInformations")
607  .HasForeignKey("InstanceId")
608  .OnDelete(DeleteBehavior.Cascade);
609  });
610 
611  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
612  {
613  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
614  .WithMany("TestMerges")
615  .HasForeignKey("MergedById")
616  .OnDelete(DeleteBehavior.Restrict);
617 
618  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
619  .WithOne("PrimaryTestMerge")
620  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
621  .OnDelete(DeleteBehavior.SetNull);
622  });
623 
624  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
625  {
626  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
627  .WithMany("CreatedUsers")
628  .HasForeignKey("CreatedById");
629  });
630 
631  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
632  {
633  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
634  .WithMany()
635  .HasForeignKey("AlphaId");
636 
637  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
638  .WithMany()
639  .HasForeignKey("BravoId");
640  });
641 #pragma warning restore 612, 618
642  }
643  }
644 }
-
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
+
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
+
DatabaseContext<TParentContext> for MySQL
+ + + +
-Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Migrations;
6 
8 {
9  [DbContext(typeof(MySqlDatabaseContext))]
10  [Migration("20180918020726_MYAddMinimumSecurity")]
11  partial class MYAddMinimumSecurity
12  {
17  protected override void BuildTargetModel(ModelBuilder modelBuilder)
18  {
19 #pragma warning disable 612, 618
20  modelBuilder
21  .HasAnnotation("ProductVersion", "2.1.3-rtm-32065")
22  .HasAnnotation("Relational:MaxIdentifierLength", 64);
23 
24  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
25  {
26  b.Property<long>("Id")
27  .ValueGeneratedOnAdd();
28 
29  b.Property<string>("ConnectionString")
30  .IsRequired();
31 
32  b.Property<bool?>("Enabled");
33 
34  b.Property<long>("InstanceId");
35 
36  b.Property<string>("Name")
37  .IsRequired();
38 
39  b.Property<int?>("Provider");
40 
41  b.HasKey("Id");
42 
43  b.HasIndex("InstanceId");
44 
45  b.HasIndex("Name")
46  .IsUnique();
47 
48  b.ToTable("ChatBots");
49  });
50 
51  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
52  {
53  b.Property<long>("Id")
54  .ValueGeneratedOnAdd();
55 
56  b.Property<long>("ChatSettingsId");
57 
58  b.Property<ulong?>("DiscordChannelId");
59 
60  b.Property<string>("IrcChannel");
61 
62  b.Property<bool?>("IsAdminChannel")
63  .IsRequired();
64 
65  b.Property<bool?>("IsUpdatesChannel")
66  .IsRequired();
67 
68  b.Property<bool?>("IsWatchdogChannel")
69  .IsRequired();
70 
71  b.Property<string>("Tag");
72 
73  b.HasKey("Id");
74 
75  b.HasIndex("ChatSettingsId", "DiscordChannelId")
76  .IsUnique();
77 
78  b.HasIndex("ChatSettingsId", "IrcChannel")
79  .IsUnique();
80 
81  b.ToTable("ChatChannels");
82  });
83 
84  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
85  {
86  b.Property<long>("Id")
87  .ValueGeneratedOnAdd();
88 
89  b.Property<string>("ByondVersion")
90  .IsRequired();
91 
92  b.Property<Guid?>("DirectoryName");
93 
94  b.Property<string>("DmeName");
95 
96  b.Property<long?>("JobId");
97 
98  b.Property<int>("MinimumSecurityLevel");
99 
100  b.Property<string>("Output");
101 
102  b.Property<long>("RevisionInformationId");
103 
104  b.HasKey("Id");
105 
106  b.HasIndex("DirectoryName");
107 
108  b.HasIndex("JobId");
109 
110  b.HasIndex("RevisionInformationId");
111 
112  b.ToTable("CompileJobs");
113  });
114 
115  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
116  {
117  b.Property<long>("Id")
118  .ValueGeneratedOnAdd();
119 
120  b.Property<string>("AccessToken");
121 
122  b.Property<bool?>("AllowWebClient")
123  .IsRequired();
124 
125  b.Property<bool?>("AutoStart")
126  .IsRequired();
127 
128  b.Property<long>("InstanceId");
129 
130  b.Property<ushort?>("PrimaryPort")
131  .IsRequired();
132 
133  b.Property<int?>("ProcessId");
134 
135  b.Property<ushort?>("SecondaryPort")
136  .IsRequired();
137 
138  b.Property<int>("SecurityLevel");
139 
140  b.Property<bool?>("SoftRestart")
141  .IsRequired();
142 
143  b.Property<bool?>("SoftShutdown")
144  .IsRequired();
145 
146  b.Property<uint?>("StartupTimeout")
147  .IsRequired();
148 
149  b.HasKey("Id");
150 
151  b.HasIndex("InstanceId")
152  .IsUnique();
153 
154  b.ToTable("DreamDaemonSettings");
155  });
156 
157  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
158  {
159  b.Property<long>("Id")
160  .ValueGeneratedOnAdd();
161 
162  b.Property<ushort?>("ApiValidationPort")
163  .IsRequired();
164 
165  b.Property<int>("ApiValidationSecurityLevel");
166 
167  b.Property<long>("InstanceId");
168 
169  b.Property<string>("ProjectName");
170 
171  b.HasKey("Id");
172 
173  b.HasIndex("InstanceId")
174  .IsUnique();
175 
176  b.ToTable("DreamMakerSettings");
177  });
178 
179  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
180  {
181  b.Property<long>("Id")
182  .ValueGeneratedOnAdd();
183 
184  b.Property<uint?>("AutoUpdateInterval")
185  .IsRequired();
186 
187  b.Property<int>("ConfigurationType");
188 
189  b.Property<string>("Name")
190  .IsRequired();
191 
192  b.Property<bool?>("Online")
193  .IsRequired();
194 
195  b.Property<string>("Path")
196  .IsRequired();
197 
198  b.Property<long?>("WatchdogReattachInformationId");
199 
200  b.HasKey("Id");
201 
202  b.HasIndex("Path")
203  .IsUnique();
204 
205  b.HasIndex("WatchdogReattachInformationId");
206 
207  b.ToTable("Instances");
208  });
209 
210  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
211  {
212  b.Property<long>("Id")
213  .ValueGeneratedOnAdd();
214 
215  b.Property<ulong>("ByondRights");
216 
217  b.Property<ulong>("ChatBotRights");
218 
219  b.Property<ulong>("ConfigurationRights");
220 
221  b.Property<ulong>("DreamDaemonRights");
222 
223  b.Property<ulong>("DreamMakerRights");
224 
225  b.Property<long>("InstanceId");
226 
227  b.Property<ulong>("InstanceUserRights");
228 
229  b.Property<ulong>("RepositoryRights");
230 
231  b.Property<long?>("UserId")
232  .IsRequired();
233 
234  b.HasKey("Id");
235 
236  b.HasIndex("InstanceId");
237 
238  b.HasIndex("UserId", "InstanceId")
239  .IsUnique();
240 
241  b.ToTable("InstanceUsers");
242  });
243 
244  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
245  {
246  b.Property<long>("Id")
247  .ValueGeneratedOnAdd();
248 
249  b.Property<ulong?>("CancelRight");
250 
251  b.Property<ulong?>("CancelRightsType");
252 
253  b.Property<bool?>("Cancelled")
254  .IsRequired();
255 
256  b.Property<long?>("CancelledById");
257 
258  b.Property<string>("Description")
259  .IsRequired();
260 
261  b.Property<string>("ExceptionDetails");
262 
263  b.Property<long>("InstanceId");
264 
265  b.Property<DateTimeOffset?>("StartedAt")
266  .IsRequired();
267 
268  b.Property<long>("StartedById");
269 
270  b.Property<DateTimeOffset?>("StoppedAt");
271 
272  b.HasKey("Id");
273 
274  b.HasIndex("CancelledById");
275 
276  b.HasIndex("InstanceId");
277 
278  b.HasIndex("StartedById");
279 
280  b.ToTable("Jobs");
281  });
282 
283  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
284  {
285  b.Property<long>("Id")
286  .ValueGeneratedOnAdd();
287 
288  b.Property<string>("AccessIdentifier")
289  .IsRequired();
290 
291  b.Property<string>("ChatChannelsJson")
292  .IsRequired();
293 
294  b.Property<string>("ChatCommandsJson")
295  .IsRequired();
296 
297  b.Property<long?>("CompileJobId");
298 
299  b.Property<bool>("IsPrimary");
300 
301  b.Property<ushort>("Port");
302 
303  b.Property<int>("ProcessId");
304 
305  b.Property<int>("RebootState");
306 
307  b.Property<string>("ServerCommandsJson")
308  .IsRequired();
309 
310  b.HasKey("Id");
311 
312  b.HasIndex("CompileJobId");
313 
314  b.ToTable("ReattachInformations");
315  });
316 
317  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
318  {
319  b.Property<long>("Id")
320  .ValueGeneratedOnAdd();
321 
322  b.Property<string>("AccessToken");
323 
324  b.Property<string>("AccessUser");
325 
326  b.Property<bool?>("AutoUpdatesKeepTestMerges")
327  .IsRequired();
328 
329  b.Property<bool?>("AutoUpdatesSynchronize")
330  .IsRequired();
331 
332  b.Property<string>("CommitterEmail")
333  .IsRequired();
334 
335  b.Property<string>("CommitterName")
336  .IsRequired();
337 
338  b.Property<long>("InstanceId");
339 
340  b.Property<bool?>("PushTestMergeCommits")
341  .IsRequired();
342 
343  b.Property<bool?>("ShowTestMergeCommitters")
344  .IsRequired();
345 
346  b.HasKey("Id");
347 
348  b.HasIndex("InstanceId")
349  .IsUnique();
350 
351  b.ToTable("RepositorySettings");
352  });
353 
354  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
355  {
356  b.Property<long>("Id")
357  .ValueGeneratedOnAdd();
358 
359  b.Property<long>("RevisionInformationId");
360 
361  b.Property<long>("TestMergeId");
362 
363  b.HasKey("Id");
364 
365  b.HasIndex("RevisionInformationId");
366 
367  b.HasIndex("TestMergeId");
368 
369  b.ToTable("RevInfoTestMerges");
370  });
371 
372  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
373  {
374  b.Property<long>("Id")
375  .ValueGeneratedOnAdd();
376 
377  b.Property<string>("CommitSha")
378  .IsRequired()
379  .HasMaxLength(40);
380 
381  b.Property<long>("InstanceId");
382 
383  b.Property<string>("OriginCommitSha")
384  .IsRequired()
385  .HasMaxLength(40);
386 
387  b.HasKey("Id");
388 
389  b.HasIndex("CommitSha")
390  .IsUnique();
391 
392  b.HasIndex("InstanceId");
393 
394  b.ToTable("RevisionInformations");
395  });
396 
397  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
398  {
399  b.Property<long>("Id")
400  .ValueGeneratedOnAdd();
401 
402  b.Property<string>("Author")
403  .IsRequired();
404 
405  b.Property<string>("BodyAtMerge")
406  .IsRequired();
407 
408  b.Property<string>("Comment");
409 
410  b.Property<DateTimeOffset>("MergedAt");
411 
412  b.Property<long>("MergedById");
413 
414  b.Property<int?>("Number")
415  .IsRequired();
416 
417  b.Property<long?>("PrimaryRevisionInformationId");
418 
419  b.Property<string>("PullRequestRevision")
420  .IsRequired();
421 
422  b.Property<string>("TitleAtMerge")
423  .IsRequired();
424 
425  b.Property<string>("Url")
426  .IsRequired();
427 
428  b.HasKey("Id");
429 
430  b.HasIndex("MergedById");
431 
432  b.HasIndex("PrimaryRevisionInformationId")
433  .IsUnique();
434 
435  b.ToTable("TestMerges");
436  });
437 
438  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
439  {
440  b.Property<long>("Id")
441  .ValueGeneratedOnAdd();
442 
443  b.Property<ulong>("AdministrationRights");
444 
445  b.Property<string>("CanonicalName")
446  .IsRequired();
447 
448  b.Property<DateTimeOffset?>("CreatedAt")
449  .IsRequired();
450 
451  b.Property<long?>("CreatedById");
452 
453  b.Property<bool?>("Enabled")
454  .IsRequired();
455 
456  b.Property<ulong>("InstanceManagerRights");
457 
458  b.Property<DateTimeOffset?>("LastPasswordUpdate");
459 
460  b.Property<string>("Name")
461  .IsRequired();
462 
463  b.Property<string>("PasswordHash");
464 
465  b.Property<string>("SystemIdentifier");
466 
467  b.HasKey("Id");
468 
469  b.HasIndex("CanonicalName")
470  .IsUnique();
471 
472  b.HasIndex("CreatedById");
473 
474  b.ToTable("Users");
475  });
476 
477  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
478  {
479  b.Property<long>("Id")
480  .ValueGeneratedOnAdd();
481 
482  b.Property<long?>("AlphaId");
483 
484  b.Property<bool>("AlphaIsActive");
485 
486  b.Property<long?>("BravoId");
487 
488  b.HasKey("Id");
489 
490  b.HasIndex("AlphaId");
491 
492  b.HasIndex("BravoId");
493 
494  b.ToTable("WatchdogReattachInformations");
495  });
496 
497  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
498  {
499  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
500  .WithMany("ChatSettings")
501  .HasForeignKey("InstanceId")
502  .OnDelete(DeleteBehavior.Cascade);
503  });
504 
505  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
506  {
507  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
508  .WithMany("Channels")
509  .HasForeignKey("ChatSettingsId")
510  .OnDelete(DeleteBehavior.Cascade);
511  });
512 
513  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
514  {
515  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
516  .WithMany()
517  .HasForeignKey("JobId");
518 
519  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
520  .WithMany("CompileJobs")
521  .HasForeignKey("RevisionInformationId")
522  .OnDelete(DeleteBehavior.Cascade);
523  });
524 
525  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
526  {
527  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
528  .WithOne("DreamDaemonSettings")
529  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
530  .OnDelete(DeleteBehavior.Cascade);
531  });
532 
533  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
534  {
535  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
536  .WithOne("DreamMakerSettings")
537  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
538  .OnDelete(DeleteBehavior.Cascade);
539  });
540 
541  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
542  {
543  b.HasOne("Tgstation.Server.Host.Models.WatchdogReattachInformation", "WatchdogReattachInformation")
544  .WithMany()
545  .HasForeignKey("WatchdogReattachInformationId");
546  });
547 
548  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
549  {
550  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
551  .WithMany("InstanceUsers")
552  .HasForeignKey("InstanceId")
553  .OnDelete(DeleteBehavior.Cascade);
554 
555  b.HasOne("Tgstation.Server.Host.Models.User")
556  .WithMany("InstanceUsers")
557  .HasForeignKey("UserId")
558  .OnDelete(DeleteBehavior.Cascade);
559  });
560 
561  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
562  {
563  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
564  .WithMany()
565  .HasForeignKey("CancelledById");
566 
567  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
568  .WithMany("Jobs")
569  .HasForeignKey("InstanceId")
570  .OnDelete(DeleteBehavior.Cascade);
571 
572  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
573  .WithMany()
574  .HasForeignKey("StartedById")
575  .OnDelete(DeleteBehavior.Cascade);
576  });
577 
578  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
579  {
580  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
581  .WithMany()
582  .HasForeignKey("CompileJobId");
583  });
584 
585  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
586  {
587  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
588  .WithOne("RepositorySettings")
589  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
590  .OnDelete(DeleteBehavior.Cascade);
591  });
592 
593  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
594  {
595  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
596  .WithMany("ActiveTestMerges")
597  .HasForeignKey("RevisionInformationId")
598  .OnDelete(DeleteBehavior.Cascade);
599 
600  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
601  .WithMany("RevisonInformations")
602  .HasForeignKey("TestMergeId")
603  .OnDelete(DeleteBehavior.Cascade);
604  });
605 
606  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
607  {
608  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
609  .WithMany("RevisionInformations")
610  .HasForeignKey("InstanceId")
611  .OnDelete(DeleteBehavior.Cascade);
612  });
613 
614  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
615  {
616  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
617  .WithMany("TestMerges")
618  .HasForeignKey("MergedById")
619  .OnDelete(DeleteBehavior.Restrict);
620 
621  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
622  .WithOne("PrimaryTestMerge")
623  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
624  .OnDelete(DeleteBehavior.SetNull);
625  });
626 
627  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
628  {
629  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
630  .WithMany("CreatedUsers")
631  .HasForeignKey("CreatedById");
632  });
633 
634  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
635  {
636  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
637  .WithMany()
638  .HasForeignKey("AlphaId");
639 
640  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
641  .WithMany()
642  .HasForeignKey("BravoId");
643  });
644 #pragma warning restore 612, 618
645  }
646  }
647 }
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
+Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Migrations;
7 
9 {
11  [Migration("20180918020726_MYAddMinimumSecurity")]
12  partial class MYAddMinimumSecurity
13  {
18  protected override void BuildTargetModel(ModelBuilder modelBuilder)
19  {
20 #pragma warning disable 612, 618
21  modelBuilder
22  .HasAnnotation("ProductVersion", "2.1.3-rtm-32065")
23  .HasAnnotation("Relational:MaxIdentifierLength", 64);
24 
25  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
26  {
27  b.Property<long>("Id")
28  .ValueGeneratedOnAdd();
29 
30  b.Property<string>("ConnectionString")
31  .IsRequired();
32 
33  b.Property<bool?>("Enabled");
34 
35  b.Property<long>("InstanceId");
36 
37  b.Property<string>("Name")
38  .IsRequired();
39 
40  b.Property<int?>("Provider");
41 
42  b.HasKey("Id");
43 
44  b.HasIndex("InstanceId");
45 
46  b.HasIndex("Name")
47  .IsUnique();
48 
49  b.ToTable("ChatBots");
50  });
51 
52  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
53  {
54  b.Property<long>("Id")
55  .ValueGeneratedOnAdd();
56 
57  b.Property<long>("ChatSettingsId");
58 
59  b.Property<ulong?>("DiscordChannelId");
60 
61  b.Property<string>("IrcChannel");
62 
63  b.Property<bool?>("IsAdminChannel")
64  .IsRequired();
65 
66  b.Property<bool?>("IsUpdatesChannel")
67  .IsRequired();
68 
69  b.Property<bool?>("IsWatchdogChannel")
70  .IsRequired();
71 
72  b.Property<string>("Tag");
73 
74  b.HasKey("Id");
75 
76  b.HasIndex("ChatSettingsId", "DiscordChannelId")
77  .IsUnique();
78 
79  b.HasIndex("ChatSettingsId", "IrcChannel")
80  .IsUnique();
81 
82  b.ToTable("ChatChannels");
83  });
84 
85  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
86  {
87  b.Property<long>("Id")
88  .ValueGeneratedOnAdd();
89 
90  b.Property<string>("ByondVersion")
91  .IsRequired();
92 
93  b.Property<Guid?>("DirectoryName");
94 
95  b.Property<string>("DmeName");
96 
97  b.Property<long?>("JobId");
98 
99  b.Property<int>("MinimumSecurityLevel");
100 
101  b.Property<string>("Output");
102 
103  b.Property<long>("RevisionInformationId");
104 
105  b.HasKey("Id");
106 
107  b.HasIndex("DirectoryName");
108 
109  b.HasIndex("JobId");
110 
111  b.HasIndex("RevisionInformationId");
112 
113  b.ToTable("CompileJobs");
114  });
115 
116  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
117  {
118  b.Property<long>("Id")
119  .ValueGeneratedOnAdd();
120 
121  b.Property<string>("AccessToken");
122 
123  b.Property<bool?>("AllowWebClient")
124  .IsRequired();
125 
126  b.Property<bool?>("AutoStart")
127  .IsRequired();
128 
129  b.Property<long>("InstanceId");
130 
131  b.Property<ushort?>("PrimaryPort")
132  .IsRequired();
133 
134  b.Property<int?>("ProcessId");
135 
136  b.Property<ushort?>("SecondaryPort")
137  .IsRequired();
138 
139  b.Property<int>("SecurityLevel");
140 
141  b.Property<bool?>("SoftRestart")
142  .IsRequired();
143 
144  b.Property<bool?>("SoftShutdown")
145  .IsRequired();
146 
147  b.Property<uint?>("StartupTimeout")
148  .IsRequired();
149 
150  b.HasKey("Id");
151 
152  b.HasIndex("InstanceId")
153  .IsUnique();
154 
155  b.ToTable("DreamDaemonSettings");
156  });
157 
158  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
159  {
160  b.Property<long>("Id")
161  .ValueGeneratedOnAdd();
162 
163  b.Property<ushort?>("ApiValidationPort")
164  .IsRequired();
165 
166  b.Property<int>("ApiValidationSecurityLevel");
167 
168  b.Property<long>("InstanceId");
169 
170  b.Property<string>("ProjectName");
171 
172  b.HasKey("Id");
173 
174  b.HasIndex("InstanceId")
175  .IsUnique();
176 
177  b.ToTable("DreamMakerSettings");
178  });
179 
180  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
181  {
182  b.Property<long>("Id")
183  .ValueGeneratedOnAdd();
184 
185  b.Property<uint?>("AutoUpdateInterval")
186  .IsRequired();
187 
188  b.Property<int>("ConfigurationType");
189 
190  b.Property<string>("Name")
191  .IsRequired();
192 
193  b.Property<bool?>("Online")
194  .IsRequired();
195 
196  b.Property<string>("Path")
197  .IsRequired();
198 
199  b.Property<long?>("WatchdogReattachInformationId");
200 
201  b.HasKey("Id");
202 
203  b.HasIndex("Path")
204  .IsUnique();
205 
206  b.HasIndex("WatchdogReattachInformationId");
207 
208  b.ToTable("Instances");
209  });
210 
211  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
212  {
213  b.Property<long>("Id")
214  .ValueGeneratedOnAdd();
215 
216  b.Property<ulong>("ByondRights");
217 
218  b.Property<ulong>("ChatBotRights");
219 
220  b.Property<ulong>("ConfigurationRights");
221 
222  b.Property<ulong>("DreamDaemonRights");
223 
224  b.Property<ulong>("DreamMakerRights");
225 
226  b.Property<long>("InstanceId");
227 
228  b.Property<ulong>("InstanceUserRights");
229 
230  b.Property<ulong>("RepositoryRights");
231 
232  b.Property<long?>("UserId")
233  .IsRequired();
234 
235  b.HasKey("Id");
236 
237  b.HasIndex("InstanceId");
238 
239  b.HasIndex("UserId", "InstanceId")
240  .IsUnique();
241 
242  b.ToTable("InstanceUsers");
243  });
244 
245  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
246  {
247  b.Property<long>("Id")
248  .ValueGeneratedOnAdd();
249 
250  b.Property<ulong?>("CancelRight");
251 
252  b.Property<ulong?>("CancelRightsType");
253 
254  b.Property<bool?>("Cancelled")
255  .IsRequired();
256 
257  b.Property<long?>("CancelledById");
258 
259  b.Property<string>("Description")
260  .IsRequired();
261 
262  b.Property<string>("ExceptionDetails");
263 
264  b.Property<long>("InstanceId");
265 
266  b.Property<DateTimeOffset?>("StartedAt")
267  .IsRequired();
268 
269  b.Property<long>("StartedById");
270 
271  b.Property<DateTimeOffset?>("StoppedAt");
272 
273  b.HasKey("Id");
274 
275  b.HasIndex("CancelledById");
276 
277  b.HasIndex("InstanceId");
278 
279  b.HasIndex("StartedById");
280 
281  b.ToTable("Jobs");
282  });
283 
284  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
285  {
286  b.Property<long>("Id")
287  .ValueGeneratedOnAdd();
288 
289  b.Property<string>("AccessIdentifier")
290  .IsRequired();
291 
292  b.Property<string>("ChatChannelsJson")
293  .IsRequired();
294 
295  b.Property<string>("ChatCommandsJson")
296  .IsRequired();
297 
298  b.Property<long?>("CompileJobId");
299 
300  b.Property<bool>("IsPrimary");
301 
302  b.Property<ushort>("Port");
303 
304  b.Property<int>("ProcessId");
305 
306  b.Property<int>("RebootState");
307 
308  b.Property<string>("ServerCommandsJson")
309  .IsRequired();
310 
311  b.HasKey("Id");
312 
313  b.HasIndex("CompileJobId");
314 
315  b.ToTable("ReattachInformations");
316  });
317 
318  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
319  {
320  b.Property<long>("Id")
321  .ValueGeneratedOnAdd();
322 
323  b.Property<string>("AccessToken");
324 
325  b.Property<string>("AccessUser");
326 
327  b.Property<bool?>("AutoUpdatesKeepTestMerges")
328  .IsRequired();
329 
330  b.Property<bool?>("AutoUpdatesSynchronize")
331  .IsRequired();
332 
333  b.Property<string>("CommitterEmail")
334  .IsRequired();
335 
336  b.Property<string>("CommitterName")
337  .IsRequired();
338 
339  b.Property<long>("InstanceId");
340 
341  b.Property<bool?>("PushTestMergeCommits")
342  .IsRequired();
343 
344  b.Property<bool?>("ShowTestMergeCommitters")
345  .IsRequired();
346 
347  b.HasKey("Id");
348 
349  b.HasIndex("InstanceId")
350  .IsUnique();
351 
352  b.ToTable("RepositorySettings");
353  });
354 
355  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
356  {
357  b.Property<long>("Id")
358  .ValueGeneratedOnAdd();
359 
360  b.Property<long>("RevisionInformationId");
361 
362  b.Property<long>("TestMergeId");
363 
364  b.HasKey("Id");
365 
366  b.HasIndex("RevisionInformationId");
367 
368  b.HasIndex("TestMergeId");
369 
370  b.ToTable("RevInfoTestMerges");
371  });
372 
373  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
374  {
375  b.Property<long>("Id")
376  .ValueGeneratedOnAdd();
377 
378  b.Property<string>("CommitSha")
379  .IsRequired()
380  .HasMaxLength(40);
381 
382  b.Property<long>("InstanceId");
383 
384  b.Property<string>("OriginCommitSha")
385  .IsRequired()
386  .HasMaxLength(40);
387 
388  b.HasKey("Id");
389 
390  b.HasIndex("CommitSha")
391  .IsUnique();
392 
393  b.HasIndex("InstanceId");
394 
395  b.ToTable("RevisionInformations");
396  });
397 
398  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
399  {
400  b.Property<long>("Id")
401  .ValueGeneratedOnAdd();
402 
403  b.Property<string>("Author")
404  .IsRequired();
405 
406  b.Property<string>("BodyAtMerge")
407  .IsRequired();
408 
409  b.Property<string>("Comment");
410 
411  b.Property<DateTimeOffset>("MergedAt");
412 
413  b.Property<long>("MergedById");
414 
415  b.Property<int?>("Number")
416  .IsRequired();
417 
418  b.Property<long?>("PrimaryRevisionInformationId");
419 
420  b.Property<string>("PullRequestRevision")
421  .IsRequired();
422 
423  b.Property<string>("TitleAtMerge")
424  .IsRequired();
425 
426  b.Property<string>("Url")
427  .IsRequired();
428 
429  b.HasKey("Id");
430 
431  b.HasIndex("MergedById");
432 
433  b.HasIndex("PrimaryRevisionInformationId")
434  .IsUnique();
435 
436  b.ToTable("TestMerges");
437  });
438 
439  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
440  {
441  b.Property<long>("Id")
442  .ValueGeneratedOnAdd();
443 
444  b.Property<ulong>("AdministrationRights");
445 
446  b.Property<string>("CanonicalName")
447  .IsRequired();
448 
449  b.Property<DateTimeOffset?>("CreatedAt")
450  .IsRequired();
451 
452  b.Property<long?>("CreatedById");
453 
454  b.Property<bool?>("Enabled")
455  .IsRequired();
456 
457  b.Property<ulong>("InstanceManagerRights");
458 
459  b.Property<DateTimeOffset?>("LastPasswordUpdate");
460 
461  b.Property<string>("Name")
462  .IsRequired();
463 
464  b.Property<string>("PasswordHash");
465 
466  b.Property<string>("SystemIdentifier");
467 
468  b.HasKey("Id");
469 
470  b.HasIndex("CanonicalName")
471  .IsUnique();
472 
473  b.HasIndex("CreatedById");
474 
475  b.ToTable("Users");
476  });
477 
478  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
479  {
480  b.Property<long>("Id")
481  .ValueGeneratedOnAdd();
482 
483  b.Property<long?>("AlphaId");
484 
485  b.Property<bool>("AlphaIsActive");
486 
487  b.Property<long?>("BravoId");
488 
489  b.HasKey("Id");
490 
491  b.HasIndex("AlphaId");
492 
493  b.HasIndex("BravoId");
494 
495  b.ToTable("WatchdogReattachInformations");
496  });
497 
498  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
499  {
500  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
501  .WithMany("ChatSettings")
502  .HasForeignKey("InstanceId")
503  .OnDelete(DeleteBehavior.Cascade);
504  });
505 
506  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
507  {
508  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
509  .WithMany("Channels")
510  .HasForeignKey("ChatSettingsId")
511  .OnDelete(DeleteBehavior.Cascade);
512  });
513 
514  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
515  {
516  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
517  .WithMany()
518  .HasForeignKey("JobId");
519 
520  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
521  .WithMany("CompileJobs")
522  .HasForeignKey("RevisionInformationId")
523  .OnDelete(DeleteBehavior.Cascade);
524  });
525 
526  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
527  {
528  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
529  .WithOne("DreamDaemonSettings")
530  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
531  .OnDelete(DeleteBehavior.Cascade);
532  });
533 
534  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
535  {
536  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
537  .WithOne("DreamMakerSettings")
538  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
539  .OnDelete(DeleteBehavior.Cascade);
540  });
541 
542  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
543  {
544  b.HasOne("Tgstation.Server.Host.Models.WatchdogReattachInformation", "WatchdogReattachInformation")
545  .WithMany()
546  .HasForeignKey("WatchdogReattachInformationId");
547  });
548 
549  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
550  {
551  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
552  .WithMany("InstanceUsers")
553  .HasForeignKey("InstanceId")
554  .OnDelete(DeleteBehavior.Cascade);
555 
556  b.HasOne("Tgstation.Server.Host.Models.User")
557  .WithMany("InstanceUsers")
558  .HasForeignKey("UserId")
559  .OnDelete(DeleteBehavior.Cascade);
560  });
561 
562  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
563  {
564  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
565  .WithMany()
566  .HasForeignKey("CancelledById");
567 
568  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
569  .WithMany("Jobs")
570  .HasForeignKey("InstanceId")
571  .OnDelete(DeleteBehavior.Cascade);
572 
573  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
574  .WithMany()
575  .HasForeignKey("StartedById")
576  .OnDelete(DeleteBehavior.Cascade);
577  });
578 
579  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
580  {
581  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
582  .WithMany()
583  .HasForeignKey("CompileJobId");
584  });
585 
586  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
587  {
588  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
589  .WithOne("RepositorySettings")
590  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
591  .OnDelete(DeleteBehavior.Cascade);
592  });
593 
594  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
595  {
596  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
597  .WithMany("ActiveTestMerges")
598  .HasForeignKey("RevisionInformationId")
599  .OnDelete(DeleteBehavior.Cascade);
600 
601  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
602  .WithMany("RevisonInformations")
603  .HasForeignKey("TestMergeId")
604  .OnDelete(DeleteBehavior.Cascade);
605  });
606 
607  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
608  {
609  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
610  .WithMany("RevisionInformations")
611  .HasForeignKey("InstanceId")
612  .OnDelete(DeleteBehavior.Cascade);
613  });
614 
615  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
616  {
617  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
618  .WithMany("TestMerges")
619  .HasForeignKey("MergedById")
620  .OnDelete(DeleteBehavior.Restrict);
621 
622  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
623  .WithOne("PrimaryTestMerge")
624  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
625  .OnDelete(DeleteBehavior.SetNull);
626  });
627 
628  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
629  {
630  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
631  .WithMany("CreatedUsers")
632  .HasForeignKey("CreatedById");
633  });
634 
635  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
636  {
637  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
638  .WithMany()
639  .HasForeignKey("AlphaId");
640 
641  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
642  .WithMany()
643  .HasForeignKey("BravoId");
644  });
645 #pragma warning restore 612, 618
646  }
647  }
648 }
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
+
DatabaseContext<TParentContext> for MySQL
+ + + +
-Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Metadata;
6 using Microsoft.EntityFrameworkCore.Migrations;
7 using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
8 
10 {
11  [DbContext(typeof(SqlServerDatabaseContext))]
12  [Migration("20180918021228_MSAddMinimumSecurity")]
13  partial class MSAddMinimumSecurity
14  {
19  protected override void BuildTargetModel(ModelBuilder modelBuilder)
20  {
21 #pragma warning disable 612, 618
22  modelBuilder
23  .HasAnnotation("ProductVersion", "2.1.3-rtm-32065")
24  .HasAnnotation("Relational:MaxIdentifierLength", 128)
25  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
26 
27  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
28  {
29  b.Property<long>("Id")
30  .ValueGeneratedOnAdd()
31  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
32 
33  b.Property<string>("ConnectionString")
34  .IsRequired();
35 
36  b.Property<bool?>("Enabled");
37 
38  b.Property<long>("InstanceId");
39 
40  b.Property<string>("Name")
41  .IsRequired();
42 
43  b.Property<int?>("Provider");
44 
45  b.HasKey("Id");
46 
47  b.HasIndex("InstanceId");
48 
49  b.HasIndex("Name")
50  .IsUnique();
51 
52  b.ToTable("ChatBots");
53  });
54 
55  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
56  {
57  b.Property<long>("Id")
58  .ValueGeneratedOnAdd()
59  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
60 
61  b.Property<long>("ChatSettingsId");
62 
63  b.Property<decimal?>("DiscordChannelId")
64  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
65 
66  b.Property<string>("IrcChannel");
67 
68  b.Property<bool?>("IsAdminChannel")
69  .IsRequired();
70 
71  b.Property<bool?>("IsUpdatesChannel")
72  .IsRequired();
73 
74  b.Property<bool?>("IsWatchdogChannel")
75  .IsRequired();
76 
77  b.Property<string>("Tag");
78 
79  b.HasKey("Id");
80 
81  b.HasIndex("ChatSettingsId", "DiscordChannelId")
82  .IsUnique()
83  .HasFilter("[DiscordChannelId] IS NOT NULL");
84 
85  b.HasIndex("ChatSettingsId", "IrcChannel")
86  .IsUnique()
87  .HasFilter("[IrcChannel] IS NOT NULL");
88 
89  b.ToTable("ChatChannels");
90  });
91 
92  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
93  {
94  b.Property<long>("Id")
95  .ValueGeneratedOnAdd()
96  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
97 
98  b.Property<string>("ByondVersion")
99  .IsRequired();
100 
101  b.Property<Guid?>("DirectoryName");
102 
103  b.Property<string>("DmeName");
104 
105  b.Property<long?>("JobId");
106 
107  b.Property<int>("MinimumSecurityLevel");
108 
109  b.Property<string>("Output");
110 
111  b.Property<long>("RevisionInformationId");
112 
113  b.HasKey("Id");
114 
115  b.HasIndex("DirectoryName");
116 
117  b.HasIndex("JobId");
118 
119  b.HasIndex("RevisionInformationId");
120 
121  b.ToTable("CompileJobs");
122  });
123 
124  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
125  {
126  b.Property<long>("Id")
127  .ValueGeneratedOnAdd()
128  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
129 
130  b.Property<string>("AccessToken");
131 
132  b.Property<bool?>("AllowWebClient")
133  .IsRequired();
134 
135  b.Property<bool?>("AutoStart")
136  .IsRequired();
137 
138  b.Property<long>("InstanceId");
139 
140  b.Property<int>("PrimaryPort");
141 
142  b.Property<int?>("ProcessId");
143 
144  b.Property<int>("SecondaryPort");
145 
146  b.Property<int>("SecurityLevel");
147 
148  b.Property<bool?>("SoftRestart")
149  .IsRequired();
150 
151  b.Property<bool?>("SoftShutdown")
152  .IsRequired();
153 
154  b.Property<long>("StartupTimeout");
155 
156  b.HasKey("Id");
157 
158  b.HasIndex("InstanceId")
159  .IsUnique();
160 
161  b.ToTable("DreamDaemonSettings");
162  });
163 
164  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
165  {
166  b.Property<long>("Id")
167  .ValueGeneratedOnAdd()
168  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
169 
170  b.Property<int>("ApiValidationPort");
171 
172  b.Property<int>("ApiValidationSecurityLevel");
173 
174  b.Property<long>("InstanceId");
175 
176  b.Property<string>("ProjectName");
177 
178  b.HasKey("Id");
179 
180  b.HasIndex("InstanceId")
181  .IsUnique();
182 
183  b.ToTable("DreamMakerSettings");
184  });
185 
186  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
187  {
188  b.Property<long>("Id")
189  .ValueGeneratedOnAdd()
190  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
191 
192  b.Property<long>("AutoUpdateInterval");
193 
194  b.Property<int>("ConfigurationType");
195 
196  b.Property<string>("Name")
197  .IsRequired();
198 
199  b.Property<bool?>("Online")
200  .IsRequired();
201 
202  b.Property<string>("Path")
203  .IsRequired();
204 
205  b.Property<long?>("WatchdogReattachInformationId");
206 
207  b.HasKey("Id");
208 
209  b.HasIndex("Path")
210  .IsUnique();
211 
212  b.HasIndex("WatchdogReattachInformationId");
213 
214  b.ToTable("Instances");
215  });
216 
217  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
218  {
219  b.Property<long>("Id")
220  .ValueGeneratedOnAdd()
221  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
222 
223  b.Property<decimal>("ByondRights")
224  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
225 
226  b.Property<decimal>("ChatBotRights")
227  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
228 
229  b.Property<decimal>("ConfigurationRights")
230  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
231 
232  b.Property<decimal>("DreamDaemonRights")
233  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
234 
235  b.Property<decimal>("DreamMakerRights")
236  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
237 
238  b.Property<long>("InstanceId");
239 
240  b.Property<decimal>("InstanceUserRights")
241  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
242 
243  b.Property<decimal>("RepositoryRights")
244  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
245 
246  b.Property<long?>("UserId")
247  .IsRequired();
248 
249  b.HasKey("Id");
250 
251  b.HasIndex("InstanceId");
252 
253  b.HasIndex("UserId", "InstanceId")
254  .IsUnique();
255 
256  b.ToTable("InstanceUsers");
257  });
258 
259  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
260  {
261  b.Property<long>("Id")
262  .ValueGeneratedOnAdd()
263  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
264 
265  b.Property<decimal?>("CancelRight")
266  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
267 
268  b.Property<decimal?>("CancelRightsType")
269  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
270 
271  b.Property<bool?>("Cancelled")
272  .IsRequired();
273 
274  b.Property<long?>("CancelledById");
275 
276  b.Property<string>("Description")
277  .IsRequired();
278 
279  b.Property<string>("ExceptionDetails");
280 
281  b.Property<long>("InstanceId");
282 
283  b.Property<DateTimeOffset?>("StartedAt")
284  .IsRequired();
285 
286  b.Property<long>("StartedById");
287 
288  b.Property<DateTimeOffset?>("StoppedAt");
289 
290  b.HasKey("Id");
291 
292  b.HasIndex("CancelledById");
293 
294  b.HasIndex("InstanceId");
295 
296  b.HasIndex("StartedById");
297 
298  b.ToTable("Jobs");
299  });
300 
301  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
302  {
303  b.Property<long>("Id")
304  .ValueGeneratedOnAdd()
305  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
306 
307  b.Property<string>("AccessIdentifier")
308  .IsRequired();
309 
310  b.Property<string>("ChatChannelsJson")
311  .IsRequired();
312 
313  b.Property<string>("ChatCommandsJson")
314  .IsRequired();
315 
316  b.Property<long?>("CompileJobId");
317 
318  b.Property<bool>("IsPrimary");
319 
320  b.Property<int>("Port");
321 
322  b.Property<int>("ProcessId");
323 
324  b.Property<int>("RebootState");
325 
326  b.Property<string>("ServerCommandsJson")
327  .IsRequired();
328 
329  b.HasKey("Id");
330 
331  b.HasIndex("CompileJobId");
332 
333  b.ToTable("ReattachInformations");
334  });
335 
336  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
337  {
338  b.Property<long>("Id")
339  .ValueGeneratedOnAdd()
340  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
341 
342  b.Property<string>("AccessToken");
343 
344  b.Property<string>("AccessUser");
345 
346  b.Property<bool?>("AutoUpdatesKeepTestMerges")
347  .IsRequired();
348 
349  b.Property<bool?>("AutoUpdatesSynchronize")
350  .IsRequired();
351 
352  b.Property<string>("CommitterEmail")
353  .IsRequired();
354 
355  b.Property<string>("CommitterName")
356  .IsRequired();
357 
358  b.Property<long>("InstanceId");
359 
360  b.Property<bool?>("PushTestMergeCommits")
361  .IsRequired();
362 
363  b.Property<bool?>("ShowTestMergeCommitters")
364  .IsRequired();
365 
366  b.HasKey("Id");
367 
368  b.HasIndex("InstanceId")
369  .IsUnique();
370 
371  b.ToTable("RepositorySettings");
372  });
373 
374  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
375  {
376  b.Property<long>("Id")
377  .ValueGeneratedOnAdd()
378  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
379 
380  b.Property<long>("RevisionInformationId");
381 
382  b.Property<long>("TestMergeId");
383 
384  b.HasKey("Id");
385 
386  b.HasIndex("RevisionInformationId");
387 
388  b.HasIndex("TestMergeId");
389 
390  b.ToTable("RevInfoTestMerges");
391  });
392 
393  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
394  {
395  b.Property<long>("Id")
396  .ValueGeneratedOnAdd()
397  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
398 
399  b.Property<string>("CommitSha")
400  .IsRequired()
401  .HasMaxLength(40);
402 
403  b.Property<long>("InstanceId");
404 
405  b.Property<string>("OriginCommitSha")
406  .IsRequired()
407  .HasMaxLength(40);
408 
409  b.HasKey("Id");
410 
411  b.HasIndex("CommitSha")
412  .IsUnique();
413 
414  b.HasIndex("InstanceId");
415 
416  b.ToTable("RevisionInformations");
417  });
418 
419  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
420  {
421  b.Property<long>("Id")
422  .ValueGeneratedOnAdd()
423  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
424 
425  b.Property<string>("Author")
426  .IsRequired();
427 
428  b.Property<string>("BodyAtMerge")
429  .IsRequired();
430 
431  b.Property<string>("Comment");
432 
433  b.Property<DateTimeOffset>("MergedAt");
434 
435  b.Property<long>("MergedById");
436 
437  b.Property<int?>("Number")
438  .IsRequired();
439 
440  b.Property<long?>("PrimaryRevisionInformationId");
441 
442  b.Property<string>("PullRequestRevision")
443  .IsRequired();
444 
445  b.Property<string>("TitleAtMerge")
446  .IsRequired();
447 
448  b.Property<string>("Url")
449  .IsRequired();
450 
451  b.HasKey("Id");
452 
453  b.HasIndex("MergedById");
454 
455  b.HasIndex("PrimaryRevisionInformationId")
456  .IsUnique()
457  .HasFilter("[PrimaryRevisionInformationId] IS NOT NULL");
458 
459  b.ToTable("TestMerges");
460  });
461 
462  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
463  {
464  b.Property<long>("Id")
465  .ValueGeneratedOnAdd()
466  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
467 
468  b.Property<decimal>("AdministrationRights")
469  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
470 
471  b.Property<string>("CanonicalName")
472  .IsRequired();
473 
474  b.Property<DateTimeOffset?>("CreatedAt")
475  .IsRequired();
476 
477  b.Property<long?>("CreatedById");
478 
479  b.Property<bool?>("Enabled")
480  .IsRequired();
481 
482  b.Property<decimal>("InstanceManagerRights")
483  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
484 
485  b.Property<DateTimeOffset?>("LastPasswordUpdate");
486 
487  b.Property<string>("Name")
488  .IsRequired();
489 
490  b.Property<string>("PasswordHash");
491 
492  b.Property<string>("SystemIdentifier");
493 
494  b.HasKey("Id");
495 
496  b.HasIndex("CanonicalName")
497  .IsUnique();
498 
499  b.HasIndex("CreatedById");
500 
501  b.ToTable("Users");
502  });
503 
504  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
505  {
506  b.Property<long>("Id")
507  .ValueGeneratedOnAdd()
508  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
509 
510  b.Property<long?>("AlphaId");
511 
512  b.Property<bool>("AlphaIsActive");
513 
514  b.Property<long?>("BravoId");
515 
516  b.HasKey("Id");
517 
518  b.HasIndex("AlphaId");
519 
520  b.HasIndex("BravoId");
521 
522  b.ToTable("WatchdogReattachInformations");
523  });
524 
525  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
526  {
527  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
528  .WithMany("ChatSettings")
529  .HasForeignKey("InstanceId")
530  .OnDelete(DeleteBehavior.Cascade);
531  });
532 
533  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
534  {
535  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
536  .WithMany("Channels")
537  .HasForeignKey("ChatSettingsId")
538  .OnDelete(DeleteBehavior.Cascade);
539  });
540 
541  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
542  {
543  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
544  .WithMany()
545  .HasForeignKey("JobId");
546 
547  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
548  .WithMany("CompileJobs")
549  .HasForeignKey("RevisionInformationId")
550  .OnDelete(DeleteBehavior.Cascade);
551  });
552 
553  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
554  {
555  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
556  .WithOne("DreamDaemonSettings")
557  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
558  .OnDelete(DeleteBehavior.Cascade);
559  });
560 
561  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
562  {
563  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
564  .WithOne("DreamMakerSettings")
565  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
566  .OnDelete(DeleteBehavior.Cascade);
567  });
568 
569  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
570  {
571  b.HasOne("Tgstation.Server.Host.Models.WatchdogReattachInformation", "WatchdogReattachInformation")
572  .WithMany()
573  .HasForeignKey("WatchdogReattachInformationId");
574  });
575 
576  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
577  {
578  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
579  .WithMany("InstanceUsers")
580  .HasForeignKey("InstanceId")
581  .OnDelete(DeleteBehavior.Cascade);
582 
583  b.HasOne("Tgstation.Server.Host.Models.User")
584  .WithMany("InstanceUsers")
585  .HasForeignKey("UserId")
586  .OnDelete(DeleteBehavior.Cascade);
587  });
588 
589  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
590  {
591  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
592  .WithMany()
593  .HasForeignKey("CancelledById");
594 
595  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
596  .WithMany("Jobs")
597  .HasForeignKey("InstanceId")
598  .OnDelete(DeleteBehavior.Cascade);
599 
600  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
601  .WithMany()
602  .HasForeignKey("StartedById")
603  .OnDelete(DeleteBehavior.Cascade);
604  });
605 
606  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
607  {
608  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
609  .WithMany()
610  .HasForeignKey("CompileJobId");
611  });
612 
613  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
614  {
615  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
616  .WithOne("RepositorySettings")
617  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
618  .OnDelete(DeleteBehavior.Cascade);
619  });
620 
621  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
622  {
623  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
624  .WithMany("ActiveTestMerges")
625  .HasForeignKey("RevisionInformationId")
626  .OnDelete(DeleteBehavior.Cascade);
627 
628  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
629  .WithMany("RevisonInformations")
630  .HasForeignKey("TestMergeId")
631  .OnDelete(DeleteBehavior.Cascade);
632  });
633 
634  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
635  {
636  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
637  .WithMany("RevisionInformations")
638  .HasForeignKey("InstanceId")
639  .OnDelete(DeleteBehavior.Cascade);
640  });
641 
642  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
643  {
644  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
645  .WithMany("TestMerges")
646  .HasForeignKey("MergedById")
647  .OnDelete(DeleteBehavior.Restrict);
648 
649  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
650  .WithOne("PrimaryTestMerge")
651  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
652  .OnDelete(DeleteBehavior.SetNull);
653  });
654 
655  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
656  {
657  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
658  .WithMany("CreatedUsers")
659  .HasForeignKey("CreatedById");
660  });
661 
662  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
663  {
664  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
665  .WithMany()
666  .HasForeignKey("AlphaId");
667 
668  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
669  .WithMany()
670  .HasForeignKey("BravoId");
671  });
672 #pragma warning restore 612, 618
673  }
674  }
675 }
+Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Metadata;
6 using Microsoft.EntityFrameworkCore.Migrations;
7 using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
9 
11 {
13  [Migration("20180918021228_MSAddMinimumSecurity")]
14  partial class MSAddMinimumSecurity
15  {
20  protected override void BuildTargetModel(ModelBuilder modelBuilder)
21  {
22 #pragma warning disable 612, 618
23  modelBuilder
24  .HasAnnotation("ProductVersion", "2.1.3-rtm-32065")
25  .HasAnnotation("Relational:MaxIdentifierLength", 128)
26  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
27 
28  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
29  {
30  b.Property<long>("Id")
31  .ValueGeneratedOnAdd()
32  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
33 
34  b.Property<string>("ConnectionString")
35  .IsRequired();
36 
37  b.Property<bool?>("Enabled");
38 
39  b.Property<long>("InstanceId");
40 
41  b.Property<string>("Name")
42  .IsRequired();
43 
44  b.Property<int?>("Provider");
45 
46  b.HasKey("Id");
47 
48  b.HasIndex("InstanceId");
49 
50  b.HasIndex("Name")
51  .IsUnique();
52 
53  b.ToTable("ChatBots");
54  });
55 
56  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
57  {
58  b.Property<long>("Id")
59  .ValueGeneratedOnAdd()
60  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
61 
62  b.Property<long>("ChatSettingsId");
63 
64  b.Property<decimal?>("DiscordChannelId")
65  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
66 
67  b.Property<string>("IrcChannel");
68 
69  b.Property<bool?>("IsAdminChannel")
70  .IsRequired();
71 
72  b.Property<bool?>("IsUpdatesChannel")
73  .IsRequired();
74 
75  b.Property<bool?>("IsWatchdogChannel")
76  .IsRequired();
77 
78  b.Property<string>("Tag");
79 
80  b.HasKey("Id");
81 
82  b.HasIndex("ChatSettingsId", "DiscordChannelId")
83  .IsUnique()
84  .HasFilter("[DiscordChannelId] IS NOT NULL");
85 
86  b.HasIndex("ChatSettingsId", "IrcChannel")
87  .IsUnique()
88  .HasFilter("[IrcChannel] IS NOT NULL");
89 
90  b.ToTable("ChatChannels");
91  });
92 
93  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
94  {
95  b.Property<long>("Id")
96  .ValueGeneratedOnAdd()
97  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
98 
99  b.Property<string>("ByondVersion")
100  .IsRequired();
101 
102  b.Property<Guid?>("DirectoryName");
103 
104  b.Property<string>("DmeName");
105 
106  b.Property<long?>("JobId");
107 
108  b.Property<int>("MinimumSecurityLevel");
109 
110  b.Property<string>("Output");
111 
112  b.Property<long>("RevisionInformationId");
113 
114  b.HasKey("Id");
115 
116  b.HasIndex("DirectoryName");
117 
118  b.HasIndex("JobId");
119 
120  b.HasIndex("RevisionInformationId");
121 
122  b.ToTable("CompileJobs");
123  });
124 
125  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
126  {
127  b.Property<long>("Id")
128  .ValueGeneratedOnAdd()
129  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
130 
131  b.Property<string>("AccessToken");
132 
133  b.Property<bool?>("AllowWebClient")
134  .IsRequired();
135 
136  b.Property<bool?>("AutoStart")
137  .IsRequired();
138 
139  b.Property<long>("InstanceId");
140 
141  b.Property<int>("PrimaryPort");
142 
143  b.Property<int?>("ProcessId");
144 
145  b.Property<int>("SecondaryPort");
146 
147  b.Property<int>("SecurityLevel");
148 
149  b.Property<bool?>("SoftRestart")
150  .IsRequired();
151 
152  b.Property<bool?>("SoftShutdown")
153  .IsRequired();
154 
155  b.Property<long>("StartupTimeout");
156 
157  b.HasKey("Id");
158 
159  b.HasIndex("InstanceId")
160  .IsUnique();
161 
162  b.ToTable("DreamDaemonSettings");
163  });
164 
165  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
166  {
167  b.Property<long>("Id")
168  .ValueGeneratedOnAdd()
169  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
170 
171  b.Property<int>("ApiValidationPort");
172 
173  b.Property<int>("ApiValidationSecurityLevel");
174 
175  b.Property<long>("InstanceId");
176 
177  b.Property<string>("ProjectName");
178 
179  b.HasKey("Id");
180 
181  b.HasIndex("InstanceId")
182  .IsUnique();
183 
184  b.ToTable("DreamMakerSettings");
185  });
186 
187  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
188  {
189  b.Property<long>("Id")
190  .ValueGeneratedOnAdd()
191  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
192 
193  b.Property<long>("AutoUpdateInterval");
194 
195  b.Property<int>("ConfigurationType");
196 
197  b.Property<string>("Name")
198  .IsRequired();
199 
200  b.Property<bool?>("Online")
201  .IsRequired();
202 
203  b.Property<string>("Path")
204  .IsRequired();
205 
206  b.Property<long?>("WatchdogReattachInformationId");
207 
208  b.HasKey("Id");
209 
210  b.HasIndex("Path")
211  .IsUnique();
212 
213  b.HasIndex("WatchdogReattachInformationId");
214 
215  b.ToTable("Instances");
216  });
217 
218  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
219  {
220  b.Property<long>("Id")
221  .ValueGeneratedOnAdd()
222  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
223 
224  b.Property<decimal>("ByondRights")
225  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
226 
227  b.Property<decimal>("ChatBotRights")
228  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
229 
230  b.Property<decimal>("ConfigurationRights")
231  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
232 
233  b.Property<decimal>("DreamDaemonRights")
234  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
235 
236  b.Property<decimal>("DreamMakerRights")
237  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
238 
239  b.Property<long>("InstanceId");
240 
241  b.Property<decimal>("InstanceUserRights")
242  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
243 
244  b.Property<decimal>("RepositoryRights")
245  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
246 
247  b.Property<long?>("UserId")
248  .IsRequired();
249 
250  b.HasKey("Id");
251 
252  b.HasIndex("InstanceId");
253 
254  b.HasIndex("UserId", "InstanceId")
255  .IsUnique();
256 
257  b.ToTable("InstanceUsers");
258  });
259 
260  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
261  {
262  b.Property<long>("Id")
263  .ValueGeneratedOnAdd()
264  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
265 
266  b.Property<decimal?>("CancelRight")
267  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
268 
269  b.Property<decimal?>("CancelRightsType")
270  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
271 
272  b.Property<bool?>("Cancelled")
273  .IsRequired();
274 
275  b.Property<long?>("CancelledById");
276 
277  b.Property<string>("Description")
278  .IsRequired();
279 
280  b.Property<string>("ExceptionDetails");
281 
282  b.Property<long>("InstanceId");
283 
284  b.Property<DateTimeOffset?>("StartedAt")
285  .IsRequired();
286 
287  b.Property<long>("StartedById");
288 
289  b.Property<DateTimeOffset?>("StoppedAt");
290 
291  b.HasKey("Id");
292 
293  b.HasIndex("CancelledById");
294 
295  b.HasIndex("InstanceId");
296 
297  b.HasIndex("StartedById");
298 
299  b.ToTable("Jobs");
300  });
301 
302  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
303  {
304  b.Property<long>("Id")
305  .ValueGeneratedOnAdd()
306  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
307 
308  b.Property<string>("AccessIdentifier")
309  .IsRequired();
310 
311  b.Property<string>("ChatChannelsJson")
312  .IsRequired();
313 
314  b.Property<string>("ChatCommandsJson")
315  .IsRequired();
316 
317  b.Property<long?>("CompileJobId");
318 
319  b.Property<bool>("IsPrimary");
320 
321  b.Property<int>("Port");
322 
323  b.Property<int>("ProcessId");
324 
325  b.Property<int>("RebootState");
326 
327  b.Property<string>("ServerCommandsJson")
328  .IsRequired();
329 
330  b.HasKey("Id");
331 
332  b.HasIndex("CompileJobId");
333 
334  b.ToTable("ReattachInformations");
335  });
336 
337  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
338  {
339  b.Property<long>("Id")
340  .ValueGeneratedOnAdd()
341  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
342 
343  b.Property<string>("AccessToken");
344 
345  b.Property<string>("AccessUser");
346 
347  b.Property<bool?>("AutoUpdatesKeepTestMerges")
348  .IsRequired();
349 
350  b.Property<bool?>("AutoUpdatesSynchronize")
351  .IsRequired();
352 
353  b.Property<string>("CommitterEmail")
354  .IsRequired();
355 
356  b.Property<string>("CommitterName")
357  .IsRequired();
358 
359  b.Property<long>("InstanceId");
360 
361  b.Property<bool?>("PushTestMergeCommits")
362  .IsRequired();
363 
364  b.Property<bool?>("ShowTestMergeCommitters")
365  .IsRequired();
366 
367  b.HasKey("Id");
368 
369  b.HasIndex("InstanceId")
370  .IsUnique();
371 
372  b.ToTable("RepositorySettings");
373  });
374 
375  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
376  {
377  b.Property<long>("Id")
378  .ValueGeneratedOnAdd()
379  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
380 
381  b.Property<long>("RevisionInformationId");
382 
383  b.Property<long>("TestMergeId");
384 
385  b.HasKey("Id");
386 
387  b.HasIndex("RevisionInformationId");
388 
389  b.HasIndex("TestMergeId");
390 
391  b.ToTable("RevInfoTestMerges");
392  });
393 
394  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
395  {
396  b.Property<long>("Id")
397  .ValueGeneratedOnAdd()
398  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
399 
400  b.Property<string>("CommitSha")
401  .IsRequired()
402  .HasMaxLength(40);
403 
404  b.Property<long>("InstanceId");
405 
406  b.Property<string>("OriginCommitSha")
407  .IsRequired()
408  .HasMaxLength(40);
409 
410  b.HasKey("Id");
411 
412  b.HasIndex("CommitSha")
413  .IsUnique();
414 
415  b.HasIndex("InstanceId");
416 
417  b.ToTable("RevisionInformations");
418  });
419 
420  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
421  {
422  b.Property<long>("Id")
423  .ValueGeneratedOnAdd()
424  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
425 
426  b.Property<string>("Author")
427  .IsRequired();
428 
429  b.Property<string>("BodyAtMerge")
430  .IsRequired();
431 
432  b.Property<string>("Comment");
433 
434  b.Property<DateTimeOffset>("MergedAt");
435 
436  b.Property<long>("MergedById");
437 
438  b.Property<int?>("Number")
439  .IsRequired();
440 
441  b.Property<long?>("PrimaryRevisionInformationId");
442 
443  b.Property<string>("PullRequestRevision")
444  .IsRequired();
445 
446  b.Property<string>("TitleAtMerge")
447  .IsRequired();
448 
449  b.Property<string>("Url")
450  .IsRequired();
451 
452  b.HasKey("Id");
453 
454  b.HasIndex("MergedById");
455 
456  b.HasIndex("PrimaryRevisionInformationId")
457  .IsUnique()
458  .HasFilter("[PrimaryRevisionInformationId] IS NOT NULL");
459 
460  b.ToTable("TestMerges");
461  });
462 
463  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
464  {
465  b.Property<long>("Id")
466  .ValueGeneratedOnAdd()
467  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
468 
469  b.Property<decimal>("AdministrationRights")
470  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
471 
472  b.Property<string>("CanonicalName")
473  .IsRequired();
474 
475  b.Property<DateTimeOffset?>("CreatedAt")
476  .IsRequired();
477 
478  b.Property<long?>("CreatedById");
479 
480  b.Property<bool?>("Enabled")
481  .IsRequired();
482 
483  b.Property<decimal>("InstanceManagerRights")
484  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
485 
486  b.Property<DateTimeOffset?>("LastPasswordUpdate");
487 
488  b.Property<string>("Name")
489  .IsRequired();
490 
491  b.Property<string>("PasswordHash");
492 
493  b.Property<string>("SystemIdentifier");
494 
495  b.HasKey("Id");
496 
497  b.HasIndex("CanonicalName")
498  .IsUnique();
499 
500  b.HasIndex("CreatedById");
501 
502  b.ToTable("Users");
503  });
504 
505  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
506  {
507  b.Property<long>("Id")
508  .ValueGeneratedOnAdd()
509  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
510 
511  b.Property<long?>("AlphaId");
512 
513  b.Property<bool>("AlphaIsActive");
514 
515  b.Property<long?>("BravoId");
516 
517  b.HasKey("Id");
518 
519  b.HasIndex("AlphaId");
520 
521  b.HasIndex("BravoId");
522 
523  b.ToTable("WatchdogReattachInformations");
524  });
525 
526  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
527  {
528  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
529  .WithMany("ChatSettings")
530  .HasForeignKey("InstanceId")
531  .OnDelete(DeleteBehavior.Cascade);
532  });
533 
534  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
535  {
536  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
537  .WithMany("Channels")
538  .HasForeignKey("ChatSettingsId")
539  .OnDelete(DeleteBehavior.Cascade);
540  });
541 
542  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
543  {
544  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
545  .WithMany()
546  .HasForeignKey("JobId");
547 
548  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
549  .WithMany("CompileJobs")
550  .HasForeignKey("RevisionInformationId")
551  .OnDelete(DeleteBehavior.Cascade);
552  });
553 
554  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
555  {
556  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
557  .WithOne("DreamDaemonSettings")
558  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
559  .OnDelete(DeleteBehavior.Cascade);
560  });
561 
562  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
563  {
564  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
565  .WithOne("DreamMakerSettings")
566  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
567  .OnDelete(DeleteBehavior.Cascade);
568  });
569 
570  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
571  {
572  b.HasOne("Tgstation.Server.Host.Models.WatchdogReattachInformation", "WatchdogReattachInformation")
573  .WithMany()
574  .HasForeignKey("WatchdogReattachInformationId");
575  });
576 
577  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
578  {
579  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
580  .WithMany("InstanceUsers")
581  .HasForeignKey("InstanceId")
582  .OnDelete(DeleteBehavior.Cascade);
583 
584  b.HasOne("Tgstation.Server.Host.Models.User")
585  .WithMany("InstanceUsers")
586  .HasForeignKey("UserId")
587  .OnDelete(DeleteBehavior.Cascade);
588  });
589 
590  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
591  {
592  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
593  .WithMany()
594  .HasForeignKey("CancelledById");
595 
596  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
597  .WithMany("Jobs")
598  .HasForeignKey("InstanceId")
599  .OnDelete(DeleteBehavior.Cascade);
600 
601  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
602  .WithMany()
603  .HasForeignKey("StartedById")
604  .OnDelete(DeleteBehavior.Cascade);
605  });
606 
607  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
608  {
609  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
610  .WithMany()
611  .HasForeignKey("CompileJobId");
612  });
613 
614  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
615  {
616  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
617  .WithOne("RepositorySettings")
618  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
619  .OnDelete(DeleteBehavior.Cascade);
620  });
621 
622  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
623  {
624  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
625  .WithMany("ActiveTestMerges")
626  .HasForeignKey("RevisionInformationId")
627  .OnDelete(DeleteBehavior.Cascade);
628 
629  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
630  .WithMany("RevisonInformations")
631  .HasForeignKey("TestMergeId")
632  .OnDelete(DeleteBehavior.Cascade);
633  });
634 
635  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
636  {
637  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
638  .WithMany("RevisionInformations")
639  .HasForeignKey("InstanceId")
640  .OnDelete(DeleteBehavior.Cascade);
641  });
642 
643  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
644  {
645  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
646  .WithMany("TestMerges")
647  .HasForeignKey("MergedById")
648  .OnDelete(DeleteBehavior.Restrict);
649 
650  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
651  .WithOne("PrimaryTestMerge")
652  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
653  .OnDelete(DeleteBehavior.SetNull);
654  });
655 
656  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
657  {
658  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
659  .WithMany("CreatedUsers")
660  .HasForeignKey("CreatedById");
661  });
662 
663  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
664  {
665  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
666  .WithMany()
667  .HasForeignKey("AlphaId");
668 
669  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
670  .WithMany()
671  .HasForeignKey("BravoId");
672  });
673 #pragma warning restore 612, 618
674  }
675  }
676 }
-
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
+
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
+ +
DatabaseContext<TParentContext> for Sqlserver
+ + +
-Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Migrations;
6 
8 {
9  [DbContext(typeof(MySqlDatabaseContext))]
10  [Migration("20180918204520_MYNullableAndForeignKeyCleanup")]
11  partial class MYNullableAndForeignKeyCleanup
12  {
17  protected override void BuildTargetModel(ModelBuilder modelBuilder)
18  {
19 #pragma warning disable 612, 618
20  modelBuilder
21  .HasAnnotation("ProductVersion", "2.1.3-rtm-32065")
22  .HasAnnotation("Relational:MaxIdentifierLength", 64);
23 
24  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
25  {
26  b.Property<long>("Id")
27  .ValueGeneratedOnAdd();
28 
29  b.Property<string>("ConnectionString")
30  .IsRequired();
31 
32  b.Property<bool?>("Enabled");
33 
34  b.Property<long>("InstanceId");
35 
36  b.Property<string>("Name")
37  .IsRequired();
38 
39  b.Property<int?>("Provider");
40 
41  b.HasKey("Id");
42 
43  b.HasIndex("InstanceId");
44 
45  b.HasIndex("Name")
46  .IsUnique();
47 
48  b.ToTable("ChatBots");
49  });
50 
51  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
52  {
53  b.Property<long>("Id")
54  .ValueGeneratedOnAdd();
55 
56  b.Property<long>("ChatSettingsId");
57 
58  b.Property<ulong?>("DiscordChannelId");
59 
60  b.Property<string>("IrcChannel");
61 
62  b.Property<bool?>("IsAdminChannel")
63  .IsRequired();
64 
65  b.Property<bool?>("IsUpdatesChannel")
66  .IsRequired();
67 
68  b.Property<bool?>("IsWatchdogChannel")
69  .IsRequired();
70 
71  b.Property<string>("Tag");
72 
73  b.HasKey("Id");
74 
75  b.HasIndex("ChatSettingsId", "DiscordChannelId")
76  .IsUnique();
77 
78  b.HasIndex("ChatSettingsId", "IrcChannel")
79  .IsUnique();
80 
81  b.ToTable("ChatChannels");
82  });
83 
84  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
85  {
86  b.Property<long>("Id")
87  .ValueGeneratedOnAdd();
88 
89  b.Property<string>("ByondVersion")
90  .IsRequired();
91 
92  b.Property<Guid?>("DirectoryName")
93  .IsRequired();
94 
95  b.Property<string>("DmeName")
96  .IsRequired();
97 
98  b.Property<long>("JobId");
99 
100  b.Property<int>("MinimumSecurityLevel");
101 
102  b.Property<string>("Output")
103  .IsRequired();
104 
105  b.Property<long>("RevisionInformationId");
106 
107  b.HasKey("Id");
108 
109  b.HasIndex("DirectoryName");
110 
111  b.HasIndex("JobId")
112  .IsUnique();
113 
114  b.HasIndex("RevisionInformationId");
115 
116  b.ToTable("CompileJobs");
117  });
118 
119  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
120  {
121  b.Property<long>("Id")
122  .ValueGeneratedOnAdd();
123 
124  b.Property<string>("AccessToken");
125 
126  b.Property<bool?>("AllowWebClient")
127  .IsRequired();
128 
129  b.Property<bool?>("AutoStart")
130  .IsRequired();
131 
132  b.Property<long>("InstanceId");
133 
134  b.Property<ushort?>("PrimaryPort")
135  .IsRequired();
136 
137  b.Property<int?>("ProcessId");
138 
139  b.Property<ushort?>("SecondaryPort")
140  .IsRequired();
141 
142  b.Property<int>("SecurityLevel");
143 
144  b.Property<bool?>("SoftRestart")
145  .IsRequired();
146 
147  b.Property<bool?>("SoftShutdown")
148  .IsRequired();
149 
150  b.Property<uint?>("StartupTimeout")
151  .IsRequired();
152 
153  b.HasKey("Id");
154 
155  b.HasIndex("InstanceId")
156  .IsUnique();
157 
158  b.ToTable("DreamDaemonSettings");
159  });
160 
161  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
162  {
163  b.Property<long>("Id")
164  .ValueGeneratedOnAdd();
165 
166  b.Property<ushort?>("ApiValidationPort")
167  .IsRequired();
168 
169  b.Property<int>("ApiValidationSecurityLevel");
170 
171  b.Property<long>("InstanceId");
172 
173  b.Property<string>("ProjectName");
174 
175  b.HasKey("Id");
176 
177  b.HasIndex("InstanceId")
178  .IsUnique();
179 
180  b.ToTable("DreamMakerSettings");
181  });
182 
183  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
184  {
185  b.Property<long>("Id")
186  .ValueGeneratedOnAdd();
187 
188  b.Property<uint?>("AutoUpdateInterval")
189  .IsRequired();
190 
191  b.Property<int>("ConfigurationType");
192 
193  b.Property<string>("Name")
194  .IsRequired();
195 
196  b.Property<bool?>("Online")
197  .IsRequired();
198 
199  b.Property<string>("Path")
200  .IsRequired();
201 
202  b.HasKey("Id");
203 
204  b.HasIndex("Path")
205  .IsUnique();
206 
207  b.ToTable("Instances");
208  });
209 
210  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
211  {
212  b.Property<long>("Id")
213  .ValueGeneratedOnAdd();
214 
215  b.Property<ulong>("ByondRights");
216 
217  b.Property<ulong>("ChatBotRights");
218 
219  b.Property<ulong>("ConfigurationRights");
220 
221  b.Property<ulong>("DreamDaemonRights");
222 
223  b.Property<ulong>("DreamMakerRights");
224 
225  b.Property<long>("InstanceId");
226 
227  b.Property<ulong>("InstanceUserRights");
228 
229  b.Property<ulong>("RepositoryRights");
230 
231  b.Property<long?>("UserId")
232  .IsRequired();
233 
234  b.HasKey("Id");
235 
236  b.HasIndex("InstanceId");
237 
238  b.HasIndex("UserId", "InstanceId")
239  .IsUnique();
240 
241  b.ToTable("InstanceUsers");
242  });
243 
244  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
245  {
246  b.Property<long>("Id")
247  .ValueGeneratedOnAdd();
248 
249  b.Property<ulong?>("CancelRight");
250 
251  b.Property<ulong?>("CancelRightsType");
252 
253  b.Property<bool?>("Cancelled")
254  .IsRequired();
255 
256  b.Property<long?>("CancelledById");
257 
258  b.Property<string>("Description")
259  .IsRequired();
260 
261  b.Property<string>("ExceptionDetails");
262 
263  b.Property<long>("InstanceId");
264 
265  b.Property<DateTimeOffset?>("StartedAt")
266  .IsRequired();
267 
268  b.Property<long>("StartedById");
269 
270  b.Property<DateTimeOffset?>("StoppedAt");
271 
272  b.HasKey("Id");
273 
274  b.HasIndex("CancelledById");
275 
276  b.HasIndex("InstanceId");
277 
278  b.HasIndex("StartedById");
279 
280  b.ToTable("Jobs");
281  });
282 
283  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
284  {
285  b.Property<long>("Id")
286  .ValueGeneratedOnAdd();
287 
288  b.Property<string>("AccessIdentifier")
289  .IsRequired();
290 
291  b.Property<string>("ChatChannelsJson")
292  .IsRequired();
293 
294  b.Property<string>("ChatCommandsJson")
295  .IsRequired();
296 
297  b.Property<long?>("CompileJobId");
298 
299  b.Property<bool>("IsPrimary");
300 
301  b.Property<ushort>("Port");
302 
303  b.Property<int>("ProcessId");
304 
305  b.Property<int>("RebootState");
306 
307  b.Property<string>("ServerCommandsJson")
308  .IsRequired();
309 
310  b.HasKey("Id");
311 
312  b.HasIndex("CompileJobId");
313 
314  b.ToTable("ReattachInformations");
315  });
316 
317  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
318  {
319  b.Property<long>("Id")
320  .ValueGeneratedOnAdd();
321 
322  b.Property<string>("AccessToken");
323 
324  b.Property<string>("AccessUser");
325 
326  b.Property<bool?>("AutoUpdatesKeepTestMerges")
327  .IsRequired();
328 
329  b.Property<bool?>("AutoUpdatesSynchronize")
330  .IsRequired();
331 
332  b.Property<string>("CommitterEmail")
333  .IsRequired();
334 
335  b.Property<string>("CommitterName")
336  .IsRequired();
337 
338  b.Property<long>("InstanceId");
339 
340  b.Property<bool?>("PushTestMergeCommits")
341  .IsRequired();
342 
343  b.Property<bool?>("ShowTestMergeCommitters")
344  .IsRequired();
345 
346  b.HasKey("Id");
347 
348  b.HasIndex("InstanceId")
349  .IsUnique();
350 
351  b.ToTable("RepositorySettings");
352  });
353 
354  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
355  {
356  b.Property<long>("Id")
357  .ValueGeneratedOnAdd();
358 
359  b.Property<long>("RevisionInformationId");
360 
361  b.Property<long>("TestMergeId");
362 
363  b.HasKey("Id");
364 
365  b.HasIndex("RevisionInformationId");
366 
367  b.HasIndex("TestMergeId");
368 
369  b.ToTable("RevInfoTestMerges");
370  });
371 
372  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
373  {
374  b.Property<long>("Id")
375  .ValueGeneratedOnAdd();
376 
377  b.Property<string>("CommitSha")
378  .IsRequired()
379  .HasMaxLength(40);
380 
381  b.Property<long>("InstanceId");
382 
383  b.Property<string>("OriginCommitSha")
384  .IsRequired()
385  .HasMaxLength(40);
386 
387  b.HasKey("Id");
388 
389  b.HasIndex("CommitSha")
390  .IsUnique();
391 
392  b.HasIndex("InstanceId");
393 
394  b.ToTable("RevisionInformations");
395  });
396 
397  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
398  {
399  b.Property<long>("Id")
400  .ValueGeneratedOnAdd();
401 
402  b.Property<string>("Author")
403  .IsRequired();
404 
405  b.Property<string>("BodyAtMerge")
406  .IsRequired();
407 
408  b.Property<string>("Comment");
409 
410  b.Property<DateTimeOffset>("MergedAt");
411 
412  b.Property<long>("MergedById");
413 
414  b.Property<int?>("Number")
415  .IsRequired();
416 
417  b.Property<long?>("PrimaryRevisionInformationId")
418  .IsRequired();
419 
420  b.Property<string>("PullRequestRevision")
421  .IsRequired();
422 
423  b.Property<string>("TitleAtMerge")
424  .IsRequired();
425 
426  b.Property<string>("Url")
427  .IsRequired();
428 
429  b.HasKey("Id");
430 
431  b.HasIndex("MergedById");
432 
433  b.HasIndex("PrimaryRevisionInformationId")
434  .IsUnique();
435 
436  b.ToTable("TestMerges");
437  });
438 
439  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
440  {
441  b.Property<long>("Id")
442  .ValueGeneratedOnAdd();
443 
444  b.Property<ulong>("AdministrationRights");
445 
446  b.Property<string>("CanonicalName")
447  .IsRequired();
448 
449  b.Property<DateTimeOffset?>("CreatedAt")
450  .IsRequired();
451 
452  b.Property<long?>("CreatedById");
453 
454  b.Property<bool?>("Enabled")
455  .IsRequired();
456 
457  b.Property<ulong>("InstanceManagerRights");
458 
459  b.Property<DateTimeOffset?>("LastPasswordUpdate");
460 
461  b.Property<string>("Name")
462  .IsRequired();
463 
464  b.Property<string>("PasswordHash");
465 
466  b.Property<string>("SystemIdentifier");
467 
468  b.HasKey("Id");
469 
470  b.HasIndex("CanonicalName")
471  .IsUnique();
472 
473  b.HasIndex("CreatedById");
474 
475  b.ToTable("Users");
476  });
477 
478  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
479  {
480  b.Property<long>("Id")
481  .ValueGeneratedOnAdd();
482 
483  b.Property<long?>("AlphaId");
484 
485  b.Property<bool>("AlphaIsActive");
486 
487  b.Property<long?>("BravoId");
488 
489  b.Property<long>("InstanceId");
490 
491  b.HasKey("Id");
492 
493  b.HasIndex("AlphaId");
494 
495  b.HasIndex("BravoId");
496 
497  b.HasIndex("InstanceId")
498  .IsUnique();
499 
500  b.ToTable("WatchdogReattachInformations");
501  });
502 
503  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
504  {
505  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
506  .WithMany("ChatSettings")
507  .HasForeignKey("InstanceId")
508  .OnDelete(DeleteBehavior.Cascade);
509  });
510 
511  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
512  {
513  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
514  .WithMany("Channels")
515  .HasForeignKey("ChatSettingsId")
516  .OnDelete(DeleteBehavior.Cascade);
517  });
518 
519  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
520  {
521  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
522  .WithOne()
523  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
524  .OnDelete(DeleteBehavior.Restrict);
525 
526  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
527  .WithMany("CompileJobs")
528  .HasForeignKey("RevisionInformationId")
529  .OnDelete(DeleteBehavior.Cascade);
530  });
531 
532  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
533  {
534  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
535  .WithOne("DreamDaemonSettings")
536  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
537  .OnDelete(DeleteBehavior.Cascade);
538  });
539 
540  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
541  {
542  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
543  .WithOne("DreamMakerSettings")
544  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
545  .OnDelete(DeleteBehavior.Cascade);
546  });
547 
548  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
549  {
550  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
551  .WithMany("InstanceUsers")
552  .HasForeignKey("InstanceId")
553  .OnDelete(DeleteBehavior.Cascade);
554 
555  b.HasOne("Tgstation.Server.Host.Models.User")
556  .WithMany("InstanceUsers")
557  .HasForeignKey("UserId")
558  .OnDelete(DeleteBehavior.Cascade);
559  });
560 
561  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
562  {
563  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
564  .WithMany()
565  .HasForeignKey("CancelledById");
566 
567  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
568  .WithMany("Jobs")
569  .HasForeignKey("InstanceId")
570  .OnDelete(DeleteBehavior.Cascade);
571 
572  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
573  .WithMany()
574  .HasForeignKey("StartedById")
575  .OnDelete(DeleteBehavior.Cascade);
576  });
577 
578  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
579  {
580  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
581  .WithMany()
582  .HasForeignKey("CompileJobId");
583  });
584 
585  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
586  {
587  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
588  .WithOne("RepositorySettings")
589  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
590  .OnDelete(DeleteBehavior.Cascade);
591  });
592 
593  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
594  {
595  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
596  .WithMany("ActiveTestMerges")
597  .HasForeignKey("RevisionInformationId")
598  .OnDelete(DeleteBehavior.Cascade);
599 
600  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
601  .WithMany("RevisonInformations")
602  .HasForeignKey("TestMergeId")
603  .OnDelete(DeleteBehavior.Cascade);
604  });
605 
606  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
607  {
608  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
609  .WithMany("RevisionInformations")
610  .HasForeignKey("InstanceId")
611  .OnDelete(DeleteBehavior.Cascade);
612  });
613 
614  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
615  {
616  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
617  .WithMany("TestMerges")
618  .HasForeignKey("MergedById")
619  .OnDelete(DeleteBehavior.Restrict);
620 
621  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
622  .WithOne("PrimaryTestMerge")
623  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
624  .OnDelete(DeleteBehavior.Restrict);
625  });
626 
627  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
628  {
629  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
630  .WithMany("CreatedUsers")
631  .HasForeignKey("CreatedById");
632  });
633 
634  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
635  {
636  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
637  .WithMany()
638  .HasForeignKey("AlphaId");
639 
640  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
641  .WithMany()
642  .HasForeignKey("BravoId");
643 
644  b.HasOne("Tgstation.Server.Host.Models.Instance")
645  .WithOne("WatchdogReattachInformation")
646  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
647  .OnDelete(DeleteBehavior.Cascade);
648  });
649 #pragma warning restore 612, 618
650  }
651  }
652 }
+Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Migrations;
7 
9 {
11  [Migration("20180918204520_MYNullableAndForeignKeyCleanup")]
12  partial class MYNullableAndForeignKeyCleanup
13  {
18  protected override void BuildTargetModel(ModelBuilder modelBuilder)
19  {
20 #pragma warning disable 612, 618
21  modelBuilder
22  .HasAnnotation("ProductVersion", "2.1.3-rtm-32065")
23  .HasAnnotation("Relational:MaxIdentifierLength", 64);
24 
25  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
26  {
27  b.Property<long>("Id")
28  .ValueGeneratedOnAdd();
29 
30  b.Property<string>("ConnectionString")
31  .IsRequired();
32 
33  b.Property<bool?>("Enabled");
34 
35  b.Property<long>("InstanceId");
36 
37  b.Property<string>("Name")
38  .IsRequired();
39 
40  b.Property<int?>("Provider");
41 
42  b.HasKey("Id");
43 
44  b.HasIndex("InstanceId");
45 
46  b.HasIndex("Name")
47  .IsUnique();
48 
49  b.ToTable("ChatBots");
50  });
51 
52  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
53  {
54  b.Property<long>("Id")
55  .ValueGeneratedOnAdd();
56 
57  b.Property<long>("ChatSettingsId");
58 
59  b.Property<ulong?>("DiscordChannelId");
60 
61  b.Property<string>("IrcChannel");
62 
63  b.Property<bool?>("IsAdminChannel")
64  .IsRequired();
65 
66  b.Property<bool?>("IsUpdatesChannel")
67  .IsRequired();
68 
69  b.Property<bool?>("IsWatchdogChannel")
70  .IsRequired();
71 
72  b.Property<string>("Tag");
73 
74  b.HasKey("Id");
75 
76  b.HasIndex("ChatSettingsId", "DiscordChannelId")
77  .IsUnique();
78 
79  b.HasIndex("ChatSettingsId", "IrcChannel")
80  .IsUnique();
81 
82  b.ToTable("ChatChannels");
83  });
84 
85  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
86  {
87  b.Property<long>("Id")
88  .ValueGeneratedOnAdd();
89 
90  b.Property<string>("ByondVersion")
91  .IsRequired();
92 
93  b.Property<Guid?>("DirectoryName")
94  .IsRequired();
95 
96  b.Property<string>("DmeName")
97  .IsRequired();
98 
99  b.Property<long>("JobId");
100 
101  b.Property<int>("MinimumSecurityLevel");
102 
103  b.Property<string>("Output")
104  .IsRequired();
105 
106  b.Property<long>("RevisionInformationId");
107 
108  b.HasKey("Id");
109 
110  b.HasIndex("DirectoryName");
111 
112  b.HasIndex("JobId")
113  .IsUnique();
114 
115  b.HasIndex("RevisionInformationId");
116 
117  b.ToTable("CompileJobs");
118  });
119 
120  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
121  {
122  b.Property<long>("Id")
123  .ValueGeneratedOnAdd();
124 
125  b.Property<string>("AccessToken");
126 
127  b.Property<bool?>("AllowWebClient")
128  .IsRequired();
129 
130  b.Property<bool?>("AutoStart")
131  .IsRequired();
132 
133  b.Property<long>("InstanceId");
134 
135  b.Property<ushort?>("PrimaryPort")
136  .IsRequired();
137 
138  b.Property<int?>("ProcessId");
139 
140  b.Property<ushort?>("SecondaryPort")
141  .IsRequired();
142 
143  b.Property<int>("SecurityLevel");
144 
145  b.Property<bool?>("SoftRestart")
146  .IsRequired();
147 
148  b.Property<bool?>("SoftShutdown")
149  .IsRequired();
150 
151  b.Property<uint?>("StartupTimeout")
152  .IsRequired();
153 
154  b.HasKey("Id");
155 
156  b.HasIndex("InstanceId")
157  .IsUnique();
158 
159  b.ToTable("DreamDaemonSettings");
160  });
161 
162  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
163  {
164  b.Property<long>("Id")
165  .ValueGeneratedOnAdd();
166 
167  b.Property<ushort?>("ApiValidationPort")
168  .IsRequired();
169 
170  b.Property<int>("ApiValidationSecurityLevel");
171 
172  b.Property<long>("InstanceId");
173 
174  b.Property<string>("ProjectName");
175 
176  b.HasKey("Id");
177 
178  b.HasIndex("InstanceId")
179  .IsUnique();
180 
181  b.ToTable("DreamMakerSettings");
182  });
183 
184  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
185  {
186  b.Property<long>("Id")
187  .ValueGeneratedOnAdd();
188 
189  b.Property<uint?>("AutoUpdateInterval")
190  .IsRequired();
191 
192  b.Property<int>("ConfigurationType");
193 
194  b.Property<string>("Name")
195  .IsRequired();
196 
197  b.Property<bool?>("Online")
198  .IsRequired();
199 
200  b.Property<string>("Path")
201  .IsRequired();
202 
203  b.HasKey("Id");
204 
205  b.HasIndex("Path")
206  .IsUnique();
207 
208  b.ToTable("Instances");
209  });
210 
211  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
212  {
213  b.Property<long>("Id")
214  .ValueGeneratedOnAdd();
215 
216  b.Property<ulong>("ByondRights");
217 
218  b.Property<ulong>("ChatBotRights");
219 
220  b.Property<ulong>("ConfigurationRights");
221 
222  b.Property<ulong>("DreamDaemonRights");
223 
224  b.Property<ulong>("DreamMakerRights");
225 
226  b.Property<long>("InstanceId");
227 
228  b.Property<ulong>("InstanceUserRights");
229 
230  b.Property<ulong>("RepositoryRights");
231 
232  b.Property<long?>("UserId")
233  .IsRequired();
234 
235  b.HasKey("Id");
236 
237  b.HasIndex("InstanceId");
238 
239  b.HasIndex("UserId", "InstanceId")
240  .IsUnique();
241 
242  b.ToTable("InstanceUsers");
243  });
244 
245  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
246  {
247  b.Property<long>("Id")
248  .ValueGeneratedOnAdd();
249 
250  b.Property<ulong?>("CancelRight");
251 
252  b.Property<ulong?>("CancelRightsType");
253 
254  b.Property<bool?>("Cancelled")
255  .IsRequired();
256 
257  b.Property<long?>("CancelledById");
258 
259  b.Property<string>("Description")
260  .IsRequired();
261 
262  b.Property<string>("ExceptionDetails");
263 
264  b.Property<long>("InstanceId");
265 
266  b.Property<DateTimeOffset?>("StartedAt")
267  .IsRequired();
268 
269  b.Property<long>("StartedById");
270 
271  b.Property<DateTimeOffset?>("StoppedAt");
272 
273  b.HasKey("Id");
274 
275  b.HasIndex("CancelledById");
276 
277  b.HasIndex("InstanceId");
278 
279  b.HasIndex("StartedById");
280 
281  b.ToTable("Jobs");
282  });
283 
284  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
285  {
286  b.Property<long>("Id")
287  .ValueGeneratedOnAdd();
288 
289  b.Property<string>("AccessIdentifier")
290  .IsRequired();
291 
292  b.Property<string>("ChatChannelsJson")
293  .IsRequired();
294 
295  b.Property<string>("ChatCommandsJson")
296  .IsRequired();
297 
298  b.Property<long?>("CompileJobId");
299 
300  b.Property<bool>("IsPrimary");
301 
302  b.Property<ushort>("Port");
303 
304  b.Property<int>("ProcessId");
305 
306  b.Property<int>("RebootState");
307 
308  b.Property<string>("ServerCommandsJson")
309  .IsRequired();
310 
311  b.HasKey("Id");
312 
313  b.HasIndex("CompileJobId");
314 
315  b.ToTable("ReattachInformations");
316  });
317 
318  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
319  {
320  b.Property<long>("Id")
321  .ValueGeneratedOnAdd();
322 
323  b.Property<string>("AccessToken");
324 
325  b.Property<string>("AccessUser");
326 
327  b.Property<bool?>("AutoUpdatesKeepTestMerges")
328  .IsRequired();
329 
330  b.Property<bool?>("AutoUpdatesSynchronize")
331  .IsRequired();
332 
333  b.Property<string>("CommitterEmail")
334  .IsRequired();
335 
336  b.Property<string>("CommitterName")
337  .IsRequired();
338 
339  b.Property<long>("InstanceId");
340 
341  b.Property<bool?>("PushTestMergeCommits")
342  .IsRequired();
343 
344  b.Property<bool?>("ShowTestMergeCommitters")
345  .IsRequired();
346 
347  b.HasKey("Id");
348 
349  b.HasIndex("InstanceId")
350  .IsUnique();
351 
352  b.ToTable("RepositorySettings");
353  });
354 
355  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
356  {
357  b.Property<long>("Id")
358  .ValueGeneratedOnAdd();
359 
360  b.Property<long>("RevisionInformationId");
361 
362  b.Property<long>("TestMergeId");
363 
364  b.HasKey("Id");
365 
366  b.HasIndex("RevisionInformationId");
367 
368  b.HasIndex("TestMergeId");
369 
370  b.ToTable("RevInfoTestMerges");
371  });
372 
373  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
374  {
375  b.Property<long>("Id")
376  .ValueGeneratedOnAdd();
377 
378  b.Property<string>("CommitSha")
379  .IsRequired()
380  .HasMaxLength(40);
381 
382  b.Property<long>("InstanceId");
383 
384  b.Property<string>("OriginCommitSha")
385  .IsRequired()
386  .HasMaxLength(40);
387 
388  b.HasKey("Id");
389 
390  b.HasIndex("CommitSha")
391  .IsUnique();
392 
393  b.HasIndex("InstanceId");
394 
395  b.ToTable("RevisionInformations");
396  });
397 
398  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
399  {
400  b.Property<long>("Id")
401  .ValueGeneratedOnAdd();
402 
403  b.Property<string>("Author")
404  .IsRequired();
405 
406  b.Property<string>("BodyAtMerge")
407  .IsRequired();
408 
409  b.Property<string>("Comment");
410 
411  b.Property<DateTimeOffset>("MergedAt");
412 
413  b.Property<long>("MergedById");
414 
415  b.Property<int?>("Number")
416  .IsRequired();
417 
418  b.Property<long?>("PrimaryRevisionInformationId")
419  .IsRequired();
420 
421  b.Property<string>("PullRequestRevision")
422  .IsRequired();
423 
424  b.Property<string>("TitleAtMerge")
425  .IsRequired();
426 
427  b.Property<string>("Url")
428  .IsRequired();
429 
430  b.HasKey("Id");
431 
432  b.HasIndex("MergedById");
433 
434  b.HasIndex("PrimaryRevisionInformationId")
435  .IsUnique();
436 
437  b.ToTable("TestMerges");
438  });
439 
440  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
441  {
442  b.Property<long>("Id")
443  .ValueGeneratedOnAdd();
444 
445  b.Property<ulong>("AdministrationRights");
446 
447  b.Property<string>("CanonicalName")
448  .IsRequired();
449 
450  b.Property<DateTimeOffset?>("CreatedAt")
451  .IsRequired();
452 
453  b.Property<long?>("CreatedById");
454 
455  b.Property<bool?>("Enabled")
456  .IsRequired();
457 
458  b.Property<ulong>("InstanceManagerRights");
459 
460  b.Property<DateTimeOffset?>("LastPasswordUpdate");
461 
462  b.Property<string>("Name")
463  .IsRequired();
464 
465  b.Property<string>("PasswordHash");
466 
467  b.Property<string>("SystemIdentifier");
468 
469  b.HasKey("Id");
470 
471  b.HasIndex("CanonicalName")
472  .IsUnique();
473 
474  b.HasIndex("CreatedById");
475 
476  b.ToTable("Users");
477  });
478 
479  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
480  {
481  b.Property<long>("Id")
482  .ValueGeneratedOnAdd();
483 
484  b.Property<long?>("AlphaId");
485 
486  b.Property<bool>("AlphaIsActive");
487 
488  b.Property<long?>("BravoId");
489 
490  b.Property<long>("InstanceId");
491 
492  b.HasKey("Id");
493 
494  b.HasIndex("AlphaId");
495 
496  b.HasIndex("BravoId");
497 
498  b.HasIndex("InstanceId")
499  .IsUnique();
500 
501  b.ToTable("WatchdogReattachInformations");
502  });
503 
504  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
505  {
506  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
507  .WithMany("ChatSettings")
508  .HasForeignKey("InstanceId")
509  .OnDelete(DeleteBehavior.Cascade);
510  });
511 
512  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
513  {
514  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
515  .WithMany("Channels")
516  .HasForeignKey("ChatSettingsId")
517  .OnDelete(DeleteBehavior.Cascade);
518  });
519 
520  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
521  {
522  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
523  .WithOne()
524  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
525  .OnDelete(DeleteBehavior.Restrict);
526 
527  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
528  .WithMany("CompileJobs")
529  .HasForeignKey("RevisionInformationId")
530  .OnDelete(DeleteBehavior.Cascade);
531  });
532 
533  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
534  {
535  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
536  .WithOne("DreamDaemonSettings")
537  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
538  .OnDelete(DeleteBehavior.Cascade);
539  });
540 
541  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
542  {
543  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
544  .WithOne("DreamMakerSettings")
545  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
546  .OnDelete(DeleteBehavior.Cascade);
547  });
548 
549  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
550  {
551  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
552  .WithMany("InstanceUsers")
553  .HasForeignKey("InstanceId")
554  .OnDelete(DeleteBehavior.Cascade);
555 
556  b.HasOne("Tgstation.Server.Host.Models.User")
557  .WithMany("InstanceUsers")
558  .HasForeignKey("UserId")
559  .OnDelete(DeleteBehavior.Cascade);
560  });
561 
562  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
563  {
564  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
565  .WithMany()
566  .HasForeignKey("CancelledById");
567 
568  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
569  .WithMany("Jobs")
570  .HasForeignKey("InstanceId")
571  .OnDelete(DeleteBehavior.Cascade);
572 
573  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
574  .WithMany()
575  .HasForeignKey("StartedById")
576  .OnDelete(DeleteBehavior.Cascade);
577  });
578 
579  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
580  {
581  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
582  .WithMany()
583  .HasForeignKey("CompileJobId");
584  });
585 
586  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
587  {
588  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
589  .WithOne("RepositorySettings")
590  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
591  .OnDelete(DeleteBehavior.Cascade);
592  });
593 
594  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
595  {
596  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
597  .WithMany("ActiveTestMerges")
598  .HasForeignKey("RevisionInformationId")
599  .OnDelete(DeleteBehavior.Cascade);
600 
601  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
602  .WithMany("RevisonInformations")
603  .HasForeignKey("TestMergeId")
604  .OnDelete(DeleteBehavior.Cascade);
605  });
606 
607  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
608  {
609  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
610  .WithMany("RevisionInformations")
611  .HasForeignKey("InstanceId")
612  .OnDelete(DeleteBehavior.Cascade);
613  });
614 
615  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
616  {
617  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
618  .WithMany("TestMerges")
619  .HasForeignKey("MergedById")
620  .OnDelete(DeleteBehavior.Restrict);
621 
622  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
623  .WithOne("PrimaryTestMerge")
624  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
625  .OnDelete(DeleteBehavior.Restrict);
626  });
627 
628  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
629  {
630  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
631  .WithMany("CreatedUsers")
632  .HasForeignKey("CreatedById");
633  });
634 
635  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
636  {
637  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
638  .WithMany()
639  .HasForeignKey("AlphaId");
640 
641  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
642  .WithMany()
643  .HasForeignKey("BravoId");
644 
645  b.HasOne("Tgstation.Server.Host.Models.Instance")
646  .WithOne("WatchdogReattachInformation")
647  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
648  .OnDelete(DeleteBehavior.Cascade);
649  });
650 #pragma warning restore 612, 618
651  }
652  }
653 }
- +
DatabaseContext<TParentContext> for MySQL
+ + + + +
-Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Metadata;
6 using Microsoft.EntityFrameworkCore.Migrations;
7 using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
8 
10 {
11  [DbContext(typeof(SqlServerDatabaseContext))]
12  [Migration("20180918205224_MSNullableAndForeignKeyCleanup")]
13  partial class MSNullableAndForeignKeyCleanup
14  {
19  protected override void BuildTargetModel(ModelBuilder modelBuilder)
20  {
21 #pragma warning disable 612, 618
22  modelBuilder
23  .HasAnnotation("ProductVersion", "2.1.3-rtm-32065")
24  .HasAnnotation("Relational:MaxIdentifierLength", 128)
25  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
26 
27  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
28  {
29  b.Property<long>("Id")
30  .ValueGeneratedOnAdd()
31  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
32 
33  b.Property<string>("ConnectionString")
34  .IsRequired();
35 
36  b.Property<bool?>("Enabled");
37 
38  b.Property<long>("InstanceId");
39 
40  b.Property<string>("Name")
41  .IsRequired();
42 
43  b.Property<int?>("Provider");
44 
45  b.HasKey("Id");
46 
47  b.HasIndex("InstanceId");
48 
49  b.HasIndex("Name")
50  .IsUnique();
51 
52  b.ToTable("ChatBots");
53  });
54 
55  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
56  {
57  b.Property<long>("Id")
58  .ValueGeneratedOnAdd()
59  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
60 
61  b.Property<long>("ChatSettingsId");
62 
63  b.Property<decimal?>("DiscordChannelId")
64  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
65 
66  b.Property<string>("IrcChannel");
67 
68  b.Property<bool?>("IsAdminChannel")
69  .IsRequired();
70 
71  b.Property<bool?>("IsUpdatesChannel")
72  .IsRequired();
73 
74  b.Property<bool?>("IsWatchdogChannel")
75  .IsRequired();
76 
77  b.Property<string>("Tag");
78 
79  b.HasKey("Id");
80 
81  b.HasIndex("ChatSettingsId", "DiscordChannelId")
82  .IsUnique()
83  .HasFilter("[DiscordChannelId] IS NOT NULL");
84 
85  b.HasIndex("ChatSettingsId", "IrcChannel")
86  .IsUnique()
87  .HasFilter("[IrcChannel] IS NOT NULL");
88 
89  b.ToTable("ChatChannels");
90  });
91 
92  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
93  {
94  b.Property<long>("Id")
95  .ValueGeneratedOnAdd()
96  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
97 
98  b.Property<string>("ByondVersion")
99  .IsRequired();
100 
101  b.Property<Guid?>("DirectoryName")
102  .IsRequired();
103 
104  b.Property<string>("DmeName")
105  .IsRequired();
106 
107  b.Property<long>("JobId");
108 
109  b.Property<int>("MinimumSecurityLevel");
110 
111  b.Property<string>("Output")
112  .IsRequired();
113 
114  b.Property<long>("RevisionInformationId");
115 
116  b.HasKey("Id");
117 
118  b.HasIndex("DirectoryName");
119 
120  b.HasIndex("JobId")
121  .IsUnique();
122 
123  b.HasIndex("RevisionInformationId");
124 
125  b.ToTable("CompileJobs");
126  });
127 
128  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
129  {
130  b.Property<long>("Id")
131  .ValueGeneratedOnAdd()
132  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
133 
134  b.Property<string>("AccessToken");
135 
136  b.Property<bool?>("AllowWebClient")
137  .IsRequired();
138 
139  b.Property<bool?>("AutoStart")
140  .IsRequired();
141 
142  b.Property<long>("InstanceId");
143 
144  b.Property<int>("PrimaryPort");
145 
146  b.Property<int?>("ProcessId");
147 
148  b.Property<int>("SecondaryPort");
149 
150  b.Property<int>("SecurityLevel");
151 
152  b.Property<bool?>("SoftRestart")
153  .IsRequired();
154 
155  b.Property<bool?>("SoftShutdown")
156  .IsRequired();
157 
158  b.Property<long>("StartupTimeout");
159 
160  b.HasKey("Id");
161 
162  b.HasIndex("InstanceId")
163  .IsUnique();
164 
165  b.ToTable("DreamDaemonSettings");
166  });
167 
168  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
169  {
170  b.Property<long>("Id")
171  .ValueGeneratedOnAdd()
172  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
173 
174  b.Property<int>("ApiValidationPort");
175 
176  b.Property<int>("ApiValidationSecurityLevel");
177 
178  b.Property<long>("InstanceId");
179 
180  b.Property<string>("ProjectName");
181 
182  b.HasKey("Id");
183 
184  b.HasIndex("InstanceId")
185  .IsUnique();
186 
187  b.ToTable("DreamMakerSettings");
188  });
189 
190  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
191  {
192  b.Property<long>("Id")
193  .ValueGeneratedOnAdd()
194  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
195 
196  b.Property<long>("AutoUpdateInterval");
197 
198  b.Property<int>("ConfigurationType");
199 
200  b.Property<string>("Name")
201  .IsRequired();
202 
203  b.Property<bool?>("Online")
204  .IsRequired();
205 
206  b.Property<string>("Path")
207  .IsRequired();
208 
209  b.HasKey("Id");
210 
211  b.HasIndex("Path")
212  .IsUnique();
213 
214  b.ToTable("Instances");
215  });
216 
217  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
218  {
219  b.Property<long>("Id")
220  .ValueGeneratedOnAdd()
221  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
222 
223  b.Property<decimal>("ByondRights")
224  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
225 
226  b.Property<decimal>("ChatBotRights")
227  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
228 
229  b.Property<decimal>("ConfigurationRights")
230  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
231 
232  b.Property<decimal>("DreamDaemonRights")
233  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
234 
235  b.Property<decimal>("DreamMakerRights")
236  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
237 
238  b.Property<long>("InstanceId");
239 
240  b.Property<decimal>("InstanceUserRights")
241  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
242 
243  b.Property<decimal>("RepositoryRights")
244  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
245 
246  b.Property<long?>("UserId")
247  .IsRequired();
248 
249  b.HasKey("Id");
250 
251  b.HasIndex("InstanceId");
252 
253  b.HasIndex("UserId", "InstanceId")
254  .IsUnique();
255 
256  b.ToTable("InstanceUsers");
257  });
258 
259  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
260  {
261  b.Property<long>("Id")
262  .ValueGeneratedOnAdd()
263  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
264 
265  b.Property<decimal?>("CancelRight")
266  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
267 
268  b.Property<decimal?>("CancelRightsType")
269  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
270 
271  b.Property<bool?>("Cancelled")
272  .IsRequired();
273 
274  b.Property<long?>("CancelledById");
275 
276  b.Property<string>("Description")
277  .IsRequired();
278 
279  b.Property<string>("ExceptionDetails");
280 
281  b.Property<long>("InstanceId");
282 
283  b.Property<DateTimeOffset?>("StartedAt")
284  .IsRequired();
285 
286  b.Property<long>("StartedById");
287 
288  b.Property<DateTimeOffset?>("StoppedAt");
289 
290  b.HasKey("Id");
291 
292  b.HasIndex("CancelledById");
293 
294  b.HasIndex("InstanceId");
295 
296  b.HasIndex("StartedById");
297 
298  b.ToTable("Jobs");
299  });
300 
301  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
302  {
303  b.Property<long>("Id")
304  .ValueGeneratedOnAdd()
305  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
306 
307  b.Property<string>("AccessIdentifier")
308  .IsRequired();
309 
310  b.Property<string>("ChatChannelsJson")
311  .IsRequired();
312 
313  b.Property<string>("ChatCommandsJson")
314  .IsRequired();
315 
316  b.Property<long?>("CompileJobId");
317 
318  b.Property<bool>("IsPrimary");
319 
320  b.Property<int>("Port");
321 
322  b.Property<int>("ProcessId");
323 
324  b.Property<int>("RebootState");
325 
326  b.Property<string>("ServerCommandsJson")
327  .IsRequired();
328 
329  b.HasKey("Id");
330 
331  b.HasIndex("CompileJobId");
332 
333  b.ToTable("ReattachInformations");
334  });
335 
336  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
337  {
338  b.Property<long>("Id")
339  .ValueGeneratedOnAdd()
340  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
341 
342  b.Property<string>("AccessToken");
343 
344  b.Property<string>("AccessUser");
345 
346  b.Property<bool?>("AutoUpdatesKeepTestMerges")
347  .IsRequired();
348 
349  b.Property<bool?>("AutoUpdatesSynchronize")
350  .IsRequired();
351 
352  b.Property<string>("CommitterEmail")
353  .IsRequired();
354 
355  b.Property<string>("CommitterName")
356  .IsRequired();
357 
358  b.Property<long>("InstanceId");
359 
360  b.Property<bool?>("PushTestMergeCommits")
361  .IsRequired();
362 
363  b.Property<bool?>("ShowTestMergeCommitters")
364  .IsRequired();
365 
366  b.HasKey("Id");
367 
368  b.HasIndex("InstanceId")
369  .IsUnique();
370 
371  b.ToTable("RepositorySettings");
372  });
373 
374  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
375  {
376  b.Property<long>("Id")
377  .ValueGeneratedOnAdd()
378  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
379 
380  b.Property<long>("RevisionInformationId");
381 
382  b.Property<long>("TestMergeId");
383 
384  b.HasKey("Id");
385 
386  b.HasIndex("RevisionInformationId");
387 
388  b.HasIndex("TestMergeId");
389 
390  b.ToTable("RevInfoTestMerges");
391  });
392 
393  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
394  {
395  b.Property<long>("Id")
396  .ValueGeneratedOnAdd()
397  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
398 
399  b.Property<string>("CommitSha")
400  .IsRequired()
401  .HasMaxLength(40);
402 
403  b.Property<long>("InstanceId");
404 
405  b.Property<string>("OriginCommitSha")
406  .IsRequired()
407  .HasMaxLength(40);
408 
409  b.HasKey("Id");
410 
411  b.HasIndex("CommitSha")
412  .IsUnique();
413 
414  b.HasIndex("InstanceId");
415 
416  b.ToTable("RevisionInformations");
417  });
418 
419  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
420  {
421  b.Property<long>("Id")
422  .ValueGeneratedOnAdd()
423  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
424 
425  b.Property<string>("Author")
426  .IsRequired();
427 
428  b.Property<string>("BodyAtMerge")
429  .IsRequired();
430 
431  b.Property<string>("Comment");
432 
433  b.Property<DateTimeOffset>("MergedAt");
434 
435  b.Property<long>("MergedById");
436 
437  b.Property<int?>("Number")
438  .IsRequired();
439 
440  b.Property<long?>("PrimaryRevisionInformationId")
441  .IsRequired();
442 
443  b.Property<string>("PullRequestRevision")
444  .IsRequired();
445 
446  b.Property<string>("TitleAtMerge")
447  .IsRequired();
448 
449  b.Property<string>("Url")
450  .IsRequired();
451 
452  b.HasKey("Id");
453 
454  b.HasIndex("MergedById");
455 
456  b.HasIndex("PrimaryRevisionInformationId")
457  .IsUnique();
458 
459  b.ToTable("TestMerges");
460  });
461 
462  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
463  {
464  b.Property<long>("Id")
465  .ValueGeneratedOnAdd()
466  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
467 
468  b.Property<decimal>("AdministrationRights")
469  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
470 
471  b.Property<string>("CanonicalName")
472  .IsRequired();
473 
474  b.Property<DateTimeOffset?>("CreatedAt")
475  .IsRequired();
476 
477  b.Property<long?>("CreatedById");
478 
479  b.Property<bool?>("Enabled")
480  .IsRequired();
481 
482  b.Property<decimal>("InstanceManagerRights")
483  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
484 
485  b.Property<DateTimeOffset?>("LastPasswordUpdate");
486 
487  b.Property<string>("Name")
488  .IsRequired();
489 
490  b.Property<string>("PasswordHash");
491 
492  b.Property<string>("SystemIdentifier");
493 
494  b.HasKey("Id");
495 
496  b.HasIndex("CanonicalName")
497  .IsUnique();
498 
499  b.HasIndex("CreatedById");
500 
501  b.ToTable("Users");
502  });
503 
504  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
505  {
506  b.Property<long>("Id")
507  .ValueGeneratedOnAdd()
508  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
509 
510  b.Property<long?>("AlphaId");
511 
512  b.Property<bool>("AlphaIsActive");
513 
514  b.Property<long?>("BravoId");
515 
516  b.Property<long>("InstanceId");
517 
518  b.HasKey("Id");
519 
520  b.HasIndex("AlphaId");
521 
522  b.HasIndex("BravoId");
523 
524  b.HasIndex("InstanceId")
525  .IsUnique();
526 
527  b.ToTable("WatchdogReattachInformations");
528  });
529 
530  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
531  {
532  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
533  .WithMany("ChatSettings")
534  .HasForeignKey("InstanceId")
535  .OnDelete(DeleteBehavior.Cascade);
536  });
537 
538  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
539  {
540  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
541  .WithMany("Channels")
542  .HasForeignKey("ChatSettingsId")
543  .OnDelete(DeleteBehavior.Cascade);
544  });
545 
546  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
547  {
548  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
549  .WithOne()
550  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
551  .OnDelete(DeleteBehavior.Restrict);
552 
553  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
554  .WithMany("CompileJobs")
555  .HasForeignKey("RevisionInformationId")
556  .OnDelete(DeleteBehavior.Cascade);
557  });
558 
559  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
560  {
561  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
562  .WithOne("DreamDaemonSettings")
563  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
564  .OnDelete(DeleteBehavior.Cascade);
565  });
566 
567  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
568  {
569  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
570  .WithOne("DreamMakerSettings")
571  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
572  .OnDelete(DeleteBehavior.Cascade);
573  });
574 
575  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
576  {
577  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
578  .WithMany("InstanceUsers")
579  .HasForeignKey("InstanceId")
580  .OnDelete(DeleteBehavior.Cascade);
581 
582  b.HasOne("Tgstation.Server.Host.Models.User")
583  .WithMany("InstanceUsers")
584  .HasForeignKey("UserId")
585  .OnDelete(DeleteBehavior.Cascade);
586  });
587 
588  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
589  {
590  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
591  .WithMany()
592  .HasForeignKey("CancelledById");
593 
594  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
595  .WithMany("Jobs")
596  .HasForeignKey("InstanceId")
597  .OnDelete(DeleteBehavior.Cascade);
598 
599  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
600  .WithMany()
601  .HasForeignKey("StartedById")
602  .OnDelete(DeleteBehavior.Cascade);
603  });
604 
605  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
606  {
607  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
608  .WithMany()
609  .HasForeignKey("CompileJobId");
610  });
611 
612  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
613  {
614  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
615  .WithOne("RepositorySettings")
616  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
617  .OnDelete(DeleteBehavior.Cascade);
618  });
619 
620  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
621  {
622  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
623  .WithMany("ActiveTestMerges")
624  .HasForeignKey("RevisionInformationId")
625  .OnDelete(DeleteBehavior.Cascade);
626 
627  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
628  .WithMany("RevisonInformations")
629  .HasForeignKey("TestMergeId")
630  .OnDelete(DeleteBehavior.Cascade);
631  });
632 
633  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
634  {
635  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
636  .WithMany("RevisionInformations")
637  .HasForeignKey("InstanceId")
638  .OnDelete(DeleteBehavior.Cascade);
639  });
640 
641  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
642  {
643  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
644  .WithMany("TestMerges")
645  .HasForeignKey("MergedById")
646  .OnDelete(DeleteBehavior.Restrict);
647 
648  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
649  .WithOne("PrimaryTestMerge")
650  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
651  .OnDelete(DeleteBehavior.Restrict);
652  });
653 
654  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
655  {
656  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
657  .WithMany("CreatedUsers")
658  .HasForeignKey("CreatedById");
659  });
660 
661  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
662  {
663  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
664  .WithMany()
665  .HasForeignKey("AlphaId");
666 
667  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
668  .WithMany()
669  .HasForeignKey("BravoId");
670 
671  b.HasOne("Tgstation.Server.Host.Models.Instance")
672  .WithOne("WatchdogReattachInformation")
673  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
674  .OnDelete(DeleteBehavior.Cascade);
675  });
676 #pragma warning restore 612, 618
677  }
678  }
679 }
+Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Metadata;
6 using Microsoft.EntityFrameworkCore.Migrations;
7 using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
9 
11 {
13  [Migration("20180918205224_MSNullableAndForeignKeyCleanup")]
14  partial class MSNullableAndForeignKeyCleanup
15  {
20  protected override void BuildTargetModel(ModelBuilder modelBuilder)
21  {
22 #pragma warning disable 612, 618
23  modelBuilder
24  .HasAnnotation("ProductVersion", "2.1.3-rtm-32065")
25  .HasAnnotation("Relational:MaxIdentifierLength", 128)
26  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
27 
28  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
29  {
30  b.Property<long>("Id")
31  .ValueGeneratedOnAdd()
32  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
33 
34  b.Property<string>("ConnectionString")
35  .IsRequired();
36 
37  b.Property<bool?>("Enabled");
38 
39  b.Property<long>("InstanceId");
40 
41  b.Property<string>("Name")
42  .IsRequired();
43 
44  b.Property<int?>("Provider");
45 
46  b.HasKey("Id");
47 
48  b.HasIndex("InstanceId");
49 
50  b.HasIndex("Name")
51  .IsUnique();
52 
53  b.ToTable("ChatBots");
54  });
55 
56  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
57  {
58  b.Property<long>("Id")
59  .ValueGeneratedOnAdd()
60  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
61 
62  b.Property<long>("ChatSettingsId");
63 
64  b.Property<decimal?>("DiscordChannelId")
65  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
66 
67  b.Property<string>("IrcChannel");
68 
69  b.Property<bool?>("IsAdminChannel")
70  .IsRequired();
71 
72  b.Property<bool?>("IsUpdatesChannel")
73  .IsRequired();
74 
75  b.Property<bool?>("IsWatchdogChannel")
76  .IsRequired();
77 
78  b.Property<string>("Tag");
79 
80  b.HasKey("Id");
81 
82  b.HasIndex("ChatSettingsId", "DiscordChannelId")
83  .IsUnique()
84  .HasFilter("[DiscordChannelId] IS NOT NULL");
85 
86  b.HasIndex("ChatSettingsId", "IrcChannel")
87  .IsUnique()
88  .HasFilter("[IrcChannel] IS NOT NULL");
89 
90  b.ToTable("ChatChannels");
91  });
92 
93  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
94  {
95  b.Property<long>("Id")
96  .ValueGeneratedOnAdd()
97  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
98 
99  b.Property<string>("ByondVersion")
100  .IsRequired();
101 
102  b.Property<Guid?>("DirectoryName")
103  .IsRequired();
104 
105  b.Property<string>("DmeName")
106  .IsRequired();
107 
108  b.Property<long>("JobId");
109 
110  b.Property<int>("MinimumSecurityLevel");
111 
112  b.Property<string>("Output")
113  .IsRequired();
114 
115  b.Property<long>("RevisionInformationId");
116 
117  b.HasKey("Id");
118 
119  b.HasIndex("DirectoryName");
120 
121  b.HasIndex("JobId")
122  .IsUnique();
123 
124  b.HasIndex("RevisionInformationId");
125 
126  b.ToTable("CompileJobs");
127  });
128 
129  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
130  {
131  b.Property<long>("Id")
132  .ValueGeneratedOnAdd()
133  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
134 
135  b.Property<string>("AccessToken");
136 
137  b.Property<bool?>("AllowWebClient")
138  .IsRequired();
139 
140  b.Property<bool?>("AutoStart")
141  .IsRequired();
142 
143  b.Property<long>("InstanceId");
144 
145  b.Property<int>("PrimaryPort");
146 
147  b.Property<int?>("ProcessId");
148 
149  b.Property<int>("SecondaryPort");
150 
151  b.Property<int>("SecurityLevel");
152 
153  b.Property<bool?>("SoftRestart")
154  .IsRequired();
155 
156  b.Property<bool?>("SoftShutdown")
157  .IsRequired();
158 
159  b.Property<long>("StartupTimeout");
160 
161  b.HasKey("Id");
162 
163  b.HasIndex("InstanceId")
164  .IsUnique();
165 
166  b.ToTable("DreamDaemonSettings");
167  });
168 
169  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
170  {
171  b.Property<long>("Id")
172  .ValueGeneratedOnAdd()
173  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
174 
175  b.Property<int>("ApiValidationPort");
176 
177  b.Property<int>("ApiValidationSecurityLevel");
178 
179  b.Property<long>("InstanceId");
180 
181  b.Property<string>("ProjectName");
182 
183  b.HasKey("Id");
184 
185  b.HasIndex("InstanceId")
186  .IsUnique();
187 
188  b.ToTable("DreamMakerSettings");
189  });
190 
191  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
192  {
193  b.Property<long>("Id")
194  .ValueGeneratedOnAdd()
195  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
196 
197  b.Property<long>("AutoUpdateInterval");
198 
199  b.Property<int>("ConfigurationType");
200 
201  b.Property<string>("Name")
202  .IsRequired();
203 
204  b.Property<bool?>("Online")
205  .IsRequired();
206 
207  b.Property<string>("Path")
208  .IsRequired();
209 
210  b.HasKey("Id");
211 
212  b.HasIndex("Path")
213  .IsUnique();
214 
215  b.ToTable("Instances");
216  });
217 
218  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
219  {
220  b.Property<long>("Id")
221  .ValueGeneratedOnAdd()
222  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
223 
224  b.Property<decimal>("ByondRights")
225  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
226 
227  b.Property<decimal>("ChatBotRights")
228  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
229 
230  b.Property<decimal>("ConfigurationRights")
231  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
232 
233  b.Property<decimal>("DreamDaemonRights")
234  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
235 
236  b.Property<decimal>("DreamMakerRights")
237  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
238 
239  b.Property<long>("InstanceId");
240 
241  b.Property<decimal>("InstanceUserRights")
242  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
243 
244  b.Property<decimal>("RepositoryRights")
245  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
246 
247  b.Property<long?>("UserId")
248  .IsRequired();
249 
250  b.HasKey("Id");
251 
252  b.HasIndex("InstanceId");
253 
254  b.HasIndex("UserId", "InstanceId")
255  .IsUnique();
256 
257  b.ToTable("InstanceUsers");
258  });
259 
260  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
261  {
262  b.Property<long>("Id")
263  .ValueGeneratedOnAdd()
264  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
265 
266  b.Property<decimal?>("CancelRight")
267  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
268 
269  b.Property<decimal?>("CancelRightsType")
270  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
271 
272  b.Property<bool?>("Cancelled")
273  .IsRequired();
274 
275  b.Property<long?>("CancelledById");
276 
277  b.Property<string>("Description")
278  .IsRequired();
279 
280  b.Property<string>("ExceptionDetails");
281 
282  b.Property<long>("InstanceId");
283 
284  b.Property<DateTimeOffset?>("StartedAt")
285  .IsRequired();
286 
287  b.Property<long>("StartedById");
288 
289  b.Property<DateTimeOffset?>("StoppedAt");
290 
291  b.HasKey("Id");
292 
293  b.HasIndex("CancelledById");
294 
295  b.HasIndex("InstanceId");
296 
297  b.HasIndex("StartedById");
298 
299  b.ToTable("Jobs");
300  });
301 
302  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
303  {
304  b.Property<long>("Id")
305  .ValueGeneratedOnAdd()
306  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
307 
308  b.Property<string>("AccessIdentifier")
309  .IsRequired();
310 
311  b.Property<string>("ChatChannelsJson")
312  .IsRequired();
313 
314  b.Property<string>("ChatCommandsJson")
315  .IsRequired();
316 
317  b.Property<long?>("CompileJobId");
318 
319  b.Property<bool>("IsPrimary");
320 
321  b.Property<int>("Port");
322 
323  b.Property<int>("ProcessId");
324 
325  b.Property<int>("RebootState");
326 
327  b.Property<string>("ServerCommandsJson")
328  .IsRequired();
329 
330  b.HasKey("Id");
331 
332  b.HasIndex("CompileJobId");
333 
334  b.ToTable("ReattachInformations");
335  });
336 
337  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
338  {
339  b.Property<long>("Id")
340  .ValueGeneratedOnAdd()
341  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
342 
343  b.Property<string>("AccessToken");
344 
345  b.Property<string>("AccessUser");
346 
347  b.Property<bool?>("AutoUpdatesKeepTestMerges")
348  .IsRequired();
349 
350  b.Property<bool?>("AutoUpdatesSynchronize")
351  .IsRequired();
352 
353  b.Property<string>("CommitterEmail")
354  .IsRequired();
355 
356  b.Property<string>("CommitterName")
357  .IsRequired();
358 
359  b.Property<long>("InstanceId");
360 
361  b.Property<bool?>("PushTestMergeCommits")
362  .IsRequired();
363 
364  b.Property<bool?>("ShowTestMergeCommitters")
365  .IsRequired();
366 
367  b.HasKey("Id");
368 
369  b.HasIndex("InstanceId")
370  .IsUnique();
371 
372  b.ToTable("RepositorySettings");
373  });
374 
375  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
376  {
377  b.Property<long>("Id")
378  .ValueGeneratedOnAdd()
379  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
380 
381  b.Property<long>("RevisionInformationId");
382 
383  b.Property<long>("TestMergeId");
384 
385  b.HasKey("Id");
386 
387  b.HasIndex("RevisionInformationId");
388 
389  b.HasIndex("TestMergeId");
390 
391  b.ToTable("RevInfoTestMerges");
392  });
393 
394  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
395  {
396  b.Property<long>("Id")
397  .ValueGeneratedOnAdd()
398  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
399 
400  b.Property<string>("CommitSha")
401  .IsRequired()
402  .HasMaxLength(40);
403 
404  b.Property<long>("InstanceId");
405 
406  b.Property<string>("OriginCommitSha")
407  .IsRequired()
408  .HasMaxLength(40);
409 
410  b.HasKey("Id");
411 
412  b.HasIndex("CommitSha")
413  .IsUnique();
414 
415  b.HasIndex("InstanceId");
416 
417  b.ToTable("RevisionInformations");
418  });
419 
420  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
421  {
422  b.Property<long>("Id")
423  .ValueGeneratedOnAdd()
424  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
425 
426  b.Property<string>("Author")
427  .IsRequired();
428 
429  b.Property<string>("BodyAtMerge")
430  .IsRequired();
431 
432  b.Property<string>("Comment");
433 
434  b.Property<DateTimeOffset>("MergedAt");
435 
436  b.Property<long>("MergedById");
437 
438  b.Property<int?>("Number")
439  .IsRequired();
440 
441  b.Property<long?>("PrimaryRevisionInformationId")
442  .IsRequired();
443 
444  b.Property<string>("PullRequestRevision")
445  .IsRequired();
446 
447  b.Property<string>("TitleAtMerge")
448  .IsRequired();
449 
450  b.Property<string>("Url")
451  .IsRequired();
452 
453  b.HasKey("Id");
454 
455  b.HasIndex("MergedById");
456 
457  b.HasIndex("PrimaryRevisionInformationId")
458  .IsUnique();
459 
460  b.ToTable("TestMerges");
461  });
462 
463  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
464  {
465  b.Property<long>("Id")
466  .ValueGeneratedOnAdd()
467  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
468 
469  b.Property<decimal>("AdministrationRights")
470  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
471 
472  b.Property<string>("CanonicalName")
473  .IsRequired();
474 
475  b.Property<DateTimeOffset?>("CreatedAt")
476  .IsRequired();
477 
478  b.Property<long?>("CreatedById");
479 
480  b.Property<bool?>("Enabled")
481  .IsRequired();
482 
483  b.Property<decimal>("InstanceManagerRights")
484  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
485 
486  b.Property<DateTimeOffset?>("LastPasswordUpdate");
487 
488  b.Property<string>("Name")
489  .IsRequired();
490 
491  b.Property<string>("PasswordHash");
492 
493  b.Property<string>("SystemIdentifier");
494 
495  b.HasKey("Id");
496 
497  b.HasIndex("CanonicalName")
498  .IsUnique();
499 
500  b.HasIndex("CreatedById");
501 
502  b.ToTable("Users");
503  });
504 
505  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
506  {
507  b.Property<long>("Id")
508  .ValueGeneratedOnAdd()
509  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
510 
511  b.Property<long?>("AlphaId");
512 
513  b.Property<bool>("AlphaIsActive");
514 
515  b.Property<long?>("BravoId");
516 
517  b.Property<long>("InstanceId");
518 
519  b.HasKey("Id");
520 
521  b.HasIndex("AlphaId");
522 
523  b.HasIndex("BravoId");
524 
525  b.HasIndex("InstanceId")
526  .IsUnique();
527 
528  b.ToTable("WatchdogReattachInformations");
529  });
530 
531  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
532  {
533  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
534  .WithMany("ChatSettings")
535  .HasForeignKey("InstanceId")
536  .OnDelete(DeleteBehavior.Cascade);
537  });
538 
539  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
540  {
541  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
542  .WithMany("Channels")
543  .HasForeignKey("ChatSettingsId")
544  .OnDelete(DeleteBehavior.Cascade);
545  });
546 
547  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
548  {
549  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
550  .WithOne()
551  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
552  .OnDelete(DeleteBehavior.Restrict);
553 
554  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
555  .WithMany("CompileJobs")
556  .HasForeignKey("RevisionInformationId")
557  .OnDelete(DeleteBehavior.Cascade);
558  });
559 
560  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
561  {
562  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
563  .WithOne("DreamDaemonSettings")
564  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
565  .OnDelete(DeleteBehavior.Cascade);
566  });
567 
568  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
569  {
570  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
571  .WithOne("DreamMakerSettings")
572  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
573  .OnDelete(DeleteBehavior.Cascade);
574  });
575 
576  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
577  {
578  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
579  .WithMany("InstanceUsers")
580  .HasForeignKey("InstanceId")
581  .OnDelete(DeleteBehavior.Cascade);
582 
583  b.HasOne("Tgstation.Server.Host.Models.User")
584  .WithMany("InstanceUsers")
585  .HasForeignKey("UserId")
586  .OnDelete(DeleteBehavior.Cascade);
587  });
588 
589  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
590  {
591  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
592  .WithMany()
593  .HasForeignKey("CancelledById");
594 
595  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
596  .WithMany("Jobs")
597  .HasForeignKey("InstanceId")
598  .OnDelete(DeleteBehavior.Cascade);
599 
600  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
601  .WithMany()
602  .HasForeignKey("StartedById")
603  .OnDelete(DeleteBehavior.Cascade);
604  });
605 
606  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
607  {
608  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
609  .WithMany()
610  .HasForeignKey("CompileJobId");
611  });
612 
613  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
614  {
615  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
616  .WithOne("RepositorySettings")
617  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
618  .OnDelete(DeleteBehavior.Cascade);
619  });
620 
621  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
622  {
623  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
624  .WithMany("ActiveTestMerges")
625  .HasForeignKey("RevisionInformationId")
626  .OnDelete(DeleteBehavior.Cascade);
627 
628  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
629  .WithMany("RevisonInformations")
630  .HasForeignKey("TestMergeId")
631  .OnDelete(DeleteBehavior.Cascade);
632  });
633 
634  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
635  {
636  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
637  .WithMany("RevisionInformations")
638  .HasForeignKey("InstanceId")
639  .OnDelete(DeleteBehavior.Cascade);
640  });
641 
642  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
643  {
644  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
645  .WithMany("TestMerges")
646  .HasForeignKey("MergedById")
647  .OnDelete(DeleteBehavior.Restrict);
648 
649  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
650  .WithOne("PrimaryTestMerge")
651  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
652  .OnDelete(DeleteBehavior.Restrict);
653  });
654 
655  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
656  {
657  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
658  .WithMany("CreatedUsers")
659  .HasForeignKey("CreatedById");
660  });
661 
662  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
663  {
664  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
665  .WithMany()
666  .HasForeignKey("AlphaId");
667 
668  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
669  .WithMany()
670  .HasForeignKey("BravoId");
671 
672  b.HasOne("Tgstation.Server.Host.Models.Instance")
673  .WithOne("WatchdogReattachInformation")
674  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
675  .OnDelete(DeleteBehavior.Cascade);
676  });
677 #pragma warning restore 612, 618
678  }
679  }
680 }
- + + +
DatabaseContext<TParentContext> for Sqlserver
+ + +
-Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Metadata;
6 using Microsoft.EntityFrameworkCore.Migrations;
7 using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
8 
10 {
11  [DbContext(typeof(SqlServerDatabaseContext))]
12  [Migration("20180926033145_MSReattachCompileJobRequired")]
13  partial class MSReattachCompileJobRequired
14  {
19  protected override void BuildTargetModel(ModelBuilder modelBuilder)
20  {
21 #pragma warning disable 612, 618
22  modelBuilder
23  .HasAnnotation("ProductVersion", "2.1.3-rtm-32065")
24  .HasAnnotation("Relational:MaxIdentifierLength", 128)
25  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
26 
27  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
28  {
29  b.Property<long>("Id")
30  .ValueGeneratedOnAdd()
31  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
32 
33  b.Property<string>("ConnectionString")
34  .IsRequired();
35 
36  b.Property<bool?>("Enabled");
37 
38  b.Property<long>("InstanceId");
39 
40  b.Property<string>("Name")
41  .IsRequired();
42 
43  b.Property<int?>("Provider");
44 
45  b.HasKey("Id");
46 
47  b.HasIndex("InstanceId");
48 
49  b.HasIndex("Name")
50  .IsUnique();
51 
52  b.ToTable("ChatBots");
53  });
54 
55  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
56  {
57  b.Property<long>("Id")
58  .ValueGeneratedOnAdd()
59  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
60 
61  b.Property<long>("ChatSettingsId");
62 
63  b.Property<decimal?>("DiscordChannelId")
64  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
65 
66  b.Property<string>("IrcChannel");
67 
68  b.Property<bool?>("IsAdminChannel")
69  .IsRequired();
70 
71  b.Property<bool?>("IsUpdatesChannel")
72  .IsRequired();
73 
74  b.Property<bool?>("IsWatchdogChannel")
75  .IsRequired();
76 
77  b.Property<string>("Tag");
78 
79  b.HasKey("Id");
80 
81  b.HasIndex("ChatSettingsId", "DiscordChannelId")
82  .IsUnique()
83  .HasFilter("[DiscordChannelId] IS NOT NULL");
84 
85  b.HasIndex("ChatSettingsId", "IrcChannel")
86  .IsUnique()
87  .HasFilter("[IrcChannel] IS NOT NULL");
88 
89  b.ToTable("ChatChannels");
90  });
91 
92  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
93  {
94  b.Property<long>("Id")
95  .ValueGeneratedOnAdd()
96  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
97 
98  b.Property<string>("ByondVersion")
99  .IsRequired();
100 
101  b.Property<Guid?>("DirectoryName")
102  .IsRequired();
103 
104  b.Property<string>("DmeName")
105  .IsRequired();
106 
107  b.Property<long>("JobId");
108 
109  b.Property<int>("MinimumSecurityLevel");
110 
111  b.Property<string>("Output")
112  .IsRequired();
113 
114  b.Property<long>("RevisionInformationId");
115 
116  b.HasKey("Id");
117 
118  b.HasIndex("DirectoryName");
119 
120  b.HasIndex("JobId")
121  .IsUnique();
122 
123  b.HasIndex("RevisionInformationId");
124 
125  b.ToTable("CompileJobs");
126  });
127 
128  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
129  {
130  b.Property<long>("Id")
131  .ValueGeneratedOnAdd()
132  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
133 
134  b.Property<string>("AccessToken");
135 
136  b.Property<bool?>("AllowWebClient")
137  .IsRequired();
138 
139  b.Property<bool?>("AutoStart")
140  .IsRequired();
141 
142  b.Property<long>("InstanceId");
143 
144  b.Property<int>("PrimaryPort");
145 
146  b.Property<int?>("ProcessId");
147 
148  b.Property<int>("SecondaryPort");
149 
150  b.Property<int>("SecurityLevel");
151 
152  b.Property<bool?>("SoftRestart")
153  .IsRequired();
154 
155  b.Property<bool?>("SoftShutdown")
156  .IsRequired();
157 
158  b.Property<long>("StartupTimeout");
159 
160  b.HasKey("Id");
161 
162  b.HasIndex("InstanceId")
163  .IsUnique();
164 
165  b.ToTable("DreamDaemonSettings");
166  });
167 
168  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
169  {
170  b.Property<long>("Id")
171  .ValueGeneratedOnAdd()
172  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
173 
174  b.Property<int>("ApiValidationPort");
175 
176  b.Property<int>("ApiValidationSecurityLevel");
177 
178  b.Property<long>("InstanceId");
179 
180  b.Property<string>("ProjectName");
181 
182  b.HasKey("Id");
183 
184  b.HasIndex("InstanceId")
185  .IsUnique();
186 
187  b.ToTable("DreamMakerSettings");
188  });
189 
190  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
191  {
192  b.Property<long>("Id")
193  .ValueGeneratedOnAdd()
194  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
195 
196  b.Property<long>("AutoUpdateInterval");
197 
198  b.Property<int>("ConfigurationType");
199 
200  b.Property<string>("Name")
201  .IsRequired();
202 
203  b.Property<bool?>("Online")
204  .IsRequired();
205 
206  b.Property<string>("Path")
207  .IsRequired();
208 
209  b.HasKey("Id");
210 
211  b.HasIndex("Path")
212  .IsUnique();
213 
214  b.ToTable("Instances");
215  });
216 
217  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
218  {
219  b.Property<long>("Id")
220  .ValueGeneratedOnAdd()
221  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
222 
223  b.Property<decimal>("ByondRights")
224  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
225 
226  b.Property<decimal>("ChatBotRights")
227  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
228 
229  b.Property<decimal>("ConfigurationRights")
230  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
231 
232  b.Property<decimal>("DreamDaemonRights")
233  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
234 
235  b.Property<decimal>("DreamMakerRights")
236  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
237 
238  b.Property<long>("InstanceId");
239 
240  b.Property<decimal>("InstanceUserRights")
241  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
242 
243  b.Property<decimal>("RepositoryRights")
244  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
245 
246  b.Property<long?>("UserId")
247  .IsRequired();
248 
249  b.HasKey("Id");
250 
251  b.HasIndex("InstanceId");
252 
253  b.HasIndex("UserId", "InstanceId")
254  .IsUnique();
255 
256  b.ToTable("InstanceUsers");
257  });
258 
259  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
260  {
261  b.Property<long>("Id")
262  .ValueGeneratedOnAdd()
263  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
264 
265  b.Property<decimal?>("CancelRight")
266  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
267 
268  b.Property<decimal?>("CancelRightsType")
269  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
270 
271  b.Property<bool?>("Cancelled")
272  .IsRequired();
273 
274  b.Property<long?>("CancelledById");
275 
276  b.Property<string>("Description")
277  .IsRequired();
278 
279  b.Property<string>("ExceptionDetails");
280 
281  b.Property<long>("InstanceId");
282 
283  b.Property<DateTimeOffset?>("StartedAt")
284  .IsRequired();
285 
286  b.Property<long>("StartedById");
287 
288  b.Property<DateTimeOffset?>("StoppedAt");
289 
290  b.HasKey("Id");
291 
292  b.HasIndex("CancelledById");
293 
294  b.HasIndex("InstanceId");
295 
296  b.HasIndex("StartedById");
297 
298  b.ToTable("Jobs");
299  });
300 
301  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
302  {
303  b.Property<long>("Id")
304  .ValueGeneratedOnAdd()
305  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
306 
307  b.Property<string>("AccessIdentifier")
308  .IsRequired();
309 
310  b.Property<string>("ChatChannelsJson")
311  .IsRequired();
312 
313  b.Property<string>("ChatCommandsJson")
314  .IsRequired();
315 
316  b.Property<long>("CompileJobId");
317 
318  b.Property<bool>("IsPrimary");
319 
320  b.Property<int>("Port");
321 
322  b.Property<int>("ProcessId");
323 
324  b.Property<int>("RebootState");
325 
326  b.Property<string>("ServerCommandsJson")
327  .IsRequired();
328 
329  b.HasKey("Id");
330 
331  b.HasIndex("CompileJobId");
332 
333  b.ToTable("ReattachInformations");
334  });
335 
336  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
337  {
338  b.Property<long>("Id")
339  .ValueGeneratedOnAdd()
340  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
341 
342  b.Property<string>("AccessToken");
343 
344  b.Property<string>("AccessUser");
345 
346  b.Property<bool?>("AutoUpdatesKeepTestMerges")
347  .IsRequired();
348 
349  b.Property<bool?>("AutoUpdatesSynchronize")
350  .IsRequired();
351 
352  b.Property<string>("CommitterEmail")
353  .IsRequired();
354 
355  b.Property<string>("CommitterName")
356  .IsRequired();
357 
358  b.Property<long>("InstanceId");
359 
360  b.Property<bool?>("PushTestMergeCommits")
361  .IsRequired();
362 
363  b.Property<bool?>("ShowTestMergeCommitters")
364  .IsRequired();
365 
366  b.HasKey("Id");
367 
368  b.HasIndex("InstanceId")
369  .IsUnique();
370 
371  b.ToTable("RepositorySettings");
372  });
373 
374  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
375  {
376  b.Property<long>("Id")
377  .ValueGeneratedOnAdd()
378  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
379 
380  b.Property<long>("RevisionInformationId");
381 
382  b.Property<long>("TestMergeId");
383 
384  b.HasKey("Id");
385 
386  b.HasIndex("RevisionInformationId");
387 
388  b.HasIndex("TestMergeId");
389 
390  b.ToTable("RevInfoTestMerges");
391  });
392 
393  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
394  {
395  b.Property<long>("Id")
396  .ValueGeneratedOnAdd()
397  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
398 
399  b.Property<string>("CommitSha")
400  .IsRequired()
401  .HasMaxLength(40);
402 
403  b.Property<long>("InstanceId");
404 
405  b.Property<string>("OriginCommitSha")
406  .IsRequired()
407  .HasMaxLength(40);
408 
409  b.HasKey("Id");
410 
411  b.HasIndex("CommitSha")
412  .IsUnique();
413 
414  b.HasIndex("InstanceId");
415 
416  b.ToTable("RevisionInformations");
417  });
418 
419  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
420  {
421  b.Property<long>("Id")
422  .ValueGeneratedOnAdd()
423  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
424 
425  b.Property<string>("Author")
426  .IsRequired();
427 
428  b.Property<string>("BodyAtMerge")
429  .IsRequired();
430 
431  b.Property<string>("Comment");
432 
433  b.Property<DateTimeOffset>("MergedAt");
434 
435  b.Property<long>("MergedById");
436 
437  b.Property<int?>("Number")
438  .IsRequired();
439 
440  b.Property<long?>("PrimaryRevisionInformationId")
441  .IsRequired();
442 
443  b.Property<string>("PullRequestRevision")
444  .IsRequired();
445 
446  b.Property<string>("TitleAtMerge")
447  .IsRequired();
448 
449  b.Property<string>("Url")
450  .IsRequired();
451 
452  b.HasKey("Id");
453 
454  b.HasIndex("MergedById");
455 
456  b.HasIndex("PrimaryRevisionInformationId")
457  .IsUnique();
458 
459  b.ToTable("TestMerges");
460  });
461 
462  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
463  {
464  b.Property<long>("Id")
465  .ValueGeneratedOnAdd()
466  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
467 
468  b.Property<decimal>("AdministrationRights")
469  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
470 
471  b.Property<string>("CanonicalName")
472  .IsRequired();
473 
474  b.Property<DateTimeOffset?>("CreatedAt")
475  .IsRequired();
476 
477  b.Property<long?>("CreatedById");
478 
479  b.Property<bool?>("Enabled")
480  .IsRequired();
481 
482  b.Property<decimal>("InstanceManagerRights")
483  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
484 
485  b.Property<DateTimeOffset?>("LastPasswordUpdate");
486 
487  b.Property<string>("Name")
488  .IsRequired();
489 
490  b.Property<string>("PasswordHash");
491 
492  b.Property<string>("SystemIdentifier");
493 
494  b.HasKey("Id");
495 
496  b.HasIndex("CanonicalName")
497  .IsUnique();
498 
499  b.HasIndex("CreatedById");
500 
501  b.ToTable("Users");
502  });
503 
504  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
505  {
506  b.Property<long>("Id")
507  .ValueGeneratedOnAdd()
508  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
509 
510  b.Property<long?>("AlphaId");
511 
512  b.Property<bool>("AlphaIsActive");
513 
514  b.Property<long?>("BravoId");
515 
516  b.Property<long>("InstanceId");
517 
518  b.HasKey("Id");
519 
520  b.HasIndex("AlphaId");
521 
522  b.HasIndex("BravoId");
523 
524  b.HasIndex("InstanceId")
525  .IsUnique();
526 
527  b.ToTable("WatchdogReattachInformations");
528  });
529 
530  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
531  {
532  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
533  .WithMany("ChatSettings")
534  .HasForeignKey("InstanceId")
535  .OnDelete(DeleteBehavior.Cascade);
536  });
537 
538  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
539  {
540  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
541  .WithMany("Channels")
542  .HasForeignKey("ChatSettingsId")
543  .OnDelete(DeleteBehavior.Cascade);
544  });
545 
546  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
547  {
548  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
549  .WithOne()
550  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
551  .OnDelete(DeleteBehavior.Restrict);
552 
553  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
554  .WithMany("CompileJobs")
555  .HasForeignKey("RevisionInformationId")
556  .OnDelete(DeleteBehavior.Cascade);
557  });
558 
559  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
560  {
561  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
562  .WithOne("DreamDaemonSettings")
563  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
564  .OnDelete(DeleteBehavior.Cascade);
565  });
566 
567  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
568  {
569  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
570  .WithOne("DreamMakerSettings")
571  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
572  .OnDelete(DeleteBehavior.Cascade);
573  });
574 
575  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
576  {
577  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
578  .WithMany("InstanceUsers")
579  .HasForeignKey("InstanceId")
580  .OnDelete(DeleteBehavior.Cascade);
581 
582  b.HasOne("Tgstation.Server.Host.Models.User")
583  .WithMany("InstanceUsers")
584  .HasForeignKey("UserId")
585  .OnDelete(DeleteBehavior.Cascade);
586  });
587 
588  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
589  {
590  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
591  .WithMany()
592  .HasForeignKey("CancelledById");
593 
594  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
595  .WithMany("Jobs")
596  .HasForeignKey("InstanceId")
597  .OnDelete(DeleteBehavior.Cascade);
598 
599  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
600  .WithMany()
601  .HasForeignKey("StartedById")
602  .OnDelete(DeleteBehavior.Cascade);
603  });
604 
605  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
606  {
607  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
608  .WithMany()
609  .HasForeignKey("CompileJobId")
610  .OnDelete(DeleteBehavior.Cascade);
611  });
612 
613  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
614  {
615  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
616  .WithOne("RepositorySettings")
617  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
618  .OnDelete(DeleteBehavior.Cascade);
619  });
620 
621  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
622  {
623  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
624  .WithMany("ActiveTestMerges")
625  .HasForeignKey("RevisionInformationId")
626  .OnDelete(DeleteBehavior.Cascade);
627 
628  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
629  .WithMany("RevisonInformations")
630  .HasForeignKey("TestMergeId")
631  .OnDelete(DeleteBehavior.Cascade);
632  });
633 
634  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
635  {
636  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
637  .WithMany("RevisionInformations")
638  .HasForeignKey("InstanceId")
639  .OnDelete(DeleteBehavior.Cascade);
640  });
641 
642  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
643  {
644  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
645  .WithMany("TestMerges")
646  .HasForeignKey("MergedById")
647  .OnDelete(DeleteBehavior.Restrict);
648 
649  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
650  .WithOne("PrimaryTestMerge")
651  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
652  .OnDelete(DeleteBehavior.Restrict);
653  });
654 
655  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
656  {
657  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
658  .WithMany("CreatedUsers")
659  .HasForeignKey("CreatedById");
660  });
661 
662  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
663  {
664  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
665  .WithMany()
666  .HasForeignKey("AlphaId");
667 
668  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
669  .WithMany()
670  .HasForeignKey("BravoId");
671 
672  b.HasOne("Tgstation.Server.Host.Models.Instance")
673  .WithOne("WatchdogReattachInformation")
674  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
675  .OnDelete(DeleteBehavior.Cascade);
676  });
677 #pragma warning restore 612, 618
678  }
679  }
680 }
+Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Metadata;
6 using Microsoft.EntityFrameworkCore.Migrations;
7 using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
9 
11 {
13  [Migration("20180926033145_MSReattachCompileJobRequired")]
14  partial class MSReattachCompileJobRequired
15  {
20  protected override void BuildTargetModel(ModelBuilder modelBuilder)
21  {
22 #pragma warning disable 612, 618
23  modelBuilder
24  .HasAnnotation("ProductVersion", "2.1.3-rtm-32065")
25  .HasAnnotation("Relational:MaxIdentifierLength", 128)
26  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
27 
28  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
29  {
30  b.Property<long>("Id")
31  .ValueGeneratedOnAdd()
32  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
33 
34  b.Property<string>("ConnectionString")
35  .IsRequired();
36 
37  b.Property<bool?>("Enabled");
38 
39  b.Property<long>("InstanceId");
40 
41  b.Property<string>("Name")
42  .IsRequired();
43 
44  b.Property<int?>("Provider");
45 
46  b.HasKey("Id");
47 
48  b.HasIndex("InstanceId");
49 
50  b.HasIndex("Name")
51  .IsUnique();
52 
53  b.ToTable("ChatBots");
54  });
55 
56  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
57  {
58  b.Property<long>("Id")
59  .ValueGeneratedOnAdd()
60  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
61 
62  b.Property<long>("ChatSettingsId");
63 
64  b.Property<decimal?>("DiscordChannelId")
65  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
66 
67  b.Property<string>("IrcChannel");
68 
69  b.Property<bool?>("IsAdminChannel")
70  .IsRequired();
71 
72  b.Property<bool?>("IsUpdatesChannel")
73  .IsRequired();
74 
75  b.Property<bool?>("IsWatchdogChannel")
76  .IsRequired();
77 
78  b.Property<string>("Tag");
79 
80  b.HasKey("Id");
81 
82  b.HasIndex("ChatSettingsId", "DiscordChannelId")
83  .IsUnique()
84  .HasFilter("[DiscordChannelId] IS NOT NULL");
85 
86  b.HasIndex("ChatSettingsId", "IrcChannel")
87  .IsUnique()
88  .HasFilter("[IrcChannel] IS NOT NULL");
89 
90  b.ToTable("ChatChannels");
91  });
92 
93  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
94  {
95  b.Property<long>("Id")
96  .ValueGeneratedOnAdd()
97  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
98 
99  b.Property<string>("ByondVersion")
100  .IsRequired();
101 
102  b.Property<Guid?>("DirectoryName")
103  .IsRequired();
104 
105  b.Property<string>("DmeName")
106  .IsRequired();
107 
108  b.Property<long>("JobId");
109 
110  b.Property<int>("MinimumSecurityLevel");
111 
112  b.Property<string>("Output")
113  .IsRequired();
114 
115  b.Property<long>("RevisionInformationId");
116 
117  b.HasKey("Id");
118 
119  b.HasIndex("DirectoryName");
120 
121  b.HasIndex("JobId")
122  .IsUnique();
123 
124  b.HasIndex("RevisionInformationId");
125 
126  b.ToTable("CompileJobs");
127  });
128 
129  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
130  {
131  b.Property<long>("Id")
132  .ValueGeneratedOnAdd()
133  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
134 
135  b.Property<string>("AccessToken");
136 
137  b.Property<bool?>("AllowWebClient")
138  .IsRequired();
139 
140  b.Property<bool?>("AutoStart")
141  .IsRequired();
142 
143  b.Property<long>("InstanceId");
144 
145  b.Property<int>("PrimaryPort");
146 
147  b.Property<int?>("ProcessId");
148 
149  b.Property<int>("SecondaryPort");
150 
151  b.Property<int>("SecurityLevel");
152 
153  b.Property<bool?>("SoftRestart")
154  .IsRequired();
155 
156  b.Property<bool?>("SoftShutdown")
157  .IsRequired();
158 
159  b.Property<long>("StartupTimeout");
160 
161  b.HasKey("Id");
162 
163  b.HasIndex("InstanceId")
164  .IsUnique();
165 
166  b.ToTable("DreamDaemonSettings");
167  });
168 
169  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
170  {
171  b.Property<long>("Id")
172  .ValueGeneratedOnAdd()
173  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
174 
175  b.Property<int>("ApiValidationPort");
176 
177  b.Property<int>("ApiValidationSecurityLevel");
178 
179  b.Property<long>("InstanceId");
180 
181  b.Property<string>("ProjectName");
182 
183  b.HasKey("Id");
184 
185  b.HasIndex("InstanceId")
186  .IsUnique();
187 
188  b.ToTable("DreamMakerSettings");
189  });
190 
191  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
192  {
193  b.Property<long>("Id")
194  .ValueGeneratedOnAdd()
195  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
196 
197  b.Property<long>("AutoUpdateInterval");
198 
199  b.Property<int>("ConfigurationType");
200 
201  b.Property<string>("Name")
202  .IsRequired();
203 
204  b.Property<bool?>("Online")
205  .IsRequired();
206 
207  b.Property<string>("Path")
208  .IsRequired();
209 
210  b.HasKey("Id");
211 
212  b.HasIndex("Path")
213  .IsUnique();
214 
215  b.ToTable("Instances");
216  });
217 
218  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
219  {
220  b.Property<long>("Id")
221  .ValueGeneratedOnAdd()
222  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
223 
224  b.Property<decimal>("ByondRights")
225  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
226 
227  b.Property<decimal>("ChatBotRights")
228  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
229 
230  b.Property<decimal>("ConfigurationRights")
231  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
232 
233  b.Property<decimal>("DreamDaemonRights")
234  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
235 
236  b.Property<decimal>("DreamMakerRights")
237  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
238 
239  b.Property<long>("InstanceId");
240 
241  b.Property<decimal>("InstanceUserRights")
242  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
243 
244  b.Property<decimal>("RepositoryRights")
245  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
246 
247  b.Property<long?>("UserId")
248  .IsRequired();
249 
250  b.HasKey("Id");
251 
252  b.HasIndex("InstanceId");
253 
254  b.HasIndex("UserId", "InstanceId")
255  .IsUnique();
256 
257  b.ToTable("InstanceUsers");
258  });
259 
260  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
261  {
262  b.Property<long>("Id")
263  .ValueGeneratedOnAdd()
264  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
265 
266  b.Property<decimal?>("CancelRight")
267  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
268 
269  b.Property<decimal?>("CancelRightsType")
270  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
271 
272  b.Property<bool?>("Cancelled")
273  .IsRequired();
274 
275  b.Property<long?>("CancelledById");
276 
277  b.Property<string>("Description")
278  .IsRequired();
279 
280  b.Property<string>("ExceptionDetails");
281 
282  b.Property<long>("InstanceId");
283 
284  b.Property<DateTimeOffset?>("StartedAt")
285  .IsRequired();
286 
287  b.Property<long>("StartedById");
288 
289  b.Property<DateTimeOffset?>("StoppedAt");
290 
291  b.HasKey("Id");
292 
293  b.HasIndex("CancelledById");
294 
295  b.HasIndex("InstanceId");
296 
297  b.HasIndex("StartedById");
298 
299  b.ToTable("Jobs");
300  });
301 
302  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
303  {
304  b.Property<long>("Id")
305  .ValueGeneratedOnAdd()
306  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
307 
308  b.Property<string>("AccessIdentifier")
309  .IsRequired();
310 
311  b.Property<string>("ChatChannelsJson")
312  .IsRequired();
313 
314  b.Property<string>("ChatCommandsJson")
315  .IsRequired();
316 
317  b.Property<long>("CompileJobId");
318 
319  b.Property<bool>("IsPrimary");
320 
321  b.Property<int>("Port");
322 
323  b.Property<int>("ProcessId");
324 
325  b.Property<int>("RebootState");
326 
327  b.Property<string>("ServerCommandsJson")
328  .IsRequired();
329 
330  b.HasKey("Id");
331 
332  b.HasIndex("CompileJobId");
333 
334  b.ToTable("ReattachInformations");
335  });
336 
337  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
338  {
339  b.Property<long>("Id")
340  .ValueGeneratedOnAdd()
341  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
342 
343  b.Property<string>("AccessToken");
344 
345  b.Property<string>("AccessUser");
346 
347  b.Property<bool?>("AutoUpdatesKeepTestMerges")
348  .IsRequired();
349 
350  b.Property<bool?>("AutoUpdatesSynchronize")
351  .IsRequired();
352 
353  b.Property<string>("CommitterEmail")
354  .IsRequired();
355 
356  b.Property<string>("CommitterName")
357  .IsRequired();
358 
359  b.Property<long>("InstanceId");
360 
361  b.Property<bool?>("PushTestMergeCommits")
362  .IsRequired();
363 
364  b.Property<bool?>("ShowTestMergeCommitters")
365  .IsRequired();
366 
367  b.HasKey("Id");
368 
369  b.HasIndex("InstanceId")
370  .IsUnique();
371 
372  b.ToTable("RepositorySettings");
373  });
374 
375  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
376  {
377  b.Property<long>("Id")
378  .ValueGeneratedOnAdd()
379  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
380 
381  b.Property<long>("RevisionInformationId");
382 
383  b.Property<long>("TestMergeId");
384 
385  b.HasKey("Id");
386 
387  b.HasIndex("RevisionInformationId");
388 
389  b.HasIndex("TestMergeId");
390 
391  b.ToTable("RevInfoTestMerges");
392  });
393 
394  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
395  {
396  b.Property<long>("Id")
397  .ValueGeneratedOnAdd()
398  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
399 
400  b.Property<string>("CommitSha")
401  .IsRequired()
402  .HasMaxLength(40);
403 
404  b.Property<long>("InstanceId");
405 
406  b.Property<string>("OriginCommitSha")
407  .IsRequired()
408  .HasMaxLength(40);
409 
410  b.HasKey("Id");
411 
412  b.HasIndex("CommitSha")
413  .IsUnique();
414 
415  b.HasIndex("InstanceId");
416 
417  b.ToTable("RevisionInformations");
418  });
419 
420  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
421  {
422  b.Property<long>("Id")
423  .ValueGeneratedOnAdd()
424  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
425 
426  b.Property<string>("Author")
427  .IsRequired();
428 
429  b.Property<string>("BodyAtMerge")
430  .IsRequired();
431 
432  b.Property<string>("Comment");
433 
434  b.Property<DateTimeOffset>("MergedAt");
435 
436  b.Property<long>("MergedById");
437 
438  b.Property<int?>("Number")
439  .IsRequired();
440 
441  b.Property<long?>("PrimaryRevisionInformationId")
442  .IsRequired();
443 
444  b.Property<string>("PullRequestRevision")
445  .IsRequired();
446 
447  b.Property<string>("TitleAtMerge")
448  .IsRequired();
449 
450  b.Property<string>("Url")
451  .IsRequired();
452 
453  b.HasKey("Id");
454 
455  b.HasIndex("MergedById");
456 
457  b.HasIndex("PrimaryRevisionInformationId")
458  .IsUnique();
459 
460  b.ToTable("TestMerges");
461  });
462 
463  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
464  {
465  b.Property<long>("Id")
466  .ValueGeneratedOnAdd()
467  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
468 
469  b.Property<decimal>("AdministrationRights")
470  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
471 
472  b.Property<string>("CanonicalName")
473  .IsRequired();
474 
475  b.Property<DateTimeOffset?>("CreatedAt")
476  .IsRequired();
477 
478  b.Property<long?>("CreatedById");
479 
480  b.Property<bool?>("Enabled")
481  .IsRequired();
482 
483  b.Property<decimal>("InstanceManagerRights")
484  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
485 
486  b.Property<DateTimeOffset?>("LastPasswordUpdate");
487 
488  b.Property<string>("Name")
489  .IsRequired();
490 
491  b.Property<string>("PasswordHash");
492 
493  b.Property<string>("SystemIdentifier");
494 
495  b.HasKey("Id");
496 
497  b.HasIndex("CanonicalName")
498  .IsUnique();
499 
500  b.HasIndex("CreatedById");
501 
502  b.ToTable("Users");
503  });
504 
505  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
506  {
507  b.Property<long>("Id")
508  .ValueGeneratedOnAdd()
509  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
510 
511  b.Property<long?>("AlphaId");
512 
513  b.Property<bool>("AlphaIsActive");
514 
515  b.Property<long?>("BravoId");
516 
517  b.Property<long>("InstanceId");
518 
519  b.HasKey("Id");
520 
521  b.HasIndex("AlphaId");
522 
523  b.HasIndex("BravoId");
524 
525  b.HasIndex("InstanceId")
526  .IsUnique();
527 
528  b.ToTable("WatchdogReattachInformations");
529  });
530 
531  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
532  {
533  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
534  .WithMany("ChatSettings")
535  .HasForeignKey("InstanceId")
536  .OnDelete(DeleteBehavior.Cascade);
537  });
538 
539  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
540  {
541  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
542  .WithMany("Channels")
543  .HasForeignKey("ChatSettingsId")
544  .OnDelete(DeleteBehavior.Cascade);
545  });
546 
547  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
548  {
549  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
550  .WithOne()
551  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
552  .OnDelete(DeleteBehavior.Restrict);
553 
554  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
555  .WithMany("CompileJobs")
556  .HasForeignKey("RevisionInformationId")
557  .OnDelete(DeleteBehavior.Cascade);
558  });
559 
560  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
561  {
562  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
563  .WithOne("DreamDaemonSettings")
564  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
565  .OnDelete(DeleteBehavior.Cascade);
566  });
567 
568  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
569  {
570  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
571  .WithOne("DreamMakerSettings")
572  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
573  .OnDelete(DeleteBehavior.Cascade);
574  });
575 
576  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
577  {
578  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
579  .WithMany("InstanceUsers")
580  .HasForeignKey("InstanceId")
581  .OnDelete(DeleteBehavior.Cascade);
582 
583  b.HasOne("Tgstation.Server.Host.Models.User")
584  .WithMany("InstanceUsers")
585  .HasForeignKey("UserId")
586  .OnDelete(DeleteBehavior.Cascade);
587  });
588 
589  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
590  {
591  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
592  .WithMany()
593  .HasForeignKey("CancelledById");
594 
595  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
596  .WithMany("Jobs")
597  .HasForeignKey("InstanceId")
598  .OnDelete(DeleteBehavior.Cascade);
599 
600  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
601  .WithMany()
602  .HasForeignKey("StartedById")
603  .OnDelete(DeleteBehavior.Cascade);
604  });
605 
606  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
607  {
608  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
609  .WithMany()
610  .HasForeignKey("CompileJobId")
611  .OnDelete(DeleteBehavior.Cascade);
612  });
613 
614  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
615  {
616  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
617  .WithOne("RepositorySettings")
618  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
619  .OnDelete(DeleteBehavior.Cascade);
620  });
621 
622  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
623  {
624  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
625  .WithMany("ActiveTestMerges")
626  .HasForeignKey("RevisionInformationId")
627  .OnDelete(DeleteBehavior.Cascade);
628 
629  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
630  .WithMany("RevisonInformations")
631  .HasForeignKey("TestMergeId")
632  .OnDelete(DeleteBehavior.Cascade);
633  });
634 
635  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
636  {
637  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
638  .WithMany("RevisionInformations")
639  .HasForeignKey("InstanceId")
640  .OnDelete(DeleteBehavior.Cascade);
641  });
642 
643  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
644  {
645  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
646  .WithMany("TestMerges")
647  .HasForeignKey("MergedById")
648  .OnDelete(DeleteBehavior.Restrict);
649 
650  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
651  .WithOne("PrimaryTestMerge")
652  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
653  .OnDelete(DeleteBehavior.Restrict);
654  });
655 
656  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
657  {
658  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
659  .WithMany("CreatedUsers")
660  .HasForeignKey("CreatedById");
661  });
662 
663  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
664  {
665  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
666  .WithMany()
667  .HasForeignKey("AlphaId");
668 
669  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
670  .WithMany()
671  .HasForeignKey("BravoId");
672 
673  b.HasOne("Tgstation.Server.Host.Models.Instance")
674  .WithOne("WatchdogReattachInformation")
675  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
676  .OnDelete(DeleteBehavior.Cascade);
677  });
678 #pragma warning restore 612, 618
679  }
680  }
681 }
- + + +
DatabaseContext<TParentContext> for Sqlserver
+ + +
-Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Migrations;
6 
8 {
9  [DbContext(typeof(MySqlDatabaseContext))]
10  [Migration("20180926034014_MYReattachCompileJobRequired")]
11  partial class MYReattachCompileJobRequired
12  {
17  protected override void BuildTargetModel(ModelBuilder modelBuilder)
18  {
19 #pragma warning disable 612, 618
20  modelBuilder
21  .HasAnnotation("ProductVersion", "2.1.3-rtm-32065")
22  .HasAnnotation("Relational:MaxIdentifierLength", 64);
23 
24  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
25  {
26  b.Property<long>("Id")
27  .ValueGeneratedOnAdd();
28 
29  b.Property<string>("ConnectionString")
30  .IsRequired();
31 
32  b.Property<bool?>("Enabled");
33 
34  b.Property<long>("InstanceId");
35 
36  b.Property<string>("Name")
37  .IsRequired();
38 
39  b.Property<int?>("Provider");
40 
41  b.HasKey("Id");
42 
43  b.HasIndex("InstanceId");
44 
45  b.HasIndex("Name")
46  .IsUnique();
47 
48  b.ToTable("ChatBots");
49  });
50 
51  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
52  {
53  b.Property<long>("Id")
54  .ValueGeneratedOnAdd();
55 
56  b.Property<long>("ChatSettingsId");
57 
58  b.Property<ulong?>("DiscordChannelId");
59 
60  b.Property<string>("IrcChannel");
61 
62  b.Property<bool?>("IsAdminChannel")
63  .IsRequired();
64 
65  b.Property<bool?>("IsUpdatesChannel")
66  .IsRequired();
67 
68  b.Property<bool?>("IsWatchdogChannel")
69  .IsRequired();
70 
71  b.Property<string>("Tag");
72 
73  b.HasKey("Id");
74 
75  b.HasIndex("ChatSettingsId", "DiscordChannelId")
76  .IsUnique();
77 
78  b.HasIndex("ChatSettingsId", "IrcChannel")
79  .IsUnique();
80 
81  b.ToTable("ChatChannels");
82  });
83 
84  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
85  {
86  b.Property<long>("Id")
87  .ValueGeneratedOnAdd();
88 
89  b.Property<string>("ByondVersion")
90  .IsRequired();
91 
92  b.Property<Guid?>("DirectoryName")
93  .IsRequired();
94 
95  b.Property<string>("DmeName")
96  .IsRequired();
97 
98  b.Property<long>("JobId");
99 
100  b.Property<int>("MinimumSecurityLevel");
101 
102  b.Property<string>("Output")
103  .IsRequired();
104 
105  b.Property<long>("RevisionInformationId");
106 
107  b.HasKey("Id");
108 
109  b.HasIndex("DirectoryName");
110 
111  b.HasIndex("JobId")
112  .IsUnique();
113 
114  b.HasIndex("RevisionInformationId");
115 
116  b.ToTable("CompileJobs");
117  });
118 
119  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
120  {
121  b.Property<long>("Id")
122  .ValueGeneratedOnAdd();
123 
124  b.Property<string>("AccessToken");
125 
126  b.Property<bool?>("AllowWebClient")
127  .IsRequired();
128 
129  b.Property<bool?>("AutoStart")
130  .IsRequired();
131 
132  b.Property<long>("InstanceId");
133 
134  b.Property<ushort?>("PrimaryPort")
135  .IsRequired();
136 
137  b.Property<int?>("ProcessId");
138 
139  b.Property<ushort?>("SecondaryPort")
140  .IsRequired();
141 
142  b.Property<int>("SecurityLevel");
143 
144  b.Property<bool?>("SoftRestart")
145  .IsRequired();
146 
147  b.Property<bool?>("SoftShutdown")
148  .IsRequired();
149 
150  b.Property<uint?>("StartupTimeout")
151  .IsRequired();
152 
153  b.HasKey("Id");
154 
155  b.HasIndex("InstanceId")
156  .IsUnique();
157 
158  b.ToTable("DreamDaemonSettings");
159  });
160 
161  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
162  {
163  b.Property<long>("Id")
164  .ValueGeneratedOnAdd();
165 
166  b.Property<ushort?>("ApiValidationPort")
167  .IsRequired();
168 
169  b.Property<int>("ApiValidationSecurityLevel");
170 
171  b.Property<long>("InstanceId");
172 
173  b.Property<string>("ProjectName");
174 
175  b.HasKey("Id");
176 
177  b.HasIndex("InstanceId")
178  .IsUnique();
179 
180  b.ToTable("DreamMakerSettings");
181  });
182 
183  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
184  {
185  b.Property<long>("Id")
186  .ValueGeneratedOnAdd();
187 
188  b.Property<uint?>("AutoUpdateInterval")
189  .IsRequired();
190 
191  b.Property<int>("ConfigurationType");
192 
193  b.Property<string>("Name")
194  .IsRequired();
195 
196  b.Property<bool?>("Online")
197  .IsRequired();
198 
199  b.Property<string>("Path")
200  .IsRequired();
201 
202  b.HasKey("Id");
203 
204  b.HasIndex("Path")
205  .IsUnique();
206 
207  b.ToTable("Instances");
208  });
209 
210  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
211  {
212  b.Property<long>("Id")
213  .ValueGeneratedOnAdd();
214 
215  b.Property<ulong>("ByondRights");
216 
217  b.Property<ulong>("ChatBotRights");
218 
219  b.Property<ulong>("ConfigurationRights");
220 
221  b.Property<ulong>("DreamDaemonRights");
222 
223  b.Property<ulong>("DreamMakerRights");
224 
225  b.Property<long>("InstanceId");
226 
227  b.Property<ulong>("InstanceUserRights");
228 
229  b.Property<ulong>("RepositoryRights");
230 
231  b.Property<long?>("UserId")
232  .IsRequired();
233 
234  b.HasKey("Id");
235 
236  b.HasIndex("InstanceId");
237 
238  b.HasIndex("UserId", "InstanceId")
239  .IsUnique();
240 
241  b.ToTable("InstanceUsers");
242  });
243 
244  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
245  {
246  b.Property<long>("Id")
247  .ValueGeneratedOnAdd();
248 
249  b.Property<ulong?>("CancelRight");
250 
251  b.Property<ulong?>("CancelRightsType");
252 
253  b.Property<bool?>("Cancelled")
254  .IsRequired();
255 
256  b.Property<long?>("CancelledById");
257 
258  b.Property<string>("Description")
259  .IsRequired();
260 
261  b.Property<string>("ExceptionDetails");
262 
263  b.Property<long>("InstanceId");
264 
265  b.Property<DateTimeOffset?>("StartedAt")
266  .IsRequired();
267 
268  b.Property<long>("StartedById");
269 
270  b.Property<DateTimeOffset?>("StoppedAt");
271 
272  b.HasKey("Id");
273 
274  b.HasIndex("CancelledById");
275 
276  b.HasIndex("InstanceId");
277 
278  b.HasIndex("StartedById");
279 
280  b.ToTable("Jobs");
281  });
282 
283  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
284  {
285  b.Property<long>("Id")
286  .ValueGeneratedOnAdd();
287 
288  b.Property<string>("AccessIdentifier")
289  .IsRequired();
290 
291  b.Property<string>("ChatChannelsJson")
292  .IsRequired();
293 
294  b.Property<string>("ChatCommandsJson")
295  .IsRequired();
296 
297  b.Property<long>("CompileJobId");
298 
299  b.Property<bool>("IsPrimary");
300 
301  b.Property<ushort>("Port");
302 
303  b.Property<int>("ProcessId");
304 
305  b.Property<int>("RebootState");
306 
307  b.Property<string>("ServerCommandsJson")
308  .IsRequired();
309 
310  b.HasKey("Id");
311 
312  b.HasIndex("CompileJobId");
313 
314  b.ToTable("ReattachInformations");
315  });
316 
317  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
318  {
319  b.Property<long>("Id")
320  .ValueGeneratedOnAdd();
321 
322  b.Property<string>("AccessToken");
323 
324  b.Property<string>("AccessUser");
325 
326  b.Property<bool?>("AutoUpdatesKeepTestMerges")
327  .IsRequired();
328 
329  b.Property<bool?>("AutoUpdatesSynchronize")
330  .IsRequired();
331 
332  b.Property<string>("CommitterEmail")
333  .IsRequired();
334 
335  b.Property<string>("CommitterName")
336  .IsRequired();
337 
338  b.Property<long>("InstanceId");
339 
340  b.Property<bool?>("PushTestMergeCommits")
341  .IsRequired();
342 
343  b.Property<bool?>("ShowTestMergeCommitters")
344  .IsRequired();
345 
346  b.HasKey("Id");
347 
348  b.HasIndex("InstanceId")
349  .IsUnique();
350 
351  b.ToTable("RepositorySettings");
352  });
353 
354  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
355  {
356  b.Property<long>("Id")
357  .ValueGeneratedOnAdd();
358 
359  b.Property<long>("RevisionInformationId");
360 
361  b.Property<long>("TestMergeId");
362 
363  b.HasKey("Id");
364 
365  b.HasIndex("RevisionInformationId");
366 
367  b.HasIndex("TestMergeId");
368 
369  b.ToTable("RevInfoTestMerges");
370  });
371 
372  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
373  {
374  b.Property<long>("Id")
375  .ValueGeneratedOnAdd();
376 
377  b.Property<string>("CommitSha")
378  .IsRequired()
379  .HasMaxLength(40);
380 
381  b.Property<long>("InstanceId");
382 
383  b.Property<string>("OriginCommitSha")
384  .IsRequired()
385  .HasMaxLength(40);
386 
387  b.HasKey("Id");
388 
389  b.HasIndex("CommitSha")
390  .IsUnique();
391 
392  b.HasIndex("InstanceId");
393 
394  b.ToTable("RevisionInformations");
395  });
396 
397  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
398  {
399  b.Property<long>("Id")
400  .ValueGeneratedOnAdd();
401 
402  b.Property<string>("Author")
403  .IsRequired();
404 
405  b.Property<string>("BodyAtMerge")
406  .IsRequired();
407 
408  b.Property<string>("Comment");
409 
410  b.Property<DateTimeOffset>("MergedAt");
411 
412  b.Property<long>("MergedById");
413 
414  b.Property<int?>("Number")
415  .IsRequired();
416 
417  b.Property<long?>("PrimaryRevisionInformationId")
418  .IsRequired();
419 
420  b.Property<string>("PullRequestRevision")
421  .IsRequired();
422 
423  b.Property<string>("TitleAtMerge")
424  .IsRequired();
425 
426  b.Property<string>("Url")
427  .IsRequired();
428 
429  b.HasKey("Id");
430 
431  b.HasIndex("MergedById");
432 
433  b.HasIndex("PrimaryRevisionInformationId")
434  .IsUnique();
435 
436  b.ToTable("TestMerges");
437  });
438 
439  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
440  {
441  b.Property<long>("Id")
442  .ValueGeneratedOnAdd();
443 
444  b.Property<ulong>("AdministrationRights");
445 
446  b.Property<string>("CanonicalName")
447  .IsRequired();
448 
449  b.Property<DateTimeOffset?>("CreatedAt")
450  .IsRequired();
451 
452  b.Property<long?>("CreatedById");
453 
454  b.Property<bool?>("Enabled")
455  .IsRequired();
456 
457  b.Property<ulong>("InstanceManagerRights");
458 
459  b.Property<DateTimeOffset?>("LastPasswordUpdate");
460 
461  b.Property<string>("Name")
462  .IsRequired();
463 
464  b.Property<string>("PasswordHash");
465 
466  b.Property<string>("SystemIdentifier");
467 
468  b.HasKey("Id");
469 
470  b.HasIndex("CanonicalName")
471  .IsUnique();
472 
473  b.HasIndex("CreatedById");
474 
475  b.ToTable("Users");
476  });
477 
478  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
479  {
480  b.Property<long>("Id")
481  .ValueGeneratedOnAdd();
482 
483  b.Property<long?>("AlphaId");
484 
485  b.Property<bool>("AlphaIsActive");
486 
487  b.Property<long?>("BravoId");
488 
489  b.Property<long>("InstanceId");
490 
491  b.HasKey("Id");
492 
493  b.HasIndex("AlphaId");
494 
495  b.HasIndex("BravoId");
496 
497  b.HasIndex("InstanceId")
498  .IsUnique();
499 
500  b.ToTable("WatchdogReattachInformations");
501  });
502 
503  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
504  {
505  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
506  .WithMany("ChatSettings")
507  .HasForeignKey("InstanceId")
508  .OnDelete(DeleteBehavior.Cascade);
509  });
510 
511  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
512  {
513  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
514  .WithMany("Channels")
515  .HasForeignKey("ChatSettingsId")
516  .OnDelete(DeleteBehavior.Cascade);
517  });
518 
519  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
520  {
521  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
522  .WithOne()
523  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
524  .OnDelete(DeleteBehavior.Restrict);
525 
526  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
527  .WithMany("CompileJobs")
528  .HasForeignKey("RevisionInformationId")
529  .OnDelete(DeleteBehavior.Cascade);
530  });
531 
532  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
533  {
534  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
535  .WithOne("DreamDaemonSettings")
536  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
537  .OnDelete(DeleteBehavior.Cascade);
538  });
539 
540  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
541  {
542  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
543  .WithOne("DreamMakerSettings")
544  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
545  .OnDelete(DeleteBehavior.Cascade);
546  });
547 
548  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
549  {
550  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
551  .WithMany("InstanceUsers")
552  .HasForeignKey("InstanceId")
553  .OnDelete(DeleteBehavior.Cascade);
554 
555  b.HasOne("Tgstation.Server.Host.Models.User")
556  .WithMany("InstanceUsers")
557  .HasForeignKey("UserId")
558  .OnDelete(DeleteBehavior.Cascade);
559  });
560 
561  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
562  {
563  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
564  .WithMany()
565  .HasForeignKey("CancelledById");
566 
567  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
568  .WithMany("Jobs")
569  .HasForeignKey("InstanceId")
570  .OnDelete(DeleteBehavior.Cascade);
571 
572  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
573  .WithMany()
574  .HasForeignKey("StartedById")
575  .OnDelete(DeleteBehavior.Cascade);
576  });
577 
578  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
579  {
580  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
581  .WithMany()
582  .HasForeignKey("CompileJobId")
583  .OnDelete(DeleteBehavior.Cascade);
584  });
585 
586  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
587  {
588  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
589  .WithOne("RepositorySettings")
590  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
591  .OnDelete(DeleteBehavior.Cascade);
592  });
593 
594  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
595  {
596  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
597  .WithMany("ActiveTestMerges")
598  .HasForeignKey("RevisionInformationId")
599  .OnDelete(DeleteBehavior.Cascade);
600 
601  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
602  .WithMany("RevisonInformations")
603  .HasForeignKey("TestMergeId")
604  .OnDelete(DeleteBehavior.Cascade);
605  });
606 
607  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
608  {
609  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
610  .WithMany("RevisionInformations")
611  .HasForeignKey("InstanceId")
612  .OnDelete(DeleteBehavior.Cascade);
613  });
614 
615  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
616  {
617  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
618  .WithMany("TestMerges")
619  .HasForeignKey("MergedById")
620  .OnDelete(DeleteBehavior.Restrict);
621 
622  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
623  .WithOne("PrimaryTestMerge")
624  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
625  .OnDelete(DeleteBehavior.Restrict);
626  });
627 
628  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
629  {
630  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
631  .WithMany("CreatedUsers")
632  .HasForeignKey("CreatedById");
633  });
634 
635  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
636  {
637  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
638  .WithMany()
639  .HasForeignKey("AlphaId");
640 
641  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
642  .WithMany()
643  .HasForeignKey("BravoId");
644 
645  b.HasOne("Tgstation.Server.Host.Models.Instance")
646  .WithOne("WatchdogReattachInformation")
647  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
648  .OnDelete(DeleteBehavior.Cascade);
649  });
650 #pragma warning restore 612, 618
651  }
652  }
653 }
+Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Migrations;
7 
9 {
11  [Migration("20180926034014_MYReattachCompileJobRequired")]
12  partial class MYReattachCompileJobRequired
13  {
18  protected override void BuildTargetModel(ModelBuilder modelBuilder)
19  {
20 #pragma warning disable 612, 618
21  modelBuilder
22  .HasAnnotation("ProductVersion", "2.1.3-rtm-32065")
23  .HasAnnotation("Relational:MaxIdentifierLength", 64);
24 
25  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
26  {
27  b.Property<long>("Id")
28  .ValueGeneratedOnAdd();
29 
30  b.Property<string>("ConnectionString")
31  .IsRequired();
32 
33  b.Property<bool?>("Enabled");
34 
35  b.Property<long>("InstanceId");
36 
37  b.Property<string>("Name")
38  .IsRequired();
39 
40  b.Property<int?>("Provider");
41 
42  b.HasKey("Id");
43 
44  b.HasIndex("InstanceId");
45 
46  b.HasIndex("Name")
47  .IsUnique();
48 
49  b.ToTable("ChatBots");
50  });
51 
52  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
53  {
54  b.Property<long>("Id")
55  .ValueGeneratedOnAdd();
56 
57  b.Property<long>("ChatSettingsId");
58 
59  b.Property<ulong?>("DiscordChannelId");
60 
61  b.Property<string>("IrcChannel");
62 
63  b.Property<bool?>("IsAdminChannel")
64  .IsRequired();
65 
66  b.Property<bool?>("IsUpdatesChannel")
67  .IsRequired();
68 
69  b.Property<bool?>("IsWatchdogChannel")
70  .IsRequired();
71 
72  b.Property<string>("Tag");
73 
74  b.HasKey("Id");
75 
76  b.HasIndex("ChatSettingsId", "DiscordChannelId")
77  .IsUnique();
78 
79  b.HasIndex("ChatSettingsId", "IrcChannel")
80  .IsUnique();
81 
82  b.ToTable("ChatChannels");
83  });
84 
85  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
86  {
87  b.Property<long>("Id")
88  .ValueGeneratedOnAdd();
89 
90  b.Property<string>("ByondVersion")
91  .IsRequired();
92 
93  b.Property<Guid?>("DirectoryName")
94  .IsRequired();
95 
96  b.Property<string>("DmeName")
97  .IsRequired();
98 
99  b.Property<long>("JobId");
100 
101  b.Property<int>("MinimumSecurityLevel");
102 
103  b.Property<string>("Output")
104  .IsRequired();
105 
106  b.Property<long>("RevisionInformationId");
107 
108  b.HasKey("Id");
109 
110  b.HasIndex("DirectoryName");
111 
112  b.HasIndex("JobId")
113  .IsUnique();
114 
115  b.HasIndex("RevisionInformationId");
116 
117  b.ToTable("CompileJobs");
118  });
119 
120  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
121  {
122  b.Property<long>("Id")
123  .ValueGeneratedOnAdd();
124 
125  b.Property<string>("AccessToken");
126 
127  b.Property<bool?>("AllowWebClient")
128  .IsRequired();
129 
130  b.Property<bool?>("AutoStart")
131  .IsRequired();
132 
133  b.Property<long>("InstanceId");
134 
135  b.Property<ushort?>("PrimaryPort")
136  .IsRequired();
137 
138  b.Property<int?>("ProcessId");
139 
140  b.Property<ushort?>("SecondaryPort")
141  .IsRequired();
142 
143  b.Property<int>("SecurityLevel");
144 
145  b.Property<bool?>("SoftRestart")
146  .IsRequired();
147 
148  b.Property<bool?>("SoftShutdown")
149  .IsRequired();
150 
151  b.Property<uint?>("StartupTimeout")
152  .IsRequired();
153 
154  b.HasKey("Id");
155 
156  b.HasIndex("InstanceId")
157  .IsUnique();
158 
159  b.ToTable("DreamDaemonSettings");
160  });
161 
162  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
163  {
164  b.Property<long>("Id")
165  .ValueGeneratedOnAdd();
166 
167  b.Property<ushort?>("ApiValidationPort")
168  .IsRequired();
169 
170  b.Property<int>("ApiValidationSecurityLevel");
171 
172  b.Property<long>("InstanceId");
173 
174  b.Property<string>("ProjectName");
175 
176  b.HasKey("Id");
177 
178  b.HasIndex("InstanceId")
179  .IsUnique();
180 
181  b.ToTable("DreamMakerSettings");
182  });
183 
184  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
185  {
186  b.Property<long>("Id")
187  .ValueGeneratedOnAdd();
188 
189  b.Property<uint?>("AutoUpdateInterval")
190  .IsRequired();
191 
192  b.Property<int>("ConfigurationType");
193 
194  b.Property<string>("Name")
195  .IsRequired();
196 
197  b.Property<bool?>("Online")
198  .IsRequired();
199 
200  b.Property<string>("Path")
201  .IsRequired();
202 
203  b.HasKey("Id");
204 
205  b.HasIndex("Path")
206  .IsUnique();
207 
208  b.ToTable("Instances");
209  });
210 
211  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
212  {
213  b.Property<long>("Id")
214  .ValueGeneratedOnAdd();
215 
216  b.Property<ulong>("ByondRights");
217 
218  b.Property<ulong>("ChatBotRights");
219 
220  b.Property<ulong>("ConfigurationRights");
221 
222  b.Property<ulong>("DreamDaemonRights");
223 
224  b.Property<ulong>("DreamMakerRights");
225 
226  b.Property<long>("InstanceId");
227 
228  b.Property<ulong>("InstanceUserRights");
229 
230  b.Property<ulong>("RepositoryRights");
231 
232  b.Property<long?>("UserId")
233  .IsRequired();
234 
235  b.HasKey("Id");
236 
237  b.HasIndex("InstanceId");
238 
239  b.HasIndex("UserId", "InstanceId")
240  .IsUnique();
241 
242  b.ToTable("InstanceUsers");
243  });
244 
245  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
246  {
247  b.Property<long>("Id")
248  .ValueGeneratedOnAdd();
249 
250  b.Property<ulong?>("CancelRight");
251 
252  b.Property<ulong?>("CancelRightsType");
253 
254  b.Property<bool?>("Cancelled")
255  .IsRequired();
256 
257  b.Property<long?>("CancelledById");
258 
259  b.Property<string>("Description")
260  .IsRequired();
261 
262  b.Property<string>("ExceptionDetails");
263 
264  b.Property<long>("InstanceId");
265 
266  b.Property<DateTimeOffset?>("StartedAt")
267  .IsRequired();
268 
269  b.Property<long>("StartedById");
270 
271  b.Property<DateTimeOffset?>("StoppedAt");
272 
273  b.HasKey("Id");
274 
275  b.HasIndex("CancelledById");
276 
277  b.HasIndex("InstanceId");
278 
279  b.HasIndex("StartedById");
280 
281  b.ToTable("Jobs");
282  });
283 
284  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
285  {
286  b.Property<long>("Id")
287  .ValueGeneratedOnAdd();
288 
289  b.Property<string>("AccessIdentifier")
290  .IsRequired();
291 
292  b.Property<string>("ChatChannelsJson")
293  .IsRequired();
294 
295  b.Property<string>("ChatCommandsJson")
296  .IsRequired();
297 
298  b.Property<long>("CompileJobId");
299 
300  b.Property<bool>("IsPrimary");
301 
302  b.Property<ushort>("Port");
303 
304  b.Property<int>("ProcessId");
305 
306  b.Property<int>("RebootState");
307 
308  b.Property<string>("ServerCommandsJson")
309  .IsRequired();
310 
311  b.HasKey("Id");
312 
313  b.HasIndex("CompileJobId");
314 
315  b.ToTable("ReattachInformations");
316  });
317 
318  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
319  {
320  b.Property<long>("Id")
321  .ValueGeneratedOnAdd();
322 
323  b.Property<string>("AccessToken");
324 
325  b.Property<string>("AccessUser");
326 
327  b.Property<bool?>("AutoUpdatesKeepTestMerges")
328  .IsRequired();
329 
330  b.Property<bool?>("AutoUpdatesSynchronize")
331  .IsRequired();
332 
333  b.Property<string>("CommitterEmail")
334  .IsRequired();
335 
336  b.Property<string>("CommitterName")
337  .IsRequired();
338 
339  b.Property<long>("InstanceId");
340 
341  b.Property<bool?>("PushTestMergeCommits")
342  .IsRequired();
343 
344  b.Property<bool?>("ShowTestMergeCommitters")
345  .IsRequired();
346 
347  b.HasKey("Id");
348 
349  b.HasIndex("InstanceId")
350  .IsUnique();
351 
352  b.ToTable("RepositorySettings");
353  });
354 
355  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
356  {
357  b.Property<long>("Id")
358  .ValueGeneratedOnAdd();
359 
360  b.Property<long>("RevisionInformationId");
361 
362  b.Property<long>("TestMergeId");
363 
364  b.HasKey("Id");
365 
366  b.HasIndex("RevisionInformationId");
367 
368  b.HasIndex("TestMergeId");
369 
370  b.ToTable("RevInfoTestMerges");
371  });
372 
373  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
374  {
375  b.Property<long>("Id")
376  .ValueGeneratedOnAdd();
377 
378  b.Property<string>("CommitSha")
379  .IsRequired()
380  .HasMaxLength(40);
381 
382  b.Property<long>("InstanceId");
383 
384  b.Property<string>("OriginCommitSha")
385  .IsRequired()
386  .HasMaxLength(40);
387 
388  b.HasKey("Id");
389 
390  b.HasIndex("CommitSha")
391  .IsUnique();
392 
393  b.HasIndex("InstanceId");
394 
395  b.ToTable("RevisionInformations");
396  });
397 
398  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
399  {
400  b.Property<long>("Id")
401  .ValueGeneratedOnAdd();
402 
403  b.Property<string>("Author")
404  .IsRequired();
405 
406  b.Property<string>("BodyAtMerge")
407  .IsRequired();
408 
409  b.Property<string>("Comment");
410 
411  b.Property<DateTimeOffset>("MergedAt");
412 
413  b.Property<long>("MergedById");
414 
415  b.Property<int?>("Number")
416  .IsRequired();
417 
418  b.Property<long?>("PrimaryRevisionInformationId")
419  .IsRequired();
420 
421  b.Property<string>("PullRequestRevision")
422  .IsRequired();
423 
424  b.Property<string>("TitleAtMerge")
425  .IsRequired();
426 
427  b.Property<string>("Url")
428  .IsRequired();
429 
430  b.HasKey("Id");
431 
432  b.HasIndex("MergedById");
433 
434  b.HasIndex("PrimaryRevisionInformationId")
435  .IsUnique();
436 
437  b.ToTable("TestMerges");
438  });
439 
440  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
441  {
442  b.Property<long>("Id")
443  .ValueGeneratedOnAdd();
444 
445  b.Property<ulong>("AdministrationRights");
446 
447  b.Property<string>("CanonicalName")
448  .IsRequired();
449 
450  b.Property<DateTimeOffset?>("CreatedAt")
451  .IsRequired();
452 
453  b.Property<long?>("CreatedById");
454 
455  b.Property<bool?>("Enabled")
456  .IsRequired();
457 
458  b.Property<ulong>("InstanceManagerRights");
459 
460  b.Property<DateTimeOffset?>("LastPasswordUpdate");
461 
462  b.Property<string>("Name")
463  .IsRequired();
464 
465  b.Property<string>("PasswordHash");
466 
467  b.Property<string>("SystemIdentifier");
468 
469  b.HasKey("Id");
470 
471  b.HasIndex("CanonicalName")
472  .IsUnique();
473 
474  b.HasIndex("CreatedById");
475 
476  b.ToTable("Users");
477  });
478 
479  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
480  {
481  b.Property<long>("Id")
482  .ValueGeneratedOnAdd();
483 
484  b.Property<long?>("AlphaId");
485 
486  b.Property<bool>("AlphaIsActive");
487 
488  b.Property<long?>("BravoId");
489 
490  b.Property<long>("InstanceId");
491 
492  b.HasKey("Id");
493 
494  b.HasIndex("AlphaId");
495 
496  b.HasIndex("BravoId");
497 
498  b.HasIndex("InstanceId")
499  .IsUnique();
500 
501  b.ToTable("WatchdogReattachInformations");
502  });
503 
504  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
505  {
506  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
507  .WithMany("ChatSettings")
508  .HasForeignKey("InstanceId")
509  .OnDelete(DeleteBehavior.Cascade);
510  });
511 
512  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
513  {
514  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
515  .WithMany("Channels")
516  .HasForeignKey("ChatSettingsId")
517  .OnDelete(DeleteBehavior.Cascade);
518  });
519 
520  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
521  {
522  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
523  .WithOne()
524  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
525  .OnDelete(DeleteBehavior.Restrict);
526 
527  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
528  .WithMany("CompileJobs")
529  .HasForeignKey("RevisionInformationId")
530  .OnDelete(DeleteBehavior.Cascade);
531  });
532 
533  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
534  {
535  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
536  .WithOne("DreamDaemonSettings")
537  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
538  .OnDelete(DeleteBehavior.Cascade);
539  });
540 
541  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
542  {
543  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
544  .WithOne("DreamMakerSettings")
545  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
546  .OnDelete(DeleteBehavior.Cascade);
547  });
548 
549  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
550  {
551  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
552  .WithMany("InstanceUsers")
553  .HasForeignKey("InstanceId")
554  .OnDelete(DeleteBehavior.Cascade);
555 
556  b.HasOne("Tgstation.Server.Host.Models.User")
557  .WithMany("InstanceUsers")
558  .HasForeignKey("UserId")
559  .OnDelete(DeleteBehavior.Cascade);
560  });
561 
562  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
563  {
564  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
565  .WithMany()
566  .HasForeignKey("CancelledById");
567 
568  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
569  .WithMany("Jobs")
570  .HasForeignKey("InstanceId")
571  .OnDelete(DeleteBehavior.Cascade);
572 
573  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
574  .WithMany()
575  .HasForeignKey("StartedById")
576  .OnDelete(DeleteBehavior.Cascade);
577  });
578 
579  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
580  {
581  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
582  .WithMany()
583  .HasForeignKey("CompileJobId")
584  .OnDelete(DeleteBehavior.Cascade);
585  });
586 
587  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
588  {
589  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
590  .WithOne("RepositorySettings")
591  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
592  .OnDelete(DeleteBehavior.Cascade);
593  });
594 
595  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
596  {
597  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
598  .WithMany("ActiveTestMerges")
599  .HasForeignKey("RevisionInformationId")
600  .OnDelete(DeleteBehavior.Cascade);
601 
602  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
603  .WithMany("RevisonInformations")
604  .HasForeignKey("TestMergeId")
605  .OnDelete(DeleteBehavior.Cascade);
606  });
607 
608  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
609  {
610  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
611  .WithMany("RevisionInformations")
612  .HasForeignKey("InstanceId")
613  .OnDelete(DeleteBehavior.Cascade);
614  });
615 
616  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
617  {
618  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
619  .WithMany("TestMerges")
620  .HasForeignKey("MergedById")
621  .OnDelete(DeleteBehavior.Restrict);
622 
623  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
624  .WithOne("PrimaryTestMerge")
625  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
626  .OnDelete(DeleteBehavior.Restrict);
627  });
628 
629  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
630  {
631  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
632  .WithMany("CreatedUsers")
633  .HasForeignKey("CreatedById");
634  });
635 
636  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
637  {
638  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
639  .WithMany()
640  .HasForeignKey("AlphaId");
641 
642  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
643  .WithMany()
644  .HasForeignKey("BravoId");
645 
646  b.HasOne("Tgstation.Server.Host.Models.Instance")
647  .WithOne("WatchdogReattachInformation")
648  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
649  .OnDelete(DeleteBehavior.Cascade);
650  });
651 #pragma warning restore 612, 618
652  }
653  }
654 }
- +
DatabaseContext<TParentContext> for MySQL
+ + + + +
-Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Metadata;
6 using Microsoft.EntityFrameworkCore.Migrations;
7 using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
8 
10 {
11  [DbContext(typeof(SqlServerDatabaseContext))]
12  [Migration("20181124231534_MSToggleTestmergeComments")]
13  partial class MSToggleTestmergeComments
14  {
19  protected override void BuildTargetModel(ModelBuilder modelBuilder)
20  {
21 #pragma warning disable 612, 618
22  modelBuilder
23  .HasAnnotation("ProductVersion", "2.1.4-rtm-31024")
24  .HasAnnotation("Relational:MaxIdentifierLength", 128)
25  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
26 
27  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
28  {
29  b.Property<long>("Id")
30  .ValueGeneratedOnAdd()
31  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
32 
33  b.Property<string>("ConnectionString")
34  .IsRequired();
35 
36  b.Property<bool?>("Enabled");
37 
38  b.Property<long>("InstanceId");
39 
40  b.Property<string>("Name")
41  .IsRequired();
42 
43  b.Property<int?>("Provider");
44 
45  b.HasKey("Id");
46 
47  b.HasIndex("InstanceId");
48 
49  b.HasIndex("Name")
50  .IsUnique();
51 
52  b.ToTable("ChatBots");
53  });
54 
55  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
56  {
57  b.Property<long>("Id")
58  .ValueGeneratedOnAdd()
59  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
60 
61  b.Property<long>("ChatSettingsId");
62 
63  b.Property<decimal?>("DiscordChannelId")
64  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
65 
66  b.Property<string>("IrcChannel");
67 
68  b.Property<bool?>("IsAdminChannel")
69  .IsRequired();
70 
71  b.Property<bool?>("IsUpdatesChannel")
72  .IsRequired();
73 
74  b.Property<bool?>("IsWatchdogChannel")
75  .IsRequired();
76 
77  b.Property<string>("Tag");
78 
79  b.HasKey("Id");
80 
81  b.HasIndex("ChatSettingsId", "DiscordChannelId")
82  .IsUnique()
83  .HasFilter("[DiscordChannelId] IS NOT NULL");
84 
85  b.HasIndex("ChatSettingsId", "IrcChannel")
86  .IsUnique()
87  .HasFilter("[IrcChannel] IS NOT NULL");
88 
89  b.ToTable("ChatChannels");
90  });
91 
92  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
93  {
94  b.Property<long>("Id")
95  .ValueGeneratedOnAdd()
96  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
97 
98  b.Property<string>("ByondVersion")
99  .IsRequired();
100 
101  b.Property<Guid?>("DirectoryName")
102  .IsRequired();
103 
104  b.Property<string>("DmeName")
105  .IsRequired();
106 
107  b.Property<long>("JobId");
108 
109  b.Property<int>("MinimumSecurityLevel");
110 
111  b.Property<string>("Output")
112  .IsRequired();
113 
114  b.Property<long>("RevisionInformationId");
115 
116  b.HasKey("Id");
117 
118  b.HasIndex("DirectoryName");
119 
120  b.HasIndex("JobId")
121  .IsUnique();
122 
123  b.HasIndex("RevisionInformationId");
124 
125  b.ToTable("CompileJobs");
126  });
127 
128  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
129  {
130  b.Property<long>("Id")
131  .ValueGeneratedOnAdd()
132  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
133 
134  b.Property<string>("AccessToken");
135 
136  b.Property<bool?>("AllowWebClient")
137  .IsRequired();
138 
139  b.Property<bool?>("AutoStart")
140  .IsRequired();
141 
142  b.Property<long>("InstanceId");
143 
144  b.Property<int>("PrimaryPort");
145 
146  b.Property<int?>("ProcessId");
147 
148  b.Property<int>("SecondaryPort");
149 
150  b.Property<int>("SecurityLevel");
151 
152  b.Property<bool?>("SoftRestart")
153  .IsRequired();
154 
155  b.Property<bool?>("SoftShutdown")
156  .IsRequired();
157 
158  b.Property<long>("StartupTimeout");
159 
160  b.HasKey("Id");
161 
162  b.HasIndex("InstanceId")
163  .IsUnique();
164 
165  b.ToTable("DreamDaemonSettings");
166  });
167 
168  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
169  {
170  b.Property<long>("Id")
171  .ValueGeneratedOnAdd()
172  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
173 
174  b.Property<int>("ApiValidationPort");
175 
176  b.Property<int>("ApiValidationSecurityLevel");
177 
178  b.Property<long>("InstanceId");
179 
180  b.Property<string>("ProjectName");
181 
182  b.HasKey("Id");
183 
184  b.HasIndex("InstanceId")
185  .IsUnique();
186 
187  b.ToTable("DreamMakerSettings");
188  });
189 
190  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
191  {
192  b.Property<long>("Id")
193  .ValueGeneratedOnAdd()
194  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
195 
196  b.Property<long>("AutoUpdateInterval");
197 
198  b.Property<int>("ConfigurationType");
199 
200  b.Property<string>("Name")
201  .IsRequired();
202 
203  b.Property<bool?>("Online")
204  .IsRequired();
205 
206  b.Property<string>("Path")
207  .IsRequired();
208 
209  b.HasKey("Id");
210 
211  b.HasIndex("Path")
212  .IsUnique();
213 
214  b.ToTable("Instances");
215  });
216 
217  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
218  {
219  b.Property<long>("Id")
220  .ValueGeneratedOnAdd()
221  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
222 
223  b.Property<decimal>("ByondRights")
224  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
225 
226  b.Property<decimal>("ChatBotRights")
227  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
228 
229  b.Property<decimal>("ConfigurationRights")
230  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
231 
232  b.Property<decimal>("DreamDaemonRights")
233  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
234 
235  b.Property<decimal>("DreamMakerRights")
236  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
237 
238  b.Property<long>("InstanceId");
239 
240  b.Property<decimal>("InstanceUserRights")
241  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
242 
243  b.Property<decimal>("RepositoryRights")
244  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
245 
246  b.Property<long?>("UserId")
247  .IsRequired();
248 
249  b.HasKey("Id");
250 
251  b.HasIndex("InstanceId");
252 
253  b.HasIndex("UserId", "InstanceId")
254  .IsUnique();
255 
256  b.ToTable("InstanceUsers");
257  });
258 
259  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
260  {
261  b.Property<long>("Id")
262  .ValueGeneratedOnAdd()
263  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
264 
265  b.Property<decimal?>("CancelRight")
266  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
267 
268  b.Property<decimal?>("CancelRightsType")
269  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
270 
271  b.Property<bool?>("Cancelled")
272  .IsRequired();
273 
274  b.Property<long?>("CancelledById");
275 
276  b.Property<string>("Description")
277  .IsRequired();
278 
279  b.Property<string>("ExceptionDetails");
280 
281  b.Property<long>("InstanceId");
282 
283  b.Property<DateTimeOffset?>("StartedAt")
284  .IsRequired();
285 
286  b.Property<long>("StartedById");
287 
288  b.Property<DateTimeOffset?>("StoppedAt");
289 
290  b.HasKey("Id");
291 
292  b.HasIndex("CancelledById");
293 
294  b.HasIndex("InstanceId");
295 
296  b.HasIndex("StartedById");
297 
298  b.ToTable("Jobs");
299  });
300 
301  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
302  {
303  b.Property<long>("Id")
304  .ValueGeneratedOnAdd()
305  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
306 
307  b.Property<string>("AccessIdentifier")
308  .IsRequired();
309 
310  b.Property<string>("ChatChannelsJson")
311  .IsRequired();
312 
313  b.Property<string>("ChatCommandsJson")
314  .IsRequired();
315 
316  b.Property<long>("CompileJobId");
317 
318  b.Property<bool>("IsPrimary");
319 
320  b.Property<int>("Port");
321 
322  b.Property<int>("ProcessId");
323 
324  b.Property<int>("RebootState");
325 
326  b.Property<string>("ServerCommandsJson")
327  .IsRequired();
328 
329  b.HasKey("Id");
330 
331  b.HasIndex("CompileJobId");
332 
333  b.ToTable("ReattachInformations");
334  });
335 
336  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
337  {
338  b.Property<long>("Id")
339  .ValueGeneratedOnAdd()
340  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
341 
342  b.Property<string>("AccessToken");
343 
344  b.Property<string>("AccessUser");
345 
346  b.Property<bool?>("AutoUpdatesKeepTestMerges")
347  .IsRequired();
348 
349  b.Property<bool?>("AutoUpdatesSynchronize")
350  .IsRequired();
351 
352  b.Property<string>("CommitterEmail")
353  .IsRequired();
354 
355  b.Property<string>("CommitterName")
356  .IsRequired();
357 
358  b.Property<long>("InstanceId");
359 
360  b.Property<bool?>("PostTestMergeComment")
361  .IsRequired();
362 
363  b.Property<bool?>("PushTestMergeCommits")
364  .IsRequired();
365 
366  b.Property<bool?>("ShowTestMergeCommitters")
367  .IsRequired();
368 
369  b.HasKey("Id");
370 
371  b.HasIndex("InstanceId")
372  .IsUnique();
373 
374  b.ToTable("RepositorySettings");
375  });
376 
377  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
378  {
379  b.Property<long>("Id")
380  .ValueGeneratedOnAdd()
381  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
382 
383  b.Property<long>("RevisionInformationId");
384 
385  b.Property<long>("TestMergeId");
386 
387  b.HasKey("Id");
388 
389  b.HasIndex("RevisionInformationId");
390 
391  b.HasIndex("TestMergeId");
392 
393  b.ToTable("RevInfoTestMerges");
394  });
395 
396  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
397  {
398  b.Property<long>("Id")
399  .ValueGeneratedOnAdd()
400  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
401 
402  b.Property<string>("CommitSha")
403  .IsRequired()
404  .HasMaxLength(40);
405 
406  b.Property<long>("InstanceId");
407 
408  b.Property<string>("OriginCommitSha")
409  .IsRequired()
410  .HasMaxLength(40);
411 
412  b.HasKey("Id");
413 
414  b.HasIndex("CommitSha")
415  .IsUnique();
416 
417  b.HasIndex("InstanceId");
418 
419  b.ToTable("RevisionInformations");
420  });
421 
422  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
423  {
424  b.Property<long>("Id")
425  .ValueGeneratedOnAdd()
426  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
427 
428  b.Property<string>("Author")
429  .IsRequired();
430 
431  b.Property<string>("BodyAtMerge")
432  .IsRequired();
433 
434  b.Property<string>("Comment");
435 
436  b.Property<DateTimeOffset>("MergedAt");
437 
438  b.Property<long>("MergedById");
439 
440  b.Property<int?>("Number")
441  .IsRequired();
442 
443  b.Property<long?>("PrimaryRevisionInformationId")
444  .IsRequired();
445 
446  b.Property<string>("PullRequestRevision")
447  .IsRequired();
448 
449  b.Property<string>("TitleAtMerge")
450  .IsRequired();
451 
452  b.Property<string>("Url")
453  .IsRequired();
454 
455  b.HasKey("Id");
456 
457  b.HasIndex("MergedById");
458 
459  b.HasIndex("PrimaryRevisionInformationId")
460  .IsUnique();
461 
462  b.ToTable("TestMerges");
463  });
464 
465  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
466  {
467  b.Property<long>("Id")
468  .ValueGeneratedOnAdd()
469  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
470 
471  b.Property<decimal>("AdministrationRights")
472  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
473 
474  b.Property<string>("CanonicalName")
475  .IsRequired();
476 
477  b.Property<DateTimeOffset?>("CreatedAt")
478  .IsRequired();
479 
480  b.Property<long?>("CreatedById");
481 
482  b.Property<bool?>("Enabled")
483  .IsRequired();
484 
485  b.Property<decimal>("InstanceManagerRights")
486  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
487 
488  b.Property<DateTimeOffset?>("LastPasswordUpdate");
489 
490  b.Property<string>("Name")
491  .IsRequired();
492 
493  b.Property<string>("PasswordHash");
494 
495  b.Property<string>("SystemIdentifier");
496 
497  b.HasKey("Id");
498 
499  b.HasIndex("CanonicalName")
500  .IsUnique();
501 
502  b.HasIndex("CreatedById");
503 
504  b.ToTable("Users");
505  });
506 
507  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
508  {
509  b.Property<long>("Id")
510  .ValueGeneratedOnAdd()
511  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
512 
513  b.Property<long?>("AlphaId");
514 
515  b.Property<bool>("AlphaIsActive");
516 
517  b.Property<long?>("BravoId");
518 
519  b.Property<long>("InstanceId");
520 
521  b.HasKey("Id");
522 
523  b.HasIndex("AlphaId");
524 
525  b.HasIndex("BravoId");
526 
527  b.HasIndex("InstanceId")
528  .IsUnique();
529 
530  b.ToTable("WatchdogReattachInformations");
531  });
532 
533  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
534  {
535  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
536  .WithMany("ChatSettings")
537  .HasForeignKey("InstanceId")
538  .OnDelete(DeleteBehavior.Cascade);
539  });
540 
541  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
542  {
543  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
544  .WithMany("Channels")
545  .HasForeignKey("ChatSettingsId")
546  .OnDelete(DeleteBehavior.Cascade);
547  });
548 
549  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
550  {
551  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
552  .WithOne()
553  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
554  .OnDelete(DeleteBehavior.Restrict);
555 
556  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
557  .WithMany("CompileJobs")
558  .HasForeignKey("RevisionInformationId")
559  .OnDelete(DeleteBehavior.Cascade);
560  });
561 
562  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
563  {
564  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
565  .WithOne("DreamDaemonSettings")
566  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
567  .OnDelete(DeleteBehavior.Cascade);
568  });
569 
570  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
571  {
572  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
573  .WithOne("DreamMakerSettings")
574  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
575  .OnDelete(DeleteBehavior.Cascade);
576  });
577 
578  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
579  {
580  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
581  .WithMany("InstanceUsers")
582  .HasForeignKey("InstanceId")
583  .OnDelete(DeleteBehavior.Cascade);
584 
585  b.HasOne("Tgstation.Server.Host.Models.User")
586  .WithMany("InstanceUsers")
587  .HasForeignKey("UserId")
588  .OnDelete(DeleteBehavior.Cascade);
589  });
590 
591  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
592  {
593  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
594  .WithMany()
595  .HasForeignKey("CancelledById");
596 
597  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
598  .WithMany("Jobs")
599  .HasForeignKey("InstanceId")
600  .OnDelete(DeleteBehavior.Cascade);
601 
602  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
603  .WithMany()
604  .HasForeignKey("StartedById")
605  .OnDelete(DeleteBehavior.Cascade);
606  });
607 
608  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
609  {
610  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
611  .WithMany()
612  .HasForeignKey("CompileJobId")
613  .OnDelete(DeleteBehavior.Cascade);
614  });
615 
616  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
617  {
618  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
619  .WithOne("RepositorySettings")
620  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
621  .OnDelete(DeleteBehavior.Cascade);
622  });
623 
624  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
625  {
626  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
627  .WithMany("ActiveTestMerges")
628  .HasForeignKey("RevisionInformationId")
629  .OnDelete(DeleteBehavior.Cascade);
630 
631  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
632  .WithMany("RevisonInformations")
633  .HasForeignKey("TestMergeId")
634  .OnDelete(DeleteBehavior.Cascade);
635  });
636 
637  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
638  {
639  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
640  .WithMany("RevisionInformations")
641  .HasForeignKey("InstanceId")
642  .OnDelete(DeleteBehavior.Cascade);
643  });
644 
645  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
646  {
647  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
648  .WithMany("TestMerges")
649  .HasForeignKey("MergedById")
650  .OnDelete(DeleteBehavior.Restrict);
651 
652  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
653  .WithOne("PrimaryTestMerge")
654  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
655  .OnDelete(DeleteBehavior.Restrict);
656  });
657 
658  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
659  {
660  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
661  .WithMany("CreatedUsers")
662  .HasForeignKey("CreatedById");
663  });
664 
665  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
666  {
667  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
668  .WithMany()
669  .HasForeignKey("AlphaId");
670 
671  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
672  .WithMany()
673  .HasForeignKey("BravoId");
674 
675  b.HasOne("Tgstation.Server.Host.Models.Instance")
676  .WithOne("WatchdogReattachInformation")
677  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
678  .OnDelete(DeleteBehavior.Cascade);
679  });
680 #pragma warning restore 612, 618
681  }
682  }
683 }
+Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Metadata;
6 using Microsoft.EntityFrameworkCore.Migrations;
7 using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
9 
11 {
13  [Migration("20181124231534_MSToggleTestmergeComments")]
14  partial class MSToggleTestmergeComments
15  {
20  protected override void BuildTargetModel(ModelBuilder modelBuilder)
21  {
22 #pragma warning disable 612, 618
23  modelBuilder
24  .HasAnnotation("ProductVersion", "2.1.4-rtm-31024")
25  .HasAnnotation("Relational:MaxIdentifierLength", 128)
26  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
27 
28  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
29  {
30  b.Property<long>("Id")
31  .ValueGeneratedOnAdd()
32  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
33 
34  b.Property<string>("ConnectionString")
35  .IsRequired();
36 
37  b.Property<bool?>("Enabled");
38 
39  b.Property<long>("InstanceId");
40 
41  b.Property<string>("Name")
42  .IsRequired();
43 
44  b.Property<int?>("Provider");
45 
46  b.HasKey("Id");
47 
48  b.HasIndex("InstanceId");
49 
50  b.HasIndex("Name")
51  .IsUnique();
52 
53  b.ToTable("ChatBots");
54  });
55 
56  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
57  {
58  b.Property<long>("Id")
59  .ValueGeneratedOnAdd()
60  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
61 
62  b.Property<long>("ChatSettingsId");
63 
64  b.Property<decimal?>("DiscordChannelId")
65  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
66 
67  b.Property<string>("IrcChannel");
68 
69  b.Property<bool?>("IsAdminChannel")
70  .IsRequired();
71 
72  b.Property<bool?>("IsUpdatesChannel")
73  .IsRequired();
74 
75  b.Property<bool?>("IsWatchdogChannel")
76  .IsRequired();
77 
78  b.Property<string>("Tag");
79 
80  b.HasKey("Id");
81 
82  b.HasIndex("ChatSettingsId", "DiscordChannelId")
83  .IsUnique()
84  .HasFilter("[DiscordChannelId] IS NOT NULL");
85 
86  b.HasIndex("ChatSettingsId", "IrcChannel")
87  .IsUnique()
88  .HasFilter("[IrcChannel] IS NOT NULL");
89 
90  b.ToTable("ChatChannels");
91  });
92 
93  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
94  {
95  b.Property<long>("Id")
96  .ValueGeneratedOnAdd()
97  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
98 
99  b.Property<string>("ByondVersion")
100  .IsRequired();
101 
102  b.Property<Guid?>("DirectoryName")
103  .IsRequired();
104 
105  b.Property<string>("DmeName")
106  .IsRequired();
107 
108  b.Property<long>("JobId");
109 
110  b.Property<int>("MinimumSecurityLevel");
111 
112  b.Property<string>("Output")
113  .IsRequired();
114 
115  b.Property<long>("RevisionInformationId");
116 
117  b.HasKey("Id");
118 
119  b.HasIndex("DirectoryName");
120 
121  b.HasIndex("JobId")
122  .IsUnique();
123 
124  b.HasIndex("RevisionInformationId");
125 
126  b.ToTable("CompileJobs");
127  });
128 
129  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
130  {
131  b.Property<long>("Id")
132  .ValueGeneratedOnAdd()
133  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
134 
135  b.Property<string>("AccessToken");
136 
137  b.Property<bool?>("AllowWebClient")
138  .IsRequired();
139 
140  b.Property<bool?>("AutoStart")
141  .IsRequired();
142 
143  b.Property<long>("InstanceId");
144 
145  b.Property<int>("PrimaryPort");
146 
147  b.Property<int?>("ProcessId");
148 
149  b.Property<int>("SecondaryPort");
150 
151  b.Property<int>("SecurityLevel");
152 
153  b.Property<bool?>("SoftRestart")
154  .IsRequired();
155 
156  b.Property<bool?>("SoftShutdown")
157  .IsRequired();
158 
159  b.Property<long>("StartupTimeout");
160 
161  b.HasKey("Id");
162 
163  b.HasIndex("InstanceId")
164  .IsUnique();
165 
166  b.ToTable("DreamDaemonSettings");
167  });
168 
169  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
170  {
171  b.Property<long>("Id")
172  .ValueGeneratedOnAdd()
173  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
174 
175  b.Property<int>("ApiValidationPort");
176 
177  b.Property<int>("ApiValidationSecurityLevel");
178 
179  b.Property<long>("InstanceId");
180 
181  b.Property<string>("ProjectName");
182 
183  b.HasKey("Id");
184 
185  b.HasIndex("InstanceId")
186  .IsUnique();
187 
188  b.ToTable("DreamMakerSettings");
189  });
190 
191  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
192  {
193  b.Property<long>("Id")
194  .ValueGeneratedOnAdd()
195  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
196 
197  b.Property<long>("AutoUpdateInterval");
198 
199  b.Property<int>("ConfigurationType");
200 
201  b.Property<string>("Name")
202  .IsRequired();
203 
204  b.Property<bool?>("Online")
205  .IsRequired();
206 
207  b.Property<string>("Path")
208  .IsRequired();
209 
210  b.HasKey("Id");
211 
212  b.HasIndex("Path")
213  .IsUnique();
214 
215  b.ToTable("Instances");
216  });
217 
218  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
219  {
220  b.Property<long>("Id")
221  .ValueGeneratedOnAdd()
222  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
223 
224  b.Property<decimal>("ByondRights")
225  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
226 
227  b.Property<decimal>("ChatBotRights")
228  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
229 
230  b.Property<decimal>("ConfigurationRights")
231  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
232 
233  b.Property<decimal>("DreamDaemonRights")
234  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
235 
236  b.Property<decimal>("DreamMakerRights")
237  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
238 
239  b.Property<long>("InstanceId");
240 
241  b.Property<decimal>("InstanceUserRights")
242  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
243 
244  b.Property<decimal>("RepositoryRights")
245  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
246 
247  b.Property<long?>("UserId")
248  .IsRequired();
249 
250  b.HasKey("Id");
251 
252  b.HasIndex("InstanceId");
253 
254  b.HasIndex("UserId", "InstanceId")
255  .IsUnique();
256 
257  b.ToTable("InstanceUsers");
258  });
259 
260  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
261  {
262  b.Property<long>("Id")
263  .ValueGeneratedOnAdd()
264  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
265 
266  b.Property<decimal?>("CancelRight")
267  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
268 
269  b.Property<decimal?>("CancelRightsType")
270  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
271 
272  b.Property<bool?>("Cancelled")
273  .IsRequired();
274 
275  b.Property<long?>("CancelledById");
276 
277  b.Property<string>("Description")
278  .IsRequired();
279 
280  b.Property<string>("ExceptionDetails");
281 
282  b.Property<long>("InstanceId");
283 
284  b.Property<DateTimeOffset?>("StartedAt")
285  .IsRequired();
286 
287  b.Property<long>("StartedById");
288 
289  b.Property<DateTimeOffset?>("StoppedAt");
290 
291  b.HasKey("Id");
292 
293  b.HasIndex("CancelledById");
294 
295  b.HasIndex("InstanceId");
296 
297  b.HasIndex("StartedById");
298 
299  b.ToTable("Jobs");
300  });
301 
302  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
303  {
304  b.Property<long>("Id")
305  .ValueGeneratedOnAdd()
306  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
307 
308  b.Property<string>("AccessIdentifier")
309  .IsRequired();
310 
311  b.Property<string>("ChatChannelsJson")
312  .IsRequired();
313 
314  b.Property<string>("ChatCommandsJson")
315  .IsRequired();
316 
317  b.Property<long>("CompileJobId");
318 
319  b.Property<bool>("IsPrimary");
320 
321  b.Property<int>("Port");
322 
323  b.Property<int>("ProcessId");
324 
325  b.Property<int>("RebootState");
326 
327  b.Property<string>("ServerCommandsJson")
328  .IsRequired();
329 
330  b.HasKey("Id");
331 
332  b.HasIndex("CompileJobId");
333 
334  b.ToTable("ReattachInformations");
335  });
336 
337  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
338  {
339  b.Property<long>("Id")
340  .ValueGeneratedOnAdd()
341  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
342 
343  b.Property<string>("AccessToken");
344 
345  b.Property<string>("AccessUser");
346 
347  b.Property<bool?>("AutoUpdatesKeepTestMerges")
348  .IsRequired();
349 
350  b.Property<bool?>("AutoUpdatesSynchronize")
351  .IsRequired();
352 
353  b.Property<string>("CommitterEmail")
354  .IsRequired();
355 
356  b.Property<string>("CommitterName")
357  .IsRequired();
358 
359  b.Property<long>("InstanceId");
360 
361  b.Property<bool?>("PostTestMergeComment")
362  .IsRequired();
363 
364  b.Property<bool?>("PushTestMergeCommits")
365  .IsRequired();
366 
367  b.Property<bool?>("ShowTestMergeCommitters")
368  .IsRequired();
369 
370  b.HasKey("Id");
371 
372  b.HasIndex("InstanceId")
373  .IsUnique();
374 
375  b.ToTable("RepositorySettings");
376  });
377 
378  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
379  {
380  b.Property<long>("Id")
381  .ValueGeneratedOnAdd()
382  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
383 
384  b.Property<long>("RevisionInformationId");
385 
386  b.Property<long>("TestMergeId");
387 
388  b.HasKey("Id");
389 
390  b.HasIndex("RevisionInformationId");
391 
392  b.HasIndex("TestMergeId");
393 
394  b.ToTable("RevInfoTestMerges");
395  });
396 
397  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
398  {
399  b.Property<long>("Id")
400  .ValueGeneratedOnAdd()
401  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
402 
403  b.Property<string>("CommitSha")
404  .IsRequired()
405  .HasMaxLength(40);
406 
407  b.Property<long>("InstanceId");
408 
409  b.Property<string>("OriginCommitSha")
410  .IsRequired()
411  .HasMaxLength(40);
412 
413  b.HasKey("Id");
414 
415  b.HasIndex("CommitSha")
416  .IsUnique();
417 
418  b.HasIndex("InstanceId");
419 
420  b.ToTable("RevisionInformations");
421  });
422 
423  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
424  {
425  b.Property<long>("Id")
426  .ValueGeneratedOnAdd()
427  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
428 
429  b.Property<string>("Author")
430  .IsRequired();
431 
432  b.Property<string>("BodyAtMerge")
433  .IsRequired();
434 
435  b.Property<string>("Comment");
436 
437  b.Property<DateTimeOffset>("MergedAt");
438 
439  b.Property<long>("MergedById");
440 
441  b.Property<int?>("Number")
442  .IsRequired();
443 
444  b.Property<long?>("PrimaryRevisionInformationId")
445  .IsRequired();
446 
447  b.Property<string>("PullRequestRevision")
448  .IsRequired();
449 
450  b.Property<string>("TitleAtMerge")
451  .IsRequired();
452 
453  b.Property<string>("Url")
454  .IsRequired();
455 
456  b.HasKey("Id");
457 
458  b.HasIndex("MergedById");
459 
460  b.HasIndex("PrimaryRevisionInformationId")
461  .IsUnique();
462 
463  b.ToTable("TestMerges");
464  });
465 
466  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
467  {
468  b.Property<long>("Id")
469  .ValueGeneratedOnAdd()
470  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
471 
472  b.Property<decimal>("AdministrationRights")
473  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
474 
475  b.Property<string>("CanonicalName")
476  .IsRequired();
477 
478  b.Property<DateTimeOffset?>("CreatedAt")
479  .IsRequired();
480 
481  b.Property<long?>("CreatedById");
482 
483  b.Property<bool?>("Enabled")
484  .IsRequired();
485 
486  b.Property<decimal>("InstanceManagerRights")
487  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
488 
489  b.Property<DateTimeOffset?>("LastPasswordUpdate");
490 
491  b.Property<string>("Name")
492  .IsRequired();
493 
494  b.Property<string>("PasswordHash");
495 
496  b.Property<string>("SystemIdentifier");
497 
498  b.HasKey("Id");
499 
500  b.HasIndex("CanonicalName")
501  .IsUnique();
502 
503  b.HasIndex("CreatedById");
504 
505  b.ToTable("Users");
506  });
507 
508  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
509  {
510  b.Property<long>("Id")
511  .ValueGeneratedOnAdd()
512  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
513 
514  b.Property<long?>("AlphaId");
515 
516  b.Property<bool>("AlphaIsActive");
517 
518  b.Property<long?>("BravoId");
519 
520  b.Property<long>("InstanceId");
521 
522  b.HasKey("Id");
523 
524  b.HasIndex("AlphaId");
525 
526  b.HasIndex("BravoId");
527 
528  b.HasIndex("InstanceId")
529  .IsUnique();
530 
531  b.ToTable("WatchdogReattachInformations");
532  });
533 
534  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
535  {
536  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
537  .WithMany("ChatSettings")
538  .HasForeignKey("InstanceId")
539  .OnDelete(DeleteBehavior.Cascade);
540  });
541 
542  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
543  {
544  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
545  .WithMany("Channels")
546  .HasForeignKey("ChatSettingsId")
547  .OnDelete(DeleteBehavior.Cascade);
548  });
549 
550  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
551  {
552  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
553  .WithOne()
554  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
555  .OnDelete(DeleteBehavior.Restrict);
556 
557  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
558  .WithMany("CompileJobs")
559  .HasForeignKey("RevisionInformationId")
560  .OnDelete(DeleteBehavior.Cascade);
561  });
562 
563  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
564  {
565  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
566  .WithOne("DreamDaemonSettings")
567  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
568  .OnDelete(DeleteBehavior.Cascade);
569  });
570 
571  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
572  {
573  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
574  .WithOne("DreamMakerSettings")
575  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
576  .OnDelete(DeleteBehavior.Cascade);
577  });
578 
579  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
580  {
581  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
582  .WithMany("InstanceUsers")
583  .HasForeignKey("InstanceId")
584  .OnDelete(DeleteBehavior.Cascade);
585 
586  b.HasOne("Tgstation.Server.Host.Models.User")
587  .WithMany("InstanceUsers")
588  .HasForeignKey("UserId")
589  .OnDelete(DeleteBehavior.Cascade);
590  });
591 
592  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
593  {
594  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
595  .WithMany()
596  .HasForeignKey("CancelledById");
597 
598  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
599  .WithMany("Jobs")
600  .HasForeignKey("InstanceId")
601  .OnDelete(DeleteBehavior.Cascade);
602 
603  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
604  .WithMany()
605  .HasForeignKey("StartedById")
606  .OnDelete(DeleteBehavior.Cascade);
607  });
608 
609  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
610  {
611  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
612  .WithMany()
613  .HasForeignKey("CompileJobId")
614  .OnDelete(DeleteBehavior.Cascade);
615  });
616 
617  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
618  {
619  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
620  .WithOne("RepositorySettings")
621  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
622  .OnDelete(DeleteBehavior.Cascade);
623  });
624 
625  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
626  {
627  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
628  .WithMany("ActiveTestMerges")
629  .HasForeignKey("RevisionInformationId")
630  .OnDelete(DeleteBehavior.Cascade);
631 
632  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
633  .WithMany("RevisonInformations")
634  .HasForeignKey("TestMergeId")
635  .OnDelete(DeleteBehavior.Cascade);
636  });
637 
638  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
639  {
640  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
641  .WithMany("RevisionInformations")
642  .HasForeignKey("InstanceId")
643  .OnDelete(DeleteBehavior.Cascade);
644  });
645 
646  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
647  {
648  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
649  .WithMany("TestMerges")
650  .HasForeignKey("MergedById")
651  .OnDelete(DeleteBehavior.Restrict);
652 
653  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
654  .WithOne("PrimaryTestMerge")
655  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
656  .OnDelete(DeleteBehavior.Restrict);
657  });
658 
659  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
660  {
661  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
662  .WithMany("CreatedUsers")
663  .HasForeignKey("CreatedById");
664  });
665 
666  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
667  {
668  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
669  .WithMany()
670  .HasForeignKey("AlphaId");
671 
672  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
673  .WithMany()
674  .HasForeignKey("BravoId");
675 
676  b.HasOne("Tgstation.Server.Host.Models.Instance")
677  .WithOne("WatchdogReattachInformation")
678  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
679  .OnDelete(DeleteBehavior.Cascade);
680  });
681 #pragma warning restore 612, 618
682  }
683  }
684 }
-
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
+
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
+ +
DatabaseContext<TParentContext> for Sqlserver
+ + +
-Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Migrations;
6 
8 {
9  [DbContext(typeof(MySqlDatabaseContext))]
10  [Migration("20181124231549_MYToggleTestmergeComments")]
11  partial class MYToggleTestmergeComments
12  {
17  protected override void BuildTargetModel(ModelBuilder modelBuilder)
18  {
19 #pragma warning disable 612, 618
20  modelBuilder
21  .HasAnnotation("ProductVersion", "2.1.4-rtm-31024")
22  .HasAnnotation("Relational:MaxIdentifierLength", 64);
23 
24  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
25  {
26  b.Property<long>("Id")
27  .ValueGeneratedOnAdd();
28 
29  b.Property<string>("ConnectionString")
30  .IsRequired();
31 
32  b.Property<bool?>("Enabled");
33 
34  b.Property<long>("InstanceId");
35 
36  b.Property<string>("Name")
37  .IsRequired();
38 
39  b.Property<int?>("Provider");
40 
41  b.HasKey("Id");
42 
43  b.HasIndex("InstanceId");
44 
45  b.HasIndex("Name")
46  .IsUnique();
47 
48  b.ToTable("ChatBots");
49  });
50 
51  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
52  {
53  b.Property<long>("Id")
54  .ValueGeneratedOnAdd();
55 
56  b.Property<long>("ChatSettingsId");
57 
58  b.Property<ulong?>("DiscordChannelId");
59 
60  b.Property<string>("IrcChannel");
61 
62  b.Property<bool?>("IsAdminChannel")
63  .IsRequired();
64 
65  b.Property<bool?>("IsUpdatesChannel")
66  .IsRequired();
67 
68  b.Property<bool?>("IsWatchdogChannel")
69  .IsRequired();
70 
71  b.Property<string>("Tag");
72 
73  b.HasKey("Id");
74 
75  b.HasIndex("ChatSettingsId", "DiscordChannelId")
76  .IsUnique();
77 
78  b.HasIndex("ChatSettingsId", "IrcChannel")
79  .IsUnique();
80 
81  b.ToTable("ChatChannels");
82  });
83 
84  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
85  {
86  b.Property<long>("Id")
87  .ValueGeneratedOnAdd();
88 
89  b.Property<string>("ByondVersion")
90  .IsRequired();
91 
92  b.Property<Guid?>("DirectoryName")
93  .IsRequired();
94 
95  b.Property<string>("DmeName")
96  .IsRequired();
97 
98  b.Property<long>("JobId");
99 
100  b.Property<int>("MinimumSecurityLevel");
101 
102  b.Property<string>("Output")
103  .IsRequired();
104 
105  b.Property<long>("RevisionInformationId");
106 
107  b.HasKey("Id");
108 
109  b.HasIndex("DirectoryName");
110 
111  b.HasIndex("JobId")
112  .IsUnique();
113 
114  b.HasIndex("RevisionInformationId");
115 
116  b.ToTable("CompileJobs");
117  });
118 
119  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
120  {
121  b.Property<long>("Id")
122  .ValueGeneratedOnAdd();
123 
124  b.Property<string>("AccessToken");
125 
126  b.Property<bool?>("AllowWebClient")
127  .IsRequired();
128 
129  b.Property<bool?>("AutoStart")
130  .IsRequired();
131 
132  b.Property<long>("InstanceId");
133 
134  b.Property<ushort?>("PrimaryPort")
135  .IsRequired();
136 
137  b.Property<int?>("ProcessId");
138 
139  b.Property<ushort?>("SecondaryPort")
140  .IsRequired();
141 
142  b.Property<int>("SecurityLevel");
143 
144  b.Property<bool?>("SoftRestart")
145  .IsRequired();
146 
147  b.Property<bool?>("SoftShutdown")
148  .IsRequired();
149 
150  b.Property<uint?>("StartupTimeout")
151  .IsRequired();
152 
153  b.HasKey("Id");
154 
155  b.HasIndex("InstanceId")
156  .IsUnique();
157 
158  b.ToTable("DreamDaemonSettings");
159  });
160 
161  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
162  {
163  b.Property<long>("Id")
164  .ValueGeneratedOnAdd();
165 
166  b.Property<ushort?>("ApiValidationPort")
167  .IsRequired();
168 
169  b.Property<int>("ApiValidationSecurityLevel");
170 
171  b.Property<long>("InstanceId");
172 
173  b.Property<string>("ProjectName");
174 
175  b.HasKey("Id");
176 
177  b.HasIndex("InstanceId")
178  .IsUnique();
179 
180  b.ToTable("DreamMakerSettings");
181  });
182 
183  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
184  {
185  b.Property<long>("Id")
186  .ValueGeneratedOnAdd();
187 
188  b.Property<uint?>("AutoUpdateInterval")
189  .IsRequired();
190 
191  b.Property<int>("ConfigurationType");
192 
193  b.Property<string>("Name")
194  .IsRequired();
195 
196  b.Property<bool?>("Online")
197  .IsRequired();
198 
199  b.Property<string>("Path")
200  .IsRequired();
201 
202  b.HasKey("Id");
203 
204  b.HasIndex("Path")
205  .IsUnique();
206 
207  b.ToTable("Instances");
208  });
209 
210  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
211  {
212  b.Property<long>("Id")
213  .ValueGeneratedOnAdd();
214 
215  b.Property<ulong>("ByondRights");
216 
217  b.Property<ulong>("ChatBotRights");
218 
219  b.Property<ulong>("ConfigurationRights");
220 
221  b.Property<ulong>("DreamDaemonRights");
222 
223  b.Property<ulong>("DreamMakerRights");
224 
225  b.Property<long>("InstanceId");
226 
227  b.Property<ulong>("InstanceUserRights");
228 
229  b.Property<ulong>("RepositoryRights");
230 
231  b.Property<long?>("UserId")
232  .IsRequired();
233 
234  b.HasKey("Id");
235 
236  b.HasIndex("InstanceId");
237 
238  b.HasIndex("UserId", "InstanceId")
239  .IsUnique();
240 
241  b.ToTable("InstanceUsers");
242  });
243 
244  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
245  {
246  b.Property<long>("Id")
247  .ValueGeneratedOnAdd();
248 
249  b.Property<ulong?>("CancelRight");
250 
251  b.Property<ulong?>("CancelRightsType");
252 
253  b.Property<bool?>("Cancelled")
254  .IsRequired();
255 
256  b.Property<long?>("CancelledById");
257 
258  b.Property<string>("Description")
259  .IsRequired();
260 
261  b.Property<string>("ExceptionDetails");
262 
263  b.Property<long>("InstanceId");
264 
265  b.Property<DateTimeOffset?>("StartedAt")
266  .IsRequired();
267 
268  b.Property<long>("StartedById");
269 
270  b.Property<DateTimeOffset?>("StoppedAt");
271 
272  b.HasKey("Id");
273 
274  b.HasIndex("CancelledById");
275 
276  b.HasIndex("InstanceId");
277 
278  b.HasIndex("StartedById");
279 
280  b.ToTable("Jobs");
281  });
282 
283  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
284  {
285  b.Property<long>("Id")
286  .ValueGeneratedOnAdd();
287 
288  b.Property<string>("AccessIdentifier")
289  .IsRequired();
290 
291  b.Property<string>("ChatChannelsJson")
292  .IsRequired();
293 
294  b.Property<string>("ChatCommandsJson")
295  .IsRequired();
296 
297  b.Property<long>("CompileJobId");
298 
299  b.Property<bool>("IsPrimary");
300 
301  b.Property<ushort>("Port");
302 
303  b.Property<int>("ProcessId");
304 
305  b.Property<int>("RebootState");
306 
307  b.Property<string>("ServerCommandsJson")
308  .IsRequired();
309 
310  b.HasKey("Id");
311 
312  b.HasIndex("CompileJobId");
313 
314  b.ToTable("ReattachInformations");
315  });
316 
317  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
318  {
319  b.Property<long>("Id")
320  .ValueGeneratedOnAdd();
321 
322  b.Property<string>("AccessToken");
323 
324  b.Property<string>("AccessUser");
325 
326  b.Property<bool?>("AutoUpdatesKeepTestMerges")
327  .IsRequired();
328 
329  b.Property<bool?>("AutoUpdatesSynchronize")
330  .IsRequired();
331 
332  b.Property<string>("CommitterEmail")
333  .IsRequired();
334 
335  b.Property<string>("CommitterName")
336  .IsRequired();
337 
338  b.Property<long>("InstanceId");
339 
340  b.Property<bool?>("PostTestMergeComment")
341  .IsRequired();
342 
343  b.Property<bool?>("PushTestMergeCommits")
344  .IsRequired();
345 
346  b.Property<bool?>("ShowTestMergeCommitters")
347  .IsRequired();
348 
349  b.HasKey("Id");
350 
351  b.HasIndex("InstanceId")
352  .IsUnique();
353 
354  b.ToTable("RepositorySettings");
355  });
356 
357  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
358  {
359  b.Property<long>("Id")
360  .ValueGeneratedOnAdd();
361 
362  b.Property<long>("RevisionInformationId");
363 
364  b.Property<long>("TestMergeId");
365 
366  b.HasKey("Id");
367 
368  b.HasIndex("RevisionInformationId");
369 
370  b.HasIndex("TestMergeId");
371 
372  b.ToTable("RevInfoTestMerges");
373  });
374 
375  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
376  {
377  b.Property<long>("Id")
378  .ValueGeneratedOnAdd();
379 
380  b.Property<string>("CommitSha")
381  .IsRequired()
382  .HasMaxLength(40);
383 
384  b.Property<long>("InstanceId");
385 
386  b.Property<string>("OriginCommitSha")
387  .IsRequired()
388  .HasMaxLength(40);
389 
390  b.HasKey("Id");
391 
392  b.HasIndex("CommitSha")
393  .IsUnique();
394 
395  b.HasIndex("InstanceId");
396 
397  b.ToTable("RevisionInformations");
398  });
399 
400  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
401  {
402  b.Property<long>("Id")
403  .ValueGeneratedOnAdd();
404 
405  b.Property<string>("Author")
406  .IsRequired();
407 
408  b.Property<string>("BodyAtMerge")
409  .IsRequired();
410 
411  b.Property<string>("Comment");
412 
413  b.Property<DateTimeOffset>("MergedAt");
414 
415  b.Property<long>("MergedById");
416 
417  b.Property<int?>("Number")
418  .IsRequired();
419 
420  b.Property<long?>("PrimaryRevisionInformationId")
421  .IsRequired();
422 
423  b.Property<string>("PullRequestRevision")
424  .IsRequired();
425 
426  b.Property<string>("TitleAtMerge")
427  .IsRequired();
428 
429  b.Property<string>("Url")
430  .IsRequired();
431 
432  b.HasKey("Id");
433 
434  b.HasIndex("MergedById");
435 
436  b.HasIndex("PrimaryRevisionInformationId")
437  .IsUnique();
438 
439  b.ToTable("TestMerges");
440  });
441 
442  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
443  {
444  b.Property<long>("Id")
445  .ValueGeneratedOnAdd();
446 
447  b.Property<ulong>("AdministrationRights");
448 
449  b.Property<string>("CanonicalName")
450  .IsRequired();
451 
452  b.Property<DateTimeOffset?>("CreatedAt")
453  .IsRequired();
454 
455  b.Property<long?>("CreatedById");
456 
457  b.Property<bool?>("Enabled")
458  .IsRequired();
459 
460  b.Property<ulong>("InstanceManagerRights");
461 
462  b.Property<DateTimeOffset?>("LastPasswordUpdate");
463 
464  b.Property<string>("Name")
465  .IsRequired();
466 
467  b.Property<string>("PasswordHash");
468 
469  b.Property<string>("SystemIdentifier");
470 
471  b.HasKey("Id");
472 
473  b.HasIndex("CanonicalName")
474  .IsUnique();
475 
476  b.HasIndex("CreatedById");
477 
478  b.ToTable("Users");
479  });
480 
481  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
482  {
483  b.Property<long>("Id")
484  .ValueGeneratedOnAdd();
485 
486  b.Property<long?>("AlphaId");
487 
488  b.Property<bool>("AlphaIsActive");
489 
490  b.Property<long?>("BravoId");
491 
492  b.Property<long>("InstanceId");
493 
494  b.HasKey("Id");
495 
496  b.HasIndex("AlphaId");
497 
498  b.HasIndex("BravoId");
499 
500  b.HasIndex("InstanceId")
501  .IsUnique();
502 
503  b.ToTable("WatchdogReattachInformations");
504  });
505 
506  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
507  {
508  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
509  .WithMany("ChatSettings")
510  .HasForeignKey("InstanceId")
511  .OnDelete(DeleteBehavior.Cascade);
512  });
513 
514  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
515  {
516  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
517  .WithMany("Channels")
518  .HasForeignKey("ChatSettingsId")
519  .OnDelete(DeleteBehavior.Cascade);
520  });
521 
522  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
523  {
524  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
525  .WithOne()
526  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
527  .OnDelete(DeleteBehavior.Restrict);
528 
529  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
530  .WithMany("CompileJobs")
531  .HasForeignKey("RevisionInformationId")
532  .OnDelete(DeleteBehavior.Cascade);
533  });
534 
535  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
536  {
537  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
538  .WithOne("DreamDaemonSettings")
539  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
540  .OnDelete(DeleteBehavior.Cascade);
541  });
542 
543  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
544  {
545  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
546  .WithOne("DreamMakerSettings")
547  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
548  .OnDelete(DeleteBehavior.Cascade);
549  });
550 
551  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
552  {
553  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
554  .WithMany("InstanceUsers")
555  .HasForeignKey("InstanceId")
556  .OnDelete(DeleteBehavior.Cascade);
557 
558  b.HasOne("Tgstation.Server.Host.Models.User")
559  .WithMany("InstanceUsers")
560  .HasForeignKey("UserId")
561  .OnDelete(DeleteBehavior.Cascade);
562  });
563 
564  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
565  {
566  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
567  .WithMany()
568  .HasForeignKey("CancelledById");
569 
570  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
571  .WithMany("Jobs")
572  .HasForeignKey("InstanceId")
573  .OnDelete(DeleteBehavior.Cascade);
574 
575  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
576  .WithMany()
577  .HasForeignKey("StartedById")
578  .OnDelete(DeleteBehavior.Cascade);
579  });
580 
581  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
582  {
583  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
584  .WithMany()
585  .HasForeignKey("CompileJobId")
586  .OnDelete(DeleteBehavior.Cascade);
587  });
588 
589  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
590  {
591  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
592  .WithOne("RepositorySettings")
593  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
594  .OnDelete(DeleteBehavior.Cascade);
595  });
596 
597  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
598  {
599  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
600  .WithMany("ActiveTestMerges")
601  .HasForeignKey("RevisionInformationId")
602  .OnDelete(DeleteBehavior.Cascade);
603 
604  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
605  .WithMany("RevisonInformations")
606  .HasForeignKey("TestMergeId")
607  .OnDelete(DeleteBehavior.Cascade);
608  });
609 
610  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
611  {
612  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
613  .WithMany("RevisionInformations")
614  .HasForeignKey("InstanceId")
615  .OnDelete(DeleteBehavior.Cascade);
616  });
617 
618  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
619  {
620  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
621  .WithMany("TestMerges")
622  .HasForeignKey("MergedById")
623  .OnDelete(DeleteBehavior.Restrict);
624 
625  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
626  .WithOne("PrimaryTestMerge")
627  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
628  .OnDelete(DeleteBehavior.Restrict);
629  });
630 
631  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
632  {
633  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
634  .WithMany("CreatedUsers")
635  .HasForeignKey("CreatedById");
636  });
637 
638  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
639  {
640  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
641  .WithMany()
642  .HasForeignKey("AlphaId");
643 
644  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
645  .WithMany()
646  .HasForeignKey("BravoId");
647 
648  b.HasOne("Tgstation.Server.Host.Models.Instance")
649  .WithOne("WatchdogReattachInformation")
650  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
651  .OnDelete(DeleteBehavior.Cascade);
652  });
653 #pragma warning restore 612, 618
654  }
655  }
656 }
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
+Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Migrations;
7 
9 {
11  [Migration("20181124231549_MYToggleTestmergeComments")]
12  partial class MYToggleTestmergeComments
13  {
18  protected override void BuildTargetModel(ModelBuilder modelBuilder)
19  {
20 #pragma warning disable 612, 618
21  modelBuilder
22  .HasAnnotation("ProductVersion", "2.1.4-rtm-31024")
23  .HasAnnotation("Relational:MaxIdentifierLength", 64);
24 
25  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
26  {
27  b.Property<long>("Id")
28  .ValueGeneratedOnAdd();
29 
30  b.Property<string>("ConnectionString")
31  .IsRequired();
32 
33  b.Property<bool?>("Enabled");
34 
35  b.Property<long>("InstanceId");
36 
37  b.Property<string>("Name")
38  .IsRequired();
39 
40  b.Property<int?>("Provider");
41 
42  b.HasKey("Id");
43 
44  b.HasIndex("InstanceId");
45 
46  b.HasIndex("Name")
47  .IsUnique();
48 
49  b.ToTable("ChatBots");
50  });
51 
52  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
53  {
54  b.Property<long>("Id")
55  .ValueGeneratedOnAdd();
56 
57  b.Property<long>("ChatSettingsId");
58 
59  b.Property<ulong?>("DiscordChannelId");
60 
61  b.Property<string>("IrcChannel");
62 
63  b.Property<bool?>("IsAdminChannel")
64  .IsRequired();
65 
66  b.Property<bool?>("IsUpdatesChannel")
67  .IsRequired();
68 
69  b.Property<bool?>("IsWatchdogChannel")
70  .IsRequired();
71 
72  b.Property<string>("Tag");
73 
74  b.HasKey("Id");
75 
76  b.HasIndex("ChatSettingsId", "DiscordChannelId")
77  .IsUnique();
78 
79  b.HasIndex("ChatSettingsId", "IrcChannel")
80  .IsUnique();
81 
82  b.ToTable("ChatChannels");
83  });
84 
85  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
86  {
87  b.Property<long>("Id")
88  .ValueGeneratedOnAdd();
89 
90  b.Property<string>("ByondVersion")
91  .IsRequired();
92 
93  b.Property<Guid?>("DirectoryName")
94  .IsRequired();
95 
96  b.Property<string>("DmeName")
97  .IsRequired();
98 
99  b.Property<long>("JobId");
100 
101  b.Property<int>("MinimumSecurityLevel");
102 
103  b.Property<string>("Output")
104  .IsRequired();
105 
106  b.Property<long>("RevisionInformationId");
107 
108  b.HasKey("Id");
109 
110  b.HasIndex("DirectoryName");
111 
112  b.HasIndex("JobId")
113  .IsUnique();
114 
115  b.HasIndex("RevisionInformationId");
116 
117  b.ToTable("CompileJobs");
118  });
119 
120  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
121  {
122  b.Property<long>("Id")
123  .ValueGeneratedOnAdd();
124 
125  b.Property<string>("AccessToken");
126 
127  b.Property<bool?>("AllowWebClient")
128  .IsRequired();
129 
130  b.Property<bool?>("AutoStart")
131  .IsRequired();
132 
133  b.Property<long>("InstanceId");
134 
135  b.Property<ushort?>("PrimaryPort")
136  .IsRequired();
137 
138  b.Property<int?>("ProcessId");
139 
140  b.Property<ushort?>("SecondaryPort")
141  .IsRequired();
142 
143  b.Property<int>("SecurityLevel");
144 
145  b.Property<bool?>("SoftRestart")
146  .IsRequired();
147 
148  b.Property<bool?>("SoftShutdown")
149  .IsRequired();
150 
151  b.Property<uint?>("StartupTimeout")
152  .IsRequired();
153 
154  b.HasKey("Id");
155 
156  b.HasIndex("InstanceId")
157  .IsUnique();
158 
159  b.ToTable("DreamDaemonSettings");
160  });
161 
162  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
163  {
164  b.Property<long>("Id")
165  .ValueGeneratedOnAdd();
166 
167  b.Property<ushort?>("ApiValidationPort")
168  .IsRequired();
169 
170  b.Property<int>("ApiValidationSecurityLevel");
171 
172  b.Property<long>("InstanceId");
173 
174  b.Property<string>("ProjectName");
175 
176  b.HasKey("Id");
177 
178  b.HasIndex("InstanceId")
179  .IsUnique();
180 
181  b.ToTable("DreamMakerSettings");
182  });
183 
184  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
185  {
186  b.Property<long>("Id")
187  .ValueGeneratedOnAdd();
188 
189  b.Property<uint?>("AutoUpdateInterval")
190  .IsRequired();
191 
192  b.Property<int>("ConfigurationType");
193 
194  b.Property<string>("Name")
195  .IsRequired();
196 
197  b.Property<bool?>("Online")
198  .IsRequired();
199 
200  b.Property<string>("Path")
201  .IsRequired();
202 
203  b.HasKey("Id");
204 
205  b.HasIndex("Path")
206  .IsUnique();
207 
208  b.ToTable("Instances");
209  });
210 
211  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
212  {
213  b.Property<long>("Id")
214  .ValueGeneratedOnAdd();
215 
216  b.Property<ulong>("ByondRights");
217 
218  b.Property<ulong>("ChatBotRights");
219 
220  b.Property<ulong>("ConfigurationRights");
221 
222  b.Property<ulong>("DreamDaemonRights");
223 
224  b.Property<ulong>("DreamMakerRights");
225 
226  b.Property<long>("InstanceId");
227 
228  b.Property<ulong>("InstanceUserRights");
229 
230  b.Property<ulong>("RepositoryRights");
231 
232  b.Property<long?>("UserId")
233  .IsRequired();
234 
235  b.HasKey("Id");
236 
237  b.HasIndex("InstanceId");
238 
239  b.HasIndex("UserId", "InstanceId")
240  .IsUnique();
241 
242  b.ToTable("InstanceUsers");
243  });
244 
245  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
246  {
247  b.Property<long>("Id")
248  .ValueGeneratedOnAdd();
249 
250  b.Property<ulong?>("CancelRight");
251 
252  b.Property<ulong?>("CancelRightsType");
253 
254  b.Property<bool?>("Cancelled")
255  .IsRequired();
256 
257  b.Property<long?>("CancelledById");
258 
259  b.Property<string>("Description")
260  .IsRequired();
261 
262  b.Property<string>("ExceptionDetails");
263 
264  b.Property<long>("InstanceId");
265 
266  b.Property<DateTimeOffset?>("StartedAt")
267  .IsRequired();
268 
269  b.Property<long>("StartedById");
270 
271  b.Property<DateTimeOffset?>("StoppedAt");
272 
273  b.HasKey("Id");
274 
275  b.HasIndex("CancelledById");
276 
277  b.HasIndex("InstanceId");
278 
279  b.HasIndex("StartedById");
280 
281  b.ToTable("Jobs");
282  });
283 
284  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
285  {
286  b.Property<long>("Id")
287  .ValueGeneratedOnAdd();
288 
289  b.Property<string>("AccessIdentifier")
290  .IsRequired();
291 
292  b.Property<string>("ChatChannelsJson")
293  .IsRequired();
294 
295  b.Property<string>("ChatCommandsJson")
296  .IsRequired();
297 
298  b.Property<long>("CompileJobId");
299 
300  b.Property<bool>("IsPrimary");
301 
302  b.Property<ushort>("Port");
303 
304  b.Property<int>("ProcessId");
305 
306  b.Property<int>("RebootState");
307 
308  b.Property<string>("ServerCommandsJson")
309  .IsRequired();
310 
311  b.HasKey("Id");
312 
313  b.HasIndex("CompileJobId");
314 
315  b.ToTable("ReattachInformations");
316  });
317 
318  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
319  {
320  b.Property<long>("Id")
321  .ValueGeneratedOnAdd();
322 
323  b.Property<string>("AccessToken");
324 
325  b.Property<string>("AccessUser");
326 
327  b.Property<bool?>("AutoUpdatesKeepTestMerges")
328  .IsRequired();
329 
330  b.Property<bool?>("AutoUpdatesSynchronize")
331  .IsRequired();
332 
333  b.Property<string>("CommitterEmail")
334  .IsRequired();
335 
336  b.Property<string>("CommitterName")
337  .IsRequired();
338 
339  b.Property<long>("InstanceId");
340 
341  b.Property<bool?>("PostTestMergeComment")
342  .IsRequired();
343 
344  b.Property<bool?>("PushTestMergeCommits")
345  .IsRequired();
346 
347  b.Property<bool?>("ShowTestMergeCommitters")
348  .IsRequired();
349 
350  b.HasKey("Id");
351 
352  b.HasIndex("InstanceId")
353  .IsUnique();
354 
355  b.ToTable("RepositorySettings");
356  });
357 
358  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
359  {
360  b.Property<long>("Id")
361  .ValueGeneratedOnAdd();
362 
363  b.Property<long>("RevisionInformationId");
364 
365  b.Property<long>("TestMergeId");
366 
367  b.HasKey("Id");
368 
369  b.HasIndex("RevisionInformationId");
370 
371  b.HasIndex("TestMergeId");
372 
373  b.ToTable("RevInfoTestMerges");
374  });
375 
376  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
377  {
378  b.Property<long>("Id")
379  .ValueGeneratedOnAdd();
380 
381  b.Property<string>("CommitSha")
382  .IsRequired()
383  .HasMaxLength(40);
384 
385  b.Property<long>("InstanceId");
386 
387  b.Property<string>("OriginCommitSha")
388  .IsRequired()
389  .HasMaxLength(40);
390 
391  b.HasKey("Id");
392 
393  b.HasIndex("CommitSha")
394  .IsUnique();
395 
396  b.HasIndex("InstanceId");
397 
398  b.ToTable("RevisionInformations");
399  });
400 
401  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
402  {
403  b.Property<long>("Id")
404  .ValueGeneratedOnAdd();
405 
406  b.Property<string>("Author")
407  .IsRequired();
408 
409  b.Property<string>("BodyAtMerge")
410  .IsRequired();
411 
412  b.Property<string>("Comment");
413 
414  b.Property<DateTimeOffset>("MergedAt");
415 
416  b.Property<long>("MergedById");
417 
418  b.Property<int?>("Number")
419  .IsRequired();
420 
421  b.Property<long?>("PrimaryRevisionInformationId")
422  .IsRequired();
423 
424  b.Property<string>("PullRequestRevision")
425  .IsRequired();
426 
427  b.Property<string>("TitleAtMerge")
428  .IsRequired();
429 
430  b.Property<string>("Url")
431  .IsRequired();
432 
433  b.HasKey("Id");
434 
435  b.HasIndex("MergedById");
436 
437  b.HasIndex("PrimaryRevisionInformationId")
438  .IsUnique();
439 
440  b.ToTable("TestMerges");
441  });
442 
443  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
444  {
445  b.Property<long>("Id")
446  .ValueGeneratedOnAdd();
447 
448  b.Property<ulong>("AdministrationRights");
449 
450  b.Property<string>("CanonicalName")
451  .IsRequired();
452 
453  b.Property<DateTimeOffset?>("CreatedAt")
454  .IsRequired();
455 
456  b.Property<long?>("CreatedById");
457 
458  b.Property<bool?>("Enabled")
459  .IsRequired();
460 
461  b.Property<ulong>("InstanceManagerRights");
462 
463  b.Property<DateTimeOffset?>("LastPasswordUpdate");
464 
465  b.Property<string>("Name")
466  .IsRequired();
467 
468  b.Property<string>("PasswordHash");
469 
470  b.Property<string>("SystemIdentifier");
471 
472  b.HasKey("Id");
473 
474  b.HasIndex("CanonicalName")
475  .IsUnique();
476 
477  b.HasIndex("CreatedById");
478 
479  b.ToTable("Users");
480  });
481 
482  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
483  {
484  b.Property<long>("Id")
485  .ValueGeneratedOnAdd();
486 
487  b.Property<long?>("AlphaId");
488 
489  b.Property<bool>("AlphaIsActive");
490 
491  b.Property<long?>("BravoId");
492 
493  b.Property<long>("InstanceId");
494 
495  b.HasKey("Id");
496 
497  b.HasIndex("AlphaId");
498 
499  b.HasIndex("BravoId");
500 
501  b.HasIndex("InstanceId")
502  .IsUnique();
503 
504  b.ToTable("WatchdogReattachInformations");
505  });
506 
507  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
508  {
509  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
510  .WithMany("ChatSettings")
511  .HasForeignKey("InstanceId")
512  .OnDelete(DeleteBehavior.Cascade);
513  });
514 
515  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
516  {
517  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
518  .WithMany("Channels")
519  .HasForeignKey("ChatSettingsId")
520  .OnDelete(DeleteBehavior.Cascade);
521  });
522 
523  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
524  {
525  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
526  .WithOne()
527  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
528  .OnDelete(DeleteBehavior.Restrict);
529 
530  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
531  .WithMany("CompileJobs")
532  .HasForeignKey("RevisionInformationId")
533  .OnDelete(DeleteBehavior.Cascade);
534  });
535 
536  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
537  {
538  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
539  .WithOne("DreamDaemonSettings")
540  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
541  .OnDelete(DeleteBehavior.Cascade);
542  });
543 
544  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
545  {
546  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
547  .WithOne("DreamMakerSettings")
548  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
549  .OnDelete(DeleteBehavior.Cascade);
550  });
551 
552  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
553  {
554  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
555  .WithMany("InstanceUsers")
556  .HasForeignKey("InstanceId")
557  .OnDelete(DeleteBehavior.Cascade);
558 
559  b.HasOne("Tgstation.Server.Host.Models.User")
560  .WithMany("InstanceUsers")
561  .HasForeignKey("UserId")
562  .OnDelete(DeleteBehavior.Cascade);
563  });
564 
565  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
566  {
567  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
568  .WithMany()
569  .HasForeignKey("CancelledById");
570 
571  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
572  .WithMany("Jobs")
573  .HasForeignKey("InstanceId")
574  .OnDelete(DeleteBehavior.Cascade);
575 
576  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
577  .WithMany()
578  .HasForeignKey("StartedById")
579  .OnDelete(DeleteBehavior.Cascade);
580  });
581 
582  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
583  {
584  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
585  .WithMany()
586  .HasForeignKey("CompileJobId")
587  .OnDelete(DeleteBehavior.Cascade);
588  });
589 
590  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
591  {
592  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
593  .WithOne("RepositorySettings")
594  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
595  .OnDelete(DeleteBehavior.Cascade);
596  });
597 
598  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
599  {
600  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
601  .WithMany("ActiveTestMerges")
602  .HasForeignKey("RevisionInformationId")
603  .OnDelete(DeleteBehavior.Cascade);
604 
605  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
606  .WithMany("RevisonInformations")
607  .HasForeignKey("TestMergeId")
608  .OnDelete(DeleteBehavior.Cascade);
609  });
610 
611  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
612  {
613  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
614  .WithMany("RevisionInformations")
615  .HasForeignKey("InstanceId")
616  .OnDelete(DeleteBehavior.Cascade);
617  });
618 
619  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
620  {
621  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
622  .WithMany("TestMerges")
623  .HasForeignKey("MergedById")
624  .OnDelete(DeleteBehavior.Restrict);
625 
626  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
627  .WithOne("PrimaryTestMerge")
628  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
629  .OnDelete(DeleteBehavior.Restrict);
630  });
631 
632  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
633  {
634  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
635  .WithMany("CreatedUsers")
636  .HasForeignKey("CreatedById");
637  });
638 
639  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
640  {
641  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
642  .WithMany()
643  .HasForeignKey("AlphaId");
644 
645  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
646  .WithMany()
647  .HasForeignKey("BravoId");
648 
649  b.HasOne("Tgstation.Server.Host.Models.Instance")
650  .WithOne("WatchdogReattachInformation")
651  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
652  .OnDelete(DeleteBehavior.Cascade);
653  });
654 #pragma warning restore 612, 618
655  }
656  }
657 }
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
+
DatabaseContext<TParentContext> for MySQL
+ + + +
-Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Metadata;
6 using Microsoft.EntityFrameworkCore.Migrations;
7 using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
8 
10 {
11  [DbContext(typeof(SqlServerDatabaseContext))]
12  [Migration("20190219041825_MSFixRevInfoIndex")]
13  partial class MSFixRevInfoIndex
14  {
19  protected override void BuildTargetModel(ModelBuilder modelBuilder)
20  {
21 #pragma warning disable 612, 618
22  modelBuilder
23  .HasAnnotation("ProductVersion", "2.1.4-rtm-31024")
24  .HasAnnotation("Relational:MaxIdentifierLength", 128)
25  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
26 
27  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
28  {
29  b.Property<long>("Id")
30  .ValueGeneratedOnAdd()
31  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
32 
33  b.Property<string>("ConnectionString")
34  .IsRequired();
35 
36  b.Property<bool?>("Enabled");
37 
38  b.Property<long>("InstanceId");
39 
40  b.Property<string>("Name")
41  .IsRequired();
42 
43  b.Property<int?>("Provider");
44 
45  b.HasKey("Id");
46 
47  b.HasIndex("InstanceId");
48 
49  b.HasIndex("Name")
50  .IsUnique();
51 
52  b.ToTable("ChatBots");
53  });
54 
55  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
56  {
57  b.Property<long>("Id")
58  .ValueGeneratedOnAdd()
59  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
60 
61  b.Property<long>("ChatSettingsId");
62 
63  b.Property<decimal?>("DiscordChannelId")
64  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
65 
66  b.Property<string>("IrcChannel");
67 
68  b.Property<bool?>("IsAdminChannel")
69  .IsRequired();
70 
71  b.Property<bool?>("IsUpdatesChannel")
72  .IsRequired();
73 
74  b.Property<bool?>("IsWatchdogChannel")
75  .IsRequired();
76 
77  b.Property<string>("Tag");
78 
79  b.HasKey("Id");
80 
81  b.HasIndex("ChatSettingsId", "DiscordChannelId")
82  .IsUnique()
83  .HasFilter("[DiscordChannelId] IS NOT NULL");
84 
85  b.HasIndex("ChatSettingsId", "IrcChannel")
86  .IsUnique()
87  .HasFilter("[IrcChannel] IS NOT NULL");
88 
89  b.ToTable("ChatChannels");
90  });
91 
92  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
93  {
94  b.Property<long>("Id")
95  .ValueGeneratedOnAdd()
96  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
97 
98  b.Property<string>("ByondVersion")
99  .IsRequired();
100 
101  b.Property<Guid?>("DirectoryName")
102  .IsRequired();
103 
104  b.Property<string>("DmeName")
105  .IsRequired();
106 
107  b.Property<long>("JobId");
108 
109  b.Property<int>("MinimumSecurityLevel");
110 
111  b.Property<string>("Output")
112  .IsRequired();
113 
114  b.Property<long>("RevisionInformationId");
115 
116  b.HasKey("Id");
117 
118  b.HasIndex("DirectoryName");
119 
120  b.HasIndex("JobId")
121  .IsUnique();
122 
123  b.HasIndex("RevisionInformationId");
124 
125  b.ToTable("CompileJobs");
126  });
127 
128  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
129  {
130  b.Property<long>("Id")
131  .ValueGeneratedOnAdd()
132  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
133 
134  b.Property<string>("AccessToken");
135 
136  b.Property<bool?>("AllowWebClient")
137  .IsRequired();
138 
139  b.Property<bool?>("AutoStart")
140  .IsRequired();
141 
142  b.Property<long>("InstanceId");
143 
144  b.Property<int>("PrimaryPort");
145 
146  b.Property<int?>("ProcessId");
147 
148  b.Property<int>("SecondaryPort");
149 
150  b.Property<int>("SecurityLevel");
151 
152  b.Property<bool?>("SoftRestart")
153  .IsRequired();
154 
155  b.Property<bool?>("SoftShutdown")
156  .IsRequired();
157 
158  b.Property<long>("StartupTimeout");
159 
160  b.HasKey("Id");
161 
162  b.HasIndex("InstanceId")
163  .IsUnique();
164 
165  b.ToTable("DreamDaemonSettings");
166  });
167 
168  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
169  {
170  b.Property<long>("Id")
171  .ValueGeneratedOnAdd()
172  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
173 
174  b.Property<int>("ApiValidationPort");
175 
176  b.Property<int>("ApiValidationSecurityLevel");
177 
178  b.Property<long>("InstanceId");
179 
180  b.Property<string>("ProjectName");
181 
182  b.HasKey("Id");
183 
184  b.HasIndex("InstanceId")
185  .IsUnique();
186 
187  b.ToTable("DreamMakerSettings");
188  });
189 
190  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
191  {
192  b.Property<long>("Id")
193  .ValueGeneratedOnAdd()
194  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
195 
196  b.Property<long>("AutoUpdateInterval");
197 
198  b.Property<int>("ConfigurationType");
199 
200  b.Property<string>("Name")
201  .IsRequired();
202 
203  b.Property<bool?>("Online")
204  .IsRequired();
205 
206  b.Property<string>("Path")
207  .IsRequired();
208 
209  b.HasKey("Id");
210 
211  b.HasIndex("Path")
212  .IsUnique();
213 
214  b.ToTable("Instances");
215  });
216 
217  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
218  {
219  b.Property<long>("Id")
220  .ValueGeneratedOnAdd()
221  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
222 
223  b.Property<decimal>("ByondRights")
224  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
225 
226  b.Property<decimal>("ChatBotRights")
227  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
228 
229  b.Property<decimal>("ConfigurationRights")
230  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
231 
232  b.Property<decimal>("DreamDaemonRights")
233  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
234 
235  b.Property<decimal>("DreamMakerRights")
236  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
237 
238  b.Property<long>("InstanceId");
239 
240  b.Property<decimal>("InstanceUserRights")
241  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
242 
243  b.Property<decimal>("RepositoryRights")
244  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
245 
246  b.Property<long?>("UserId")
247  .IsRequired();
248 
249  b.HasKey("Id");
250 
251  b.HasIndex("InstanceId");
252 
253  b.HasIndex("UserId", "InstanceId")
254  .IsUnique();
255 
256  b.ToTable("InstanceUsers");
257  });
258 
259  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
260  {
261  b.Property<long>("Id")
262  .ValueGeneratedOnAdd()
263  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
264 
265  b.Property<decimal?>("CancelRight")
266  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
267 
268  b.Property<decimal?>("CancelRightsType")
269  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
270 
271  b.Property<bool?>("Cancelled")
272  .IsRequired();
273 
274  b.Property<long?>("CancelledById");
275 
276  b.Property<string>("Description")
277  .IsRequired();
278 
279  b.Property<string>("ExceptionDetails");
280 
281  b.Property<long>("InstanceId");
282 
283  b.Property<DateTimeOffset?>("StartedAt")
284  .IsRequired();
285 
286  b.Property<long>("StartedById");
287 
288  b.Property<DateTimeOffset?>("StoppedAt");
289 
290  b.HasKey("Id");
291 
292  b.HasIndex("CancelledById");
293 
294  b.HasIndex("InstanceId");
295 
296  b.HasIndex("StartedById");
297 
298  b.ToTable("Jobs");
299  });
300 
301  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
302  {
303  b.Property<long>("Id")
304  .ValueGeneratedOnAdd()
305  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
306 
307  b.Property<string>("AccessIdentifier")
308  .IsRequired();
309 
310  b.Property<string>("ChatChannelsJson")
311  .IsRequired();
312 
313  b.Property<string>("ChatCommandsJson")
314  .IsRequired();
315 
316  b.Property<long>("CompileJobId");
317 
318  b.Property<bool>("IsPrimary");
319 
320  b.Property<int>("Port");
321 
322  b.Property<int>("ProcessId");
323 
324  b.Property<int>("RebootState");
325 
326  b.Property<string>("ServerCommandsJson")
327  .IsRequired();
328 
329  b.HasKey("Id");
330 
331  b.HasIndex("CompileJobId");
332 
333  b.ToTable("ReattachInformations");
334  });
335 
336  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
337  {
338  b.Property<long>("Id")
339  .ValueGeneratedOnAdd()
340  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
341 
342  b.Property<string>("AccessToken");
343 
344  b.Property<string>("AccessUser");
345 
346  b.Property<bool?>("AutoUpdatesKeepTestMerges")
347  .IsRequired();
348 
349  b.Property<bool?>("AutoUpdatesSynchronize")
350  .IsRequired();
351 
352  b.Property<string>("CommitterEmail")
353  .IsRequired();
354 
355  b.Property<string>("CommitterName")
356  .IsRequired();
357 
358  b.Property<long>("InstanceId");
359 
360  b.Property<bool?>("PostTestMergeComment")
361  .IsRequired();
362 
363  b.Property<bool?>("PushTestMergeCommits")
364  .IsRequired();
365 
366  b.Property<bool?>("ShowTestMergeCommitters")
367  .IsRequired();
368 
369  b.HasKey("Id");
370 
371  b.HasIndex("InstanceId")
372  .IsUnique();
373 
374  b.ToTable("RepositorySettings");
375  });
376 
377  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
378  {
379  b.Property<long>("Id")
380  .ValueGeneratedOnAdd()
381  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
382 
383  b.Property<long>("RevisionInformationId");
384 
385  b.Property<long>("TestMergeId");
386 
387  b.HasKey("Id");
388 
389  b.HasIndex("RevisionInformationId");
390 
391  b.HasIndex("TestMergeId");
392 
393  b.ToTable("RevInfoTestMerges");
394  });
395 
396  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
397  {
398  b.Property<long>("Id")
399  .ValueGeneratedOnAdd()
400  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
401 
402  b.Property<string>("CommitSha")
403  .IsRequired()
404  .HasMaxLength(40);
405 
406  b.Property<long>("InstanceId");
407 
408  b.Property<string>("OriginCommitSha")
409  .IsRequired()
410  .HasMaxLength(40);
411 
412  b.HasKey("Id");
413 
414  b.HasIndex("InstanceId", "CommitSha")
415  .IsUnique();
416 
417  b.ToTable("RevisionInformations");
418  });
419 
420  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
421  {
422  b.Property<long>("Id")
423  .ValueGeneratedOnAdd()
424  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
425 
426  b.Property<string>("Author")
427  .IsRequired();
428 
429  b.Property<string>("BodyAtMerge")
430  .IsRequired();
431 
432  b.Property<string>("Comment");
433 
434  b.Property<DateTimeOffset>("MergedAt");
435 
436  b.Property<long>("MergedById");
437 
438  b.Property<int?>("Number")
439  .IsRequired();
440 
441  b.Property<long?>("PrimaryRevisionInformationId")
442  .IsRequired();
443 
444  b.Property<string>("PullRequestRevision")
445  .IsRequired();
446 
447  b.Property<string>("TitleAtMerge")
448  .IsRequired();
449 
450  b.Property<string>("Url")
451  .IsRequired();
452 
453  b.HasKey("Id");
454 
455  b.HasIndex("MergedById");
456 
457  b.HasIndex("PrimaryRevisionInformationId")
458  .IsUnique();
459 
460  b.ToTable("TestMerges");
461  });
462 
463  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
464  {
465  b.Property<long>("Id")
466  .ValueGeneratedOnAdd()
467  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
468 
469  b.Property<decimal>("AdministrationRights")
470  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
471 
472  b.Property<string>("CanonicalName")
473  .IsRequired();
474 
475  b.Property<DateTimeOffset?>("CreatedAt")
476  .IsRequired();
477 
478  b.Property<long?>("CreatedById");
479 
480  b.Property<bool?>("Enabled")
481  .IsRequired();
482 
483  b.Property<decimal>("InstanceManagerRights")
484  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
485 
486  b.Property<DateTimeOffset?>("LastPasswordUpdate");
487 
488  b.Property<string>("Name")
489  .IsRequired();
490 
491  b.Property<string>("PasswordHash");
492 
493  b.Property<string>("SystemIdentifier");
494 
495  b.HasKey("Id");
496 
497  b.HasIndex("CanonicalName")
498  .IsUnique();
499 
500  b.HasIndex("CreatedById");
501 
502  b.ToTable("Users");
503  });
504 
505  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
506  {
507  b.Property<long>("Id")
508  .ValueGeneratedOnAdd()
509  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
510 
511  b.Property<long?>("AlphaId");
512 
513  b.Property<bool>("AlphaIsActive");
514 
515  b.Property<long?>("BravoId");
516 
517  b.Property<long>("InstanceId");
518 
519  b.HasKey("Id");
520 
521  b.HasIndex("AlphaId");
522 
523  b.HasIndex("BravoId");
524 
525  b.HasIndex("InstanceId")
526  .IsUnique();
527 
528  b.ToTable("WatchdogReattachInformations");
529  });
530 
531  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
532  {
533  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
534  .WithMany("ChatSettings")
535  .HasForeignKey("InstanceId")
536  .OnDelete(DeleteBehavior.Cascade);
537  });
538 
539  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
540  {
541  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
542  .WithMany("Channels")
543  .HasForeignKey("ChatSettingsId")
544  .OnDelete(DeleteBehavior.Cascade);
545  });
546 
547  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
548  {
549  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
550  .WithOne()
551  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
552  .OnDelete(DeleteBehavior.Restrict);
553 
554  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
555  .WithMany("CompileJobs")
556  .HasForeignKey("RevisionInformationId")
557  .OnDelete(DeleteBehavior.Cascade);
558  });
559 
560  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
561  {
562  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
563  .WithOne("DreamDaemonSettings")
564  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
565  .OnDelete(DeleteBehavior.Cascade);
566  });
567 
568  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
569  {
570  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
571  .WithOne("DreamMakerSettings")
572  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
573  .OnDelete(DeleteBehavior.Cascade);
574  });
575 
576  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
577  {
578  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
579  .WithMany("InstanceUsers")
580  .HasForeignKey("InstanceId")
581  .OnDelete(DeleteBehavior.Cascade);
582 
583  b.HasOne("Tgstation.Server.Host.Models.User")
584  .WithMany("InstanceUsers")
585  .HasForeignKey("UserId")
586  .OnDelete(DeleteBehavior.Cascade);
587  });
588 
589  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
590  {
591  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
592  .WithMany()
593  .HasForeignKey("CancelledById");
594 
595  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
596  .WithMany("Jobs")
597  .HasForeignKey("InstanceId")
598  .OnDelete(DeleteBehavior.Cascade);
599 
600  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
601  .WithMany()
602  .HasForeignKey("StartedById")
603  .OnDelete(DeleteBehavior.Cascade);
604  });
605 
606  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
607  {
608  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
609  .WithMany()
610  .HasForeignKey("CompileJobId")
611  .OnDelete(DeleteBehavior.Cascade);
612  });
613 
614  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
615  {
616  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
617  .WithOne("RepositorySettings")
618  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
619  .OnDelete(DeleteBehavior.Cascade);
620  });
621 
622  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
623  {
624  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
625  .WithMany("ActiveTestMerges")
626  .HasForeignKey("RevisionInformationId")
627  .OnDelete(DeleteBehavior.Cascade);
628 
629  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
630  .WithMany("RevisonInformations")
631  .HasForeignKey("TestMergeId")
632  .OnDelete(DeleteBehavior.Cascade);
633  });
634 
635  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
636  {
637  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
638  .WithMany("RevisionInformations")
639  .HasForeignKey("InstanceId")
640  .OnDelete(DeleteBehavior.Cascade);
641  });
642 
643  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
644  {
645  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
646  .WithMany("TestMerges")
647  .HasForeignKey("MergedById")
648  .OnDelete(DeleteBehavior.Restrict);
649 
650  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
651  .WithOne("PrimaryTestMerge")
652  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
653  .OnDelete(DeleteBehavior.Restrict);
654  });
655 
656  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
657  {
658  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
659  .WithMany("CreatedUsers")
660  .HasForeignKey("CreatedById");
661  });
662 
663  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
664  {
665  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
666  .WithMany()
667  .HasForeignKey("AlphaId");
668 
669  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
670  .WithMany()
671  .HasForeignKey("BravoId");
672 
673  b.HasOne("Tgstation.Server.Host.Models.Instance")
674  .WithOne("WatchdogReattachInformation")
675  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
676  .OnDelete(DeleteBehavior.Cascade);
677  });
678 #pragma warning restore 612, 618
679  }
680  }
681 }
+Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Metadata;
6 using Microsoft.EntityFrameworkCore.Migrations;
7 using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
9 
11 {
13  [Migration("20190219041825_MSFixRevInfoIndex")]
14  partial class MSFixRevInfoIndex
15  {
20  protected override void BuildTargetModel(ModelBuilder modelBuilder)
21  {
22 #pragma warning disable 612, 618
23  modelBuilder
24  .HasAnnotation("ProductVersion", "2.1.4-rtm-31024")
25  .HasAnnotation("Relational:MaxIdentifierLength", 128)
26  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
27 
28  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
29  {
30  b.Property<long>("Id")
31  .ValueGeneratedOnAdd()
32  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
33 
34  b.Property<string>("ConnectionString")
35  .IsRequired();
36 
37  b.Property<bool?>("Enabled");
38 
39  b.Property<long>("InstanceId");
40 
41  b.Property<string>("Name")
42  .IsRequired();
43 
44  b.Property<int?>("Provider");
45 
46  b.HasKey("Id");
47 
48  b.HasIndex("InstanceId");
49 
50  b.HasIndex("Name")
51  .IsUnique();
52 
53  b.ToTable("ChatBots");
54  });
55 
56  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
57  {
58  b.Property<long>("Id")
59  .ValueGeneratedOnAdd()
60  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
61 
62  b.Property<long>("ChatSettingsId");
63 
64  b.Property<decimal?>("DiscordChannelId")
65  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
66 
67  b.Property<string>("IrcChannel");
68 
69  b.Property<bool?>("IsAdminChannel")
70  .IsRequired();
71 
72  b.Property<bool?>("IsUpdatesChannel")
73  .IsRequired();
74 
75  b.Property<bool?>("IsWatchdogChannel")
76  .IsRequired();
77 
78  b.Property<string>("Tag");
79 
80  b.HasKey("Id");
81 
82  b.HasIndex("ChatSettingsId", "DiscordChannelId")
83  .IsUnique()
84  .HasFilter("[DiscordChannelId] IS NOT NULL");
85 
86  b.HasIndex("ChatSettingsId", "IrcChannel")
87  .IsUnique()
88  .HasFilter("[IrcChannel] IS NOT NULL");
89 
90  b.ToTable("ChatChannels");
91  });
92 
93  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
94  {
95  b.Property<long>("Id")
96  .ValueGeneratedOnAdd()
97  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
98 
99  b.Property<string>("ByondVersion")
100  .IsRequired();
101 
102  b.Property<Guid?>("DirectoryName")
103  .IsRequired();
104 
105  b.Property<string>("DmeName")
106  .IsRequired();
107 
108  b.Property<long>("JobId");
109 
110  b.Property<int>("MinimumSecurityLevel");
111 
112  b.Property<string>("Output")
113  .IsRequired();
114 
115  b.Property<long>("RevisionInformationId");
116 
117  b.HasKey("Id");
118 
119  b.HasIndex("DirectoryName");
120 
121  b.HasIndex("JobId")
122  .IsUnique();
123 
124  b.HasIndex("RevisionInformationId");
125 
126  b.ToTable("CompileJobs");
127  });
128 
129  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
130  {
131  b.Property<long>("Id")
132  .ValueGeneratedOnAdd()
133  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
134 
135  b.Property<string>("AccessToken");
136 
137  b.Property<bool?>("AllowWebClient")
138  .IsRequired();
139 
140  b.Property<bool?>("AutoStart")
141  .IsRequired();
142 
143  b.Property<long>("InstanceId");
144 
145  b.Property<int>("PrimaryPort");
146 
147  b.Property<int?>("ProcessId");
148 
149  b.Property<int>("SecondaryPort");
150 
151  b.Property<int>("SecurityLevel");
152 
153  b.Property<bool?>("SoftRestart")
154  .IsRequired();
155 
156  b.Property<bool?>("SoftShutdown")
157  .IsRequired();
158 
159  b.Property<long>("StartupTimeout");
160 
161  b.HasKey("Id");
162 
163  b.HasIndex("InstanceId")
164  .IsUnique();
165 
166  b.ToTable("DreamDaemonSettings");
167  });
168 
169  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
170  {
171  b.Property<long>("Id")
172  .ValueGeneratedOnAdd()
173  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
174 
175  b.Property<int>("ApiValidationPort");
176 
177  b.Property<int>("ApiValidationSecurityLevel");
178 
179  b.Property<long>("InstanceId");
180 
181  b.Property<string>("ProjectName");
182 
183  b.HasKey("Id");
184 
185  b.HasIndex("InstanceId")
186  .IsUnique();
187 
188  b.ToTable("DreamMakerSettings");
189  });
190 
191  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
192  {
193  b.Property<long>("Id")
194  .ValueGeneratedOnAdd()
195  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
196 
197  b.Property<long>("AutoUpdateInterval");
198 
199  b.Property<int>("ConfigurationType");
200 
201  b.Property<string>("Name")
202  .IsRequired();
203 
204  b.Property<bool?>("Online")
205  .IsRequired();
206 
207  b.Property<string>("Path")
208  .IsRequired();
209 
210  b.HasKey("Id");
211 
212  b.HasIndex("Path")
213  .IsUnique();
214 
215  b.ToTable("Instances");
216  });
217 
218  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
219  {
220  b.Property<long>("Id")
221  .ValueGeneratedOnAdd()
222  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
223 
224  b.Property<decimal>("ByondRights")
225  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
226 
227  b.Property<decimal>("ChatBotRights")
228  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
229 
230  b.Property<decimal>("ConfigurationRights")
231  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
232 
233  b.Property<decimal>("DreamDaemonRights")
234  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
235 
236  b.Property<decimal>("DreamMakerRights")
237  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
238 
239  b.Property<long>("InstanceId");
240 
241  b.Property<decimal>("InstanceUserRights")
242  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
243 
244  b.Property<decimal>("RepositoryRights")
245  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
246 
247  b.Property<long?>("UserId")
248  .IsRequired();
249 
250  b.HasKey("Id");
251 
252  b.HasIndex("InstanceId");
253 
254  b.HasIndex("UserId", "InstanceId")
255  .IsUnique();
256 
257  b.ToTable("InstanceUsers");
258  });
259 
260  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
261  {
262  b.Property<long>("Id")
263  .ValueGeneratedOnAdd()
264  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
265 
266  b.Property<decimal?>("CancelRight")
267  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
268 
269  b.Property<decimal?>("CancelRightsType")
270  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
271 
272  b.Property<bool?>("Cancelled")
273  .IsRequired();
274 
275  b.Property<long?>("CancelledById");
276 
277  b.Property<string>("Description")
278  .IsRequired();
279 
280  b.Property<string>("ExceptionDetails");
281 
282  b.Property<long>("InstanceId");
283 
284  b.Property<DateTimeOffset?>("StartedAt")
285  .IsRequired();
286 
287  b.Property<long>("StartedById");
288 
289  b.Property<DateTimeOffset?>("StoppedAt");
290 
291  b.HasKey("Id");
292 
293  b.HasIndex("CancelledById");
294 
295  b.HasIndex("InstanceId");
296 
297  b.HasIndex("StartedById");
298 
299  b.ToTable("Jobs");
300  });
301 
302  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
303  {
304  b.Property<long>("Id")
305  .ValueGeneratedOnAdd()
306  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
307 
308  b.Property<string>("AccessIdentifier")
309  .IsRequired();
310 
311  b.Property<string>("ChatChannelsJson")
312  .IsRequired();
313 
314  b.Property<string>("ChatCommandsJson")
315  .IsRequired();
316 
317  b.Property<long>("CompileJobId");
318 
319  b.Property<bool>("IsPrimary");
320 
321  b.Property<int>("Port");
322 
323  b.Property<int>("ProcessId");
324 
325  b.Property<int>("RebootState");
326 
327  b.Property<string>("ServerCommandsJson")
328  .IsRequired();
329 
330  b.HasKey("Id");
331 
332  b.HasIndex("CompileJobId");
333 
334  b.ToTable("ReattachInformations");
335  });
336 
337  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
338  {
339  b.Property<long>("Id")
340  .ValueGeneratedOnAdd()
341  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
342 
343  b.Property<string>("AccessToken");
344 
345  b.Property<string>("AccessUser");
346 
347  b.Property<bool?>("AutoUpdatesKeepTestMerges")
348  .IsRequired();
349 
350  b.Property<bool?>("AutoUpdatesSynchronize")
351  .IsRequired();
352 
353  b.Property<string>("CommitterEmail")
354  .IsRequired();
355 
356  b.Property<string>("CommitterName")
357  .IsRequired();
358 
359  b.Property<long>("InstanceId");
360 
361  b.Property<bool?>("PostTestMergeComment")
362  .IsRequired();
363 
364  b.Property<bool?>("PushTestMergeCommits")
365  .IsRequired();
366 
367  b.Property<bool?>("ShowTestMergeCommitters")
368  .IsRequired();
369 
370  b.HasKey("Id");
371 
372  b.HasIndex("InstanceId")
373  .IsUnique();
374 
375  b.ToTable("RepositorySettings");
376  });
377 
378  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
379  {
380  b.Property<long>("Id")
381  .ValueGeneratedOnAdd()
382  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
383 
384  b.Property<long>("RevisionInformationId");
385 
386  b.Property<long>("TestMergeId");
387 
388  b.HasKey("Id");
389 
390  b.HasIndex("RevisionInformationId");
391 
392  b.HasIndex("TestMergeId");
393 
394  b.ToTable("RevInfoTestMerges");
395  });
396 
397  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
398  {
399  b.Property<long>("Id")
400  .ValueGeneratedOnAdd()
401  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
402 
403  b.Property<string>("CommitSha")
404  .IsRequired()
405  .HasMaxLength(40);
406 
407  b.Property<long>("InstanceId");
408 
409  b.Property<string>("OriginCommitSha")
410  .IsRequired()
411  .HasMaxLength(40);
412 
413  b.HasKey("Id");
414 
415  b.HasIndex("InstanceId", "CommitSha")
416  .IsUnique();
417 
418  b.ToTable("RevisionInformations");
419  });
420 
421  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
422  {
423  b.Property<long>("Id")
424  .ValueGeneratedOnAdd()
425  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
426 
427  b.Property<string>("Author")
428  .IsRequired();
429 
430  b.Property<string>("BodyAtMerge")
431  .IsRequired();
432 
433  b.Property<string>("Comment");
434 
435  b.Property<DateTimeOffset>("MergedAt");
436 
437  b.Property<long>("MergedById");
438 
439  b.Property<int?>("Number")
440  .IsRequired();
441 
442  b.Property<long?>("PrimaryRevisionInformationId")
443  .IsRequired();
444 
445  b.Property<string>("PullRequestRevision")
446  .IsRequired();
447 
448  b.Property<string>("TitleAtMerge")
449  .IsRequired();
450 
451  b.Property<string>("Url")
452  .IsRequired();
453 
454  b.HasKey("Id");
455 
456  b.HasIndex("MergedById");
457 
458  b.HasIndex("PrimaryRevisionInformationId")
459  .IsUnique();
460 
461  b.ToTable("TestMerges");
462  });
463 
464  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
465  {
466  b.Property<long>("Id")
467  .ValueGeneratedOnAdd()
468  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
469 
470  b.Property<decimal>("AdministrationRights")
471  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
472 
473  b.Property<string>("CanonicalName")
474  .IsRequired();
475 
476  b.Property<DateTimeOffset?>("CreatedAt")
477  .IsRequired();
478 
479  b.Property<long?>("CreatedById");
480 
481  b.Property<bool?>("Enabled")
482  .IsRequired();
483 
484  b.Property<decimal>("InstanceManagerRights")
485  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
486 
487  b.Property<DateTimeOffset?>("LastPasswordUpdate");
488 
489  b.Property<string>("Name")
490  .IsRequired();
491 
492  b.Property<string>("PasswordHash");
493 
494  b.Property<string>("SystemIdentifier");
495 
496  b.HasKey("Id");
497 
498  b.HasIndex("CanonicalName")
499  .IsUnique();
500 
501  b.HasIndex("CreatedById");
502 
503  b.ToTable("Users");
504  });
505 
506  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
507  {
508  b.Property<long>("Id")
509  .ValueGeneratedOnAdd()
510  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
511 
512  b.Property<long?>("AlphaId");
513 
514  b.Property<bool>("AlphaIsActive");
515 
516  b.Property<long?>("BravoId");
517 
518  b.Property<long>("InstanceId");
519 
520  b.HasKey("Id");
521 
522  b.HasIndex("AlphaId");
523 
524  b.HasIndex("BravoId");
525 
526  b.HasIndex("InstanceId")
527  .IsUnique();
528 
529  b.ToTable("WatchdogReattachInformations");
530  });
531 
532  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
533  {
534  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
535  .WithMany("ChatSettings")
536  .HasForeignKey("InstanceId")
537  .OnDelete(DeleteBehavior.Cascade);
538  });
539 
540  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
541  {
542  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
543  .WithMany("Channels")
544  .HasForeignKey("ChatSettingsId")
545  .OnDelete(DeleteBehavior.Cascade);
546  });
547 
548  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
549  {
550  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
551  .WithOne()
552  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
553  .OnDelete(DeleteBehavior.Restrict);
554 
555  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
556  .WithMany("CompileJobs")
557  .HasForeignKey("RevisionInformationId")
558  .OnDelete(DeleteBehavior.Cascade);
559  });
560 
561  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
562  {
563  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
564  .WithOne("DreamDaemonSettings")
565  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
566  .OnDelete(DeleteBehavior.Cascade);
567  });
568 
569  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
570  {
571  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
572  .WithOne("DreamMakerSettings")
573  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
574  .OnDelete(DeleteBehavior.Cascade);
575  });
576 
577  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
578  {
579  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
580  .WithMany("InstanceUsers")
581  .HasForeignKey("InstanceId")
582  .OnDelete(DeleteBehavior.Cascade);
583 
584  b.HasOne("Tgstation.Server.Host.Models.User")
585  .WithMany("InstanceUsers")
586  .HasForeignKey("UserId")
587  .OnDelete(DeleteBehavior.Cascade);
588  });
589 
590  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
591  {
592  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
593  .WithMany()
594  .HasForeignKey("CancelledById");
595 
596  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
597  .WithMany("Jobs")
598  .HasForeignKey("InstanceId")
599  .OnDelete(DeleteBehavior.Cascade);
600 
601  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
602  .WithMany()
603  .HasForeignKey("StartedById")
604  .OnDelete(DeleteBehavior.Cascade);
605  });
606 
607  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
608  {
609  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
610  .WithMany()
611  .HasForeignKey("CompileJobId")
612  .OnDelete(DeleteBehavior.Cascade);
613  });
614 
615  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
616  {
617  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
618  .WithOne("RepositorySettings")
619  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
620  .OnDelete(DeleteBehavior.Cascade);
621  });
622 
623  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
624  {
625  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
626  .WithMany("ActiveTestMerges")
627  .HasForeignKey("RevisionInformationId")
628  .OnDelete(DeleteBehavior.Cascade);
629 
630  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
631  .WithMany("RevisonInformations")
632  .HasForeignKey("TestMergeId")
633  .OnDelete(DeleteBehavior.Cascade);
634  });
635 
636  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
637  {
638  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
639  .WithMany("RevisionInformations")
640  .HasForeignKey("InstanceId")
641  .OnDelete(DeleteBehavior.Cascade);
642  });
643 
644  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
645  {
646  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
647  .WithMany("TestMerges")
648  .HasForeignKey("MergedById")
649  .OnDelete(DeleteBehavior.Restrict);
650 
651  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
652  .WithOne("PrimaryTestMerge")
653  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
654  .OnDelete(DeleteBehavior.Restrict);
655  });
656 
657  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
658  {
659  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
660  .WithMany("CreatedUsers")
661  .HasForeignKey("CreatedById");
662  });
663 
664  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
665  {
666  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
667  .WithMany()
668  .HasForeignKey("AlphaId");
669 
670  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
671  .WithMany()
672  .HasForeignKey("BravoId");
673 
674  b.HasOne("Tgstation.Server.Host.Models.Instance")
675  .WithOne("WatchdogReattachInformation")
676  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
677  .OnDelete(DeleteBehavior.Cascade);
678  });
679 #pragma warning restore 612, 618
680  }
681  }
682 }
-
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
+ +
DatabaseContext<TParentContext> for Sqlserver
+ + + +
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
-Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Migrations;
6 
8 {
9  [DbContext(typeof(MySqlDatabaseContext))]
10  [Migration("20190219042440_MYFixRevInfoIndex")]
11  partial class MYFixRevInfoIndex
12  {
17  protected override void BuildTargetModel(ModelBuilder modelBuilder)
18  {
19 #pragma warning disable 612, 618
20  modelBuilder
21  .HasAnnotation("ProductVersion", "2.1.4-rtm-31024")
22  .HasAnnotation("Relational:MaxIdentifierLength", 64);
23 
24  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
25  {
26  b.Property<long>("Id")
27  .ValueGeneratedOnAdd();
28 
29  b.Property<string>("ConnectionString")
30  .IsRequired();
31 
32  b.Property<bool?>("Enabled");
33 
34  b.Property<long>("InstanceId");
35 
36  b.Property<string>("Name")
37  .IsRequired();
38 
39  b.Property<int?>("Provider");
40 
41  b.HasKey("Id");
42 
43  b.HasIndex("InstanceId");
44 
45  b.HasIndex("Name")
46  .IsUnique();
47 
48  b.ToTable("ChatBots");
49  });
50 
51  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
52  {
53  b.Property<long>("Id")
54  .ValueGeneratedOnAdd();
55 
56  b.Property<long>("ChatSettingsId");
57 
58  b.Property<ulong?>("DiscordChannelId");
59 
60  b.Property<string>("IrcChannel");
61 
62  b.Property<bool?>("IsAdminChannel")
63  .IsRequired();
64 
65  b.Property<bool?>("IsUpdatesChannel")
66  .IsRequired();
67 
68  b.Property<bool?>("IsWatchdogChannel")
69  .IsRequired();
70 
71  b.Property<string>("Tag");
72 
73  b.HasKey("Id");
74 
75  b.HasIndex("ChatSettingsId", "DiscordChannelId")
76  .IsUnique();
77 
78  b.HasIndex("ChatSettingsId", "IrcChannel")
79  .IsUnique();
80 
81  b.ToTable("ChatChannels");
82  });
83 
84  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
85  {
86  b.Property<long>("Id")
87  .ValueGeneratedOnAdd();
88 
89  b.Property<string>("ByondVersion")
90  .IsRequired();
91 
92  b.Property<Guid?>("DirectoryName")
93  .IsRequired();
94 
95  b.Property<string>("DmeName")
96  .IsRequired();
97 
98  b.Property<long>("JobId");
99 
100  b.Property<int>("MinimumSecurityLevel");
101 
102  b.Property<string>("Output")
103  .IsRequired();
104 
105  b.Property<long>("RevisionInformationId");
106 
107  b.HasKey("Id");
108 
109  b.HasIndex("DirectoryName");
110 
111  b.HasIndex("JobId")
112  .IsUnique();
113 
114  b.HasIndex("RevisionInformationId");
115 
116  b.ToTable("CompileJobs");
117  });
118 
119  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
120  {
121  b.Property<long>("Id")
122  .ValueGeneratedOnAdd();
123 
124  b.Property<string>("AccessToken");
125 
126  b.Property<bool?>("AllowWebClient")
127  .IsRequired();
128 
129  b.Property<bool?>("AutoStart")
130  .IsRequired();
131 
132  b.Property<long>("InstanceId");
133 
134  b.Property<ushort?>("PrimaryPort")
135  .IsRequired();
136 
137  b.Property<int?>("ProcessId");
138 
139  b.Property<ushort?>("SecondaryPort")
140  .IsRequired();
141 
142  b.Property<int>("SecurityLevel");
143 
144  b.Property<bool?>("SoftRestart")
145  .IsRequired();
146 
147  b.Property<bool?>("SoftShutdown")
148  .IsRequired();
149 
150  b.Property<uint?>("StartupTimeout")
151  .IsRequired();
152 
153  b.HasKey("Id");
154 
155  b.HasIndex("InstanceId")
156  .IsUnique();
157 
158  b.ToTable("DreamDaemonSettings");
159  });
160 
161  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
162  {
163  b.Property<long>("Id")
164  .ValueGeneratedOnAdd();
165 
166  b.Property<ushort?>("ApiValidationPort")
167  .IsRequired();
168 
169  b.Property<int>("ApiValidationSecurityLevel");
170 
171  b.Property<long>("InstanceId");
172 
173  b.Property<string>("ProjectName");
174 
175  b.HasKey("Id");
176 
177  b.HasIndex("InstanceId")
178  .IsUnique();
179 
180  b.ToTable("DreamMakerSettings");
181  });
182 
183  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
184  {
185  b.Property<long>("Id")
186  .ValueGeneratedOnAdd();
187 
188  b.Property<uint?>("AutoUpdateInterval")
189  .IsRequired();
190 
191  b.Property<int>("ConfigurationType");
192 
193  b.Property<string>("Name")
194  .IsRequired();
195 
196  b.Property<bool?>("Online")
197  .IsRequired();
198 
199  b.Property<string>("Path")
200  .IsRequired();
201 
202  b.HasKey("Id");
203 
204  b.HasIndex("Path")
205  .IsUnique();
206 
207  b.ToTable("Instances");
208  });
209 
210  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
211  {
212  b.Property<long>("Id")
213  .ValueGeneratedOnAdd();
214 
215  b.Property<ulong>("ByondRights");
216 
217  b.Property<ulong>("ChatBotRights");
218 
219  b.Property<ulong>("ConfigurationRights");
220 
221  b.Property<ulong>("DreamDaemonRights");
222 
223  b.Property<ulong>("DreamMakerRights");
224 
225  b.Property<long>("InstanceId");
226 
227  b.Property<ulong>("InstanceUserRights");
228 
229  b.Property<ulong>("RepositoryRights");
230 
231  b.Property<long?>("UserId")
232  .IsRequired();
233 
234  b.HasKey("Id");
235 
236  b.HasIndex("InstanceId");
237 
238  b.HasIndex("UserId", "InstanceId")
239  .IsUnique();
240 
241  b.ToTable("InstanceUsers");
242  });
243 
244  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
245  {
246  b.Property<long>("Id")
247  .ValueGeneratedOnAdd();
248 
249  b.Property<ulong?>("CancelRight");
250 
251  b.Property<ulong?>("CancelRightsType");
252 
253  b.Property<bool?>("Cancelled")
254  .IsRequired();
255 
256  b.Property<long?>("CancelledById");
257 
258  b.Property<string>("Description")
259  .IsRequired();
260 
261  b.Property<string>("ExceptionDetails");
262 
263  b.Property<long>("InstanceId");
264 
265  b.Property<DateTimeOffset?>("StartedAt")
266  .IsRequired();
267 
268  b.Property<long>("StartedById");
269 
270  b.Property<DateTimeOffset?>("StoppedAt");
271 
272  b.HasKey("Id");
273 
274  b.HasIndex("CancelledById");
275 
276  b.HasIndex("InstanceId");
277 
278  b.HasIndex("StartedById");
279 
280  b.ToTable("Jobs");
281  });
282 
283  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
284  {
285  b.Property<long>("Id")
286  .ValueGeneratedOnAdd();
287 
288  b.Property<string>("AccessIdentifier")
289  .IsRequired();
290 
291  b.Property<string>("ChatChannelsJson")
292  .IsRequired();
293 
294  b.Property<string>("ChatCommandsJson")
295  .IsRequired();
296 
297  b.Property<long>("CompileJobId");
298 
299  b.Property<bool>("IsPrimary");
300 
301  b.Property<ushort>("Port");
302 
303  b.Property<int>("ProcessId");
304 
305  b.Property<int>("RebootState");
306 
307  b.Property<string>("ServerCommandsJson")
308  .IsRequired();
309 
310  b.HasKey("Id");
311 
312  b.HasIndex("CompileJobId");
313 
314  b.ToTable("ReattachInformations");
315  });
316 
317  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
318  {
319  b.Property<long>("Id")
320  .ValueGeneratedOnAdd();
321 
322  b.Property<string>("AccessToken");
323 
324  b.Property<string>("AccessUser");
325 
326  b.Property<bool?>("AutoUpdatesKeepTestMerges")
327  .IsRequired();
328 
329  b.Property<bool?>("AutoUpdatesSynchronize")
330  .IsRequired();
331 
332  b.Property<string>("CommitterEmail")
333  .IsRequired();
334 
335  b.Property<string>("CommitterName")
336  .IsRequired();
337 
338  b.Property<long>("InstanceId");
339 
340  b.Property<bool?>("PostTestMergeComment")
341  .IsRequired();
342 
343  b.Property<bool?>("PushTestMergeCommits")
344  .IsRequired();
345 
346  b.Property<bool?>("ShowTestMergeCommitters")
347  .IsRequired();
348 
349  b.HasKey("Id");
350 
351  b.HasIndex("InstanceId")
352  .IsUnique();
353 
354  b.ToTable("RepositorySettings");
355  });
356 
357  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
358  {
359  b.Property<long>("Id")
360  .ValueGeneratedOnAdd();
361 
362  b.Property<long>("RevisionInformationId");
363 
364  b.Property<long>("TestMergeId");
365 
366  b.HasKey("Id");
367 
368  b.HasIndex("RevisionInformationId");
369 
370  b.HasIndex("TestMergeId");
371 
372  b.ToTable("RevInfoTestMerges");
373  });
374 
375  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
376  {
377  b.Property<long>("Id")
378  .ValueGeneratedOnAdd();
379 
380  b.Property<string>("CommitSha")
381  .IsRequired()
382  .HasMaxLength(40);
383 
384  b.Property<long>("InstanceId");
385 
386  b.Property<string>("OriginCommitSha")
387  .IsRequired()
388  .HasMaxLength(40);
389 
390  b.HasKey("Id");
391 
392  b.HasIndex("InstanceId", "CommitSha")
393  .IsUnique();
394 
395  b.ToTable("RevisionInformations");
396  });
397 
398  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
399  {
400  b.Property<long>("Id")
401  .ValueGeneratedOnAdd();
402 
403  b.Property<string>("Author")
404  .IsRequired();
405 
406  b.Property<string>("BodyAtMerge")
407  .IsRequired();
408 
409  b.Property<string>("Comment");
410 
411  b.Property<DateTimeOffset>("MergedAt");
412 
413  b.Property<long>("MergedById");
414 
415  b.Property<int?>("Number")
416  .IsRequired();
417 
418  b.Property<long?>("PrimaryRevisionInformationId")
419  .IsRequired();
420 
421  b.Property<string>("PullRequestRevision")
422  .IsRequired();
423 
424  b.Property<string>("TitleAtMerge")
425  .IsRequired();
426 
427  b.Property<string>("Url")
428  .IsRequired();
429 
430  b.HasKey("Id");
431 
432  b.HasIndex("MergedById");
433 
434  b.HasIndex("PrimaryRevisionInformationId")
435  .IsUnique();
436 
437  b.ToTable("TestMerges");
438  });
439 
440  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
441  {
442  b.Property<long>("Id")
443  .ValueGeneratedOnAdd();
444 
445  b.Property<ulong>("AdministrationRights");
446 
447  b.Property<string>("CanonicalName")
448  .IsRequired();
449 
450  b.Property<DateTimeOffset?>("CreatedAt")
451  .IsRequired();
452 
453  b.Property<long?>("CreatedById");
454 
455  b.Property<bool?>("Enabled")
456  .IsRequired();
457 
458  b.Property<ulong>("InstanceManagerRights");
459 
460  b.Property<DateTimeOffset?>("LastPasswordUpdate");
461 
462  b.Property<string>("Name")
463  .IsRequired();
464 
465  b.Property<string>("PasswordHash");
466 
467  b.Property<string>("SystemIdentifier");
468 
469  b.HasKey("Id");
470 
471  b.HasIndex("CanonicalName")
472  .IsUnique();
473 
474  b.HasIndex("CreatedById");
475 
476  b.ToTable("Users");
477  });
478 
479  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
480  {
481  b.Property<long>("Id")
482  .ValueGeneratedOnAdd();
483 
484  b.Property<long?>("AlphaId");
485 
486  b.Property<bool>("AlphaIsActive");
487 
488  b.Property<long?>("BravoId");
489 
490  b.Property<long>("InstanceId");
491 
492  b.HasKey("Id");
493 
494  b.HasIndex("AlphaId");
495 
496  b.HasIndex("BravoId");
497 
498  b.HasIndex("InstanceId")
499  .IsUnique();
500 
501  b.ToTable("WatchdogReattachInformations");
502  });
503 
504  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
505  {
506  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
507  .WithMany("ChatSettings")
508  .HasForeignKey("InstanceId")
509  .OnDelete(DeleteBehavior.Cascade);
510  });
511 
512  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
513  {
514  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
515  .WithMany("Channels")
516  .HasForeignKey("ChatSettingsId")
517  .OnDelete(DeleteBehavior.Cascade);
518  });
519 
520  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
521  {
522  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
523  .WithOne()
524  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
525  .OnDelete(DeleteBehavior.Restrict);
526 
527  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
528  .WithMany("CompileJobs")
529  .HasForeignKey("RevisionInformationId")
530  .OnDelete(DeleteBehavior.Cascade);
531  });
532 
533  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
534  {
535  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
536  .WithOne("DreamDaemonSettings")
537  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
538  .OnDelete(DeleteBehavior.Cascade);
539  });
540 
541  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
542  {
543  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
544  .WithOne("DreamMakerSettings")
545  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
546  .OnDelete(DeleteBehavior.Cascade);
547  });
548 
549  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
550  {
551  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
552  .WithMany("InstanceUsers")
553  .HasForeignKey("InstanceId")
554  .OnDelete(DeleteBehavior.Cascade);
555 
556  b.HasOne("Tgstation.Server.Host.Models.User")
557  .WithMany("InstanceUsers")
558  .HasForeignKey("UserId")
559  .OnDelete(DeleteBehavior.Cascade);
560  });
561 
562  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
563  {
564  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
565  .WithMany()
566  .HasForeignKey("CancelledById");
567 
568  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
569  .WithMany("Jobs")
570  .HasForeignKey("InstanceId")
571  .OnDelete(DeleteBehavior.Cascade);
572 
573  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
574  .WithMany()
575  .HasForeignKey("StartedById")
576  .OnDelete(DeleteBehavior.Cascade);
577  });
578 
579  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
580  {
581  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
582  .WithMany()
583  .HasForeignKey("CompileJobId")
584  .OnDelete(DeleteBehavior.Cascade);
585  });
586 
587  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
588  {
589  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
590  .WithOne("RepositorySettings")
591  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
592  .OnDelete(DeleteBehavior.Cascade);
593  });
594 
595  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
596  {
597  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
598  .WithMany("ActiveTestMerges")
599  .HasForeignKey("RevisionInformationId")
600  .OnDelete(DeleteBehavior.Cascade);
601 
602  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
603  .WithMany("RevisonInformations")
604  .HasForeignKey("TestMergeId")
605  .OnDelete(DeleteBehavior.Cascade);
606  });
607 
608  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
609  {
610  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
611  .WithMany("RevisionInformations")
612  .HasForeignKey("InstanceId")
613  .OnDelete(DeleteBehavior.Cascade);
614  });
615 
616  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
617  {
618  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
619  .WithMany("TestMerges")
620  .HasForeignKey("MergedById")
621  .OnDelete(DeleteBehavior.Restrict);
622 
623  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
624  .WithOne("PrimaryTestMerge")
625  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
626  .OnDelete(DeleteBehavior.Restrict);
627  });
628 
629  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
630  {
631  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
632  .WithMany("CreatedUsers")
633  .HasForeignKey("CreatedById");
634  });
635 
636  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
637  {
638  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
639  .WithMany()
640  .HasForeignKey("AlphaId");
641 
642  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
643  .WithMany()
644  .HasForeignKey("BravoId");
645 
646  b.HasOne("Tgstation.Server.Host.Models.Instance")
647  .WithOne("WatchdogReattachInformation")
648  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
649  .OnDelete(DeleteBehavior.Cascade);
650  });
651 #pragma warning restore 612, 618
652  }
653  }
654 }
+Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 using Microsoft.EntityFrameworkCore.Migrations;
7 
9 {
11  [Migration("20190219042440_MYFixRevInfoIndex")]
12  partial class MYFixRevInfoIndex
13  {
18  protected override void BuildTargetModel(ModelBuilder modelBuilder)
19  {
20 #pragma warning disable 612, 618
21  modelBuilder
22  .HasAnnotation("ProductVersion", "2.1.4-rtm-31024")
23  .HasAnnotation("Relational:MaxIdentifierLength", 64);
24 
25  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
26  {
27  b.Property<long>("Id")
28  .ValueGeneratedOnAdd();
29 
30  b.Property<string>("ConnectionString")
31  .IsRequired();
32 
33  b.Property<bool?>("Enabled");
34 
35  b.Property<long>("InstanceId");
36 
37  b.Property<string>("Name")
38  .IsRequired();
39 
40  b.Property<int?>("Provider");
41 
42  b.HasKey("Id");
43 
44  b.HasIndex("InstanceId");
45 
46  b.HasIndex("Name")
47  .IsUnique();
48 
49  b.ToTable("ChatBots");
50  });
51 
52  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
53  {
54  b.Property<long>("Id")
55  .ValueGeneratedOnAdd();
56 
57  b.Property<long>("ChatSettingsId");
58 
59  b.Property<ulong?>("DiscordChannelId");
60 
61  b.Property<string>("IrcChannel");
62 
63  b.Property<bool?>("IsAdminChannel")
64  .IsRequired();
65 
66  b.Property<bool?>("IsUpdatesChannel")
67  .IsRequired();
68 
69  b.Property<bool?>("IsWatchdogChannel")
70  .IsRequired();
71 
72  b.Property<string>("Tag");
73 
74  b.HasKey("Id");
75 
76  b.HasIndex("ChatSettingsId", "DiscordChannelId")
77  .IsUnique();
78 
79  b.HasIndex("ChatSettingsId", "IrcChannel")
80  .IsUnique();
81 
82  b.ToTable("ChatChannels");
83  });
84 
85  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
86  {
87  b.Property<long>("Id")
88  .ValueGeneratedOnAdd();
89 
90  b.Property<string>("ByondVersion")
91  .IsRequired();
92 
93  b.Property<Guid?>("DirectoryName")
94  .IsRequired();
95 
96  b.Property<string>("DmeName")
97  .IsRequired();
98 
99  b.Property<long>("JobId");
100 
101  b.Property<int>("MinimumSecurityLevel");
102 
103  b.Property<string>("Output")
104  .IsRequired();
105 
106  b.Property<long>("RevisionInformationId");
107 
108  b.HasKey("Id");
109 
110  b.HasIndex("DirectoryName");
111 
112  b.HasIndex("JobId")
113  .IsUnique();
114 
115  b.HasIndex("RevisionInformationId");
116 
117  b.ToTable("CompileJobs");
118  });
119 
120  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
121  {
122  b.Property<long>("Id")
123  .ValueGeneratedOnAdd();
124 
125  b.Property<string>("AccessToken");
126 
127  b.Property<bool?>("AllowWebClient")
128  .IsRequired();
129 
130  b.Property<bool?>("AutoStart")
131  .IsRequired();
132 
133  b.Property<long>("InstanceId");
134 
135  b.Property<ushort?>("PrimaryPort")
136  .IsRequired();
137 
138  b.Property<int?>("ProcessId");
139 
140  b.Property<ushort?>("SecondaryPort")
141  .IsRequired();
142 
143  b.Property<int>("SecurityLevel");
144 
145  b.Property<bool?>("SoftRestart")
146  .IsRequired();
147 
148  b.Property<bool?>("SoftShutdown")
149  .IsRequired();
150 
151  b.Property<uint?>("StartupTimeout")
152  .IsRequired();
153 
154  b.HasKey("Id");
155 
156  b.HasIndex("InstanceId")
157  .IsUnique();
158 
159  b.ToTable("DreamDaemonSettings");
160  });
161 
162  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
163  {
164  b.Property<long>("Id")
165  .ValueGeneratedOnAdd();
166 
167  b.Property<ushort?>("ApiValidationPort")
168  .IsRequired();
169 
170  b.Property<int>("ApiValidationSecurityLevel");
171 
172  b.Property<long>("InstanceId");
173 
174  b.Property<string>("ProjectName");
175 
176  b.HasKey("Id");
177 
178  b.HasIndex("InstanceId")
179  .IsUnique();
180 
181  b.ToTable("DreamMakerSettings");
182  });
183 
184  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
185  {
186  b.Property<long>("Id")
187  .ValueGeneratedOnAdd();
188 
189  b.Property<uint?>("AutoUpdateInterval")
190  .IsRequired();
191 
192  b.Property<int>("ConfigurationType");
193 
194  b.Property<string>("Name")
195  .IsRequired();
196 
197  b.Property<bool?>("Online")
198  .IsRequired();
199 
200  b.Property<string>("Path")
201  .IsRequired();
202 
203  b.HasKey("Id");
204 
205  b.HasIndex("Path")
206  .IsUnique();
207 
208  b.ToTable("Instances");
209  });
210 
211  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
212  {
213  b.Property<long>("Id")
214  .ValueGeneratedOnAdd();
215 
216  b.Property<ulong>("ByondRights");
217 
218  b.Property<ulong>("ChatBotRights");
219 
220  b.Property<ulong>("ConfigurationRights");
221 
222  b.Property<ulong>("DreamDaemonRights");
223 
224  b.Property<ulong>("DreamMakerRights");
225 
226  b.Property<long>("InstanceId");
227 
228  b.Property<ulong>("InstanceUserRights");
229 
230  b.Property<ulong>("RepositoryRights");
231 
232  b.Property<long?>("UserId")
233  .IsRequired();
234 
235  b.HasKey("Id");
236 
237  b.HasIndex("InstanceId");
238 
239  b.HasIndex("UserId", "InstanceId")
240  .IsUnique();
241 
242  b.ToTable("InstanceUsers");
243  });
244 
245  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
246  {
247  b.Property<long>("Id")
248  .ValueGeneratedOnAdd();
249 
250  b.Property<ulong?>("CancelRight");
251 
252  b.Property<ulong?>("CancelRightsType");
253 
254  b.Property<bool?>("Cancelled")
255  .IsRequired();
256 
257  b.Property<long?>("CancelledById");
258 
259  b.Property<string>("Description")
260  .IsRequired();
261 
262  b.Property<string>("ExceptionDetails");
263 
264  b.Property<long>("InstanceId");
265 
266  b.Property<DateTimeOffset?>("StartedAt")
267  .IsRequired();
268 
269  b.Property<long>("StartedById");
270 
271  b.Property<DateTimeOffset?>("StoppedAt");
272 
273  b.HasKey("Id");
274 
275  b.HasIndex("CancelledById");
276 
277  b.HasIndex("InstanceId");
278 
279  b.HasIndex("StartedById");
280 
281  b.ToTable("Jobs");
282  });
283 
284  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
285  {
286  b.Property<long>("Id")
287  .ValueGeneratedOnAdd();
288 
289  b.Property<string>("AccessIdentifier")
290  .IsRequired();
291 
292  b.Property<string>("ChatChannelsJson")
293  .IsRequired();
294 
295  b.Property<string>("ChatCommandsJson")
296  .IsRequired();
297 
298  b.Property<long>("CompileJobId");
299 
300  b.Property<bool>("IsPrimary");
301 
302  b.Property<ushort>("Port");
303 
304  b.Property<int>("ProcessId");
305 
306  b.Property<int>("RebootState");
307 
308  b.Property<string>("ServerCommandsJson")
309  .IsRequired();
310 
311  b.HasKey("Id");
312 
313  b.HasIndex("CompileJobId");
314 
315  b.ToTable("ReattachInformations");
316  });
317 
318  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
319  {
320  b.Property<long>("Id")
321  .ValueGeneratedOnAdd();
322 
323  b.Property<string>("AccessToken");
324 
325  b.Property<string>("AccessUser");
326 
327  b.Property<bool?>("AutoUpdatesKeepTestMerges")
328  .IsRequired();
329 
330  b.Property<bool?>("AutoUpdatesSynchronize")
331  .IsRequired();
332 
333  b.Property<string>("CommitterEmail")
334  .IsRequired();
335 
336  b.Property<string>("CommitterName")
337  .IsRequired();
338 
339  b.Property<long>("InstanceId");
340 
341  b.Property<bool?>("PostTestMergeComment")
342  .IsRequired();
343 
344  b.Property<bool?>("PushTestMergeCommits")
345  .IsRequired();
346 
347  b.Property<bool?>("ShowTestMergeCommitters")
348  .IsRequired();
349 
350  b.HasKey("Id");
351 
352  b.HasIndex("InstanceId")
353  .IsUnique();
354 
355  b.ToTable("RepositorySettings");
356  });
357 
358  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
359  {
360  b.Property<long>("Id")
361  .ValueGeneratedOnAdd();
362 
363  b.Property<long>("RevisionInformationId");
364 
365  b.Property<long>("TestMergeId");
366 
367  b.HasKey("Id");
368 
369  b.HasIndex("RevisionInformationId");
370 
371  b.HasIndex("TestMergeId");
372 
373  b.ToTable("RevInfoTestMerges");
374  });
375 
376  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
377  {
378  b.Property<long>("Id")
379  .ValueGeneratedOnAdd();
380 
381  b.Property<string>("CommitSha")
382  .IsRequired()
383  .HasMaxLength(40);
384 
385  b.Property<long>("InstanceId");
386 
387  b.Property<string>("OriginCommitSha")
388  .IsRequired()
389  .HasMaxLength(40);
390 
391  b.HasKey("Id");
392 
393  b.HasIndex("InstanceId", "CommitSha")
394  .IsUnique();
395 
396  b.ToTable("RevisionInformations");
397  });
398 
399  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
400  {
401  b.Property<long>("Id")
402  .ValueGeneratedOnAdd();
403 
404  b.Property<string>("Author")
405  .IsRequired();
406 
407  b.Property<string>("BodyAtMerge")
408  .IsRequired();
409 
410  b.Property<string>("Comment");
411 
412  b.Property<DateTimeOffset>("MergedAt");
413 
414  b.Property<long>("MergedById");
415 
416  b.Property<int?>("Number")
417  .IsRequired();
418 
419  b.Property<long?>("PrimaryRevisionInformationId")
420  .IsRequired();
421 
422  b.Property<string>("PullRequestRevision")
423  .IsRequired();
424 
425  b.Property<string>("TitleAtMerge")
426  .IsRequired();
427 
428  b.Property<string>("Url")
429  .IsRequired();
430 
431  b.HasKey("Id");
432 
433  b.HasIndex("MergedById");
434 
435  b.HasIndex("PrimaryRevisionInformationId")
436  .IsUnique();
437 
438  b.ToTable("TestMerges");
439  });
440 
441  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
442  {
443  b.Property<long>("Id")
444  .ValueGeneratedOnAdd();
445 
446  b.Property<ulong>("AdministrationRights");
447 
448  b.Property<string>("CanonicalName")
449  .IsRequired();
450 
451  b.Property<DateTimeOffset?>("CreatedAt")
452  .IsRequired();
453 
454  b.Property<long?>("CreatedById");
455 
456  b.Property<bool?>("Enabled")
457  .IsRequired();
458 
459  b.Property<ulong>("InstanceManagerRights");
460 
461  b.Property<DateTimeOffset?>("LastPasswordUpdate");
462 
463  b.Property<string>("Name")
464  .IsRequired();
465 
466  b.Property<string>("PasswordHash");
467 
468  b.Property<string>("SystemIdentifier");
469 
470  b.HasKey("Id");
471 
472  b.HasIndex("CanonicalName")
473  .IsUnique();
474 
475  b.HasIndex("CreatedById");
476 
477  b.ToTable("Users");
478  });
479 
480  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
481  {
482  b.Property<long>("Id")
483  .ValueGeneratedOnAdd();
484 
485  b.Property<long?>("AlphaId");
486 
487  b.Property<bool>("AlphaIsActive");
488 
489  b.Property<long?>("BravoId");
490 
491  b.Property<long>("InstanceId");
492 
493  b.HasKey("Id");
494 
495  b.HasIndex("AlphaId");
496 
497  b.HasIndex("BravoId");
498 
499  b.HasIndex("InstanceId")
500  .IsUnique();
501 
502  b.ToTable("WatchdogReattachInformations");
503  });
504 
505  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
506  {
507  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
508  .WithMany("ChatSettings")
509  .HasForeignKey("InstanceId")
510  .OnDelete(DeleteBehavior.Cascade);
511  });
512 
513  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
514  {
515  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
516  .WithMany("Channels")
517  .HasForeignKey("ChatSettingsId")
518  .OnDelete(DeleteBehavior.Cascade);
519  });
520 
521  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
522  {
523  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
524  .WithOne()
525  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
526  .OnDelete(DeleteBehavior.Restrict);
527 
528  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
529  .WithMany("CompileJobs")
530  .HasForeignKey("RevisionInformationId")
531  .OnDelete(DeleteBehavior.Cascade);
532  });
533 
534  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
535  {
536  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
537  .WithOne("DreamDaemonSettings")
538  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
539  .OnDelete(DeleteBehavior.Cascade);
540  });
541 
542  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
543  {
544  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
545  .WithOne("DreamMakerSettings")
546  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
547  .OnDelete(DeleteBehavior.Cascade);
548  });
549 
550  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
551  {
552  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
553  .WithMany("InstanceUsers")
554  .HasForeignKey("InstanceId")
555  .OnDelete(DeleteBehavior.Cascade);
556 
557  b.HasOne("Tgstation.Server.Host.Models.User")
558  .WithMany("InstanceUsers")
559  .HasForeignKey("UserId")
560  .OnDelete(DeleteBehavior.Cascade);
561  });
562 
563  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
564  {
565  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
566  .WithMany()
567  .HasForeignKey("CancelledById");
568 
569  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
570  .WithMany("Jobs")
571  .HasForeignKey("InstanceId")
572  .OnDelete(DeleteBehavior.Cascade);
573 
574  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
575  .WithMany()
576  .HasForeignKey("StartedById")
577  .OnDelete(DeleteBehavior.Cascade);
578  });
579 
580  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
581  {
582  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
583  .WithMany()
584  .HasForeignKey("CompileJobId")
585  .OnDelete(DeleteBehavior.Cascade);
586  });
587 
588  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
589  {
590  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
591  .WithOne("RepositorySettings")
592  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
593  .OnDelete(DeleteBehavior.Cascade);
594  });
595 
596  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
597  {
598  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
599  .WithMany("ActiveTestMerges")
600  .HasForeignKey("RevisionInformationId")
601  .OnDelete(DeleteBehavior.Cascade);
602 
603  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
604  .WithMany("RevisonInformations")
605  .HasForeignKey("TestMergeId")
606  .OnDelete(DeleteBehavior.Cascade);
607  });
608 
609  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
610  {
611  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
612  .WithMany("RevisionInformations")
613  .HasForeignKey("InstanceId")
614  .OnDelete(DeleteBehavior.Cascade);
615  });
616 
617  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
618  {
619  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
620  .WithMany("TestMerges")
621  .HasForeignKey("MergedById")
622  .OnDelete(DeleteBehavior.Restrict);
623 
624  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
625  .WithOne("PrimaryTestMerge")
626  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
627  .OnDelete(DeleteBehavior.Restrict);
628  });
629 
630  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
631  {
632  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
633  .WithMany("CreatedUsers")
634  .HasForeignKey("CreatedById");
635  });
636 
637  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
638  {
639  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
640  .WithMany()
641  .HasForeignKey("AlphaId");
642 
643  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
644  .WithMany()
645  .HasForeignKey("BravoId");
646 
647  b.HasOne("Tgstation.Server.Host.Models.Instance")
648  .WithOne("WatchdogReattachInformation")
649  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
650  .OnDelete(DeleteBehavior.Cascade);
651  });
652 #pragma warning restore 612, 618
653  }
654  }
655 }
-
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
+
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
+
DatabaseContext<TParentContext> for MySQL
+ + + +
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.Extensions.Logging;
3 using Microsoft.Extensions.Options;
4 using Microsoft.Extensions.Primitives;
5 using Octokit;
6 using System;
7 using System.Collections.Generic;
8 using System.Globalization;
9 using System.Linq;
10 using System.Net;
11 using System.Threading;
12 using System.Threading.Tasks;
13 using Tgstation.Server.Api;
18 using Tgstation.Server.Host.IO;
21 
23 {
27  [Route(Routes.Administration)]
29  {
30  const string RestartNotSupportedException = "This deployment of tgstation-server is lacking the Tgstation.Server.Host.Watchdog component. Restarts and version changes cannot be completed!";
31 
32  const string OctokitException = "Bad GitHub API response, check configuration! Exception: {0}";
33 
38 
43 
48 
53 
58 
63 
68 
82  public AdministrationController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IGitHubClientFactory gitHubClientFactory, IServerControl serverUpdater, IApplication application, IIOManager ioManager, IPlatformIdentifier platformIdentifier, ILogger<AdministrationController> logger, IOptions<UpdatesConfiguration> updatesConfigurationOptions, IOptions<GeneralConfiguration> generalConfigurationOptions) : base(databaseContext, authenticationContextFactory, logger, false, true)
83  {
84  this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
85  this.serverUpdater = serverUpdater ?? throw new ArgumentNullException(nameof(serverUpdater));
86  this.application = application ?? throw new ArgumentNullException(nameof(application));
87  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
88  this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
89  updatesConfiguration = updatesConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(updatesConfigurationOptions));
90  generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
91  }
92 
93  StatusCodeResult RateLimit(RateLimitExceededException exception)
94  {
95  Logger.LogWarning("Exceeded GitHub rate limit! Exception {0}", exception);
96  var secondsString = Math.Ceiling((exception.Reset - DateTimeOffset.Now).TotalSeconds).ToString(CultureInfo.InvariantCulture);
97  Response.Headers.Add("Retry-After", new StringValues(secondsString));
98  return StatusCode(429);
99  }
100 
107  async Task<IActionResult> CheckReleasesAndApplyUpdate(Version newVersion, CancellationToken cancellationToken)
108  {
109  Logger.LogDebug("Looking for GitHub releases version {0}...", newVersion);
110  IEnumerable<Release> releases;
111  try
112  {
113  var gitHubClient = GetGitHubClient();
114  releases = await gitHubClient
115  .Repository
116  .Release
118  .WithToken(cancellationToken)
119  .ConfigureAwait(false);
120  }
121  catch (RateLimitExceededException e)
122  {
123  return RateLimit(e);
124  }
125  catch (ApiException e)
126  {
127  Logger.LogWarning(OctokitException, e);
128  return StatusCode((int)HttpStatusCode.FailedDependency);
129  }
130 
131  releases = releases.Where(x => x.TagName.StartsWith(updatesConfiguration.GitTagPrefix, StringComparison.InvariantCulture));
132 
133  Logger.LogTrace("Release query complete!");
134 
135  foreach (var release in releases)
136  if (Version.TryParse(release.TagName.Replace(updatesConfiguration.GitTagPrefix, String.Empty, StringComparison.Ordinal), out var version) && version == newVersion)
137  {
138  var asset = release.Assets.Where(x => x.Name.Equals(updatesConfiguration.UpdatePackageAssetName, StringComparison.Ordinal)).FirstOrDefault();
139  if (asset == default)
140  continue;
141 
142  if (!serverUpdater.ApplyUpdate(version, new Uri(asset.BrowserDownloadUrl), ioManager))
143  return Conflict(new ErrorMessage
144  {
145  Message = "An update operation is already in progress!"
146  });
147  return Accepted(); // gtfo of here before all the cancellation tokens fire
148  }
149 
150  return StatusCode((int)HttpStatusCode.Gone);
151  }
152 
154 
162  [HttpGet]
163  [TgsAuthorize]
164  [ProducesResponseType(typeof(Administration), 200)]
165  [ProducesResponseType(424)]
166  [ProducesResponseType(typeof(ErrorMessage), 429)]
167  public async Task<IActionResult> Read()
168  {
169  try
170  {
171  Version greatestVersion = null;
172  Uri repoUrl = null;
173  try
174  {
175  var gitHubClient = GetGitHubClient();
176  var repositoryTask = gitHubClient.Repository.Get(updatesConfiguration.GitHubRepositoryId);
177  var releases = (await gitHubClient.Repository.Release.GetAll(updatesConfiguration.GitHubRepositoryId).ConfigureAwait(false)).Where(x => x.TagName.StartsWith(updatesConfiguration.GitTagPrefix, StringComparison.InvariantCulture));
178 
179  foreach (var I in releases)
180  if (Version.TryParse(I.TagName.Replace(updatesConfiguration.GitTagPrefix, String.Empty, StringComparison.Ordinal), out var version)
181  && version.Major == application.Version.Major
182  && (greatestVersion == null || version > greatestVersion))
183  greatestVersion = version;
184  repoUrl = new Uri((await repositoryTask.ConfigureAwait(false)).HtmlUrl);
185  }
186  catch (NotFoundException e)
187  {
188  Logger.LogWarning("Not found exception while retrieving upstream repository info: {0}", e);
189  }
190 
191  return Json(new Administration
192  {
193  LatestVersion = greatestVersion,
194  TrackedRepositoryUrl = repoUrl,
195  WindowsHost = platformIdentifier.IsWindows
196  });
197  }
198  catch (RateLimitExceededException e)
199  {
200  return RateLimit(e);
201  }
202  catch (ApiException e)
203  {
204  Logger.LogWarning(OctokitException, e);
205  return StatusCode((int)HttpStatusCode.FailedDependency, new ErrorMessage
206  {
207  Message = e.Message
208  });
209  }
210  }
211 
219  [HttpPost]
220  [TgsAuthorize(AdministrationRights.ChangeVersion)]
221  [ProducesResponseType(typeof(ErrorMessage), 422)]
222  public async Task<IActionResult> Update([FromBody] Administration model, CancellationToken cancellationToken)
223  {
224  if (model == null)
225  throw new ArgumentNullException(nameof(model));
226 
227  if (model.NewVersion == null)
228  return BadRequest(new ErrorMessage { Message = "Missing new version!" });
229 
230  if (model.NewVersion.Major != application.Version.Major)
231  return BadRequest(new ErrorMessage { Message = "Cannot update to a different suite version!" });
232 
234  return UnprocessableEntity(new ErrorMessage
235  {
237  });
238 
239  return await CheckReleasesAndApplyUpdate(model.NewVersion, cancellationToken).ConfigureAwait(false);
240  }
241 
248  [HttpDelete("{id}")]
249  [TgsAuthorize(AdministrationRights.RestartHost)]
250  [ProducesResponseType(200)]
251  [ProducesResponseType(typeof(ErrorMessage), 422)]
252  public async Task<IActionResult> Delete()
253  {
254  try
255  {
257  {
258  Logger.LogDebug("Restart request failed due to lack of host watchdog!");
259  return UnprocessableEntity(new ErrorMessage
260  {
262  });
263  }
264 
265  await serverUpdater.Restart().ConfigureAwait(false);
266  return Ok();
267  }
268  catch (InvalidOperationException)
269  {
270  return StatusCode((int)HttpStatusCode.ServiceUnavailable);
271  }
272  }
273  }
274 }
- - -
async Task< IActionResult > Read()
Get Administration server information.
+Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.Extensions.Logging;
3 using Microsoft.Extensions.Options;
4 using Microsoft.Extensions.Primitives;
5 using Octokit;
6 using System;
7 using System.Collections.Generic;
8 using System.Globalization;
9 using System.Linq;
10 using System.Net;
11 using System.Threading;
12 using System.Threading.Tasks;
13 using Tgstation.Server.Api;
20 using Tgstation.Server.Host.IO;
23 
25 {
29  [Route(Routes.Administration)]
31  {
32  const string RestartNotSupportedException = "This deployment of tgstation-server is lacking the Tgstation.Server.Host.Watchdog component. Restarts and version changes cannot be completed!";
33 
34  const string OctokitException = "Bad GitHub API response, check configuration! Exception: {0}";
35 
40 
45 
50 
55 
60 
65 
70 
85  IDatabaseContext databaseContext,
86  IAuthenticationContextFactory authenticationContextFactory,
92  ILogger<AdministrationController> logger,
93  IOptions<UpdatesConfiguration> updatesConfigurationOptions,
94  IOptions<GeneralConfiguration> generalConfigurationOptions)
95  : base(
96  databaseContext,
97  authenticationContextFactory,
98  logger,
99  false,
100  true)
101  {
102  this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
103  this.serverUpdater = serverUpdater ?? throw new ArgumentNullException(nameof(serverUpdater));
104  this.application = application ?? throw new ArgumentNullException(nameof(application));
105  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
106  this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
107  updatesConfiguration = updatesConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(updatesConfigurationOptions));
108  generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
109  }
110 
111  StatusCodeResult RateLimit(RateLimitExceededException exception)
112  {
113  Logger.LogWarning("Exceeded GitHub rate limit! Exception {0}", exception);
114  var secondsString = Math.Ceiling((exception.Reset - DateTimeOffset.Now).TotalSeconds).ToString(CultureInfo.InvariantCulture);
115  Response.Headers.Add("Retry-After", new StringValues(secondsString));
116  return StatusCode(429);
117  }
118 
125  async Task<IActionResult> CheckReleasesAndApplyUpdate(Version newVersion, CancellationToken cancellationToken)
126  {
127  Logger.LogDebug("Looking for GitHub releases version {0}...", newVersion);
128  IEnumerable<Release> releases;
129  try
130  {
131  var gitHubClient = GetGitHubClient();
132  releases = await gitHubClient
133  .Repository
134  .Release
136  .WithToken(cancellationToken)
137  .ConfigureAwait(false);
138  }
139  catch (RateLimitExceededException e)
140  {
141  return RateLimit(e);
142  }
143  catch (ApiException e)
144  {
145  Logger.LogWarning(OctokitException, e);
146  return StatusCode((int)HttpStatusCode.FailedDependency);
147  }
148 
149  releases = releases.Where(x => x.TagName.StartsWith(updatesConfiguration.GitTagPrefix, StringComparison.InvariantCulture));
150 
151  Logger.LogTrace("Release query complete!");
152 
153  foreach (var release in releases)
154  if (Version.TryParse(release.TagName.Replace(updatesConfiguration.GitTagPrefix, String.Empty, StringComparison.Ordinal), out var version) && version == newVersion)
155  {
156  var asset = release.Assets.Where(x => x.Name.Equals(updatesConfiguration.UpdatePackageAssetName, StringComparison.Ordinal)).FirstOrDefault();
157  if (asset == default)
158  continue;
159 
160  if (!serverUpdater.ApplyUpdate(version, new Uri(asset.BrowserDownloadUrl), ioManager))
161  return Conflict(new ErrorMessage
162  {
163  Message = "An update operation is already in progress!"
164  });
165  return Accepted(); // gtfo of here before all the cancellation tokens fire
166  }
167 
168  return StatusCode((int)HttpStatusCode.Gone);
169  }
170 
172 
180  [HttpGet]
181  [TgsAuthorize]
182  [ProducesResponseType(typeof(Administration), 200)]
183  [ProducesResponseType(424)]
184  [ProducesResponseType(typeof(ErrorMessage), 429)]
185  public async Task<IActionResult> Read()
186  {
187  try
188  {
189  Version greatestVersion = null;
190  Uri repoUrl = null;
191  try
192  {
193  var gitHubClient = GetGitHubClient();
194  var repositoryTask = gitHubClient.Repository.Get(updatesConfiguration.GitHubRepositoryId);
195  var releases = (await gitHubClient.Repository.Release.GetAll(updatesConfiguration.GitHubRepositoryId).ConfigureAwait(false)).Where(x => x.TagName.StartsWith(updatesConfiguration.GitTagPrefix, StringComparison.InvariantCulture));
196 
197  foreach (var I in releases)
198  if (Version.TryParse(I.TagName.Replace(updatesConfiguration.GitTagPrefix, String.Empty, StringComparison.Ordinal), out var version)
199  && version.Major == application.Version.Major
200  && (greatestVersion == null || version > greatestVersion))
201  greatestVersion = version;
202  repoUrl = new Uri((await repositoryTask.ConfigureAwait(false)).HtmlUrl);
203  }
204  catch (NotFoundException e)
205  {
206  Logger.LogWarning("Not found exception while retrieving upstream repository info: {0}", e);
207  }
208 
209  return Json(new Administration
210  {
211  LatestVersion = greatestVersion,
212  TrackedRepositoryUrl = repoUrl,
213  WindowsHost = platformIdentifier.IsWindows
214  });
215  }
216  catch (RateLimitExceededException e)
217  {
218  return RateLimit(e);
219  }
220  catch (ApiException e)
221  {
222  Logger.LogWarning(OctokitException, e);
223  return StatusCode((int)HttpStatusCode.FailedDependency, new ErrorMessage
224  {
225  Message = e.Message
226  });
227  }
228  }
229 
241  [HttpPost]
242  [TgsAuthorize(AdministrationRights.ChangeVersion)]
243  [ProducesResponseType(202)]
244  [ProducesResponseType(410)]
245  [ProducesResponseType(typeof(ErrorMessage), 422)]
246  [ProducesResponseType(424)]
247  [ProducesResponseType(typeof(ErrorMessage), 429)]
248  public async Task<IActionResult> Update([FromBody] Administration model, CancellationToken cancellationToken)
249  {
250  if (model == null)
251  throw new ArgumentNullException(nameof(model));
252 
253  if (model.NewVersion == null)
254  return BadRequest(new ErrorMessage { Message = "Missing new version!" });
255 
256  if (model.NewVersion.Major != application.Version.Major)
257  return BadRequest(new ErrorMessage { Message = "Cannot update to a different suite version!" });
258 
260  return UnprocessableEntity(new ErrorMessage
261  {
263  });
264 
265  return await CheckReleasesAndApplyUpdate(model.NewVersion, cancellationToken).ConfigureAwait(false);
266  }
267 
274  [HttpDelete]
275  [TgsAuthorize(AdministrationRights.RestartHost)]
276  [ProducesResponseType(200)]
277  [ProducesResponseType(typeof(ErrorMessage), 422)]
278  public async Task<IActionResult> Delete()
279  {
280  try
281  {
283  {
284  Logger.LogDebug("Restart request failed due to lack of host watchdog!");
285  return UnprocessableEntity(new ErrorMessage
286  {
288  });
289  }
290 
291  await serverUpdater.Restart().ConfigureAwait(false);
292  return Ok();
293  }
294  catch (InvalidOperationException)
295  {
296  return StatusCode((int)HttpStatusCode.ServiceUnavailable);
297  }
298  }
299  }
300 }
+ +
async Task< IActionResult > Read()
Get Administration server information.
bool ApplyUpdate(Version version, Uri updateZipUrl, IIOManager ioManager)
Run a new Host assembly and stop the current one. This will likely trigger all active CancellationTok...
-
string GitTagPrefix
Prefix before the System.Version of TGS published in git tags
+ +
string GitTagPrefix
Prefix before the global::System.Version of TGS published in git tags
string GitHubAccessToken
A GitHub personal access token to use for bypassing rate limits on requests. Requires no scopes
-
async Task< IActionResult > Delete()
Attempts to restart the server
+
async Task< IActionResult > Delete()
Attempts to restart the server.
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
-
readonly IIOManager ioManager
The IIOManager for the AdministrationController
+
readonly IIOManager ioManager
The IIOManager for the AdministrationController
long GitHubRepositoryId
The Octokit.Repository.Id of the tgstation-server fork to recieve updates from
-
readonly IGitHubClientFactory gitHubClientFactory
The IGitHubClientFactory for the AdministrationController
+
readonly IGitHubClientFactory gitHubClientFactory
The IGitHubClientFactory for the AdministrationController
string UpdatePackageAssetName
Asset package containing the new Host assembly in zip form
- -
readonly UpdatesConfiguration updatesConfiguration
The UpdatesConfiguration for the AdministrationController
+
readonly UpdatesConfiguration updatesConfiguration
The UpdatesConfiguration for the AdministrationController
bool WatchdogPresent
true if live updates are supported, false. ApplyUpdate(Version, Uri, IIOManager) and Restart will fai...
- -
readonly IApplication application
The IApplication for the AdministrationController
+ +
readonly IApplication application
The IApplication for the AdministrationController
AdministrationRights
Rights for Models.Administration
const string Administration
The Models.Administration controller
Definition: Routes.cs:19
-
StatusCodeResult RateLimit(RateLimitExceededException exception)
+
StatusCodeResult RateLimit(RateLimitExceededException exception)
Represents administrative server information
Configuration for the automatic update system
Routes to a server actions
Definition: Routes.cs:9
-
async Task< IActionResult > Update([FromBody] Administration model, CancellationToken cancellationToken)
Attempt to perform a server upgrade.
- + +
async Task< IActionResult > Update([FromBody] Administration model, CancellationToken cancellationToken)
Attempt to perform a server upgrade.
+ -
async Task< IActionResult > CheckReleasesAndApplyUpdate(Version newVersion, CancellationToken cancellationToken)
Try to download and apply an update with a given newVersion .
+
async Task< IActionResult > CheckReleasesAndApplyUpdate(Version newVersion, CancellationToken cancellationToken)
Try to download and apply an update with a given newVersion .
-
AdministrationController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IGitHubClientFactory gitHubClientFactory, IServerControl serverUpdater, IApplication application, IIOManager ioManager, IPlatformIdentifier platformIdentifier, ILogger< AdministrationController > logger, IOptions< UpdatesConfiguration > updatesConfigurationOptions, IOptions< GeneralConfiguration > generalConfigurationOptions)
Construct an AdministrationController
-
bool IsWindows
If the current platform is a Windows platform
+
AdministrationController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IGitHubClientFactory gitHubClientFactory, IServerControl serverUpdater, IApplication application, IIOManager ioManager, IPlatformIdentifier platformIdentifier, ILogger< AdministrationController > logger, IOptions< UpdatesConfiguration > updatesConfigurationOptions, IOptions< GeneralConfiguration > generalConfigurationOptions)
Construct an AdministrationController
- +
IGitHubClient CreateClient()
Create a client with anonymous authentication. Low rate limit
-
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for the AdministrationController
+
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for the AdministrationController
+
ILogger Logger
The ILogger for the ApiController
Interface for using filesystems
Definition: IIOManager.cs:11
-
For identifying the current platform
+
For identifying the current platform
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
-
readonly IServerControl serverUpdater
The IServerControl for the AdministrationController
+
readonly IServerControl serverUpdater
The IServerControl for the AdministrationController
Version Version
The version of the Application
Definition: IApplication.cs:23
-
readonly GeneralConfiguration generalConfiguration
The GeneralConfiguration for the AdministrationController
+
readonly GeneralConfiguration generalConfiguration
The GeneralConfiguration for the AdministrationController
+
Represents a service that may take an updated Host assembly and run it, stopping the current assembly...
+
bool IsWindows
If the current platform is a Windows platform
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Http;
2 using Microsoft.AspNetCore.Mvc;
3 using Microsoft.AspNetCore.Mvc.Filters;
4 using Microsoft.Extensions.Logging;
5 using System;
6 using System.Globalization;
7 using System.Linq;
8 using System.Net;
9 using System.Threading.Tasks;
10 using Tgstation.Server.Api;
14 
16 {
20  [Produces(ApiHeaders.ApplicationJson)]
21  [ApiController]
22  public abstract class ApiController : Controller
23  {
27  protected ApiHeaders ApiHeaders { get; private set; }
28 
32  protected IDatabaseContext DatabaseContext { get; }
33 
38 
42  protected ILogger Logger { get; }
43 
47  protected Models.Instance Instance { get; }
48 
52  readonly bool requireInstance;
53 
57  readonly bool requireHeaders;
58 
67  public ApiController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ILogger logger, bool requireInstance, bool requireHeaders)
68  {
69  DatabaseContext = databaseContext ?? throw new ArgumentNullException(nameof(databaseContext));
70  if (authenticationContextFactory == null)
71  throw new ArgumentNullException(nameof(authenticationContextFactory));
72  Logger = logger ?? throw new ArgumentNullException(nameof(logger));
73  AuthenticationContext = authenticationContextFactory.CurrentAuthenticationContext;
75  this.requireInstance = requireInstance;
76  this.requireHeaders = requireHeaders;
77  }
78 
80  #pragma warning disable CA1506 // TODO: Decomplexify
81  public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
82  {
83  // ALL valid token and login requests that match a route go through this function
84  // 404 is returned before
85  if (AuthenticationContext != null && AuthenticationContext.User == null)
86  {
87  // valid token, expired password
88  await Unauthorized().ExecuteResultAsync(context).ConfigureAwait(false);
89  return;
90  }
91 
92  // validate the headers
93  try
94  {
95  ApiHeaders = new ApiHeaders(Request.GetTypedHeaders());
96 
97  if (!ApiHeaders.Compatible())
98  {
99  await StatusCode((int)HttpStatusCode.UpgradeRequired, new ErrorMessage
100  {
101  Message = "Provided API version is incompatible with server version!"
102  }).ExecuteResultAsync(context).ConfigureAwait(false);
103  return;
104  }
105 
106  if (requireInstance)
107  {
108  if (!ApiHeaders.InstanceId.HasValue)
109  {
110  await BadRequest(new ErrorMessage { Message = "Missing Instance header!" }).ExecuteResultAsync(context).ConfigureAwait(false);
111  return;
112  }
113 
115  {
116  // accessing an instance they don't have access to or one that's disabled
117  await Forbid().ExecuteResultAsync(context).ConfigureAwait(false);
118  return;
119  }
120  }
121  }
122  catch (InvalidOperationException e)
123  {
124  if (requireHeaders)
125  {
126  await BadRequest(new ErrorMessage { Message = e.Message }).ExecuteResultAsync(context).ConfigureAwait(false);
127  return;
128  }
129  }
130 
131  if (ModelState?.IsValid == false)
132  {
133  var errorMessages = ModelState.SelectMany(x => x.Value.Errors).Select(x => x.ErrorMessage);
134  await BadRequest(new ErrorMessage { Message = String.Join(Environment.NewLine, errorMessages) }).ExecuteResultAsync(context).ConfigureAwait(false);
135  return;
136  }
137 
138  if (ApiHeaders != null)
139  Logger.LogDebug("Request made by User ID {0}. Api version: {1}. User-Agent: {2}. Type: {3}. Route {4}{5} to Instance {6}", AuthenticationContext?.User.Id.ToString(CultureInfo.InvariantCulture), ApiHeaders.ApiVersion, ApiHeaders.RawUserAgent, Request.Method, Request.Path, Request.QueryString, ApiHeaders.InstanceId);
140 
141  try
142  {
143  await base.OnActionExecutionAsync(context, next).ConfigureAwait(false);
144  }
145  catch (OperationCanceledException e)
146  {
147  Logger.LogDebug("Request cancelled! Exception: {0}", e);
148  throw;
149  }
150  }
151  #pragma warning restore CA1506
152  }
153 }
- +Go to the documentation of this file.
1 using Microsoft.AspNetCore.Http;
2 using Microsoft.AspNetCore.Mvc;
3 using Microsoft.AspNetCore.Mvc.Filters;
4 using Microsoft.Extensions.Logging;
5 using System;
6 using System.Globalization;
7 using System.Linq;
8 using System.Net;
9 using System.Threading.Tasks;
10 using Tgstation.Server.Api;
14 
16 {
20  [Produces(ApiHeaders.ApplicationJson)]
21  [ApiController]
22  public abstract class ApiController : Controller
23  {
27  protected ApiHeaders ApiHeaders { get; private set; }
28 
32  protected IDatabaseContext DatabaseContext { get; }
33 
38 
42  protected ILogger Logger { get; }
43 
47  protected Models.Instance Instance { get; }
48 
52  readonly bool requireInstance;
53 
57  readonly bool requireHeaders;
58 
67  public ApiController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ILogger logger, bool requireInstance, bool requireHeaders)
68  {
69  DatabaseContext = databaseContext ?? throw new ArgumentNullException(nameof(databaseContext));
70  if (authenticationContextFactory == null)
71  throw new ArgumentNullException(nameof(authenticationContextFactory));
72  Logger = logger ?? throw new ArgumentNullException(nameof(logger));
73  AuthenticationContext = authenticationContextFactory.CurrentAuthenticationContext;
75  this.requireInstance = requireInstance;
76  this.requireHeaders = requireHeaders;
77  }
78 
80  #pragma warning disable CA1506 // TODO: Decomplexify
81  public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
82  {
83  // ALL valid token and login requests that match a route go through this function
84  // 404 is returned before
85  if (AuthenticationContext != null && AuthenticationContext.User == null)
86  {
87  // valid token, expired password
88  await Unauthorized().ExecuteResultAsync(context).ConfigureAwait(false);
89  return;
90  }
91 
92  // validate the headers
93  try
94  {
95  ApiHeaders = new ApiHeaders(Request.GetTypedHeaders());
96 
97  if (!ApiHeaders.Compatible())
98  {
99  await StatusCode((int)HttpStatusCode.UpgradeRequired, new ErrorMessage
100  {
101  Message = "Provided API version is incompatible with server version!"
102  }).ExecuteResultAsync(context).ConfigureAwait(false);
103  return;
104  }
105 
106  if (requireInstance)
107  {
108  if (!ApiHeaders.InstanceId.HasValue)
109  {
110  await BadRequest(new ErrorMessage { Message = "Missing Instance header!" }).ExecuteResultAsync(context).ConfigureAwait(false);
111  return;
112  }
113 
115  {
116  // accessing an instance they don't have access to or one that's disabled
117  await Forbid().ExecuteResultAsync(context).ConfigureAwait(false);
118  return;
119  }
120  }
121  }
122  catch (InvalidOperationException e)
123  {
124  if (requireHeaders)
125  {
126  await BadRequest(new ErrorMessage { Message = e.Message }).ExecuteResultAsync(context).ConfigureAwait(false);
127  return;
128  }
129  }
130 
131  if (ModelState?.IsValid == false)
132  {
133  var errorMessages = ModelState.SelectMany(x => x.Value.Errors).Select(x => x.ErrorMessage);
134  await BadRequest(new ErrorMessage { Message = String.Join(Environment.NewLine, errorMessages) }).ExecuteResultAsync(context).ConfigureAwait(false);
135  return;
136  }
137 
138  if (ApiHeaders != null)
139  Logger.LogDebug("Request made by User ID {0}. Api version: {1}. User-Agent: {2}. Type: {3}. Route {4}{5} to Instance {6}", AuthenticationContext?.User.Id.ToString(CultureInfo.InvariantCulture), ApiHeaders.ApiVersion, ApiHeaders.RawUserAgent, Request.Method, Request.Path, Request.QueryString, ApiHeaders.InstanceId);
140 
141  try
142  {
143  await base.OnActionExecutionAsync(context, next).ConfigureAwait(false);
144  }
145  catch (OperationCanceledException e)
146  {
147  Logger.LogDebug("Request cancelled! Exception: {0}", e);
148  throw;
149  }
150  }
151  #pragma warning restore CA1506
152  }
153 }
ApiController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ILogger logger, bool requireInstance, bool requireHeaders)
Construct an ApiController
- +
override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
-
const string ApplicationJson
TODO: Remove this when https://github.com/dotnet/corefx/pull/26701 makes it into the sdk
Definition: ApiHeaders.cs:22
Version ApiVersion
The client's API version
Definition: ApiHeaders.cs:82
bool Compatible()
Checks if the ApiVersion is compatible with Version
Represents the currently authenticated Api.Models.User
ApiHeaders ApiHeaders
The ApiHeaders for the operation
+
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:17
+
string Message
A human readable description of the error
Definition: ErrorMessage.cs:13
-
string RawUserAgent
The client's raw user agent
Definition: ApiHeaders.cs:77
@@ -105,6 +104,7 @@ $(function() {
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+
diff --git a/_application_8cs_source.html b/_application_8cs_source.html index 5a4b35e0e1..fbe933899c 100644 --- a/_application_8cs_source.html +++ b/_application_8cs_source.html @@ -71,48 +71,53 @@ $(function() {
Application.cs
-Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Cyberboss.AspNetCore.AsyncInitializer;
3 using Microsoft.AspNetCore.Authentication.JwtBearer;
4 using Microsoft.AspNetCore.Builder;
5 using Microsoft.AspNetCore.Cors.Infrastructure;
6 using Microsoft.AspNetCore.Hosting;
7 using Microsoft.AspNetCore.Identity;
8 using Microsoft.AspNetCore.Mvc;
9 using Microsoft.Extensions.Configuration;
10 using Microsoft.Extensions.DependencyInjection;
11 using Microsoft.Extensions.Hosting;
12 using Microsoft.Extensions.Logging;
13 using Microsoft.Extensions.Options;
14 using Microsoft.Extensions.Primitives;
15 using Microsoft.Net.Http.Headers;
16 using Microsoft.OpenApi.Models;
17 using Newtonsoft.Json;
18 using Newtonsoft.Json.Converters;
19 using Serilog;
20 using Serilog.Events;
21 using Serilog.Formatting.Display;
22 using System;
23 using System.Globalization;
24 using System.IdentityModel.Tokens.Jwt;
25 using System.Linq;
26 using System.Threading.Tasks;
27 using Tgstation.Server.Api;
35 using Tgstation.Server.Host.IO;
38 
40 {
42 #pragma warning disable CA1506
43  sealed class Application : IApplication
44  {
46  public string VersionPrefix => "tgstation-server";
47 
49  public Version Version { get; }
50 
52  public string VersionString { get; }
53 
57  readonly IConfiguration configuration;
58 
63 
67  readonly Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment;
68 
72  readonly TaskCompletionSource<object> startupTcs;
73 
78 
85  public Application(
86  IConfiguration configuration,
88  Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment)
89  {
90  this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
91  this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider));
92  this.hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
93 
94  startupTcs = new TaskCompletionSource<object>();
95 
97  VersionString = String.Format(CultureInfo.InvariantCulture, "{0} v{1}", VersionPrefix, Version);
98  }
99 
104  public void ConfigureServices(IServiceCollection services)
105  {
106  if (services == null)
107  throw new ArgumentNullException(nameof(services));
108 
109  // needful
110  services.AddSingleton<IApplication>(this);
111 
112  // configure configuration
113  services.UseStandardConfig<UpdatesConfiguration>(configuration);
114  services.UseStandardConfig<DatabaseConfiguration>(configuration);
115  services.UseStandardConfig<GeneralConfiguration>(configuration);
116  services.UseStandardConfig<FileLoggingConfiguration>(configuration);
117  services.UseStandardConfig<ControlPanelConfiguration>(configuration);
118 
119  // enable options which give us config reloading
120  services.AddOptions();
121 
122  // this is needful for the setup wizard
123  services.AddLogging();
124 
125  // other stuff needed for for setup wizard and configuration
126  services.AddSingleton<IIOManager, DefaultIOManager>();
127  services.AddSingleton<IConsole, IO.Console>();
128  services.AddSingleton<IDBConnectionFactory, DBConnectionFactory>();
129  services.AddSingleton<ISetupWizard, SetupWizard>();
130  services.AddSingleton<IPlatformIdentifier, PlatformIdentifier>();
131  services.AddSingleton<IAsyncDelayer, AsyncDelayer>();
132 
133  GeneralConfiguration generalConfiguration;
134  DatabaseConfiguration databaseConfiguration;
135  FileLoggingConfiguration fileLoggingConfiguration;
136  ControlPanelConfiguration controlPanelConfiguration;
137  IIOManager ioManager;
138  IPlatformIdentifier platformIdentifier;
139 
140  // temporarily build the service provider in it's current state
141  // do it here so we can run the setup wizard if necessary
142  // also allows us to get some options and other services we need for continued configuration
143  using (var provider = services.BuildServiceProvider())
144  {
145  // run the wizard if necessary
146  var setupWizard = provider.GetRequiredService<ISetupWizard>();
147  var applicationLifetime = provider.GetRequiredService<Microsoft.AspNetCore.Hosting.IApplicationLifetime>();
148  var setupWizardRan = setupWizard.CheckRunWizard(applicationLifetime.ApplicationStopping).GetAwaiter().GetResult();
149 
150  // load the configuration options we need
151  var generalOptions = provider.GetRequiredService<IOptions<GeneralConfiguration>>();
152  generalConfiguration = generalOptions.Value;
153 
154  // unless this is set, in which case, we leave
155  if (setupWizardRan && generalConfiguration.SetupWizardMode == SetupWizardMode.Only)
156  throw new OperationCanceledException("Exiting due to SetupWizardMode configuration!"); // we don't inject a logger in the constuctor to log this because it's not yet configured
157 
158  var dbOptions = provider.GetRequiredService<IOptions<DatabaseConfiguration>>();
159  databaseConfiguration = dbOptions.Value;
160 
161  var loggingOptions = provider.GetRequiredService<IOptions<FileLoggingConfiguration>>();
162  fileLoggingConfiguration = loggingOptions.Value;
163 
164  var controlPanelOptions = provider.GetRequiredService<IOptions<ControlPanelConfiguration>>();
165  controlPanelConfiguration = controlPanelOptions.Value;
166 
167  ioManager = provider.GetRequiredService<IIOManager>();
168  platformIdentifier = provider.GetRequiredService<IPlatformIdentifier>();
169  }
170 
171  // setup file logging via serilog
172  if (!fileLoggingConfiguration.Disable)
173  services.AddLogging(builder =>
174  {
175  // common app data is C:/ProgramData on windows, else /usr/shar
176  var logPath = !String.IsNullOrEmpty(fileLoggingConfiguration.Directory) ? fileLoggingConfiguration.Directory : ioManager.ConcatPath(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), VersionPrefix, "Logs");
177 
178  logPath = ioManager.ConcatPath(logPath, "tgs-{Date}.log");
179 
180  LogEventLevel? ConvertLogLevel(LogLevel logLevel)
181  {
182  switch (logLevel)
183  {
184  case LogLevel.Critical:
185  return LogEventLevel.Fatal;
186  case LogLevel.Debug:
187  return LogEventLevel.Debug;
188  case LogLevel.Error:
189  return LogEventLevel.Error;
190  case LogLevel.Information:
191  return LogEventLevel.Information;
192  case LogLevel.Trace:
193  return LogEventLevel.Verbose;
194  case LogLevel.Warning:
195  return LogEventLevel.Warning;
196  case LogLevel.None:
197  return null;
198  default:
199  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid log level {0}", logLevel));
200  }
201  }
202 
203  var logEventLevel = ConvertLogLevel(fileLoggingConfiguration.LogLevel);
204  var microsoftEventLevel = ConvertLogLevel(fileLoggingConfiguration.MicrosoftLogLevel);
205 
206  var formatter = new MessageTemplateTextFormatter("{Timestamp:o} {RequestId,13} [{Level:u3}] {SourceContext:l}: {Message} ({EventId:x8}){NewLine}{Exception}", null);
207 
208  var configuration = new LoggerConfiguration()
209  .Enrich.FromLogContext()
210  .WriteTo.Async(w => w.RollingFile(formatter, logPath, shared: true, flushToDiskInterval: TimeSpan.FromSeconds(2)));
211 
212  if (logEventLevel.HasValue)
213  configuration.MinimumLevel.Is(logEventLevel.Value);
214 
215  if (microsoftEventLevel.HasValue)
216  configuration.MinimumLevel.Override("Microsoft", microsoftEventLevel.Value);
217 
218  builder.AddSerilog(configuration.CreateLogger(), true);
219  });
220 
221  // configure bearer token validation
222  services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(jwtBearerOptions =>
223  {
224  // this line isn't actually run until the first request is made
225  // at that point tokenFactory will be populated
226  jwtBearerOptions.TokenValidationParameters = tokenFactory.ValidationParameters;
227  jwtBearerOptions.Events = new JwtBearerEvents
228  {
229  // Application is our composition root so this monstrosity of a line is okay
230  OnTokenValidated = ctx => ctx.HttpContext.RequestServices.GetRequiredService<IClaimsInjector>().InjectClaimsIntoContext(ctx, ctx.HttpContext.RequestAborted)
231  };
232  });
233 
234  // fucking prevents converting 'sub' to M$ bs
235  // can't be done in the above lambda, that's too late
236  JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
237 
238  // add mvc, configure the json serializer settings
239  services
240  .AddMvc(options =>
241  {
242  var dataAnnotationValidator = options.ModelValidatorProviders.Single(validator => validator.GetType().Name == "DataAnnotationsModelValidatorProvider");
243  options.ModelValidatorProviders.Remove(dataAnnotationValidator);
244  })
245  .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
246  .AddJsonOptions(options =>
247  {
248  options.AllowInputFormatterExceptionMessages = true;
249  options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
250  options.SerializerSettings.CheckAdditionalContent = true;
251  options.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Error;
252  options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
253  options.SerializerSettings.Converters = new[] { new VersionConverter() };
254  });
255 
256  if (hostingEnvironment.IsDevelopment())
257  services.AddSwaggerGen(
258  c =>
259  {
260  c.SwaggerDoc(
261  "v1",
262  new OpenApiInfo
263  {
264  Title = "TGS API",
265  Version = "v4"
266  });
267 
268  // Important to do this before applying our own filters
269  // Otherwise we'll get NullReferenceExceptions on parameters to be setup in our document filter
270  var assemblyLocation = assemblyInformationProvider.Path;
271  var filePath = ioManager.ConcatPath(ioManager.GetDirectoryName(assemblyLocation), String.Concat(ioManager.GetFileNameWithoutExtension(assemblyLocation), ".xml"));
272  c.IncludeXmlComments(filePath);
273 
274  c.OperationFilter<TgsOpenApiFilters>();
275  c.DocumentFilter<TgsOpenApiFilters>();
276 
277  c.AddSecurityDefinition(TgsOpenApiFilters.PasswordSecuritySchemeId, new OpenApiSecurityScheme
278  {
279  In = ParameterLocation.Header,
280  Type = SecuritySchemeType.Http,
281  Name = HeaderNames.Authorization,
282  Scheme = ApiHeaders.BasicAuthenticationScheme
283  });
284 
285  c.AddSecurityDefinition(TgsOpenApiFilters.TokenSecuritySchemeId, new OpenApiSecurityScheme
286  {
287  BearerFormat = "JWT",
288  In = ParameterLocation.Header,
289  Type = SecuritySchemeType.Http,
290  Name = HeaderNames.Authorization,
291  Scheme = ApiHeaders.JwtAuthenticationScheme
292  });
293  });
294 
295  // enable browser detection
296  services.AddDetectionCore().AddBrowser();
297 
298  // CORS conditionally enabled later
299  services.AddCors();
300 
301  void AddTypedContext<TContext>() where TContext : DatabaseContext<TContext>
302  {
303  services.AddDbContext<TContext>(builder =>
304  {
305  if (hostingEnvironment.IsDevelopment())
306  builder.EnableSensitiveDataLogging();
307  });
308  services.AddScoped<IDatabaseContext>(x => x.GetRequiredService<TContext>());
309  }
310 
311  // add the correct database context type
312  var dbType = databaseConfiguration.DatabaseType;
313  switch (dbType)
314  {
315  case DatabaseType.MySql:
316  case DatabaseType.MariaDB:
317  AddTypedContext<MySqlDatabaseContext>();
318  break;
319  case DatabaseType.SqlServer:
320  AddTypedContext<SqlServerDatabaseContext>();
321  break;
322  default:
323  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid {0}: {1}!", nameof(DatabaseType), dbType));
324  }
325 
326  // configure other database services
327  services.AddSingleton<IDatabaseContextFactory, DatabaseContextFactory>();
328  services.AddSingleton<IDatabaseSeeder, DatabaseSeeder>();
329 
330  // configure security services
332  services.AddScoped<IClaimsInjector, ClaimsInjector>();
333  services.AddSingleton<IIdentityCache, IdentityCache>();
334  services.AddSingleton<ICryptographySuite, CryptographySuite>();
335  services.AddSingleton<ITokenFactory, TokenFactory>();
336  services.AddSingleton<IPasswordHasher<Models.User>, PasswordHasher<Models.User>>();
337 
338  // configure platform specific services
339  if (platformIdentifier.IsWindows)
340  {
341  services.AddSingleton<ISystemIdentityFactory, WindowsSystemIdentityFactory>();
342  services.AddSingleton<ISymlinkFactory, WindowsSymlinkFactory>();
343  services.AddSingleton<IByondInstaller, WindowsByondInstaller>();
344  services.AddSingleton<IPostWriteHandler, WindowsPostWriteHandler>();
345 
346  services.AddSingleton<WindowsNetworkPromptReaper>();
347  services.AddSingleton<INetworkPromptReaper>(x => x.GetRequiredService<WindowsNetworkPromptReaper>());
348  services.AddSingleton<IHostedService>(x => x.GetRequiredService<WindowsNetworkPromptReaper>());
349  }
350  else
351  {
352  services.AddSingleton<ISystemIdentityFactory, PosixSystemIdentityFactory>();
353  services.AddSingleton<ISymlinkFactory, PosixSymlinkFactory>();
354  services.AddSingleton<IByondInstaller, PosixByondInstaller>();
355  services.AddSingleton<IPostWriteHandler, PosixPostWriteHandler>();
356  services.AddSingleton<INetworkPromptReaper, PosixNetworkPromptReaper>();
357  }
358 
359  // configure misc services
360  services.AddSingleton<ISynchronousIOManager, SynchronousIOManager>();
361  services.AddSingleton<IGitHubClientFactory, GitHubClientFactory>();
362  services.AddSingleton<IProcessExecutor, ProcessExecutor>();
363  services.AddSingleton<IByondTopicSender>(new ByondTopicSender
364  {
365  ReceiveTimeout = generalConfiguration.ByondTopicTimeout,
366  SendTimeout = generalConfiguration.ByondTopicTimeout
367  });
368 
369  // configure component services
370  services.AddSingleton<ICredentialsProvider, CredentialsProvider>();
371  services.AddSingleton<IProviderFactory, ProviderFactory>();
372  services.AddSingleton<IChatFactory, ChatFactory>();
373  services.AddSingleton<IWatchdogFactory, WatchdogFactory>();
374  services.AddSingleton<IInstanceFactory, InstanceFactory>();
375 
376  // configure root services
377  services.AddSingleton<InstanceManager>();
378  services.AddSingleton<IInstanceManager>(x => x.GetRequiredService<InstanceManager>());
379  services.AddSingleton<IHostedService>(x => x.GetRequiredService<InstanceManager>());
380 
381  services.AddSingleton<IJobManager, JobManager>();
382  }
383 
392  public void Configure(IApplicationBuilder applicationBuilder, IServerControl serverControl, ITokenFactory tokenFactory, IOptions<ControlPanelConfiguration> controlPanelConfigurationOptions, ILogger<Application> logger)
393  {
394  if (applicationBuilder == null)
395  throw new ArgumentNullException(nameof(applicationBuilder));
396  if (serverControl == null)
397  throw new ArgumentNullException(nameof(serverControl));
398 
399  this.tokenFactory = tokenFactory ?? throw new ArgumentNullException(nameof(tokenFactory));
400 
401  var controlPanelConfiguration = controlPanelConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(controlPanelConfigurationOptions));
402 
403  if (logger == null)
404  throw new ArgumentNullException(nameof(logger));
405 
406  logger.LogInformation(VersionString);
407  logger.LogDebug("Content Root: {0}", hostingEnvironment.ContentRootPath);
408  logger.LogTrace("Web Root: {0}", hostingEnvironment.WebRootPath);
409 
410  // attempt to restart the server if the configuration changes
411  if (serverControl.WatchdogPresent)
412  ChangeToken.OnChange(configuration.GetReloadToken, () => serverControl.Restart());
413 
414  // setup the HTTP request pipeline
415  // Final point where we wrap exceptions in a 500 (ErrorMessage) response
416  applicationBuilder.UseServerErrorHandling();
417 
418  // should anything after this throw an exception, catch it and display a detailed html page
419  if (hostingEnvironment.IsDevelopment())
420  applicationBuilder.UseDeveloperExceptionPage(); // it is not worth it to limit this, you should only ever get it if you're an authorized user
421 
422  // suppress OperationCancelledExceptions, they are just aborted HTTP requests
423  applicationBuilder.UseCancelledRequestSuppression();
424 
425  if (hostingEnvironment.IsDevelopment())
426  {
427  applicationBuilder.UseSwagger();
428  applicationBuilder.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TGS API V4"));
429  }
430 
431  // Set up CORS based on configuration if necessary
432  Action<CorsPolicyBuilder> corsBuilder = null;
433  if (controlPanelConfiguration.AllowAnyOrigin)
434  {
435  logger.LogTrace("Access-Control-Allow-Origin: *");
436  corsBuilder = builder => builder.AllowAnyOrigin();
437  }
438  else if (controlPanelConfiguration.AllowedOrigins?.Count > 0)
439  {
440  logger.LogTrace("Access-Control-Allow-Origin: ", String.Join(',', controlPanelConfiguration.AllowedOrigins));
441  corsBuilder = builder => builder.WithOrigins(controlPanelConfiguration.AllowedOrigins.ToArray());
442  }
443 
444  var originalBuilder = corsBuilder;
445  corsBuilder = builder =>
446  {
447  builder.AllowAnyHeader().AllowAnyMethod();
448  originalBuilder?.Invoke(builder);
449  };
450  applicationBuilder.UseCors(corsBuilder);
451 
452  // Do not service requests until Ready is called, this will return 503 until that point
453  applicationBuilder.UseAsyncInitialization(async cancellationToken =>
454  {
455  using (cancellationToken.Register(() => startupTcs.SetCanceled()))
456  await startupTcs.Task.ConfigureAwait(false);
457  });
458 
459  // spa loading if necessary
460  if (controlPanelConfiguration.Enable)
461  {
462  logger.LogWarning("Web control panel enabled. This is a highly WIP feature!");
463  applicationBuilder.UseStaticFiles();
464  }
465  else
466  logger.LogDebug("Web control panel disabled!");
467 
468  // authenticate JWT tokens using our security pipeline if present, returns 401 if bad
469  applicationBuilder.UseAuthentication();
470 
471  // suppress and log database exceptions
472  applicationBuilder.UseDbConflictHandling();
473 
474  // majority of handling is done in the controllers
475  applicationBuilder.UseMvc();
476 
477  // 404 anything that gets this far
478  }
479 
481  public void Ready(Exception initializationError)
482  {
483  lock (startupTcs)
484  {
485  if (startupTcs.Task.IsCompleted)
486  throw new InvalidOperationException("Ready has already been called!");
487  if (initializationError == null)
488  startupTcs.SetResult(null);
489  else
490  startupTcs.SetException(initializationError);
491  }
492  }
493  }
494 }
LogLevel MicrosoftLogLevel
The minimum Microsoft.Extensions.Logging.LogLevel to display in logs for Microsoft library sources
- +Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Cyberboss.AspNetCore.AsyncInitializer;
3 using Microsoft.AspNetCore.Authentication.JwtBearer;
4 using Microsoft.AspNetCore.Builder;
5 using Microsoft.AspNetCore.Cors.Infrastructure;
6 using Microsoft.AspNetCore.Hosting;
7 using Microsoft.AspNetCore.Identity;
8 using Microsoft.AspNetCore.Mvc;
9 using Microsoft.Extensions.Configuration;
10 using Microsoft.Extensions.DependencyInjection;
11 using Microsoft.Extensions.Hosting;
12 using Microsoft.Extensions.Logging;
13 using Microsoft.Extensions.Options;
14 using Microsoft.Extensions.Primitives;
15 using Newtonsoft.Json;
16 using Newtonsoft.Json.Converters;
17 using Serilog;
18 using Serilog.Events;
19 using Serilog.Formatting.Display;
20 using System;
21 using System.Globalization;
22 using System.IdentityModel.Tokens.Jwt;
23 using System.Linq;
24 using System.Threading.Tasks;
25 using Tgstation.Server.Api;
34 using Tgstation.Server.Host.IO;
38 
40 {
42 #pragma warning disable CA1506
43  sealed class Application : IApplication
44  {
46  public string VersionPrefix => "tgstation-server";
47 
49  public Version Version { get; }
50 
52  public string VersionString { get; }
53 
57  readonly IConfiguration configuration;
58 
63 
68 
72  readonly Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment;
73 
77  readonly TaskCompletionSource<object> startupTcs;
78 
83 
91  public Application(
92  IConfiguration configuration,
94  Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment,
96  {
97  this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
98  this.assemblyInformationProvider = assemblyInformationProvider ?? throw new ArgumentNullException(nameof(assemblyInformationProvider));
99  this.hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
100  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
101 
102  startupTcs = new TaskCompletionSource<object>();
103 
105  VersionString = String.Format(CultureInfo.InvariantCulture, "{0} v{1}", VersionPrefix, Version);
106  }
107 
112  public void ConfigureServices(IServiceCollection services)
113  {
114  if (services == null)
115  throw new ArgumentNullException(nameof(services));
116 
117  // needful
118  services.AddSingleton<IApplication>(this);
119 
120  // configure configuration
121  services.UseStandardConfig<UpdatesConfiguration>(configuration);
122  services.UseStandardConfig<DatabaseConfiguration>(configuration);
123  services.UseStandardConfig<GeneralConfiguration>(configuration);
124  services.UseStandardConfig<FileLoggingConfiguration>(configuration);
125  services.UseStandardConfig<ControlPanelConfiguration>(configuration);
126 
127  // enable options which give us config reloading
128  services.AddOptions();
129 
130  // this is needful for the setup wizard
131  services.AddLogging();
132 
133  // other stuff needed for for setup wizard and configuration
134  services.AddSingleton<IConsole, IO.Console>();
135  services.AddSingleton<IDatabaseConnectionFactory, DatabaseConnectionFactory>();
136  services.AddSingleton<ISetupWizard, SetupWizard>();
137  services.AddSingleton<IPlatformIdentifier, PlatformIdentifier>();
138  services.AddSingleton<IAsyncDelayer, AsyncDelayer>();
139 
140  GeneralConfiguration generalConfiguration;
141  DatabaseConfiguration databaseConfiguration;
142  FileLoggingConfiguration fileLoggingConfiguration;
143  ControlPanelConfiguration controlPanelConfiguration;
144  IPlatformIdentifier platformIdentifier;
145 
146  // temporarily build the service provider in it's current state
147  // do it here so we can run the setup wizard if necessary
148  // also allows us to get some options and other services we need for continued configuration
149  using (var provider = services.BuildServiceProvider())
150  {
151  // run the wizard if necessary
152  var setupWizard = provider.GetRequiredService<ISetupWizard>();
153  var applicationLifetime = provider.GetRequiredService<Microsoft.AspNetCore.Hosting.IApplicationLifetime>();
154  var setupWizardRan = setupWizard.CheckRunWizard(applicationLifetime.ApplicationStopping).GetAwaiter().GetResult();
155 
156  // load the configuration options we need
157  var generalOptions = provider.GetRequiredService<IOptions<GeneralConfiguration>>();
158  generalConfiguration = generalOptions.Value;
159 
160  // unless this is set, in which case, we leave
161  if (setupWizardRan && generalConfiguration.SetupWizardMode == SetupWizardMode.Only)
162  throw new OperationCanceledException("Exiting due to SetupWizardMode configuration!"); // we don't inject a logger in the constuctor to log this because it's not yet configured
163 
164  var dbOptions = provider.GetRequiredService<IOptions<DatabaseConfiguration>>();
165  databaseConfiguration = dbOptions.Value;
166 
167  var loggingOptions = provider.GetRequiredService<IOptions<FileLoggingConfiguration>>();
168  fileLoggingConfiguration = loggingOptions.Value;
169 
170  var controlPanelOptions = provider.GetRequiredService<IOptions<ControlPanelConfiguration>>();
171  controlPanelConfiguration = controlPanelOptions.Value;
172 
173  platformIdentifier = provider.GetRequiredService<IPlatformIdentifier>();
174  }
175 
176  // setup file logging via serilog
177  if (!fileLoggingConfiguration.Disable)
178  services.AddLogging(builder =>
179  {
180  // common app data is C:/ProgramData on windows, else /usr/shar
181  var logPath = !String.IsNullOrEmpty(fileLoggingConfiguration.Directory) ? fileLoggingConfiguration.Directory : ioManager.ConcatPath(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), VersionPrefix, "Logs");
182 
183  logPath = ioManager.ConcatPath(logPath, "tgs-{Date}.log");
184 
185  LogEventLevel? ConvertLogLevel(LogLevel logLevel)
186  {
187  switch (logLevel)
188  {
189  case LogLevel.Critical:
190  return LogEventLevel.Fatal;
191  case LogLevel.Debug:
192  return LogEventLevel.Debug;
193  case LogLevel.Error:
194  return LogEventLevel.Error;
195  case LogLevel.Information:
196  return LogEventLevel.Information;
197  case LogLevel.Trace:
198  return LogEventLevel.Verbose;
199  case LogLevel.Warning:
200  return LogEventLevel.Warning;
201  case LogLevel.None:
202  return null;
203  default:
204  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid log level {0}", logLevel));
205  }
206  }
207 
208  var logEventLevel = ConvertLogLevel(fileLoggingConfiguration.LogLevel);
209  var microsoftEventLevel = ConvertLogLevel(fileLoggingConfiguration.MicrosoftLogLevel);
210 
211  var formatter = new MessageTemplateTextFormatter("{Timestamp:o} {RequestId,13} [{Level:u3}] {SourceContext:l}: {Message} ({EventId:x8}){NewLine}{Exception}", null);
212 
213  var configuration = new LoggerConfiguration()
214  .Enrich.FromLogContext()
215  .WriteTo.Async(w => w.RollingFile(formatter, logPath, shared: true, flushToDiskInterval: TimeSpan.FromSeconds(2)));
216 
217  if (logEventLevel.HasValue)
218  configuration.MinimumLevel.Is(logEventLevel.Value);
219 
220  if (microsoftEventLevel.HasValue)
221  configuration.MinimumLevel.Override("Microsoft", microsoftEventLevel.Value);
222 
223  builder.AddSerilog(configuration.CreateLogger(), true);
224  });
225 
226  // configure bearer token validation
227  services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(jwtBearerOptions =>
228  {
229  // this line isn't actually run until the first request is made
230  // at that point tokenFactory will be populated
231  jwtBearerOptions.TokenValidationParameters = tokenFactory.ValidationParameters;
232  jwtBearerOptions.Events = new JwtBearerEvents
233  {
234  // Application is our composition root so this monstrosity of a line is okay
235  OnTokenValidated = ctx => ctx.HttpContext.RequestServices.GetRequiredService<IClaimsInjector>().InjectClaimsIntoContext(ctx, ctx.HttpContext.RequestAborted)
236  };
237  });
238 
239  // fucking prevents converting 'sub' to M$ bs
240  // can't be done in the above lambda, that's too late
241  JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
242 
243  // add mvc, configure the json serializer settings
244  services
245  .AddMvc(options =>
246  {
247  var dataAnnotationValidator = options.ModelValidatorProviders.Single(validator => validator.GetType().Name == "DataAnnotationsModelValidatorProvider");
248  options.ModelValidatorProviders.Remove(dataAnnotationValidator);
249  })
250  .SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
251  .AddJsonOptions(options =>
252  {
253  options.AllowInputFormatterExceptionMessages = true;
254  options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
255  options.SerializerSettings.CheckAdditionalContent = true;
256  options.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Error;
257  options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
258  options.SerializerSettings.Converters = new[] { new VersionConverter() };
259  });
260 
261  if (hostingEnvironment.IsDevelopment())
262  {
263  string GetDocumentationFilePath(string assemblyLocation) => ioManager.ConcatPath(ioManager.GetDirectoryName(assemblyLocation), String.Concat(ioManager.GetFileNameWithoutExtension(assemblyLocation), ".xml"));
264  var assemblyDocumentationPath = GetDocumentationFilePath(assemblyInformationProvider.Path);
265  var apiDocumentationPath = GetDocumentationFilePath(typeof(ApiHeaders).Assembly.Location);
266  services.AddSwaggerGen(genOptions => SwaggerConfiguration.Configure(genOptions, assemblyDocumentationPath, apiDocumentationPath));
267  }
268 
269  // enable browser detection
270  services.AddDetectionCore().AddBrowser();
271 
272  // CORS conditionally enabled later
273  services.AddCors();
274 
275  void AddTypedContext<TContext>() where TContext : DatabaseContext<TContext>
276  {
277  services.AddDbContext<TContext>(builder =>
278  {
279  if (hostingEnvironment.IsDevelopment())
280  builder.EnableSensitiveDataLogging();
281  });
282  services.AddScoped<IDatabaseContext>(x => x.GetRequiredService<TContext>());
283  }
284 
285  // add the correct database context type
286  var dbType = databaseConfiguration.DatabaseType;
287  switch (dbType)
288  {
289  case DatabaseType.MySql:
290  case DatabaseType.MariaDB:
291  AddTypedContext<MySqlDatabaseContext>();
292  break;
293  case DatabaseType.SqlServer:
294  AddTypedContext<SqlServerDatabaseContext>();
295  break;
296  default:
297  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid {0}: {1}!", nameof(DatabaseType), dbType));
298  }
299 
300  // configure other database services
301  services.AddSingleton<IDatabaseContextFactory, DatabaseContextFactory>();
302  services.AddSingleton<IDatabaseSeeder, DatabaseSeeder>();
303 
304  // configure security services
306  services.AddScoped<IClaimsInjector, ClaimsInjector>();
307  services.AddSingleton<IIdentityCache, IdentityCache>();
308  services.AddSingleton<ICryptographySuite, CryptographySuite>();
309  services.AddSingleton<ITokenFactory, TokenFactory>();
310  services.AddSingleton<IPasswordHasher<Models.User>, PasswordHasher<Models.User>>();
311 
312  // configure platform specific services
313  if (platformIdentifier.IsWindows)
314  {
315  if (generalConfiguration.UseBasicWatchdogOnWindows)
316  services.AddSingleton<IWatchdogFactory, WatchdogFactory>();
317  else
318  services.AddSingleton<IWatchdogFactory, WindowsWatchdogFactory>();
319 
320  services.AddSingleton<ISystemIdentityFactory, WindowsSystemIdentityFactory>();
321  services.AddSingleton<ISymlinkFactory, WindowsSymlinkFactory>();
322  services.AddSingleton<IByondInstaller, WindowsByondInstaller>();
323  services.AddSingleton<IPostWriteHandler, WindowsPostWriteHandler>();
324 
325  services.AddSingleton<WindowsNetworkPromptReaper>();
326  services.AddSingleton<INetworkPromptReaper>(x => x.GetRequiredService<WindowsNetworkPromptReaper>());
327  services.AddSingleton<IHostedService>(x => x.GetRequiredService<WindowsNetworkPromptReaper>());
328  }
329  else
330  {
331  services.AddSingleton<IWatchdogFactory, WatchdogFactory>();
332  services.AddSingleton<ISystemIdentityFactory, PosixSystemIdentityFactory>();
333  services.AddSingleton<ISymlinkFactory, PosixSymlinkFactory>();
334  services.AddSingleton<IByondInstaller, PosixByondInstaller>();
335  services.AddSingleton<IPostWriteHandler, PosixPostWriteHandler>();
336  services.AddSingleton<INetworkPromptReaper, PosixNetworkPromptReaper>();
337  }
338 
339  // configure misc services
340  services.AddSingleton<ISynchronousIOManager, SynchronousIOManager>();
341  services.AddSingleton<IGitHubClientFactory, GitHubClientFactory>();
342  services.AddSingleton<IProcessExecutor, ProcessExecutor>();
343  services.AddSingleton<IByondTopicSender>(new ByondTopicSender
344  {
345  ReceiveTimeout = generalConfiguration.ByondTopicTimeout,
346  SendTimeout = generalConfiguration.ByondTopicTimeout
347  });
348 
349  // configure component services
350  services.AddSingleton<ICredentialsProvider, CredentialsProvider>();
351  services.AddSingleton<IProviderFactory, ProviderFactory>();
352  services.AddSingleton<IChatFactory, ChatFactory>();
353  services.AddSingleton<IInstanceFactory, InstanceFactory>();
354 
355  // configure root services
356  services.AddSingleton<InstanceManager>();
357  services.AddSingleton<IInstanceManager>(x => x.GetRequiredService<InstanceManager>());
358  services.AddSingleton<IHostedService>(x => x.GetRequiredService<InstanceManager>());
359 
360  services.AddSingleton<IJobManager, JobManager>();
361  }
362 
371  public void Configure(IApplicationBuilder applicationBuilder, IServerControl serverControl, ITokenFactory tokenFactory, IOptions<ControlPanelConfiguration> controlPanelConfigurationOptions, ILogger<Application> logger)
372  {
373  if (applicationBuilder == null)
374  throw new ArgumentNullException(nameof(applicationBuilder));
375  if (serverControl == null)
376  throw new ArgumentNullException(nameof(serverControl));
377 
378  this.tokenFactory = tokenFactory ?? throw new ArgumentNullException(nameof(tokenFactory));
379 
380  var controlPanelConfiguration = controlPanelConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(controlPanelConfigurationOptions));
381 
382  if (logger == null)
383  throw new ArgumentNullException(nameof(logger));
384 
385  logger.LogInformation(VersionString);
386  logger.LogDebug("Content Root: {0}", hostingEnvironment.ContentRootPath);
387  logger.LogTrace("Web Root: {0}", hostingEnvironment.WebRootPath);
388 
389  // attempt to restart the server if the configuration changes
390  if (serverControl.WatchdogPresent)
391  ChangeToken.OnChange(configuration.GetReloadToken, () => serverControl.Restart());
392 
393  // setup the HTTP request pipeline
394  // Final point where we wrap exceptions in a 500 (ErrorMessage) response
395  applicationBuilder.UseServerErrorHandling();
396 
397  // should anything after this throw an exception, catch it and display a detailed html page
398  if (hostingEnvironment.IsDevelopment())
399  applicationBuilder.UseDeveloperExceptionPage(); // it is not worth it to limit this, you should only ever get it if you're an authorized user
400 
401  // suppress OperationCancelledExceptions, they are just aborted HTTP requests
402  applicationBuilder.UseCancelledRequestSuppression();
403 
404  if (hostingEnvironment.IsDevelopment())
405  {
406  applicationBuilder.UseSwagger();
407  applicationBuilder.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "TGS API V4"));
408  }
409 
410  // Set up CORS based on configuration if necessary
411  Action<CorsPolicyBuilder> corsBuilder = null;
412  if (controlPanelConfiguration.AllowAnyOrigin)
413  {
414  logger.LogTrace("Access-Control-Allow-Origin: *");
415  corsBuilder = builder => builder.AllowAnyOrigin();
416  }
417  else if (controlPanelConfiguration.AllowedOrigins?.Count > 0)
418  {
419  logger.LogTrace("Access-Control-Allow-Origin: ", String.Join(',', controlPanelConfiguration.AllowedOrigins));
420  corsBuilder = builder => builder.WithOrigins(controlPanelConfiguration.AllowedOrigins.ToArray());
421  }
422 
423  var originalBuilder = corsBuilder;
424  corsBuilder = builder =>
425  {
426  builder.AllowAnyHeader().AllowAnyMethod();
427  originalBuilder?.Invoke(builder);
428  };
429  applicationBuilder.UseCors(corsBuilder);
430 
431  // Do not service requests until Ready is called, this will return 503 until that point
432  applicationBuilder.UseAsyncInitialization(async cancellationToken =>
433  {
434  using (cancellationToken.Register(() => startupTcs.SetCanceled()))
435  await startupTcs.Task.ConfigureAwait(false);
436  });
437 
438  // spa loading if necessary
439  if (controlPanelConfiguration.Enable)
440  {
441  logger.LogWarning("Web control panel enabled. This is a highly WIP feature!");
442  applicationBuilder.UseStaticFiles();
443  }
444  else
445  logger.LogDebug("Web control panel disabled!");
446 
447  // authenticate JWT tokens using our security pipeline if present, returns 401 if bad
448  applicationBuilder.UseAuthentication();
449 
450  // suppress and log database exceptions
451  applicationBuilder.UseDbConflictHandling();
452 
453  // majority of handling is done in the controllers
454  applicationBuilder.UseMvc();
455 
456  // 404 anything that gets this far
457  }
458 
460  public void Ready(Exception initializationError)
461  {
462  lock (startupTcs)
463  {
464  if (startupTcs.Task.IsCompleted)
465  throw new InvalidOperationException("Ready has already been called!");
466  if (initializationError == null)
467  startupTcs.SetResult(null);
468  else
469  startupTcs.SetException(initializationError);
470  }
471  }
472  }
473 }
LogLevel MicrosoftLogLevel
The minimum Microsoft.Extensions.Logging.LogLevel to display in logs for Microsoft library sources
- -
readonly Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment
The Microsoft.AspNetCore.Hosting.IHostingEnvironment for the Application
Definition: Application.cs:67
+
readonly Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment
The Microsoft.AspNetCore.Hosting.IHostingEnvironment for the Application
Definition: Application.cs:72
+
IPostWriteHandler for POSIX systems
Handles changing file modes/permissions after writing
-
void Configure(IApplicationBuilder applicationBuilder, IServerControl serverControl, ITokenFactory tokenFactory, IOptions< ControlPanelConfiguration > controlPanelConfigurationOptions, ILogger< Application > logger)
Configure the Application
Definition: Application.cs:392
-
const string PasswordSecuritySchemeId
The OpenApiSecurityScheme name for password authentication.
+
void Configure(IApplicationBuilder applicationBuilder, IServerControl serverControl, ITokenFactory tokenFactory, IOptions< ControlPanelConfiguration > controlPanelConfigurationOptions, ILogger< Application > logger)
Configure the Application
Definition: Application.cs:371
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
+ - +
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
SetupWizardMode
Determines if the Core.ISetupWizard will run
-
Abstraction for System.Console
Definition: IConsole.cs:9
+
Abstraction for global::System.Console
Definition: IConsole.cs:9
bool WatchdogPresent
true if live updates are supported, false. ApplyUpdate(Version, Uri, IIOManager) and Restart will fai...
-
LogLevel LogLevel
The minimum Microsoft.Extensions.Logging.LogLevel to display in logs
+
For initially seeding a database
-
ITokenFactory tokenFactory
The ITokenFactory for the Application
Definition: Application.cs:77
+
ITokenFactory tokenFactory
The ITokenFactory for the Application
Definition: Application.cs:82
-
For initially seeding a database
+ + - + +
Implements various filters for Swashbuckle.
string GetDirectoryName(string path)
Gets the directory portion of a given path
-
string Path
Gets the path to the executing assembly.
+
Application(IConfiguration configuration, IAssemblyInformationProvider assemblyInformationProvider, Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment, IIOManager ioManager)
Construct an Application
Definition: Application.cs:91
ISystemIdentityFactory for windows systems. Uses long running tasks due to potential networked domain...
Contains various cryptographic functions
+ + +
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:17
+
Configuration for the automatic update system
@@ -120,65 +125,73 @@ $(function() {
For downloading and installing BYOND extractions for a given system
For accessing the disk in a synchronous manner
+
DatabaseType DatabaseType
The Configuration.DatabaseType to create
+ + - -
void Ready(Exception initializationError)
Mark the IApplication as ready to run
Definition: Application.cs:481
- + +
void Ready(Exception initializationError)
Mark the IApplication as ready to run
Definition: Application.cs:460
+ - +
IPostWriteHandler for Windows systems
+ -
readonly TaskCompletionSource< object > startupTcs
The TaskCompletionSource<TResult> used for determining when the Application is Ready(Exception)
Definition: Application.cs:72
- - - - +
readonly TaskCompletionSource< object > startupTcs
The TaskCompletionSource<TResult> used for determining when the Application is Ready(Exception)
Definition: Application.cs:77
+ + - +
static void Configure(SwaggerGenOptions swaggerGenOptions, string assemblyDocumentationPath, string apiDocumentationPath)
Configure the swagger settings.
+ +
string GetFileNameWithoutExtension(string path)
Gets the file name portion of a path with
-
void ConfigureServices(IServiceCollection services)
Configure dependency injected services
Definition: Application.cs:104
+
void ConfigureServices(IServiceCollection services)
Configure dependency injected services
Definition: Application.cs:112
+ -
TokenValidationParameters ValidationParameters
The TokenValidationParameters for the ITokenFactory
-
Configuration options for the Models.DatabaseContext<TParentContext>
+ +
Configuration options for the Database.DatabaseContext<TParentContext>
+
Manages the runtime of Jobs
Definition: IJobManager.cs:13
-
IIOManager that resolves paths to Environment.CurrentDirectory
-
For injecting System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look for
- + +
For injecting global::System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look f...
+
readonly IIOManager ioManager
The IIOManager for the Application.
Definition: Application.cs:67
DatabaseType
Type of database to user
Definition: DatabaseType.cs:6
-
Application(IConfiguration configuration, IAssemblyInformationProvider assemblyInformationProvider, Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment)
Construct an Application
Definition: Application.cs:85
- +
The command line Configuration setup wizard
Definition: ISetupWizard.cs:9
-
IOperationFilter and IDocumentFilter for the server.
+
Task< bool > CheckRunWizard(CancellationToken cancellationToken)
Run the setup wizard if necessary
Interface for using filesystems
Definition: IIOManager.cs:11
On Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort()....
-
const string TokenSecuritySchemeId
The OpenApiSecurityScheme name for token authentication.
-
For identifying the current platform
- + +
For identifying the current platform
readonly IConfiguration configuration
The IConfiguration for the Application
Definition: Application.cs:57
string ConcatPath(params string[] paths)
Combines an array of strings into a path
+ + +
Represents a service that may take an updated Host assembly and run it, stopping the current assembly...
- + - +
bool IsWindows
If the current platform is a Windows platform
+
diff --git a/_application_builder_extensions_8cs.html b/_application_builder_extensions_8cs.html index 42208a160b..3d1dd2b248 100644 --- a/_application_builder_extensions_8cs.html +++ b/_application_builder_extensions_8cs.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/ApplicationBuilderExtensions.cs File Reference +tgstation-server: src/Tgstation.Server.Host/Extensions/ApplicationBuilderExtensions.cs File Reference @@ -63,7 +63,7 @@ $(function() {
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

class  Tgstation.Server.Host.Core.ApplicationBuilderExtensions
 Extensions for IApplicationBuilder More...
class  Tgstation.Server.Host.Extensions.ApplicationBuilderExtensions
 Extensions for IApplicationBuilder More...
 
- +

@@ -91,7 +91,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
namespace  Tgstation.Server.Host.Extensions
 
diff --git a/_application_builder_extensions_8cs_source.html b/_application_builder_extensions_8cs_source.html index e8c7aa5d18..abfe97544c 100644 --- a/_application_builder_extensions_8cs_source.html +++ b/_application_builder_extensions_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/ApplicationBuilderExtensions.cs Source File +tgstation-server: src/Tgstation.Server.Host/Extensions/ApplicationBuilderExtensions.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,16 +71,16 @@ $(function() {
ApplicationBuilderExtensions.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Builder;
2 using Microsoft.AspNetCore.Http;
3 using Microsoft.AspNetCore.Mvc;
4 using Microsoft.EntityFrameworkCore;
5 using Microsoft.Extensions.DependencyInjection;
6 using Microsoft.Extensions.Logging;
7 using System;
8 using System.Globalization;
9 using System.Net;
11 
13 {
18  {
24  static ILogger GetLogger(HttpContext httpContext) => httpContext.RequestServices.GetRequiredService<ILogger<Application>>();
25 
30  public static void UseDbConflictHandling(this IApplicationBuilder applicationBuilder)
31  {
32  if (applicationBuilder == null)
33  throw new ArgumentNullException(nameof(applicationBuilder));
34  applicationBuilder.Use(async (context, next) =>
35  {
36  var logger = GetLogger(context);
37  try
38  {
39  await next().ConfigureAwait(false);
40  }
41  catch (DbUpdateException e)
42  {
43  logger.LogDebug("Database conflict: {0}", e.Message);
44  await new ConflictObjectResult(new ErrorMessage { Message = String.Format(CultureInfo.InvariantCulture, "A database conflict has occurred: {0}", (e.InnerException ?? e).Message) }).ExecuteResultAsync(new ActionContext
45  {
46  HttpContext = context
47  }).ConfigureAwait(false);
48  }
49  });
50  }
51 
56  public static void UseCancelledRequestSuppression(this IApplicationBuilder applicationBuilder)
57  {
58  if (applicationBuilder == null)
59  throw new ArgumentNullException(nameof(applicationBuilder));
60  applicationBuilder.Use(async (context, next) =>
61  {
62  var logger = GetLogger(context);
63  try
64  {
65  await next().ConfigureAwait(false);
66  }
67  catch (OperationCanceledException)
68  {
69  logger.LogDebug("Request cancelled!");
70  }
71  });
72  }
73 
78  public static void UseServerErrorHandling(this IApplicationBuilder applicationBuilder)
79  {
80  if (applicationBuilder == null)
81  throw new ArgumentNullException(nameof(applicationBuilder));
82  applicationBuilder.Use(async (context, next) =>
83  {
84  var logger = GetLogger(context);
85  try
86  {
87  await next().ConfigureAwait(false);
88  }
89  catch (Exception e)
90  {
91  logger.LogError("Failed request: {0}", e);
92  await new ObjectResult(
93  new ErrorMessage
94  {
95  Message = $"A unhandled exception has occurred: {e}"
96  })
97  {
98  StatusCode = (int)HttpStatusCode.InternalServerError
99  }
100  .ExecuteResultAsync(new ActionContext
101  {
102  HttpContext = context
103  }).ConfigureAwait(false);
104  }
105  });
106  }
107  }
108 }
static void UseServerErrorHandling(this IApplicationBuilder applicationBuilder)
Suppress all in flight exceptions with error 500.
+Go to the documentation of this file.
1 using Microsoft.AspNetCore.Builder;
2 using Microsoft.AspNetCore.Http;
3 using Microsoft.AspNetCore.Mvc;
4 using Microsoft.EntityFrameworkCore;
5 using Microsoft.Extensions.DependencyInjection;
6 using Microsoft.Extensions.Logging;
7 using System;
8 using System.Globalization;
9 using System.Net;
11 
13 {
18  {
24  static ILogger GetLogger(HttpContext httpContext) => httpContext.RequestServices.GetRequiredService<ILoggerFactory>().CreateLogger(typeof(ApplicationBuilderExtensions));
25 
30  public static void UseDbConflictHandling(this IApplicationBuilder applicationBuilder)
31  {
32  if (applicationBuilder == null)
33  throw new ArgumentNullException(nameof(applicationBuilder));
34  applicationBuilder.Use(async (context, next) =>
35  {
36  var logger = GetLogger(context);
37  try
38  {
39  await next().ConfigureAwait(false);
40  }
41  catch (DbUpdateException e)
42  {
43  logger.LogDebug("Database conflict: {0}", e.Message);
44  await new ConflictObjectResult(new ErrorMessage { Message = String.Format(CultureInfo.InvariantCulture, "A database conflict has occurred: {0}", (e.InnerException ?? e).Message) }).ExecuteResultAsync(new ActionContext
45  {
46  HttpContext = context
47  }).ConfigureAwait(false);
48  }
49  });
50  }
51 
56  public static void UseCancelledRequestSuppression(this IApplicationBuilder applicationBuilder)
57  {
58  if (applicationBuilder == null)
59  throw new ArgumentNullException(nameof(applicationBuilder));
60  applicationBuilder.Use(async (context, next) =>
61  {
62  var logger = GetLogger(context);
63  try
64  {
65  await next().ConfigureAwait(false);
66  }
67  catch (OperationCanceledException)
68  {
69  logger.LogDebug("Request cancelled!");
70  }
71  });
72  }
73 
78  public static void UseServerErrorHandling(this IApplicationBuilder applicationBuilder)
79  {
80  if (applicationBuilder == null)
81  throw new ArgumentNullException(nameof(applicationBuilder));
82  applicationBuilder.Use(async (context, next) =>
83  {
84  var logger = GetLogger(context);
85  try
86  {
87  await next().ConfigureAwait(false);
88  }
89  catch (Exception e)
90  {
91  logger.LogError("Failed request: {0}", e);
92  await new ObjectResult(
93  new ErrorMessage
94  {
95  Message = $"A unhandled exception has occurred: {e}"
96  })
97  {
98  StatusCode = (int)HttpStatusCode.InternalServerError
99  }
100  .ExecuteResultAsync(new ActionContext
101  {
102  HttpContext = context
103  }).ConfigureAwait(false);
104  }
105  });
106  }
107  }
108 }
static void UseDbConflictHandling(this IApplicationBuilder applicationBuilder)
Return a ConflictObjectResult for DbUpdateExceptions
+ - -
static ILogger GetLogger(HttpContext httpContext)
Gets a ILogger from a given httpContext
- -
static void UseDbConflictHandling(this IApplicationBuilder applicationBuilder)
Return a ConflictObjectResult for DbUpdateExceptions
+ +
static void UseServerErrorHandling(this IApplicationBuilder applicationBuilder)
Suppress all in flight exceptions with error 500.
+
static void UseCancelledRequestSuppression(this IApplicationBuilder applicationBuilder)
Suppress TaskCanceledException warnings when a user aborts a request
+
static ILogger GetLogger(HttpContext httpContext)
Gets a ILogger from a given httpContext
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
-
static void UseCancelledRequestSuppression(this IApplicationBuilder applicationBuilder)
Suppress TaskCanceledException warnings when a user aborts a request
diff --git a/_assembly_information_provider_8cs.html b/_assembly_information_provider_8cs.html index 788cd6ed60..2a97d4ab2b 100644 --- a/_assembly_information_provider_8cs.html +++ b/_assembly_information_provider_8cs.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/AssemblyInformationProvider.cs File Reference +tgstation-server: src/Tgstation.Server.Host/System/AssemblyInformationProvider.cs File Reference @@ -63,7 +63,7 @@ $(function() {
@@ -79,7 +79,7 @@ $(function() { - +

Classes

class  Tgstation.Server.Host.Core.AssemblyInformationProvider
class  Tgstation.Server.Host.System.AssemblyInformationProvider
 
- +

@@ -90,7 +90,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
namespace  Tgstation.Server.Host.System
 
diff --git a/_assembly_information_provider_8cs_source.html b/_assembly_information_provider_8cs_source.html index 1b43c8d1ef..efb34f2e70 100644 --- a/_assembly_information_provider_8cs_source.html +++ b/_assembly_information_provider_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/AssemblyInformationProvider.cs Source File +tgstation-server: src/Tgstation.Server.Host/System/AssemblyInformationProvider.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,12 +71,12 @@ $(function() {
AssemblyInformationProvider.cs
-Go to the documentation of this file.
1 using System.Reflection;
2 
4 {
7  {
9  public string Path { get; }
10 
12  public AssemblyName Name { get; }
13 
18  {
19  Assembly assembly = Assembly.GetExecutingAssembly();
20  Path = assembly.Location;
21  Name = assembly.GetName();
22  }
23  }
24 }
- - - -
AssemblyInformationProvider()
Initializes a new instance of the AssemblyInformationProvider class.
- +Go to the documentation of this file.
1 using System.Reflection;
2 
4 {
7  {
9  public string Path { get; }
10 
12  public AssemblyName Name { get; }
13 
18  {
19  Assembly assembly = Assembly.GetExecutingAssembly();
20  Path = assembly.Location;
21  Name = assembly.GetName();
22  }
23  }
24 }
+ + + +
AssemblyInformationProvider()
Initializes a new instance of the AssemblyInformationProvider class.
+
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using System;
3 using System.Linq;
4 using System.Threading;
5 using System.Threading.Tasks;
7 
9 {
12  {
15 
20 
25 
30 
38  {
39  this.systemIdentityFactory = systemIdentityFactory ?? throw new ArgumentNullException(nameof(systemIdentityFactory));
40  this.databaseContext = databaseContext ?? throw new ArgumentNullException(nameof(databaseContext));
41  this.identityCache = identityCache ?? throw new ArgumentNullException(nameof(identityCache));
42  }
43 
45  public void Dispose() => CurrentAuthenticationContext?.Dispose();
46 
48  public async Task CreateAuthenticationContext(long userId, long? instanceId, DateTimeOffset validAfter, CancellationToken cancellationToken)
49  {
50  if (CurrentAuthenticationContext != null)
51  throw new InvalidOperationException("Authentication context has already been loaded");
52 
53  var userQuery = databaseContext.Users.Where(x => x.Id == userId)
54  .Include(x => x.CreatedBy)
55  .FirstOrDefaultAsync(cancellationToken);
56 
57  var instanceUserQuery = instanceId.HasValue ? databaseContext.InstanceUsers
58  .Where(x => x.UserId == userId && x.InstanceId == instanceId && x.Instance.Online.Value)
59  .Include(x => x.Instance)
60  .FirstOrDefaultAsync(cancellationToken) : Task.FromResult<InstanceUser>(null);
61 
62  var user = await userQuery.ConfigureAwait(false);
63  if (user == default)
64  {
66  return;
67  }
68 
69  ISystemIdentity systemIdentity;
70  if (user.SystemIdentifier != null)
71  systemIdentity = identityCache.LoadCachedIdentity(user);
72  else
73  {
74  if (user.LastPasswordUpdate.HasValue && user.LastPasswordUpdate > validAfter)
75  {
77  return;
78  }
79 
80  systemIdentity = null;
81  }
82 
83  try
84  {
85  var instanceUser = await instanceUserQuery.ConfigureAwait(false);
86 
87  CurrentAuthenticationContext = new AuthenticationContext(systemIdentity, user, instanceUser);
88  }
89  catch
90  {
91  systemIdentity?.Dispose();
92  throw;
93  }
94  }
95  }
96 }
- +Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using System;
3 using System.Linq;
4 using System.Threading;
5 using System.Threading.Tasks;
8 
10 {
13  {
16 
21 
26 
31 
39  {
40  this.systemIdentityFactory = systemIdentityFactory ?? throw new ArgumentNullException(nameof(systemIdentityFactory));
41  this.databaseContext = databaseContext ?? throw new ArgumentNullException(nameof(databaseContext));
42  this.identityCache = identityCache ?? throw new ArgumentNullException(nameof(identityCache));
43  }
44 
46  public void Dispose() => CurrentAuthenticationContext?.Dispose();
47 
49  public async Task CreateAuthenticationContext(long userId, long? instanceId, DateTimeOffset validAfter, CancellationToken cancellationToken)
50  {
51  if (CurrentAuthenticationContext != null)
52  throw new InvalidOperationException("Authentication context has already been loaded");
53 
54  var userQuery = databaseContext.Users.Where(x => x.Id == userId)
55  .Include(x => x.CreatedBy)
56  .FirstOrDefaultAsync(cancellationToken);
57 
58  var instanceUserQuery = instanceId.HasValue ? databaseContext.InstanceUsers
59  .Where(x => x.UserId == userId && x.InstanceId == instanceId && x.Instance.Online.Value)
60  .Include(x => x.Instance)
61  .FirstOrDefaultAsync(cancellationToken) : Task.FromResult<InstanceUser>(null);
62 
63  var user = await userQuery.ConfigureAwait(false);
64  if (user == default)
65  {
67  return;
68  }
69 
70  ISystemIdentity systemIdentity;
71  if (user.SystemIdentifier != null)
72  systemIdentity = identityCache.LoadCachedIdentity(user);
73  else
74  {
75  if (user.LastPasswordUpdate.HasValue && user.LastPasswordUpdate > validAfter)
76  {
78  return;
79  }
80 
81  systemIdentity = null;
82  }
83 
84  try
85  {
86  var instanceUser = await instanceUserQuery.ConfigureAwait(false);
87 
88  CurrentAuthenticationContext = new AuthenticationContext(systemIdentity, user, instanceUser);
89  }
90  catch
91  {
92  systemIdentity?.Dispose();
93  throw;
94  }
95  }
96  }
97 }
-
AuthenticationContextFactory(ISystemIdentityFactory systemIdentityFactory, IDatabaseContext databaseContext, IIdentityCache identityCache)
Construct an AuthenticationContextFactory
-
Represents a user on the current System.Runtime.InteropServices.OSPlatform
+
AuthenticationContextFactory(ISystemIdentityFactory systemIdentityFactory, IDatabaseContext databaseContext, IIdentityCache identityCache)
Construct an AuthenticationContextFactory
+
Represents a user on the current global::System.Runtime.InteropServices.OSPlatform
ISystemIdentity LoadCachedIdentity(User user)
Attempt to load a cached ISystemIdentity
-
DbSet< User > Users
The Users in the IDatabaseContext
Represents the currently authenticated Api.Models.User
+ -
readonly IIdentityCache identityCache
The IIdentityCache for the AuthenticationContextFactory
- +
readonly IIdentityCache identityCache
The IIdentityCache for the AuthenticationContextFactory
+ -
readonly ISystemIdentityFactory systemIdentityFactory
The ISystemIdentityFactory for the AuthenticationContextFactory
-
readonly IDatabaseContext databaseContext
The IDatabaseContext for the AuthenticationContextFactory
+
readonly ISystemIdentityFactory systemIdentityFactory
The ISystemIdentityFactory for the AuthenticationContextFactory
+
readonly IDatabaseContext databaseContext
The IDatabaseContext for the AuthenticationContextFactory
+
DbSet< User > Users
The Users in the IDatabaseContext
+
DbSet< InstanceUser > InstanceUsers
The InstanceUsers in the IDatabaseContext
- + + -
DbSet< InstanceUser > InstanceUsers
The InstanceUsers in the IDatabaseContext
-
async Task CreateAuthenticationContext(long userId, long? instanceId, DateTimeOffset validAfter, CancellationToken cancellationToken)
Create an IAuthenticationContext to populate CurrentAuthenticationContext
+
async Task CreateAuthenticationContext(long userId, long? instanceId, DateTimeOffset validAfter, CancellationToken cancellationToken)
Create an IAuthenticationContext to populate CurrentAuthenticationContext
diff --git a/_basic_watchdog_8cs_source.html b/_basic_watchdog_8cs_source.html index 5e38722d4a..5ade9309bb 100644 --- a/_basic_watchdog_8cs_source.html +++ b/_basic_watchdog_8cs_source.html @@ -71,86 +71,81 @@ $(function() {
BasicWatchdog.cs
-Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Globalization;
5 using System.Threading;
6 using System.Threading.Tasks;
11 
13 {
17  sealed class BasicWatchdog : WatchdogBase
18  {
20  public override bool AlphaIsActive => true;
21 
23  public override Models.CompileJob ActiveCompileJob => server?.Dmb.CompileJob;
24 
26  public override RebootState? RebootState => server?.RebootState;
27 
32 
50  public BasicWatchdog(
51  IChat chat,
52  ISessionControllerFactory sessionControllerFactory,
53  IDmbFactory dmbFactory,
56  IByondTopicSender byondTopicSender,
59  IServerControl serverControl,
60  IAsyncDelayer asyncDelayer,
61  ILogger<BasicWatchdog> logger,
62  DreamDaemonLaunchParameters initialLaunchParameters,
63  Api.Models.Instance instance,
64  bool autoStart)
65  : base(
66  chat,
67  sessionControllerFactory,
68  dmbFactory,
73  jobManager,
74  serverControl,
75  asyncDelayer,
76  logger,
77  initialLaunchParameters,
78  instance,
79  autoStart)
80  { }
81 
82  async Task<MonitorAction> HandleMonitorWakeup(MonitorActivationReason reason, CancellationToken cancellationToken)
83  {
84  switch (reason)
85  {
86  case MonitorActivationReason.ActiveServerCrashed:
87  string exitWord = server.TerminationWasRequested ? "exited" : "crashed";
88  if (server.RebootState == Watchdog.RebootState.Shutdown)
89  {
90  // the time for graceful shutdown is now
91  await Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Server {0}! Exiting due to graceful termination request...", exitWord), cancellationToken).ConfigureAwait(false);
93  return MonitorAction.Exit;
94  }
95 
96  await Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Server {0}! Rebooting...", exitWord), cancellationToken).ConfigureAwait(false);
97  return MonitorAction.Restart;
98  case MonitorActivationReason.ActiveServerRebooted:
99  var rebootState = server.RebootState;
101 
102  switch (rebootState)
103  {
104  case Watchdog.RebootState.Normal:
105  bool dmbUpdatePending = ActiveLaunchParameters != LastLaunchParameters;
106  return dmbUpdatePending ? MonitorAction.Restart : MonitorAction.Continue;
107  case Watchdog.RebootState.Restart:
108  return MonitorAction.Restart;
109  case Watchdog.RebootState.Shutdown:
110  // graceful shutdown time
111  await Chat.SendWatchdogMessage("Active server rebooted! Exiting due to graceful termination request...", cancellationToken).ConfigureAwait(false);
113  return MonitorAction.Exit;
114  default:
115  throw new InvalidOperationException($"Invalid reboot state: {rebootState}");
116  }
117 
118  case MonitorActivationReason.ActiveLaunchParametersUpdated:
119  case MonitorActivationReason.NewDmbAvailable:
120  await server.SetRebootState(Watchdog.RebootState.Restart, cancellationToken).ConfigureAwait(false);
121  return MonitorAction.Continue;
122  case MonitorActivationReason.InactiveServerCrashed:
123  case MonitorActivationReason.InactiveServerRebooted:
124  case MonitorActivationReason.InactiveServerStartupComplete:
125  throw new NotSupportedException($"Unsupported activation reason: {reason}");
126  default:
127  throw new InvalidOperationException($"Invalid activation reason: {reason}");
128  }
129  }
130 
134  {
135  AlphaIsActive = true,
136  Alpha = server?.Release()
137  };
138 
140  protected override void DisposeAndNullControllers()
141  {
142  server?.Dispose();
143  server = null;
144  Running = false;
145  }
146 
148  protected override ISessionController GetActiveController() => server;
149 
151  protected override async Task InitControllers(Action callBeforeRecurse, Task chatTask, WatchdogReattachInformation reattachInfo, CancellationToken cancellationToken)
152  {
153  // good ole sanity, should never fucking trigger but i don't trust myself even though I should
154  // TODO: Unit test this instead?
155  if (server != null)
156  throw new InvalidOperationException("Entered LaunchNoLock with server not being null!");
157 
158  // don't need a new dmb if reattaching
159  var doesntNeedNewDmb = reattachInfo?.Alpha != null && reattachInfo?.Bravo != null;
160  var dmbToUse = doesntNeedNewDmb ? null : DmbFactory.LockNextDmb(1);
161 
162  var serverToReattach = reattachInfo?.Alpha ?? reattachInfo?.Bravo;
163  var serverToKill = reattachInfo?.Bravo ?? reattachInfo?.Alpha;
164 
165  // vice versa
166  if (reattachInfo?.AlphaIsActive == false)
167  {
168  var temp = serverToReattach;
169  serverToReattach = serverToKill;
170  serverToKill = temp;
171  }
172 
173  // if this try catches something, both servers are killed
174  bool inactiveServerWasKilled = false;
175  try
176  {
177  // start the alpha server task, either by launch a new process or attaching to an existing one
178  // The tasks returned are mainly for writing interop files to the directories among other things and should generally never fail
179  // The tasks pertaining to server startup times are in the ISessionControllers
180  Task<ISessionController> serverLaunchTask, inactiveReattachTask;
181  if (!doesntNeedNewDmb)
182  serverLaunchTask = SessionControllerFactory.LaunchNew(ActiveLaunchParameters, dmbToUse, null, true, true, false, cancellationToken);
183  else
184  serverLaunchTask = SessionControllerFactory.Reattach(serverToReattach, cancellationToken);
185 
186  bool thereIsAnInactiveServerToKill = serverToKill != null;
187  if (thereIsAnInactiveServerToKill)
188  inactiveReattachTask = SessionControllerFactory.Reattach(serverToKill, cancellationToken);
189  else
190  inactiveReattachTask = Task.FromResult<ISessionController>(null);
191 
192  // retrieve the session controller
193  server = await serverLaunchTask.ConfigureAwait(false);
194 
195  // failed reattaches will return null
197 
198  var inactiveServerController = await inactiveReattachTask.ConfigureAwait(false);
199  inactiveServerController?.Dispose();
200  inactiveServerWasKilled = inactiveServerController != null;
201 
202  // possiblity of null servers due to failed reattaches
203  if (server == null)
204  {
205  callBeforeRecurse();
206  await NotifyOfFailedReattach(thereIsAnInactiveServerToKill && !inactiveServerWasKilled, cancellationToken).ConfigureAwait(false);
207  return;
208  }
209 
210  await CheckLaunchResult(server, "Server", cancellationToken).ConfigureAwait(false);
211 
213  }
214  catch
215  {
216  // kill the controllers
217  bool serverWasActive = server != null;
219 
220  // server didn't get control of this dmb
221  if (dmbToUse != null && !serverWasActive)
222  dmbToUse.Dispose();
223 
224  if (serverToKill != null && !inactiveServerWasKilled)
225  serverToKill.Dmb.Dispose();
226  throw;
227  }
228  }
229 
231  protected override async Task MonitorLifetimes(CancellationToken cancellationToken)
232  {
233  Logger.LogTrace("Entered MonitorLifetimes");
234 
235  // this function is responsible for calling HandlerMonitorWakeup when necessary and manitaining the MonitorState
236  var iteration = 1;
237  for (MonitorAction nextAction = MonitorAction.Continue; nextAction != MonitorAction.Exit; ++iteration)
238  {
239  // always start out with continue
240  nextAction = MonitorAction.Continue;
241 
242  // dump some info to the logs
243  Logger.LogDebug("Iteration {0} of monitor loop", iteration);
244  try
245  {
246  Logger.LogDebug("Server Compile Job ID: {0}", server.Dmb.CompileJob.Id);
247 
248  // load the activation tasks into local variables
249  Task activeServerLifetime = server.Lifetime;
250  var activeServerReboot = server.OnReboot;
251  Task activeLaunchParametersChanged = ActiveParametersUpdated.Task;
252  var newDmbAvailable = DmbFactory.OnNewerDmb;
253 
254  // cancel waiting if requested
255  var cancelTcs = new TaskCompletionSource<object>();
256  using (cancellationToken.Register(() => cancelTcs.SetCanceled()))
257  {
258  var toWaitOn = Task.WhenAny(activeServerLifetime, activeServerReboot, newDmbAvailable, cancelTcs.Task, activeLaunchParametersChanged);
259 
260  // wait for something to happen
261  await toWaitOn.ConfigureAwait(false);
262  cancellationToken.ThrowIfCancellationRequested();
263  }
264 
265  var chatTask = Task.CompletedTask;
266  using (await SemaphoreSlimContext.Lock(Semaphore, cancellationToken).ConfigureAwait(false))
267  {
268  // always run HandleMonitorWakeup from the context of the semaphore lock
269  // multiple things may have happened, handle them one at a time
270  for (var moreActivationsToProcess = true; moreActivationsToProcess && (nextAction == MonitorAction.Continue || nextAction == MonitorAction.Skip);)
271  {
272  MonitorActivationReason activationReason = default; // this will always be assigned before being used
273 
274  // process the tasks in this order and call HandlerMonitorWakup for each
275  bool CheckActivationReason(ref Task task, MonitorActivationReason testActivationReason)
276  {
277  var taskCompleted = task?.IsCompleted == true;
278  task = null;
279  if (nextAction == MonitorAction.Skip)
280  nextAction = MonitorAction.Continue;
281  else if (taskCompleted)
282  {
283  activationReason = testActivationReason;
284  return true;
285  }
286 
287  return false;
288  }
289 
290  if (CheckActivationReason(ref activeServerLifetime, MonitorActivationReason.ActiveServerCrashed)
291  || CheckActivationReason(ref activeServerReboot, MonitorActivationReason.ActiveServerRebooted)
292  || CheckActivationReason(ref newDmbAvailable, MonitorActivationReason.NewDmbAvailable)
293  || CheckActivationReason(ref activeLaunchParametersChanged, MonitorActivationReason.ActiveLaunchParametersUpdated))
294  nextAction = await HandleMonitorWakeup(activationReason, cancellationToken).ConfigureAwait(false);
295  else
296  moreActivationsToProcess = false;
297  }
298  }
299 
300  // full reboot required
301  if (nextAction == MonitorAction.Restart)
302  {
303  Logger.LogDebug("Next state action is to restart");
305 
306  for (var retryAttempts = 1; nextAction == MonitorAction.Restart; ++retryAttempts)
307  {
308  Exception launchException = null;
309  using (await SemaphoreSlimContext.Lock(Semaphore, cancellationToken).ConfigureAwait(false))
310  try
311  {
312  // use LaunchImplNoLock without announcements or restarting the monitor
313  await LaunchImplNoLock(false, false, null, cancellationToken).ConfigureAwait(false);
314  if (Running)
315  {
316  Logger.LogDebug("Relaunch successful, resetting monitor state...");
317  break; // continue on main loop
318  }
319  }
320  catch (OperationCanceledException)
321  {
322  throw;
323  }
324  catch (Exception e)
325  {
326  launchException = e;
327  }
328 
329  await chatTask.ConfigureAwait(false);
330  if (!Running)
331  {
332  if (launchException == null)
333  Logger.LogWarning("Failed to automatically restart the watchdog! Attempt: {0}", retryAttempts);
334  else
335  Logger.LogWarning("Failed to automatically restart the watchdog! Attempt: {0}, Exception: {1}", retryAttempts, launchException);
336  var retryDelay = Math.Min(Math.Pow(2, retryAttempts), 3600); // max of one hour, increasing by a power of 2 each time
337  chatTask = Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Failed to restart watchdog (Attempt: {0}), retrying in {1} seconds...", retryAttempts, retryDelay), cancellationToken);
338  await Task.WhenAll(AsyncDelayer.Delay(TimeSpan.FromSeconds(retryDelay), cancellationToken), chatTask).ConfigureAwait(false);
339  }
340  }
341  }
342  }
343  catch (OperationCanceledException)
344  {
345  Logger.LogDebug("Monitor cancelled");
346  break;
347  }
348  catch (Exception e)
349  {
350  // really, this should NEVER happen
351  Logger.LogError("Monitor crashed! Iteration: {0}, NextAction: {1}, Exception: {2}", iteration, nextAction, e);
352  await Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Monitor crashed, this should NEVER happen! Please report this, full details in logs! Restarting monitor... Error: {0}", e.Message), cancellationToken).ConfigureAwait(false);
353  }
354  }
355 
356  Logger.LogTrace("Monitor exiting...");
357  }
358  }
359 }
-
Manages the runtime of Jobs
Definition: IJobManager.cs:12
-
readonly bool autoStart
If the WatchdogBase should LaunchImplNoLock(bool, bool, WatchdogReattachInformation,...
+Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Diagnostics;
5 using System.Globalization;
6 using System.Threading;
7 using System.Threading.Tasks;
14 
16 {
21  {
23  public sealed override bool AlphaIsActive => true;
24 
26  public sealed override Models.CompileJob ActiveCompileJob => Server?.Dmb.CompileJob;
27 
29  public sealed override RebootState? RebootState => Server?.RebootState;
30 
34  protected ISessionController Server { get; private set; }
35 
53  public BasicWatchdog(
54  IChat chat,
55  ISessionControllerFactory sessionControllerFactory,
56  IDmbFactory dmbFactory,
59  IByondTopicSender byondTopicSender,
62  IServerControl serverControl,
63  IAsyncDelayer asyncDelayer,
64  ILogger<BasicWatchdog> logger,
65  DreamDaemonLaunchParameters initialLaunchParameters,
66  Api.Models.Instance instance,
67  bool autoStart)
68  : base(
69  chat,
70  sessionControllerFactory,
71  dmbFactory,
76  jobManager,
77  serverControl,
78  asyncDelayer,
79  logger,
80  initialLaunchParameters,
81  instance,
82  autoStart)
83  { }
84 
85  async Task<MonitorAction> HandleMonitorWakeup(MonitorActivationReason reason, CancellationToken cancellationToken)
86  {
87  switch (reason)
88  {
89  case MonitorActivationReason.ActiveServerCrashed:
90  string exitWord = Server.TerminationWasRequested ? "exited" : "crashed";
91  if (Server.RebootState == Watchdog.RebootState.Shutdown)
92  {
93  // the time for graceful shutdown is now
94  await Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Server {0}! Exiting due to graceful termination request...", exitWord), cancellationToken).ConfigureAwait(false);
96  return MonitorAction.Exit;
97  }
98 
99  await Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Server {0}! Rebooting...", exitWord), cancellationToken).ConfigureAwait(false);
100  return MonitorAction.Restart;
101  case MonitorActivationReason.ActiveServerRebooted:
102  var rebootState = Server.RebootState;
103  Server.ResetRebootState();
104 
105  switch (rebootState)
106  {
107  case Watchdog.RebootState.Normal:
108  return HandleNormalReboot();
109  case Watchdog.RebootState.Restart:
110  return MonitorAction.Restart;
111  case Watchdog.RebootState.Shutdown:
112  // graceful shutdown time
113  await Chat.SendWatchdogMessage("Active server rebooted! Exiting due to graceful termination request...", cancellationToken).ConfigureAwait(false);
115  return MonitorAction.Exit;
116  default:
117  throw new InvalidOperationException($"Invalid reboot state: {rebootState}");
118  }
119 
120  case MonitorActivationReason.ActiveLaunchParametersUpdated:
121  await Server.SetRebootState(Watchdog.RebootState.Restart, cancellationToken).ConfigureAwait(false);
122  return MonitorAction.Continue;
123  case MonitorActivationReason.NewDmbAvailable:
124  await HandleNewDmbAvailable(cancellationToken).ConfigureAwait(false);
125  return MonitorAction.Continue;
126  case MonitorActivationReason.InactiveServerCrashed:
127  case MonitorActivationReason.InactiveServerRebooted:
128  case MonitorActivationReason.InactiveServerStartupComplete:
129  throw new NotSupportedException($"Unsupported activation reason: {reason}");
130  default:
131  throw new InvalidOperationException($"Invalid activation reason: {reason}");
132  }
133  }
134 
136  protected sealed override WatchdogReattachInformation CreateReattachInformation()
138  {
139  AlphaIsActive = true,
140  Alpha = Server?.Release()
141  };
142 
144  protected override void DisposeAndNullControllers()
145  {
146  Server?.Dispose();
147  Server = null;
148  Running = false;
149  }
150 
152  protected sealed override ISessionController GetActiveController() => Server;
153 
155  protected sealed override async Task InitControllers(Action callBeforeRecurse, Task chatTask, WatchdogReattachInformation reattachInfo, CancellationToken cancellationToken)
156  {
157  Debug.Assert(Server == null, "Entered LaunchNoLock with server not being null!");
158 
159  // don't need a new dmb if reattaching
160  var doesntNeedNewDmb = reattachInfo?.Alpha != null && reattachInfo?.Bravo != null;
161  var dmbToUse = doesntNeedNewDmb ? null : DmbFactory.LockNextDmb(1);
162 
163  var serverToReattach = reattachInfo?.Alpha ?? reattachInfo?.Bravo;
164  var serverToKill = reattachInfo?.Bravo ?? reattachInfo?.Alpha;
165 
166  // vice versa
167  if (reattachInfo?.AlphaIsActive == false)
168  {
169  var temp = serverToReattach;
170  serverToReattach = serverToKill;
171  serverToKill = temp;
172  }
173 
174  // if this try catches something, both servers are killed
175  bool inactiveServerWasKilled = false;
176  try
177  {
178  // start the alpha server task, either by launch a new process or attaching to an existing one
179  // The tasks returned are mainly for writing interop files to the directories among other things and should generally never fail
180  // The tasks pertaining to server startup times are in the ISessionControllers
181  Task<ISessionController> serverLaunchTask, inactiveReattachTask;
182  if (!doesntNeedNewDmb)
183  {
184  dmbToUse = await PrepServerForLaunch(dmbToUse, cancellationToken).ConfigureAwait(false);
185  serverLaunchTask = SessionControllerFactory.LaunchNew(ActiveLaunchParameters, dmbToUse, null, true, true, false, cancellationToken);
186  }
187  else
188  serverLaunchTask = SessionControllerFactory.Reattach(serverToReattach, cancellationToken);
189 
190  bool thereIsAnInactiveServerToKill = serverToKill != null;
191  if (thereIsAnInactiveServerToKill)
192  inactiveReattachTask = SessionControllerFactory.Reattach(serverToKill, cancellationToken);
193  else
194  inactiveReattachTask = Task.FromResult<ISessionController>(null);
195 
196  // retrieve the session controller
197  Server = await serverLaunchTask.ConfigureAwait(false);
198 
199  // failed reattaches will return null
200  Server?.SetHighPriority();
201 
202  var inactiveServerController = await inactiveReattachTask.ConfigureAwait(false);
203  inactiveServerController?.Dispose();
204  inactiveServerWasKilled = inactiveServerController != null;
205 
206  // possiblity of null servers due to failed reattaches
207  if (Server == null)
208  {
209  callBeforeRecurse();
210  await NotifyOfFailedReattach(thereIsAnInactiveServerToKill && !inactiveServerWasKilled, cancellationToken).ConfigureAwait(false);
211  return;
212  }
213 
214  await CheckLaunchResult(Server, "Server", cancellationToken).ConfigureAwait(false);
215 
216  Server.EnableCustomChatCommands();
217  }
218  catch
219  {
220  // kill the controllers
221  bool serverWasActive = Server != null;
223 
224  // server didn't get control of this dmb
225  if (dmbToUse != null && !serverWasActive)
226  dmbToUse.Dispose();
227 
228  if (serverToKill != null && !inactiveServerWasKilled)
229  serverToKill.Dmb.Dispose();
230  throw;
231  }
232  }
233 
235  protected sealed override async Task MonitorLifetimes(CancellationToken cancellationToken)
236  {
237  Logger.LogTrace("Entered MonitorLifetimes");
238 
239  // this function is responsible for calling HandlerMonitorWakeup when necessary and manitaining the MonitorState
240  var iteration = 1;
241  for (MonitorAction nextAction = MonitorAction.Continue; nextAction != MonitorAction.Exit; ++iteration)
242  {
243  // always start out with continue
244  nextAction = MonitorAction.Continue;
245 
246  // dump some info to the logs
247  Logger.LogDebug("Iteration {0} of monitor loop", iteration);
248  try
249  {
250  Logger.LogDebug("Server Compile Job ID: {0}", Server.Dmb.CompileJob.Id);
251 
252  // load the activation tasks into local variables
253  Task activeServerLifetime = Server.Lifetime;
254  var activeServerReboot = Server.OnReboot;
255  Task activeLaunchParametersChanged = ActiveParametersUpdated.Task;
256  var newDmbAvailable = DmbFactory.OnNewerDmb;
257 
258  // cancel waiting if requested
259  var cancelTcs = new TaskCompletionSource<object>();
260  using (cancellationToken.Register(() => cancelTcs.SetCanceled()))
261  {
262  var toWaitOn = Task.WhenAny(activeServerLifetime, activeServerReboot, newDmbAvailable, cancelTcs.Task, activeLaunchParametersChanged);
263 
264  // wait for something to happen
265  await toWaitOn.ConfigureAwait(false);
266  cancellationToken.ThrowIfCancellationRequested();
267  }
268 
269  var chatTask = Task.CompletedTask;
270  using (await SemaphoreSlimContext.Lock(Semaphore, cancellationToken).ConfigureAwait(false))
271  {
272  // always run HandleMonitorWakeup from the context of the semaphore lock
273  // multiple things may have happened, handle them one at a time
274  for (var moreActivationsToProcess = true; moreActivationsToProcess && (nextAction == MonitorAction.Continue || nextAction == MonitorAction.Skip);)
275  {
276  MonitorActivationReason activationReason = default; // this will always be assigned before being used
277 
278  // process the tasks in this order and call HandlerMonitorWakup for each
279  bool CheckActivationReason(ref Task task, MonitorActivationReason testActivationReason)
280  {
281  var taskCompleted = task?.IsCompleted == true;
282  task = null;
283  if (nextAction == MonitorAction.Skip)
284  nextAction = MonitorAction.Continue;
285  else if (taskCompleted)
286  {
287  activationReason = testActivationReason;
288  return true;
289  }
290 
291  return false;
292  }
293 
294  if (CheckActivationReason(ref activeServerLifetime, MonitorActivationReason.ActiveServerCrashed)
295  || CheckActivationReason(ref activeServerReboot, MonitorActivationReason.ActiveServerRebooted)
296  || CheckActivationReason(ref newDmbAvailable, MonitorActivationReason.NewDmbAvailable)
297  || CheckActivationReason(ref activeLaunchParametersChanged, MonitorActivationReason.ActiveLaunchParametersUpdated))
298  {
299  Logger.LogTrace("Monitor activation: {0}", activationReason);
300  nextAction = await HandleMonitorWakeup(activationReason, cancellationToken).ConfigureAwait(false);
301  }
302  else
303  moreActivationsToProcess = false;
304  }
305  }
306 
307  // full reboot required
308  if (nextAction == MonitorAction.Restart)
309  {
310  Logger.LogDebug("Next state action is to restart");
312 
313  for (var retryAttempts = 1; nextAction == MonitorAction.Restart; ++retryAttempts)
314  {
315  Exception launchException = null;
316  using (await SemaphoreSlimContext.Lock(Semaphore, cancellationToken).ConfigureAwait(false))
317  try
318  {
319  // use LaunchImplNoLock without announcements or restarting the monitor
320  await LaunchImplNoLock(false, false, null, cancellationToken).ConfigureAwait(false);
321  if (Running)
322  {
323  Logger.LogDebug("Relaunch successful, resetting monitor state...");
324  break; // continue on main loop
325  }
326  }
327  catch (OperationCanceledException)
328  {
329  throw;
330  }
331  catch (Exception e)
332  {
333  launchException = e;
334  }
335 
336  await chatTask.ConfigureAwait(false);
337  if (!Running)
338  {
339  if (launchException == null)
340  Logger.LogWarning("Failed to automatically restart the watchdog! Attempt: {0}", retryAttempts);
341  else
342  Logger.LogWarning("Failed to automatically restart the watchdog! Attempt: {0}, Exception: {1}", retryAttempts, launchException);
343  var retryDelay = Math.Min(Math.Pow(2, retryAttempts), 3600); // max of one hour, increasing by a power of 2 each time
344  chatTask = Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Failed to restart watchdog (Attempt: {0}), retrying in {1} seconds...", retryAttempts, retryDelay), cancellationToken);
345  await Task.WhenAll(AsyncDelayer.Delay(TimeSpan.FromSeconds(retryDelay), cancellationToken), chatTask).ConfigureAwait(false);
346  }
347  }
348  }
349  }
350  catch (OperationCanceledException)
351  {
352  Logger.LogDebug("Monitor cancelled");
353  break;
354  }
355  catch (Exception e)
356  {
357  // really, this should NEVER happen
358  Logger.LogError("Monitor crashed! Iteration: {0}, NextAction: {1}, Exception: {2}", iteration, nextAction, e);
359  await Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Monitor crashed, this should NEVER happen! Please report this, full details in logs! Restarting monitor... Error: {0}", e.Message), cancellationToken).ConfigureAwait(false);
360  }
361  }
362 
363  Logger.LogTrace("Monitor exiting...");
364  }
365 
370  protected virtual MonitorAction HandleNormalReboot()
371  {
372  bool dmbUpdatePending = ActiveLaunchParameters != LastLaunchParameters;
373  return dmbUpdatePending ? MonitorAction.Restart : MonitorAction.Continue;
374  }
375 
381  protected virtual Task HandleNewDmbAvailable(CancellationToken cancellationToken) => Server.SetRebootState(Watchdog.RebootState.Restart, cancellationToken);
382 
389  protected virtual Task<IDmbProvider> PrepServerForLaunch(IDmbProvider dmbToUse, CancellationToken cancellationToken) => Task.FromResult(dmbToUse);
390  }
391 }
readonly bool autoStart
If the WatchdogBase should LaunchImplNoLock(bool, bool, WatchdogReattachInformation,...
- -
override ISessionController GetActiveController()
Get the active ISessionController.
-
CompileJob CompileJob
The CompileJob of the .dmb
Definition: IDmbProvider.cs:29
-
Task< int > Lifetime
The Task<TResult> resulting in the exit code of the process
Definition: IProcessBase.cs:14
-
long Id
The ID of the entity.
Definition: EntityId.cs:11
- - - -
async Task LaunchImplNoLock(bool startMonitor, bool announce, WatchdogReattachInformation reattachInfo, CancellationToken cancellationToken)
Launches the watchdog.
+ + +
async Task LaunchImplNoLock(bool startMonitor, bool announce, WatchdogReattachInformation reattachInfo, CancellationToken cancellationToken)
Launches the watchdog.
- + +
Consumes EventTypes and takes the appropriate actions
- -
SemaphoreSlim Semaphore
The SemaphoreSlim for the WatchdogBase.
Definition: WatchdogBase.cs:55
+ +
SemaphoreSlim Semaphore
The SemaphoreSlim for the WatchdogBase.
Definition: WatchdogBase.cs:58
+
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
-
void EnableCustomChatCommands()
Enables the reading of custom chat commands from the ISessionController
-
Task< bool > SetRebootState(RebootState newRebootState, CancellationToken cancellationToken)
Attempts to change the current RebootState to newRebootState
-
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
-
override async Task InitControllers(Action callBeforeRecurse, Task chatTask, WatchdogReattachInformation reattachInfo, CancellationToken cancellationToken)
Starts all ISessionControllers.
-
async Task< MonitorAction > HandleMonitorWakeup(MonitorActivationReason reason, CancellationToken cancellationToken)
+
virtual Task HandleNewDmbAvailable(CancellationToken cancellationToken)
Handler for MonitorActivationReason.NewDmbAvailable.
+
async Task< MonitorAction > HandleMonitorWakeup(MonitorActivationReason reason, CancellationToken cancellationToken)
-
BasicWatchdog(IChat chat, ISessionControllerFactory sessionControllerFactory, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IDatabaseContextFactory databaseContextFactory, IByondTopicSender byondTopicSender, IEventConsumer eventConsumer, IJobManager jobManager, IServerControl serverControl, IAsyncDelayer asyncDelayer, ILogger< BasicWatchdog > logger, DreamDaemonLaunchParameters initialLaunchParameters, Api.Models.Instance instance, bool autoStart)
Initializes a new instance of the ExperimentalWatchdog class.
+
BasicWatchdog(IChat chat, ISessionControllerFactory sessionControllerFactory, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IDatabaseContextFactory databaseContextFactory, IByondTopicSender byondTopicSender, IEventConsumer eventConsumer, IJobManager jobManager, IServerControl serverControl, IAsyncDelayer asyncDelayer, ILogger< BasicWatchdog > logger, DreamDaemonLaunchParameters initialLaunchParameters, Api.Models.Instance instance, bool autoStart)
Initializes a new instance of the BasicWatchdog class.
Task SendWatchdogMessage(string message, CancellationToken cancellationToken)
Send a chat message to configured watchdog channels
Definition: Chat.cs:514
-
readonly IByondTopicSender byondTopicSender
The IByondTopicSender for the ExperimentalWatchdog
+
sealed override Models.CompileJob ActiveCompileJob
+
virtual MonitorAction HandleNormalReboot()
Handler for MonitorActivationReason.ActiveServerRebooted when the RebootState is RebootState....
+
readonly IByondTopicSender byondTopicSender
The IByondTopicSender for the ExperimentalWatchdog
-
ISessionController server
The single ISessionController.
-
readonly IJobManager jobManager
The IJobManager for the ExperimentalWatchdog
+
readonly IJobManager jobManager
The IJobManager for the ExperimentalWatchdog
+
virtual Task< IDmbProvider > PrepServerForLaunch(IDmbProvider dmbToUse, CancellationToken cancellationToken)
Prepare the server to launch a new instance with the WatchdogBase.ActiveLaunchParameters and a given ...
For managing connected chat services
Definition: IChat.cs:13
- -
readonly IReattachInfoHandler reattachInfoHandler
The IReattachInfoHandler for the WatchdogBase
Definition: WatchdogBase.cs:90
+ +
readonly IReattachInfoHandler reattachInfoHandler
The IReattachInfoHandler for the WatchdogBase
Definition: WatchdogBase.cs:93
-
Handles communication with a DreamDaemon IProcess
- -
void SetHighPriority()
Set's the owned System.Diagnostics.Process.PriorityClass to System.Diagnostics.ProcessPriorityClass....
-
bool TerminationWasRequested
If the DreamDaemon instance sent a
+
Handles communication with a DreamDaemon IProcess
- - - -
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the ExperimentalWatchdog
Definition: WatchdogBase.cs:95
-
async Task< ISessionController > LaunchNew(DreamDaemonLaunchParameters launchParameters, IDmbProvider dmbProvider, IByondExecutableLock currentByondLock, bool primaryPort, bool primaryDirectory, bool apiValidate, CancellationToken cancellationToken)
Create a ISessionController from a freshly launch DreamDaemon instance
-
TaskCompletionSource< object > ActiveParametersUpdated
TaskCompletionSource<TResult> that completes when ActiveLaunchParameters are changed and we are Runni...
Definition: WatchdogBase.cs:50
- - -
ReattachInformation Alpha
ReattachInformation for the Alpha session
+
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the ExperimentalWatchdog
Definition: WatchdogBase.cs:98
+
async Task< ISessionController > LaunchNew(DreamDaemonLaunchParameters launchParameters, IDmbProvider dmbProvider, IByondExecutableLock currentByondLock, bool primaryPort, bool primaryDirectory, bool apiValidate, CancellationToken cancellationToken)
Create a ISessionController from a freshly launch DreamDaemon instance
+
TaskCompletionSource< object > ActiveParametersUpdated
TaskCompletionSource<TResult> that completes when ActiveLaunchParameters are changed and we are Runni...
Definition: WatchdogBase.cs:53
+
sealed override async Task InitControllers(Action callBeforeRecurse, Task chatTask, WatchdogReattachInformation reattachInfo, CancellationToken cancellationToken)
Starts all ISessionControllers.
+ + +
ReattachInformation Alpha
ReattachInformation for the Alpha session
Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan
+
sealed override async Task MonitorLifetimes(CancellationToken cancellationToken)
The loop that watches the watchdog
+
sealed override WatchdogReattachInformation CreateReattachInformation()
Create the WatchdogReattachInformation for the ISessionControllers.
MonitorActivationReason
Reasons for the monitor to wake up
-
async Task< ISessionController > Reattach(ReattachInformation reattachInformation, CancellationToken cancellationToken)
Create a ISessionController from an existing DreamDaemon instance
-
ReattachInformation Release()
Releases the IProcess without terminating it. Also calls System.IDisposable.Dispose
+
async Task< ISessionController > Reattach(ReattachInformation reattachInformation, CancellationToken cancellationToken)
Create a ISessionController from an existing DreamDaemon instance
- -
IDmbProvider LockNextDmb(int lockCount)
Gets the next IDmbProvider
Definition: DmbFactory.cs:149
-
readonly IEventConsumer eventConsumer
The IEventConsumer for the ExperimentalWatchdog
+ + + + +
ISessionController Server
The single ISessionController.
+
sealed override ISessionController GetActiveController()
Get the active ISessionController.
+
readonly IEventConsumer eventConsumer
The IEventConsumer for the ExperimentalWatchdog
+
Manages the runtime of Jobs
Definition: IJobManager.cs:13
-
async Task NotifyOfFailedReattach(bool inactiveReattachSuccess, CancellationToken cancellationToken)
Send a chat message and log about a failed reattach operation and attempts another call to LaunchImpl...
-
async Task CheckLaunchResult(ISessionController controller, string serverName, CancellationToken cancellationToken)
Check the LaunchResult of a given controller for errors and throw a JobException if any are detected...
+ +
async Task NotifyOfFailedReattach(bool inactiveReattachSuccess, CancellationToken cancellationToken)
Send a chat message and log about a failed reattach operation and attempts another call to LaunchImpl...
+
async Task CheckLaunchResult(ISessionController controller, string serverName, CancellationToken cancellationToken)
Check the LaunchResult of a given controller for errors and throw a JobException if any are detected...
-
ILogger Logger
The ILogger for the WatchdogBase.
Definition: WatchdogBase.cs:60
-
override WatchdogReattachInformation CreateReattachInformation()
Create the WatchdogReattachInformation for the ISessionControllers.
-
readonly Api.Models.Instance instance
The Api.Models.Instance for the WatchdogBase.
Definition: WatchdogBase.cs:85
-
ReattachInformation Bravo
ReattachInformation for the Bravo session
-
override async Task MonitorLifetimes(CancellationToken cancellationToken)
The loop that watches the watchdog
-
Task OnReboot
A Task that completes when the server calls /world/Reboot()
+
ILogger Logger
The ILogger for the WatchdogBase.
Definition: WatchdogBase.cs:63
+
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
+ +
readonly Api.Models.Instance instance
The Api.Models.Instance for the WatchdogBase.
Definition: WatchdogBase.cs:88
+
ReattachInformation Bravo
ReattachInformation for the Bravo session
MonitorAction
The action for the monitor loop to take when control is returned to it
Definition: MonitorAction.cs:6
+
IDmbProvider LockNextDmb(int lockCount)
Gets the next IDmbProvider
Definition: DmbFactory.cs:149
Handles saving and loading WatchdogReattachInformation
static async Task< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore
-
void ResetRebootState()
Changes RebootState to Components.Watchdog.RebootState.Normal without telling the DMAPI
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
- + + -
override void DisposeAndNullControllers()
Call IDisposable.Dispose and null the fields for all ISessionControllers and set Running to false.
+
override void DisposeAndNullControllers()
Call IDisposable.Dispose and null the fields for all ISessionControllers and set Running to false.
Represents a service that may take an updated Host assembly and run it, stopping the current assembly...
diff --git a/_byond_controller_8cs_source.html b/_byond_controller_8cs_source.html index 3fae3545ac..9b3cf72ab1 100644 --- a/_byond_controller_8cs_source.html +++ b/_byond_controller_8cs_source.html @@ -71,43 +71,44 @@ $(function() {
ByondController.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 using System.Threading;
7 using System.Threading.Tasks;
8 using Tgstation.Server.Api;
15 
17 {
21  [Route(Routes.Byond)]
22  public sealed class ByondController : ApiController
23  {
28 
33 
42  public ByondController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, IJobManager jobManager, ILogger<ByondController> logger) : base(databaseContext, authenticationContextFactory, logger, true, true)
43  {
44  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
45  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
46  }
47 
53  [HttpGet]
54  [TgsAuthorize(ByondRights.ReadActive)]
55  [ProducesResponseType(typeof(Api.Models.Byond), 200)]
56  public Task<IActionResult> Read() => Task.FromResult<IActionResult>(
57  Json(new Api.Models.Byond
58  {
59  Version = instanceManager.GetInstance(Instance).ByondManager.ActiveVersion
60  }));
61 
67  [HttpGet(Routes.List)]
68  [TgsAuthorize(ByondRights.ListInstalled)]
69  [ProducesResponseType(typeof(IEnumerable<Api.Models.Byond>), 200)]
70  public Task<IActionResult> List() => Task.FromResult<IActionResult>(
71  Json(instanceManager.GetInstance(Instance).ByondManager.InstalledVersions.Select(x => new Api.Models.Byond
72  {
73  Version = x
74  })));
75 
84  [HttpPost]
85  [TgsAuthorize(ByondRights.ChangeVersion)]
86  [ProducesResponseType(typeof(Api.Models.Byond), 200)]
87  [ProducesResponseType(typeof(Api.Models.Byond), 202)]
88  public async Task<IActionResult> Update([FromBody] Api.Models.Byond model, CancellationToken cancellationToken)
89  {
90  if (model == null)
91  throw new ArgumentNullException(nameof(model));
92 
93  if (model.Version == null)
94  return BadRequest(new ErrorMessage { Message = "Missing version!" });
95 
97 
98  // remove cruff fields
99  var installingVersion = new Version(model.Version.Major, model.Version.Minor);
100 
101  var result = new Api.Models.Byond();
102 
103  if (byondManager.InstalledVersions.Any(x => x == model.Version))
104  {
105  Logger.LogInformation("User ID {0} changing instance ID {1} BYOND version to {2}", AuthenticationContext.User.Id, Instance.Id, installingVersion);
106  await byondManager.ChangeVersion(model.Version, cancellationToken).ConfigureAwait(false);
107  }
108  else
109  {
110  Logger.LogInformation("User ID {0} installing BYOND version to {2} on instance ID {1}", AuthenticationContext.User.Id, Instance.Id, installingVersion);
111 
112  // run the install through the job manager
113  var job = new Models.Job
114  {
115  Description = $"Install BYOND version {installingVersion}",
116  StartedBy = AuthenticationContext.User,
117  CancelRightsType = RightsType.Byond,
118  CancelRight = (ulong)ByondRights.CancelInstall,
120  };
121  await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressHandler, ct) => byondManager.ChangeVersion(installingVersion, ct), cancellationToken).ConfigureAwait(false);
122  result.InstallJob = job.ToApi();
123  }
124 
125  if ((AuthenticationContext.GetRight(RightsType.Byond) & (ulong)ByondRights.ReadActive) != 0)
126  result.Version = byondManager.ActiveVersion;
127  return result.InstallJob != null ? (IActionResult)Accepted(result) : Json(result);
128  }
129  }
130 }
-
const string Byond
The Models.Byond controller
Definition: Routes.cs:34
-
Manages the runtime of Jobs
Definition: IJobManager.cs:12
+Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 using System.Threading;
7 using System.Threading.Tasks;
8 using Tgstation.Server.Api;
16 
18 {
22  [Route(Routes.Byond)]
23  public sealed class ByondController : ApiController
24  {
29 
34 
43  public ByondController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, IJobManager jobManager, ILogger<ByondController> logger) : base(databaseContext, authenticationContextFactory, logger, true, true)
44  {
45  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
46  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
47  }
48 
54  [HttpGet]
55  [TgsAuthorize(ByondRights.ReadActive)]
56  [ProducesResponseType(typeof(Api.Models.Byond), 200)]
57  public Task<IActionResult> Read() => Task.FromResult<IActionResult>(
58  Json(new Api.Models.Byond
59  {
60  Version = instanceManager.GetInstance(Instance).ByondManager.ActiveVersion
61  }));
62 
68  [HttpGet(Routes.List)]
69  [TgsAuthorize(ByondRights.ListInstalled)]
70  [ProducesResponseType(typeof(IEnumerable<Api.Models.Byond>), 200)]
71  public Task<IActionResult> List() => Task.FromResult<IActionResult>(
72  Json(instanceManager.GetInstance(Instance).ByondManager.InstalledVersions.Select(x => new Api.Models.Byond
73  {
74  Version = x
75  })));
76 
85  [HttpPost]
86  [TgsAuthorize(ByondRights.ChangeVersion)]
87  [ProducesResponseType(typeof(Api.Models.Byond), 200)]
88  [ProducesResponseType(typeof(Api.Models.Byond), 202)]
89  public async Task<IActionResult> Update([FromBody] Api.Models.Byond model, CancellationToken cancellationToken)
90  {
91  if (model == null)
92  throw new ArgumentNullException(nameof(model));
93 
94  if (model.Version == null)
95  return BadRequest(new ErrorMessage { Message = "Missing version!" });
96 
98 
99  // remove cruff fields
100  var installingVersion = new Version(model.Version.Major, model.Version.Minor);
101 
102  var result = new Api.Models.Byond();
103 
104  if (byondManager.InstalledVersions.Any(x => x == model.Version))
105  {
106  Logger.LogInformation("User ID {0} changing instance ID {1} BYOND version to {2}", AuthenticationContext.User.Id, Instance.Id, installingVersion);
107  await byondManager.ChangeVersion(model.Version, cancellationToken).ConfigureAwait(false);
108  }
109  else
110  {
111  Logger.LogInformation("User ID {0} installing BYOND version to {2} on instance ID {1}", AuthenticationContext.User.Id, Instance.Id, installingVersion);
112 
113  // run the install through the job manager
114  var job = new Models.Job
115  {
116  Description = $"Install BYOND version {installingVersion}",
117  StartedBy = AuthenticationContext.User,
118  CancelRightsType = RightsType.Byond,
119  CancelRight = (ulong)ByondRights.CancelInstall,
121  };
122  await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressHandler, ct) => byondManager.ChangeVersion(installingVersion, ct), cancellationToken).ConfigureAwait(false);
123  result.InstallJob = job.ToApi();
124  }
125 
126  if ((AuthenticationContext.GetRight(RightsType.Byond) & (ulong)ByondRights.ReadActive) != 0)
127  result.Version = byondManager.ActiveVersion;
128  return result.InstallJob != null ? (IActionResult)Accepted(result) : Json(result);
129  }
130  }
131 }
const string Byond
The Models.Byond controller
Definition: Routes.cs:34
- +
ByondRights
Rights for Models.Byond
Definition: ByondRights.cs:9
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
IInstance GetInstance(Models.Instance metadata)
Get the IInstance associated with given metadata
-
Controller for managing Api.Models.Byond.Versions
+
Controller for managing Api.Models.Byond.Versions
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
-
Task RegisterOperation(Job job, Func< Job, IDatabaseContext, Action< int >, CancellationToken, Task > operation, CancellationToken cancellationToken)
Registers a given Job and begins running it
-
readonly IJobManager jobManager
The IJobManager for the ByondController
- +
readonly IJobManager jobManager
The IJobManager for the ByondController
Routes to a server actions
Definition: Routes.cs:9
+
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
-
ByondController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, IJobManager jobManager, ILogger< ByondController > logger)
Construct a ByondController
-
readonly IInstanceManager instanceManager
The IInstanceManager for the ByondController
+
ByondController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, IJobManager jobManager, ILogger< ByondController > logger)
Construct a ByondController
+
readonly IInstanceManager instanceManager
The IInstanceManager for the ByondController
long Id
The ID of the User
Definition: User.cs:15
ILogger Logger
The ILogger for the ApiController
Metadata about a server instance
Definition: Instance.cs:9
+
Manages the runtime of Jobs
Definition: IJobManager.cs:13
+
Task< IActionResult > List()
Lists installed Api.Models.Byond versions.
const string List
The postfix for list operations
Definition: Routes.cs:84
-
async Task< IActionResult > Update([FromBody] Api.Models.Byond model, CancellationToken cancellationToken)
Changes the active BYOND version to the one specified in a given model .
-
IByondManager ByondManager
The IByondManager for the IInstance
Definition: IInstance.cs:27
+
async Task< IActionResult > Update([FromBody] Api.Models.Byond model, CancellationToken cancellationToken)
Changes the active BYOND version to the one specified in a given model .
+
Task RegisterOperation(Job job, Func< Job, IDatabaseContext, Action< int >, CancellationToken, Task > operation, CancellationToken cancellationToken)
Registers a given Job and begins running it
+
IByondManager ByondManager
The IByondManager for the IInstance
Definition: IInstance.cs:28
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+
Task< IActionResult > Read()
Gets the active Api.Models.Byond version.
diff --git a/_byond_manager_8cs_source.html b/_byond_manager_8cs_source.html index 81b1be5625..1188b5ef8d 100644 --- a/_byond_manager_8cs_source.html +++ b/_byond_manager_8cs_source.html @@ -71,53 +71,54 @@ $(function() {
ByondManager.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using System;
3 using System.Collections.Generic;
4 using System.Globalization;
5 using System.Linq;
6 using System.Net;
7 using System.Text;
8 using System.Threading;
9 using System.Threading.Tasks;
11 using Tgstation.Server.Host.IO;
12 
14 {
16  sealed class ByondManager : IByondManager
17  {
21  public const string BinPath = "byond/bin";
22 
26  const string VersionFileName = "Version.txt";
27 
31  const string ActiveVersionFileName = "ActiveVersion.txt";
32 
34  public Version ActiveVersion { get; private set; }
35 
37  public IReadOnlyList<Version> InstalledVersions
38  {
39  get
40  {
41  lock (installedVersions)
42  return installedVersions.Select(x => Version.Parse(x.Key)).ToList();
43  }
44  }
45 
50 
55 
60 
64  readonly ILogger<ByondManager> logger;
65 
69  readonly Dictionary<string, Task> installedVersions;
70 
74  readonly SemaphoreSlim semaphore;
75 
81  static string VersionKey(Version version) => new Version(version.Major, version.Minor).ToString();
82 
91  {
92  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
93  this.byondInstaller = byondInstaller ?? throw new ArgumentNullException(nameof(byondInstaller));
94  this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
95  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
96 
97  installedVersions = new Dictionary<string, Task>();
98  semaphore = new SemaphoreSlim(1);
99  }
100 
102  public void Dispose() => semaphore.Dispose();
103 
110  async Task InstallVersion(Version version, CancellationToken cancellationToken)
111  {
112  var ourTcs = new TaskCompletionSource<object>();
113  Task inProgressTask;
114 
115  var versionKey = VersionKey(version);
116  bool installed;
117  lock (installedVersions)
118  {
119  installed = installedVersions.TryGetValue(versionKey, out inProgressTask);
120  if (!installed)
121  installedVersions.Add(versionKey, ourTcs.Task);
122  }
123 
124  if (installed)
125  using (cancellationToken.Register(() => ourTcs.SetCanceled()))
126  {
127  await Task.WhenAny(ourTcs.Task, inProgressTask).ConfigureAwait(false);
128  cancellationToken.ThrowIfCancellationRequested();
129  return;
130  }
131 
132  // okay up to us to install it then
133  try
134  {
135  await eventConsumer.HandleEvent(EventType.ByondInstallStart, new List<string> { versionKey }, cancellationToken).ConfigureAwait(false);
136  var downloadTask = byondInstaller.DownloadVersion(version, cancellationToken);
137 
138  await ioManager.DeleteDirectory(versionKey, cancellationToken).ConfigureAwait(false);
139  await ioManager.CreateDirectory(versionKey, cancellationToken).ConfigureAwait(false);
140 
141  try
142  {
143  var download = await downloadTask.ConfigureAwait(false);
144  await ioManager.ZipToDirectory(versionKey, download, cancellationToken).ConfigureAwait(false);
145  await byondInstaller.InstallByond(ioManager.ResolvePath(versionKey), version, cancellationToken).ConfigureAwait(false);
146 
147  // make sure to do this last because this is what tells us we have a valid version in the future
148  await ioManager.WriteAllBytes(ioManager.ConcatPath(versionKey, VersionFileName), Encoding.UTF8.GetBytes(version.ToString()), cancellationToken).ConfigureAwait(false);
149  }
150  catch (WebException e)
151  {
152  // since the user can easily provide non-exitent version numbers, we'll turn this into a JobException
153  throw new JobException(String.Format(CultureInfo.InvariantCulture, "Error downloading BYOND version: {0}", e.Message));
154  }
155  catch (OperationCanceledException)
156  {
157  throw;
158  }
159  catch
160  {
161  await ioManager.DeleteDirectory(versionKey, cancellationToken).ConfigureAwait(false);
162  throw;
163  }
164 
165  ourTcs.SetResult(null);
166  }
167  catch (Exception e)
168  {
169  if (!(e is OperationCanceledException))
170  await eventConsumer.HandleEvent(EventType.ByondInstallFail, new List<string> { e.Message }, cancellationToken).ConfigureAwait(false);
171  lock (installedVersions)
172  installedVersions.Remove(versionKey);
173  ourTcs.SetException(e);
174  throw;
175  }
176  }
177 
179  public async Task ChangeVersion(Version version, CancellationToken cancellationToken)
180  {
181  if (version == null)
182  throw new ArgumentNullException(nameof(version));
183  var versionKey = VersionKey(version);
184  await InstallVersion(version, cancellationToken).ConfigureAwait(false);
185  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
186  {
187  await ioManager.WriteAllBytes(ActiveVersionFileName, Encoding.UTF8.GetBytes(versionKey), cancellationToken).ConfigureAwait(false);
188  await eventConsumer.HandleEvent(EventType.ByondActiveVersionChange, new List<string> { ActiveVersion != null ? VersionKey(ActiveVersion) : null, versionKey }, cancellationToken).ConfigureAwait(false);
189  ActiveVersion = version;
190  }
191  }
192 
194  public async Task<IByondExecutableLock> UseExecutables(Version requiredVersion, CancellationToken cancellationToken)
195  {
196  var versionToUse = requiredVersion ?? ActiveVersion;
197  if (versionToUse == null)
198  throw new JobException("No BYOND versions installed!");
199  await InstallVersion(versionToUse, cancellationToken).ConfigureAwait(false);
200 
201  var versionKey = VersionKey(versionToUse);
202 
204  }
205 
207  public async Task StartAsync(CancellationToken cancellationToken)
208  {
209  async Task<byte[]> GetActiveVersion()
210  {
211  var activeVersionFileExists = await ioManager.FileExists(ActiveVersionFileName, cancellationToken).ConfigureAwait(false);
212  return !activeVersionFileExists ? null : await ioManager.ReadAllBytes(ActiveVersionFileName, cancellationToken).ConfigureAwait(false);
213  }
214 
215  var activeVersionBytesTask = GetActiveVersion();
216 
217  await ioManager.CreateDirectory(".", cancellationToken).ConfigureAwait(false);
218  var directories = await ioManager.GetDirectories(".", cancellationToken).ConfigureAwait(false);
219 
220  async Task ReadVersion(string path)
221  {
222  var versionFile = ioManager.ConcatPath(path, VersionFileName);
223  if (!await ioManager.FileExists(versionFile, cancellationToken).ConfigureAwait(false))
224  {
225  logger.LogInformation("Cleaning unparsable version path: {0}", ioManager.ResolvePath(path));
226  await ioManager.DeleteDirectory(path, cancellationToken).ConfigureAwait(false); // cleanup
227  return;
228  }
229 
230  var bytes = await ioManager.ReadAllBytes(versionFile, cancellationToken).ConfigureAwait(false);
231  var text = Encoding.UTF8.GetString(bytes);
232  if (Version.TryParse(text, out var version))
233  {
234  var key = VersionKey(version);
235  lock (installedVersions)
236  if (!installedVersions.ContainsKey(key))
237  {
238  installedVersions.Add(key, Task.CompletedTask);
239  return;
240  }
241  }
242 
243  await ioManager.DeleteDirectory(path, cancellationToken).ConfigureAwait(false);
244  }
245 
246  await Task.WhenAll(directories.Select(x => ReadVersion(x))).ConfigureAwait(false);
247 
248  var activeVersionBytes = await activeVersionBytesTask.ConfigureAwait(false);
249  if (activeVersionBytes != null)
250  {
251  var activeVersionString = Encoding.UTF8.GetString(activeVersionBytes);
252  if (Version.TryParse(activeVersionString, out var activeVersion))
253  ActiveVersion = activeVersion;
254  else
255  await ioManager.DeleteFile(ActiveVersionFileName, cancellationToken).ConfigureAwait(false);
256  }
257  }
258 
260  public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
261  }
262 }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
-
readonly IIOManager ioManager
The IIOManager for the ByondManager
Definition: ByondManager.cs:49
+Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using System;
3 using System.Collections.Generic;
4 using System.Globalization;
5 using System.Linq;
6 using System.Net;
7 using System.Text;
8 using System.Threading;
9 using System.Threading.Tasks;
11 using Tgstation.Server.Host.IO;
13 
15 {
17  sealed class ByondManager : IByondManager
18  {
22  public const string BinPath = "byond/bin";
23 
27  const string VersionFileName = "Version.txt";
28 
32  const string ActiveVersionFileName = "ActiveVersion.txt";
33 
35  public Version ActiveVersion { get; private set; }
36 
38  public IReadOnlyList<Version> InstalledVersions
39  {
40  get
41  {
42  lock (installedVersions)
43  return installedVersions.Select(x => Version.Parse(x.Key)).ToList();
44  }
45  }
46 
51 
56 
61 
65  readonly ILogger<ByondManager> logger;
66 
70  readonly Dictionary<string, Task> installedVersions;
71 
75  readonly SemaphoreSlim semaphore;
76 
82  static string VersionKey(Version version) => new Version(version.Major, version.Minor).ToString();
83 
92  {
93  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
94  this.byondInstaller = byondInstaller ?? throw new ArgumentNullException(nameof(byondInstaller));
95  this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
96  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
97 
98  installedVersions = new Dictionary<string, Task>();
99  semaphore = new SemaphoreSlim(1);
100  }
101 
103  public void Dispose() => semaphore.Dispose();
104 
111  async Task InstallVersion(Version version, CancellationToken cancellationToken)
112  {
113  var ourTcs = new TaskCompletionSource<object>();
114  Task inProgressTask;
115 
116  var versionKey = VersionKey(version);
117  bool installed;
118  lock (installedVersions)
119  {
120  installed = installedVersions.TryGetValue(versionKey, out inProgressTask);
121  if (!installed)
122  installedVersions.Add(versionKey, ourTcs.Task);
123  }
124 
125  if (installed)
126  using (cancellationToken.Register(() => ourTcs.SetCanceled()))
127  {
128  await Task.WhenAny(ourTcs.Task, inProgressTask).ConfigureAwait(false);
129  cancellationToken.ThrowIfCancellationRequested();
130  return;
131  }
132 
133  // okay up to us to install it then
134  try
135  {
136  await eventConsumer.HandleEvent(EventType.ByondInstallStart, new List<string> { versionKey }, cancellationToken).ConfigureAwait(false);
137  var downloadTask = byondInstaller.DownloadVersion(version, cancellationToken);
138 
139  await ioManager.DeleteDirectory(versionKey, cancellationToken).ConfigureAwait(false);
140  await ioManager.CreateDirectory(versionKey, cancellationToken).ConfigureAwait(false);
141 
142  try
143  {
144  var download = await downloadTask.ConfigureAwait(false);
145  await ioManager.ZipToDirectory(versionKey, download, cancellationToken).ConfigureAwait(false);
146  await byondInstaller.InstallByond(ioManager.ResolvePath(versionKey), version, cancellationToken).ConfigureAwait(false);
147 
148  // make sure to do this last because this is what tells us we have a valid version in the future
149  await ioManager.WriteAllBytes(ioManager.ConcatPath(versionKey, VersionFileName), Encoding.UTF8.GetBytes(version.ToString()), cancellationToken).ConfigureAwait(false);
150  }
151  catch (WebException e)
152  {
153  // since the user can easily provide non-exitent version numbers, we'll turn this into a JobException
154  throw new JobException(String.Format(CultureInfo.InvariantCulture, "Error downloading BYOND version: {0}", e.Message));
155  }
156  catch (OperationCanceledException)
157  {
158  throw;
159  }
160  catch
161  {
162  await ioManager.DeleteDirectory(versionKey, cancellationToken).ConfigureAwait(false);
163  throw;
164  }
165 
166  ourTcs.SetResult(null);
167  }
168  catch (Exception e)
169  {
170  if (!(e is OperationCanceledException))
171  await eventConsumer.HandleEvent(EventType.ByondInstallFail, new List<string> { e.Message }, cancellationToken).ConfigureAwait(false);
172  lock (installedVersions)
173  installedVersions.Remove(versionKey);
174  ourTcs.SetException(e);
175  throw;
176  }
177  }
178 
180  public async Task ChangeVersion(Version version, CancellationToken cancellationToken)
181  {
182  if (version == null)
183  throw new ArgumentNullException(nameof(version));
184  var versionKey = VersionKey(version);
185  await InstallVersion(version, cancellationToken).ConfigureAwait(false);
186  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
187  {
188  await ioManager.WriteAllBytes(ActiveVersionFileName, Encoding.UTF8.GetBytes(versionKey), cancellationToken).ConfigureAwait(false);
189  await eventConsumer.HandleEvent(EventType.ByondActiveVersionChange, new List<string> { ActiveVersion != null ? VersionKey(ActiveVersion) : null, versionKey }, cancellationToken).ConfigureAwait(false);
190  ActiveVersion = version;
191  }
192  }
193 
195  public async Task<IByondExecutableLock> UseExecutables(Version requiredVersion, CancellationToken cancellationToken)
196  {
197  var versionToUse = requiredVersion ?? ActiveVersion;
198  if (versionToUse == null)
199  throw new JobException("No BYOND versions installed!");
200  await InstallVersion(versionToUse, cancellationToken).ConfigureAwait(false);
201 
202  var versionKey = VersionKey(versionToUse);
203 
205  }
206 
208  public async Task StartAsync(CancellationToken cancellationToken)
209  {
210  async Task<byte[]> GetActiveVersion()
211  {
212  var activeVersionFileExists = await ioManager.FileExists(ActiveVersionFileName, cancellationToken).ConfigureAwait(false);
213  return !activeVersionFileExists ? null : await ioManager.ReadAllBytes(ActiveVersionFileName, cancellationToken).ConfigureAwait(false);
214  }
215 
216  var activeVersionBytesTask = GetActiveVersion();
217 
218  await ioManager.CreateDirectory(".", cancellationToken).ConfigureAwait(false);
219  var directories = await ioManager.GetDirectories(".", cancellationToken).ConfigureAwait(false);
220 
221  async Task ReadVersion(string path)
222  {
223  var versionFile = ioManager.ConcatPath(path, VersionFileName);
224  if (!await ioManager.FileExists(versionFile, cancellationToken).ConfigureAwait(false))
225  {
226  logger.LogInformation("Cleaning unparsable version path: {0}", ioManager.ResolvePath(path));
227  await ioManager.DeleteDirectory(path, cancellationToken).ConfigureAwait(false); // cleanup
228  return;
229  }
230 
231  var bytes = await ioManager.ReadAllBytes(versionFile, cancellationToken).ConfigureAwait(false);
232  var text = Encoding.UTF8.GetString(bytes);
233  if (Version.TryParse(text, out var version))
234  {
235  var key = VersionKey(version);
236  lock (installedVersions)
237  if (!installedVersions.ContainsKey(key))
238  {
239  installedVersions.Add(key, Task.CompletedTask);
240  return;
241  }
242  }
243 
244  await ioManager.DeleteDirectory(path, cancellationToken).ConfigureAwait(false);
245  }
246 
247  await Task.WhenAll(directories.Select(x => ReadVersion(x))).ConfigureAwait(false);
248 
249  var activeVersionBytes = await activeVersionBytesTask.ConfigureAwait(false);
250  if (activeVersionBytes != null)
251  {
252  var activeVersionString = Encoding.UTF8.GetString(activeVersionBytes);
253  if (Version.TryParse(activeVersionString, out var activeVersion))
254  ActiveVersion = activeVersion;
255  else
256  await ioManager.DeleteFile(ActiveVersionFileName, cancellationToken).ConfigureAwait(false);
257  }
258  }
259 
261  public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
262  }
263 }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory, removes and does not enter any symlinks encounterd.
+
readonly IIOManager ioManager
The IIOManager for the ByondManager
Definition: ByondManager.cs:50
Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content
Consumes EventTypes and takes the appropriate actions
- -
const string ActiveVersionFileName
The file in which we store the VersionKey(Version) for the active installation
Definition: ByondManager.cs:31
+ +
const string ActiveVersionFileName
The file in which we store the VersionKey(Version) for the active installation
Definition: ByondManager.cs:32
Task ZipToDirectory(string path, byte[] zipFileBytes, CancellationToken cancellationToken)
Extract a set of zipFileBytes to a given path
Task< IReadOnlyList< string > > GetDirectories(string path, CancellationToken cancellationToken)
Returns directory names in a given path
string DreamMakerName
Get the file name of the DreamMaker executable
Task< byte[]> DownloadVersion(Version version, CancellationToken cancellationToken)
Download a given BYOND version
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
-
async Task StartAsync(CancellationToken cancellationToken)
+
async Task StartAsync(CancellationToken cancellationToken)
Task InstallByond(string path, Version version, CancellationToken cancellationToken)
Does actions necessary to get an extracted BYOND installation working
Task CreateDirectory(string path, CancellationToken cancellationToken)
Create a directory at path
string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
-
async Task< IByondExecutableLock > UseExecutables(Version requiredVersion, CancellationToken cancellationToken)
Lock the current installation's location and return a IByondExecutableLock
- +
async Task< IByondExecutableLock > UseExecutables(Version requiredVersion, CancellationToken cancellationToken)
Lock the current installation's location and return a IByondExecutableLock
+
For downloading and installing BYOND extractions for a given system
Task< bool > FileExists(string path, CancellationToken cancellationToken)
Check that the file at path exists
-
async Task InstallVersion(Version version, CancellationToken cancellationToken)
Installs a BYOND version if it isn't already
+
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
+
async Task InstallVersion(Version version, CancellationToken cancellationToken)
Installs a BYOND version if it isn't already
-
readonly Dictionary< string, Task > installedVersions
Map of byond Versions to Tasks that complete when they are installed
Definition: ByondManager.cs:69
-
ByondManager(IIOManager ioManager, IByondInstaller byondInstaller, IEventConsumer eventConsumer, ILogger< ByondManager > logger)
Construct a ByondManager
Definition: ByondManager.cs:90
-
readonly ILogger< ByondManager > logger
The ILogger for the ByondManager
Definition: ByondManager.cs:64
+
readonly Dictionary< string, Task > installedVersions
Map of byond Versions to Tasks that complete when they are installed
Definition: ByondManager.cs:70
+
ByondManager(IIOManager ioManager, IByondInstaller byondInstaller, IEventConsumer eventConsumer, ILogger< ByondManager > logger)
Construct a ByondManager
Definition: ByondManager.cs:91
+
readonly ILogger< ByondManager > logger
The ILogger for the ByondManager
Definition: ByondManager.cs:65
string DreamDaemonName
Get the file name of the DreamDaemon executable
-
const string VersionFileName
The file in which we store the VersionKey(Version) for installations
Definition: ByondManager.cs:26
- -
async Task ChangeVersion(Version version, CancellationToken cancellationToken)
Change the active BYOND version
+
const string VersionFileName
The file in which we store the VersionKey(Version) for installations
Definition: ByondManager.cs:27
+ + +
async Task ChangeVersion(Version version, CancellationToken cancellationToken)
Change the active BYOND version
-
readonly IByondInstaller byondInstaller
The IByondInstaller for the ByondManager
Definition: ByondManager.cs:54
+
readonly IByondInstaller byondInstaller
The IByondInstaller for the ByondManager
Definition: ByondManager.cs:55
Interface for using filesystems
Definition: IIOManager.cs:11
Task< bool > HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
Handle a given eventType
Task StopAsync(CancellationToken cancellationToken)
static string VersionKey(Version version)
Converts a BYOND version to a string
Task< byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
Returns all the contents of a file at path as a byte array
Task DeleteFile(string path, CancellationToken cancellationToken)
Deletes a file at path
-
readonly SemaphoreSlim semaphore
The SemaphoreSlim for the ByondManager
Definition: ByondManager.cs:74
+
readonly SemaphoreSlim semaphore
The SemaphoreSlim for the ByondManager
Definition: ByondManager.cs:75
-
const string BinPath
The path to the BYOND bin folder
Definition: ByondManager.cs:21
+
const string BinPath
The path to the BYOND bin folder
Definition: ByondManager.cs:22
static async Task< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore
string ConcatPath(params string[] paths)
Combines an array of strings into a path
-
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
-
readonly IEventConsumer eventConsumer
The IEventConsumer for the ByondManager
Definition: ByondManager.cs:59
+
readonly IEventConsumer eventConsumer
The IEventConsumer for the ByondManager
Definition: ByondManager.cs:60
diff --git a/_chat_controller_8cs_source.html b/_chat_controller_8cs_source.html index b2b58c9eff..1fe9823605 100644 --- a/_chat_controller_8cs_source.html +++ b/_chat_controller_8cs_source.html @@ -71,29 +71,27 @@ $(function() {
ChatController.cs
-Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Linq.Expressions;
5 using System.Net;
6 using System.Reflection;
7 using System.Threading;
8 using System.Threading.Tasks;
9 using Microsoft.AspNetCore.Mvc;
10 using Microsoft.EntityFrameworkCore;
11 using Microsoft.Extensions.Logging;
12 using Tgstation.Server.Api;
18 using Z.EntityFramework.Plus;
19 
21 {
25  [Route(Routes.Chat)]
26  public sealed class ChatController : ApiController
27  {
32 
40  public ChatController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, ILogger<ChatController> logger) : base(databaseContext, authenticationContextFactory, logger, true, true)
41  {
42  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
43  }
44 
50  static Models.ChatChannel ConvertApiChatChannel(Api.Models.ChatChannel api) => new Models.ChatChannel
51  {
52  DiscordChannelId = api.DiscordChannelId,
53  IrcChannel = api.IrcChannel,
54  IsAdminChannel = api.IsAdminChannel ?? false,
55  IsWatchdogChannel = api.IsWatchdogChannel ?? false,
56  IsUpdatesChannel = api.IsUpdatesChannel ?? false,
57  Tag = api.Tag
58  };
59 
67  [HttpPut]
68  [TgsAuthorize(ChatBotRights.Create)]
69  [ProducesResponseType(typeof(Api.Models.ChatBot), 201)]
70  public async Task<IActionResult> Create([FromBody] Api.Models.ChatBot model, CancellationToken cancellationToken)
71  {
72  if (model == null)
73  throw new ArgumentNullException(nameof(model));
74 
75  if (String.IsNullOrWhiteSpace(model.Name))
76  return BadRequest(new ErrorMessage { Message = "name cannot be null or whitespace!" });
77 
78  if (String.IsNullOrWhiteSpace(model.ConnectionString))
79  return BadRequest(new ErrorMessage { Message = "connection_string cannot be null or whitespace!" });
80 
81  if (!model.Provider.HasValue)
82  return BadRequest(new ErrorMessage { Message = "provider cannot be null!" });
83 
84  switch (model.Provider)
85  {
86  case ChatProvider.Discord:
87  case ChatProvider.Irc:
88  break;
89  default:
90  return BadRequest(new ErrorMessage { Message = "Invalid provider!" });
91  }
92 
93  if (!model.ValidateProviderChannelTypes())
94  return BadRequest(new ErrorMessage { Message = "One or more of channels aren't formatted correctly for the given provider!" });
95 
96  model.Enabled = model.Enabled ?? false;
97 
98  // try to update das db first
99  var dbModel = new Models.ChatBot
100  {
101  Name = model.Name,
102  ConnectionString = model.ConnectionString,
103  Enabled = model.Enabled,
104  Channels = model.Channels?.Select(x => ConvertApiChatChannel(x)).ToList() ?? new List<Models.ChatChannel>(), // important that this isn't null
105  InstanceId = Instance.Id,
106  Provider = model.Provider,
107  };
108 
109  DatabaseContext.ChatBots.Add(dbModel);
110 
111  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
112 
113  try
114  {
115  try
116  {
117  // try to create it
118  var instance = instanceManager.GetInstance(Instance);
119  await instance.Chat.ChangeSettings(dbModel, cancellationToken).ConfigureAwait(false);
120 
121  if (dbModel.Channels.Count > 0)
122  await instance.Chat.ChangeChannels(dbModel.Id, dbModel.Channels, cancellationToken).ConfigureAwait(false);
123  }
124  catch
125  {
126  // undo the add
127  DatabaseContext.ChatBots.Remove(dbModel);
128  await DatabaseContext.Save(default).ConfigureAwait(false);
129  throw;
130  }
131  }
132  catch (InvalidOperationException e)
133  {
134  return BadRequest(new ErrorMessage { Message = e.Message });
135  }
136 
137  return StatusCode((int)HttpStatusCode.Created, dbModel.ToApi());
138  }
139 
147  [HttpDelete("{id}")]
148  [TgsAuthorize(ChatBotRights.Delete)]
149  [ProducesResponseType(200)]
150  public async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
151  {
152  var instance = instanceManager.GetInstance(Instance);
153  await Task.WhenAll(instance.Chat.DeleteConnection(id, cancellationToken), DatabaseContext.ChatBots.Where(x => x.Id == id).DeleteAsync(cancellationToken)).ConfigureAwait(false);
154 
155  return Ok();
156  }
157 
164  [HttpGet(Routes.List)]
165  [TgsAuthorize(ChatBotRights.Read)]
166  [ProducesResponseType(typeof(IEnumerable<Api.Models.ChatBot>), 200)]
167  public async Task<IActionResult> List(CancellationToken cancellationToken)
168  {
169  var query = DatabaseContext.ChatBots.Where(x => x.InstanceId == Instance.Id).Include(x => x.Channels);
170 
171  var results = await query.ToListAsync(cancellationToken).ConfigureAwait(false);
172 
173  var connectionStrings = (AuthenticationContext.GetRight(RightsType.ChatBots) & (ulong)ChatBotRights.ReadConnectionString) != 0;
174 
175  if (!connectionStrings)
176  foreach (var I in results)
177  I.ConnectionString = null;
178 
179  return Json(results.Select(x => x.ToApi()));
180  }
181 
190  [HttpGet("{id}")]
191  [TgsAuthorize(ChatBotRights.Read)]
192  [ProducesResponseType(typeof(Api.Models.ChatBot), 200)]
193  [ProducesResponseType(410)]
194  public async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
195  {
196  var query = DatabaseContext.ChatBots.Where(x => x.Id == id).Include(x => x.Channels);
197 
198  var results = await query.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
199  if (results == default)
200  return StatusCode((int)HttpStatusCode.Gone);
201 
202  var connectionStrings = (AuthenticationContext.GetRight(RightsType.ChatBots) & (ulong)ChatBotRights.ReadConnectionString) != 0;
203 
204  if (!connectionStrings)
205  results.ConnectionString = null;
206 
207  return Json(results.ToApi());
208  }
209 
217  [HttpPost]
218  [TgsAuthorize(ChatBotRights.WriteChannels | ChatBotRights.WriteConnectionString | ChatBotRights.WriteEnabled | ChatBotRights.WriteName | ChatBotRights.WriteProvider)]
219  [ProducesResponseType(200)]
220  [ProducesResponseType(typeof(Api.Models.ChatBot), 200)]
221  #pragma warning disable CA1506 // TODO: Decomplexify
222  public async Task<IActionResult> Update([FromBody] Api.Models.ChatBot model, CancellationToken cancellationToken)
223  {
224  if (model == null)
225  throw new ArgumentNullException(nameof(model));
226 
227  if (model.Provider.HasValue && !model.ValidateProviderChannelTypes())
228  return BadRequest(new ErrorMessage { Message = "One or more of channels aren't formatted correctly for the given provider!" });
229 
230  var query = DatabaseContext.ChatBots.Where(x => x.InstanceId == Instance.Id && x.Id == model.Id).Include(x => x.Channels);
231 
232  var current = await query.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
233 
234  if (current == default)
235  return StatusCode((int)HttpStatusCode.Gone);
236 
237  var userRights = (ChatBotRights)AuthenticationContext.GetRight(RightsType.ChatBots);
238 
239  bool anySettingsModified = false;
240 
241  bool CheckModified<T>(Expression<Func<Api.Models.Internal.ChatBot, T>> expression, ChatBotRights requiredRight)
242  {
243  var memberSelectorExpression = (MemberExpression)expression.Body;
244  var property = (PropertyInfo)memberSelectorExpression.Member;
245 
246  var newVal = property.GetValue(model);
247  if (newVal == null)
248  return false;
249  if (!userRights.HasFlag(requiredRight) && property.GetValue(current) != newVal)
250  return true;
251 
252  property.SetValue(current, newVal);
253  anySettingsModified = true;
254  return false;
255  }
256 
257  var oldProvider = current.Provider;
258 
259  if (CheckModified(x => x.ConnectionString, ChatBotRights.WriteConnectionString)
260  || CheckModified(x => x.Enabled, ChatBotRights.WriteEnabled)
261  || CheckModified(x => x.Name, ChatBotRights.WriteName)
262  || CheckModified(x => x.Provider, ChatBotRights.WriteProvider)
263  || (model.Channels != null && !userRights.HasFlag(ChatBotRights.WriteChannels)))
264  return Forbid();
265 
266  var hasChannels = model.Channels != null;
267  if (hasChannels || (model.Provider.HasValue && model.Provider != oldProvider))
268  {
269  DatabaseContext.ChatChannels.RemoveRange(current.Channels);
270  if (hasChannels)
271  {
272  var dbChannels = model.Channels.Select(x => ConvertApiChatChannel(x)).ToList();
273  DatabaseContext.ChatChannels.AddRange(dbChannels);
274  current.Channels = dbChannels;
275  }
276  else
277  current.Channels.Clear();
278  }
279 
280  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
281 
283 
284  if (anySettingsModified)
285  await chat.ChangeSettings(current, cancellationToken).ConfigureAwait(false); // have to rebuild the thing first
286 
287  if (model.Channels != null || anySettingsModified)
288  await chat.ChangeChannels(current.Id, current.Channels, cancellationToken).ConfigureAwait(false);
289 
290  if (userRights.HasFlag(ChatBotRights.Read))
291  {
292  if (!userRights.HasFlag(ChatBotRights.ReadConnectionString))
293  current.ConnectionString = null;
294  return Json(current.ToApi());
295  }
296 
297  return Ok();
298  }
299  #pragma warning restore CA1506
300  }
301 }
+Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Linq.Expressions;
5 using System.Net;
6 using System.Reflection;
7 using System.Threading;
8 using System.Threading.Tasks;
9 using Microsoft.AspNetCore.Mvc;
10 using Microsoft.EntityFrameworkCore;
11 using Microsoft.Extensions.Logging;
12 using Tgstation.Server.Api;
19 using Z.EntityFramework.Plus;
20 
22 {
26  [Route(Routes.Chat)]
27  public sealed class ChatController : ApiController
28  {
33 
41  public ChatController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, ILogger<ChatController> logger) : base(databaseContext, authenticationContextFactory, logger, true, true)
42  {
43  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
44  }
45 
51  static Models.ChatChannel ConvertApiChatChannel(Api.Models.ChatChannel api) => new Models.ChatChannel
52  {
53  DiscordChannelId = api.DiscordChannelId,
54  IrcChannel = api.IrcChannel,
55  IsAdminChannel = api.IsAdminChannel ?? false,
56  IsWatchdogChannel = api.IsWatchdogChannel ?? false,
57  IsUpdatesChannel = api.IsUpdatesChannel ?? false,
58  Tag = api.Tag
59  };
60 
68  [HttpPut]
69  [TgsAuthorize(ChatBotRights.Create)]
70  [ProducesResponseType(typeof(Api.Models.ChatBot), 201)]
71  public async Task<IActionResult> Create([FromBody] Api.Models.ChatBot model, CancellationToken cancellationToken)
72  {
73  if (model == null)
74  throw new ArgumentNullException(nameof(model));
75 
76  if (String.IsNullOrWhiteSpace(model.Name))
77  return BadRequest(new ErrorMessage { Message = "name cannot be null or whitespace!" });
78 
79  if (String.IsNullOrWhiteSpace(model.ConnectionString))
80  return BadRequest(new ErrorMessage { Message = "connection_string cannot be null or whitespace!" });
81 
82  if (!model.Provider.HasValue)
83  return BadRequest(new ErrorMessage { Message = "provider cannot be null!" });
84 
85  switch (model.Provider)
86  {
87  case ChatProvider.Discord:
88  case ChatProvider.Irc:
89  break;
90  default:
91  return BadRequest(new ErrorMessage { Message = "Invalid provider!" });
92  }
93 
94  if (!model.ValidateProviderChannelTypes())
95  return BadRequest(new ErrorMessage { Message = "One or more of channels aren't formatted correctly for the given provider!" });
96 
97  model.Enabled = model.Enabled ?? false;
98 
99  // try to update das db first
100  var dbModel = new Models.ChatBot
101  {
102  Name = model.Name,
103  ConnectionString = model.ConnectionString,
104  Enabled = model.Enabled,
105  Channels = model.Channels?.Select(x => ConvertApiChatChannel(x)).ToList() ?? new List<Models.ChatChannel>(), // important that this isn't null
106  InstanceId = Instance.Id,
107  Provider = model.Provider,
108  };
109 
110  DatabaseContext.ChatBots.Add(dbModel);
111 
112  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
113 
114  try
115  {
116  try
117  {
118  // try to create it
119  var instance = instanceManager.GetInstance(Instance);
120  await instance.Chat.ChangeSettings(dbModel, cancellationToken).ConfigureAwait(false);
121 
122  if (dbModel.Channels.Count > 0)
123  await instance.Chat.ChangeChannels(dbModel.Id, dbModel.Channels, cancellationToken).ConfigureAwait(false);
124  }
125  catch
126  {
127  // undo the add
128  DatabaseContext.ChatBots.Remove(dbModel);
129  await DatabaseContext.Save(default).ConfigureAwait(false);
130  throw;
131  }
132  }
133  catch (InvalidOperationException e)
134  {
135  return BadRequest(new ErrorMessage { Message = e.Message });
136  }
137 
138  return StatusCode((int)HttpStatusCode.Created, dbModel.ToApi());
139  }
140 
148  [HttpDelete("{id}")]
149  [TgsAuthorize(ChatBotRights.Delete)]
150  [ProducesResponseType(200)]
151  public async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
152  {
153  var instance = instanceManager.GetInstance(Instance);
154  await Task.WhenAll(instance.Chat.DeleteConnection(id, cancellationToken), DatabaseContext.ChatBots.Where(x => x.Id == id).DeleteAsync(cancellationToken)).ConfigureAwait(false);
155 
156  return Ok();
157  }
158 
165  [HttpGet(Routes.List)]
166  [TgsAuthorize(ChatBotRights.Read)]
167  [ProducesResponseType(typeof(IEnumerable<Api.Models.ChatBot>), 200)]
168  public async Task<IActionResult> List(CancellationToken cancellationToken)
169  {
170  var query = DatabaseContext.ChatBots.Where(x => x.InstanceId == Instance.Id).Include(x => x.Channels);
171 
172  var results = await query.ToListAsync(cancellationToken).ConfigureAwait(false);
173 
174  var connectionStrings = (AuthenticationContext.GetRight(RightsType.ChatBots) & (ulong)ChatBotRights.ReadConnectionString) != 0;
175 
176  if (!connectionStrings)
177  foreach (var I in results)
178  I.ConnectionString = null;
179 
180  return Json(results.Select(x => x.ToApi()));
181  }
182 
191  [HttpGet("{id}")]
192  [TgsAuthorize(ChatBotRights.Read)]
193  [ProducesResponseType(typeof(Api.Models.ChatBot), 200)]
194  [ProducesResponseType(410)]
195  public async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
196  {
197  var query = DatabaseContext.ChatBots.Where(x => x.Id == id).Include(x => x.Channels);
198 
199  var results = await query.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
200  if (results == default)
201  return StatusCode((int)HttpStatusCode.Gone);
202 
203  var connectionStrings = (AuthenticationContext.GetRight(RightsType.ChatBots) & (ulong)ChatBotRights.ReadConnectionString) != 0;
204 
205  if (!connectionStrings)
206  results.ConnectionString = null;
207 
208  return Json(results.ToApi());
209  }
210 
218  [HttpPost]
219  [TgsAuthorize(ChatBotRights.WriteChannels | ChatBotRights.WriteConnectionString | ChatBotRights.WriteEnabled | ChatBotRights.WriteName | ChatBotRights.WriteProvider)]
220  [ProducesResponseType(200)]
221  [ProducesResponseType(typeof(Api.Models.ChatBot), 200)]
222  #pragma warning disable CA1506 // TODO: Decomplexify
223  public async Task<IActionResult> Update([FromBody] Api.Models.ChatBot model, CancellationToken cancellationToken)
224  {
225  if (model == null)
226  throw new ArgumentNullException(nameof(model));
227 
228  if (model.Provider.HasValue && !model.ValidateProviderChannelTypes())
229  return BadRequest(new ErrorMessage { Message = "One or more of channels aren't formatted correctly for the given provider!" });
230 
231  var query = DatabaseContext.ChatBots.Where(x => x.InstanceId == Instance.Id && x.Id == model.Id).Include(x => x.Channels);
232 
233  var current = await query.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
234 
235  if (current == default)
236  return StatusCode((int)HttpStatusCode.Gone);
237 
238  var userRights = (ChatBotRights)AuthenticationContext.GetRight(RightsType.ChatBots);
239 
240  bool anySettingsModified = false;
241 
242  bool CheckModified<T>(Expression<Func<Api.Models.Internal.ChatBot, T>> expression, ChatBotRights requiredRight)
243  {
244  var memberSelectorExpression = (MemberExpression)expression.Body;
245  var property = (PropertyInfo)memberSelectorExpression.Member;
246 
247  var newVal = property.GetValue(model);
248  if (newVal == null)
249  return false;
250  if (!userRights.HasFlag(requiredRight) && property.GetValue(current) != newVal)
251  return true;
252 
253  property.SetValue(current, newVal);
254  anySettingsModified = true;
255  return false;
256  }
257 
258  var oldProvider = current.Provider;
259 
260  if (CheckModified(x => x.ConnectionString, ChatBotRights.WriteConnectionString)
261  || CheckModified(x => x.Enabled, ChatBotRights.WriteEnabled)
262  || CheckModified(x => x.Name, ChatBotRights.WriteName)
263  || CheckModified(x => x.Provider, ChatBotRights.WriteProvider)
264  || (model.Channels != null && !userRights.HasFlag(ChatBotRights.WriteChannels)))
265  return Forbid();
266 
267  var hasChannels = model.Channels != null;
268  if (hasChannels || (model.Provider.HasValue && model.Provider != oldProvider))
269  {
270  DatabaseContext.ChatChannels.RemoveRange(current.Channels);
271  if (hasChannels)
272  {
273  var dbChannels = model.Channels.Select(x => ConvertApiChatChannel(x)).ToList();
274  DatabaseContext.ChatChannels.AddRange(dbChannels);
275  current.Channels = dbChannels;
276  }
277  else
278  current.Channels.Clear();
279  }
280 
281  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
282 
284 
285  if (anySettingsModified)
286  await chat.ChangeSettings(current, cancellationToken).ConfigureAwait(false); // have to rebuild the thing first
287 
288  if (model.Channels != null || anySettingsModified)
289  await chat.ChangeChannels(current.Id, current.Channels, cancellationToken).ConfigureAwait(false);
290 
291  if (userRights.HasFlag(ChatBotRights.Read))
292  {
293  if (!userRights.HasFlag(ChatBotRights.ReadConnectionString))
294  current.ConnectionString = null;
295  return Json(current.ToApi());
296  }
297 
298  return Ok();
299  }
300  #pragma warning restore CA1506
301  }
302 }
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
- - +
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
IInstance GetInstance(Models.Instance metadata)
Get the IInstance associated with given metadata
- -
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
+
Routes to a server actions
Definition: Routes.cs:9
-
async Task< IActionResult > Delete(long id, CancellationToken cancellationToken)
Delete a Api.Models.ChatBot.
-
ChatController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, ILogger< ChatController > logger)
Construct a ChatController
-
IChat Chat
The IChat for the IInstance
Definition: IInstance.cs:37
-
async Task< IActionResult > List(CancellationToken cancellationToken)
List Api.Models.ChatBots.
+
async Task< IActionResult > Delete(long id, CancellationToken cancellationToken)
Delete a Api.Models.ChatBot.
+
ChatController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, ILogger< ChatController > logger)
Construct a ChatController
+ +
IChat Chat
The IChat for the IInstance
Definition: IInstance.cs:38
+
async Task< IActionResult > List(CancellationToken cancellationToken)
List Api.Models.ChatBots.
string Message
A human readable description of the error
Definition: ErrorMessage.cs:13
-
async Task< IActionResult > Update([FromBody] Api.Models.ChatBot model, CancellationToken cancellationToken)
Updates a chat bot model .
+
async Task< IActionResult > Update([FromBody] Api.Models.ChatBot model, CancellationToken cancellationToken)
Updates a chat bot model .
const string Chat
The Models.ChatBot controller
Definition: Routes.cs:69
-
ulong? DiscordChannelId
The Discord channel ID
Definition: ChatChannel.cs:18
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
@@ -101,17 +99,20 @@ $(function() {
Metadata about a server instance
Definition: Instance.cs:9
-
ApiController for managing Api.Models.ChatBots
+
ApiController for managing Api.Models.ChatBots
static Models.ChatChannel ConvertApiChatChannel(Api.Models.ChatChannel api)
Converts api to a ChatChannel
-
readonly IInstanceManager instanceManager
The IInstanceManager for the ChatController
+
readonly IInstanceManager instanceManager
The IInstanceManager for the ChatController
+
const string List
The postfix for list operations
Definition: Routes.cs:84
-
async Task< IActionResult > Create([FromBody] Api.Models.ChatBot model, CancellationToken cancellationToken)
Create a new chat bot model .
+
async Task< IActionResult > Create([FromBody] Api.Models.ChatBot model, CancellationToken cancellationToken)
Create a new chat bot model .
ChatProvider
Represents a chat service provider
Definition: ChatProvider.cs:6
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
-
async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Get a specific Api.Models.ChatBot.
+
async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Get a specific Api.Models.ChatBot.
+ +
diff --git a/_claims_injector_8cs_source.html b/_claims_injector_8cs_source.html index 075d0a134e..3962877bf8 100644 --- a/_claims_injector_8cs_source.html +++ b/_claims_injector_8cs_source.html @@ -71,28 +71,28 @@ $(function() {
ClaimsInjector.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Authentication.JwtBearer;
2 using Microsoft.AspNetCore.Http;
3 using System;
4 using System.Collections.Generic;
5 using System.Globalization;
6 using System.IdentityModel.Tokens.Jwt;
7 using System.Security.Claims;
8 using System.Threading;
9 using System.Threading.Tasks;
10 using Tgstation.Server.Api;
13 
15 {
18  {
23 
28 
35  {
36  this.databaseContext = databaseContext ?? throw new ArgumentNullException(nameof(databaseContext));
37  this.authenticationContextFactory = authenticationContextFactory ?? throw new ArgumentNullException(nameof(authenticationContextFactory));
38  }
39 
41  public async Task InjectClaimsIntoContext(TokenValidatedContext tokenValidatedContext, CancellationToken cancellationToken)
42  {
43  if (tokenValidatedContext == null)
44  throw new ArgumentNullException(nameof(tokenValidatedContext));
45 
46  // Find the user id in the token
47  var userIdClaim = tokenValidatedContext.Principal.FindFirst(JwtRegisteredClaimNames.Sub);
48  if (userIdClaim == default)
49  throw new InvalidOperationException("Missing required claim!");
50 
51  long userId;
52  try
53  {
54  userId = Int64.Parse(userIdClaim.Value, CultureInfo.InvariantCulture);
55  }
56  catch (Exception e)
57  {
58  throw new InvalidOperationException("Failed to parse user ID!", e);
59  }
60 
61  ApiHeaders apiHeaders;
62  try
63  {
64  apiHeaders = new ApiHeaders(tokenValidatedContext.HttpContext.Request.GetTypedHeaders());
65  }
66  catch (InvalidOperationException)
67  {
68  // we are not responsible for handling header validation issues
69  return;
70  }
71 
72  // This populates the CurrentAuthenticationContext field for use by us and subsequent controllers
73  await authenticationContextFactory.CreateAuthenticationContext(userId, apiHeaders.InstanceId, tokenValidatedContext.SecurityToken.ValidFrom, cancellationToken).ConfigureAwait(false);
74 
76 
77  var enumerator = Enum.GetValues(typeof(RightsType));
78  var claims = new List<Claim>();
79  foreach (RightsType I in enumerator)
80  {
81  // if there's no instance user, do a weird thing and add all the instance roles
82  // we need it so we can get to OnActionExecutionAsync where we can properly decide between BadRequest and Forbid
83  // if user is null that means they got the token with an expired password
84  var rightInt = authenticationContext.User == null || (RightsHelper.IsInstanceRight(I) && authenticationContext.InstanceUser == null) ? ~0U : authenticationContext.GetRight(I);
85  var rightEnum = RightsHelper.RightToType(I);
86  var right = (Enum)Enum.ToObject(rightEnum, rightInt);
87  foreach (Enum J in Enum.GetValues(rightEnum))
88  if (right.HasFlag(J))
89  claims.Add(new Claim(ClaimTypes.Role, RightsHelper.RoleName(I, J)));
90  }
91 
92  tokenValidatedContext.Principal.AddIdentity(new ClaimsIdentity(claims));
93  }
94  }
95 }
static bool IsInstanceRight(RightsType rightsType)
Check if a given rightsType is meant for an Models.Instance
- +Go to the documentation of this file.
1 using Microsoft.AspNetCore.Authentication.JwtBearer;
2 using Microsoft.AspNetCore.Http;
3 using System;
4 using System.Collections.Generic;
5 using System.Globalization;
6 using System.IdentityModel.Tokens.Jwt;
7 using System.Security.Claims;
8 using System.Threading;
9 using System.Threading.Tasks;
10 using Tgstation.Server.Api;
13 
15 {
18  {
23 
28 
35  {
36  this.databaseContext = databaseContext ?? throw new ArgumentNullException(nameof(databaseContext));
37  this.authenticationContextFactory = authenticationContextFactory ?? throw new ArgumentNullException(nameof(authenticationContextFactory));
38  }
39 
41  public async Task InjectClaimsIntoContext(TokenValidatedContext tokenValidatedContext, CancellationToken cancellationToken)
42  {
43  if (tokenValidatedContext == null)
44  throw new ArgumentNullException(nameof(tokenValidatedContext));
45 
46  // Find the user id in the token
47  var userIdClaim = tokenValidatedContext.Principal.FindFirst(JwtRegisteredClaimNames.Sub);
48  if (userIdClaim == default)
49  throw new InvalidOperationException("Missing required claim!");
50 
51  long userId;
52  try
53  {
54  userId = Int64.Parse(userIdClaim.Value, CultureInfo.InvariantCulture);
55  }
56  catch (Exception e)
57  {
58  throw new InvalidOperationException("Failed to parse user ID!", e);
59  }
60 
61  ApiHeaders apiHeaders;
62  try
63  {
64  apiHeaders = new ApiHeaders(tokenValidatedContext.HttpContext.Request.GetTypedHeaders());
65  }
66  catch (InvalidOperationException)
67  {
68  // we are not responsible for handling header validation issues
69  return;
70  }
71 
72  // This populates the CurrentAuthenticationContext field for use by us and subsequent controllers
73  await authenticationContextFactory.CreateAuthenticationContext(userId, apiHeaders.InstanceId, tokenValidatedContext.SecurityToken.ValidFrom, cancellationToken).ConfigureAwait(false);
74 
76 
77  var enumerator = Enum.GetValues(typeof(RightsType));
78  var claims = new List<Claim>();
79  foreach (RightsType I in enumerator)
80  {
81  // if there's no instance user, do a weird thing and add all the instance roles
82  // we need it so we can get to OnActionExecutionAsync where we can properly decide between BadRequest and Forbid
83  // if user is null that means they got the token with an expired password
84  var rightInt = authenticationContext.User == null || (RightsHelper.IsInstanceRight(I) && authenticationContext.InstanceUser == null) ? ~0U : authenticationContext.GetRight(I);
85  var rightEnum = RightsHelper.RightToType(I);
86  var right = (Enum)Enum.ToObject(rightEnum, rightInt);
87  foreach (Enum J in Enum.GetValues(rightEnum))
88  if (right.HasFlag(J))
89  claims.Add(new Claim(ClaimTypes.Role, RightsHelper.RoleName(I, J)));
90  }
91 
92  tokenValidatedContext.Principal.AddIdentity(new ClaimsIdentity(claims));
93  }
94  }
95 }
static bool IsInstanceRight(RightsType rightsType)
Check if a given rightsType is meant for an Models.Instance
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
-
Task CreateAuthenticationContext(long userId, long? instanceId, DateTimeOffset validAfter, CancellationToken cancellationToken)
Create an IAuthenticationContext to populate CurrentAuthenticationContext
-
async Task InjectClaimsIntoContext(TokenValidatedContext tokenValidatedContext, CancellationToken cancellationToken)
Setup the System.Security.Claims.Claims for a given tokenValidatedContext
+
async Task InjectClaimsIntoContext(TokenValidatedContext tokenValidatedContext, CancellationToken cancellationToken)
Setup the global::System.Security.Claims.Claims for a given tokenValidatedContext
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:17
ClaimsInjector(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory)
Construct a ClaimsInjector
+
readonly IAuthenticationContextFactory authenticationContextFactory
The IAuthenticationContextFactory for the ClaimsInjector
long? InstanceId
The Models.Instance.Id being accessed
Definition: ApiHeaders.cs:67
static Type RightToType(RightsType rightsType)
Map a given rightsType to its respective Enum Type
-
For injecting System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look for
+
For injecting global::System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look f...
readonly IDatabaseContext databaseContext
The IDatabaseContext for the ClaimsInjector
IAuthenticationContext CurrentAuthenticationContext
The IAuthenticationContext the IAuthenticationContextFactory created
+
static string RoleName(RightsType rightsType, Enum right)
Gets the role claim name used for a given rightsType and right
Definition: RightsHelper.cs:61
diff --git a/_comm_context_8cs_source.html b/_comm_context_8cs_source.html index 1cbf5b5e6b..ba276efaf3 100644 --- a/_comm_context_8cs_source.html +++ b/_comm_context_8cs_source.html @@ -71,7 +71,7 @@ $(function() {
CommContext.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Newtonsoft.Json;
3 using System;
4 using System.Collections.Generic;
5 using System.IO;
6 using System.Text;
7 using System.Threading;
8 using System.Threading.Tasks;
9 using Tgstation.Server.Host.IO;
10 
12 {
14  sealed class CommContext : ICommContext
15  {
20 
24  readonly ILogger<CommContext> logger;
25 
29  readonly FileSystemWatcher fileSystemWatcher;
30 
34  readonly CancellationTokenSource cancellationTokenSource;
35 
39  readonly CancellationToken cancellationToken;
40 
45 
49  bool disposed;
50 
58  public CommContext(IIOManager ioManager, ILogger<CommContext> logger, string directory, string filter)
59  {
60  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
61  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
62 
63  directory = ioManager.ResolvePath(directory) ?? throw new ArgumentNullException(nameof(directory));
64  if (filter == null)
65  throw new ArgumentNullException(nameof(filter));
66 
67  fileSystemWatcher = new FileSystemWatcher(directory, filter)
68  {
69  EnableRaisingEvents = true,
70  IncludeSubdirectories = false,
71  NotifyFilter = NotifyFilters.LastWrite
72  };
73 
74  fileSystemWatcher.Created += HandleWrite;
75  fileSystemWatcher.Changed += HandleWrite;
76 
77  cancellationTokenSource = new CancellationTokenSource();
79  disposed = false;
80  }
81 
83  public void Dispose()
84  {
85  if (disposed)
86  return;
87  disposed = true;
88  fileSystemWatcher.Dispose();
89  cancellationTokenSource.Cancel();
90  cancellationTokenSource.Dispose();
91  }
92 
98  async void HandleWrite(object sender, FileSystemEventArgs e) // this is what async void was made for
99  {
100  try
101  {
102  var fileBytes = await ioManager.ReadAllBytes(e.FullPath, cancellationToken).ConfigureAwait(false);
103  var file = Encoding.UTF8.GetString(fileBytes);
104 
105  logger.LogTrace("Read interop command json: {0}", file);
106 
107  CommCommand command;
108  try
109  {
110  command = new CommCommand
111  {
112  Parameters = JsonConvert.DeserializeObject<IReadOnlyDictionary<string, object>>(file),
113  RawJson = file
114  };
115  }
116  catch (JsonException ex)
117  {
118  // file not fully written yet
119  logger.LogDebug("Suppressing json convert exception for command file write: {0}", ex);
120  return;
121  }
122 
123  await (handler?.HandleInterop(command, cancellationToken) ?? Task.CompletedTask).ConfigureAwait(false);
124  }
125  catch (OperationCanceledException) { }
126  catch (Exception ex)
127  {
128  logger.LogDebug("Exception while trying to handle command json write: {0}", ex);
129  }
130  }
131 
134  {
135  if (this.handler != null)
136  throw new InvalidOperationException("RegisterHandler already called!");
137  this.handler = handler ?? throw new ArgumentNullException(nameof(handler));
138  }
139  }
140 }
readonly CancellationToken cancellationToken
The CancellationToken for the CommContext
Definition: CommContext.cs:39
+Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Newtonsoft.Json;
3 using System;
4 using System.Collections.Generic;
5 using System.IO;
6 using System.Text;
7 using System.Threading;
8 using System.Threading.Tasks;
9 using Tgstation.Server.Host.IO;
10 
12 {
14  sealed class CommContext : ICommContext
15  {
20 
24  readonly ILogger<CommContext> logger;
25 
29  readonly FileSystemWatcher fileSystemWatcher;
30 
34  readonly CancellationTokenSource cancellationTokenSource;
35 
39  readonly CancellationToken cancellationToken;
40 
45 
49  bool disposed;
50 
58  public CommContext(IIOManager ioManager, ILogger<CommContext> logger, string directory, string filter)
59  {
60  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
61  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
62 
63  directory = ioManager.ResolvePath(directory) ?? throw new ArgumentNullException(nameof(directory));
64  if (filter == null)
65  throw new ArgumentNullException(nameof(filter));
66 
67  fileSystemWatcher = new FileSystemWatcher(directory, filter)
68  {
69  EnableRaisingEvents = true,
70  IncludeSubdirectories = false,
71  NotifyFilter = NotifyFilters.LastWrite
72  };
73 
74  fileSystemWatcher.Created += HandleWrite;
75  fileSystemWatcher.Changed += HandleWrite;
76 
77  cancellationTokenSource = new CancellationTokenSource();
79  disposed = false;
80  }
81 
83  public void Dispose()
84  {
85  if (disposed)
86  return;
87  disposed = true;
88  fileSystemWatcher.Dispose();
89  cancellationTokenSource.Cancel();
90  cancellationTokenSource.Dispose();
91  }
92 
98  async void HandleWrite(object sender, FileSystemEventArgs e) // this is what async void was made for
99  {
100  try
101  {
102  var fileBytes = await ioManager.ReadAllBytes(e.FullPath, cancellationToken).ConfigureAwait(false);
103  var file = Encoding.UTF8.GetString(fileBytes);
104 
105  logger.LogTrace("Read interop command json: {0}", file);
106 
107  CommCommand command;
108  try
109  {
110  command = new CommCommand
111  {
112  Parameters = JsonConvert.DeserializeObject<IReadOnlyDictionary<string, object>>(file),
113  RawJson = file
114  };
115  }
116  catch (JsonException ex)
117  {
118  // file not fully written yet
119  logger.LogDebug("Suppressing json convert exception for command file write: {0}", ex);
120  return;
121  }
122 
123  await (handler?.HandleInterop(command, cancellationToken) ?? Task.CompletedTask).ConfigureAwait(false);
124  }
125  catch (OperationCanceledException) { }
126  catch (Exception ex)
127  {
128  logger.LogError("Exception while trying to handle command json write: {0}", ex);
129  }
130  }
131 
134  {
135  if (this.handler != null)
136  throw new InvalidOperationException("RegisterHandler already called!");
137  this.handler = handler ?? throw new ArgumentNullException(nameof(handler));
138  }
139  }
140 }
readonly CancellationToken cancellationToken
The CancellationToken for the CommContext
Definition: CommContext.cs:39
Represents a registration of an interop session
Definition: ICommContext.cs:8
readonly FileSystemWatcher fileSystemWatcher
The FileSystemWatcher for the CommContext
Definition: CommContext.cs:29
string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
diff --git a/_command_factory_8cs_source.html b/_command_factory_8cs_source.html index 925e2d7693..a3b5d2d1bf 100644 --- a/_command_factory_8cs_source.html +++ b/_command_factory_8cs_source.html @@ -71,35 +71,36 @@ $(function() {
CommandFactory.cs
-Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
7 
9 {
12  {
17 
22 
27 
32 
36  readonly Models.Instance instance;
37 
42 
52  {
53  this.application = application ?? throw new ArgumentNullException(nameof(application));
54  this.byondManager = byondManager ?? throw new ArgumentNullException(nameof(byondManager));
55  this.repositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager));
56  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
57  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
58  }
59 
65  {
66  if (this.watchdog != null)
67  throw new InvalidOperationException("SetWatchdog has already been called!");
68  this.watchdog = watchdog ?? throw new ArgumentNullException(nameof(watchdog));
69  }
70 
72  public IReadOnlyList<ICommand> GenerateCommands()
73  {
74  if (watchdog == null)
75  throw new InvalidOperationException("SetWatchdog has not been called!");
76  return new List<ICommand>
77  {
82  new KekCommand()
83  };
84  }
85  }
86 }
+Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
8 
10 {
13  {
18 
23 
28 
33 
37  readonly Models.Instance instance;
38 
43 
53  {
54  this.application = application ?? throw new ArgumentNullException(nameof(application));
55  this.byondManager = byondManager ?? throw new ArgumentNullException(nameof(byondManager));
56  this.repositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager));
57  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
58  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
59  }
60 
66  {
67  if (this.watchdog != null)
68  throw new InvalidOperationException("SetWatchdog has already been called!");
69  this.watchdog = watchdog ?? throw new ArgumentNullException(nameof(watchdog));
70  }
71 
73  public IReadOnlyList<ICommand> GenerateCommands()
74  {
75  if (watchdog == null)
76  throw new InvalidOperationException("SetWatchdog has not been called!");
77  return new List<ICommand>
78  {
83  new KekCommand()
84  };
85  }
86  }
87 }
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
-
readonly IByondManager byondManager
The IByondManager for the CommandFactory
-
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
-
readonly Models.Instance instance
The Models.Instance for the CommandFactory
+
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
+
readonly IByondManager byondManager
The IByondManager for the CommandFactory
+
readonly Models.Instance instance
The Models.Instance for the CommandFactory
ICommand to return the IApplication.VersionString
-
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the CommandFactory
+
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the CommandFactory
Command for reading the active Api.Models.TestMerges
-
IWatchdog watchdog
The IWatchdog for the CommandFactory
-
CommandFactory(IApplication application, IByondManager byondManager, IRepositoryManager repositoryManager, IDatabaseContextFactory databaseContextFactory, Models.Instance instance)
Construct a CommandFactory
-
IReadOnlyList< ICommand > GenerateCommands()
Generate builtin ICommands
+
IWatchdog watchdog
The IWatchdog for the CommandFactory
+
CommandFactory(IApplication application, IByondManager byondManager, IRepositoryManager repositoryManager, IDatabaseContextFactory databaseContextFactory, Models.Instance instance)
Construct a CommandFactory
+
IReadOnlyList< ICommand > GenerateCommands()
Generate builtin ICommands
For displaying Api.Models.Internal.RevisionInformation
For displaying the installed Byond version
Definition: ByondCommand.cs:14
-
void SetWatchdog(IWatchdog watchdog)
Set a watchdog for the CommandFactory
- -
readonly IApplication application
The IApplication for the CommandFactory
+
void SetWatchdog(IWatchdog watchdog)
Set a watchdog for the CommandFactory
+ +
readonly IApplication application
The IApplication for the CommandFactory
+ -
readonly IRepositoryManager repositoryManager
The IRepositoryManager for the CommandFactory
+
readonly IRepositoryManager repositoryManager
The IRepositoryManager for the CommandFactory
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
diff --git a/_components_2_watchdog_2_i_watchdog_factory_8cs_source.html b/_components_2_watchdog_2_i_watchdog_factory_8cs_source.html index 0d5e1512da..6eaf50b5c5 100644 --- a/_components_2_watchdog_2_i_watchdog_factory_8cs_source.html +++ b/_components_2_watchdog_2_i_watchdog_factory_8cs_source.html @@ -71,25 +71,27 @@ $(function() {
IWatchdogFactory.cs
-Go to the documentation of this file.
4 
6 {
10  interface IWatchdogFactory
11  {
23  IWatchdog CreateWatchdog(IChat chat, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IEventConsumer eventConsumer, ISessionControllerFactory sessionControllerFactory, Api.Models.Instance instance, DreamDaemonSettings settings);
24  }
25 }
- +Go to the documentation of this file.
4 using Tgstation.Server.Host.IO;
5 
7 {
11  interface IWatchdogFactory
12  {
26  IChat chat,
27  IDmbFactory dmbFactory,
28  IReattachInfoHandler reattachInfoHandler,
29  IEventConsumer eventConsumer,
30  ISessionControllerFactory sessionControllerFactory,
31  IIOManager ioManager,
32  Api.Models.Instance instance,
33  DreamDaemonSettings settings);
34  }
35 }
-
IWatchdog CreateWatchdog(IChat chat, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IEventConsumer eventConsumer, ISessionControllerFactory sessionControllerFactory, Api.Models.Instance instance, DreamDaemonSettings settings)
Creates a IWatchdog
+
Consumes EventTypes and takes the appropriate actions
For managing connected chat services
Definition: IChat.cs:13
- - +
IWatchdog CreateWatchdog(IChat chat, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IEventConsumer eventConsumer, ISessionControllerFactory sessionControllerFactory, IIOManager ioManager, Api.Models.Instance instance, DreamDaemonSettings settings)
Creates a IWatchdog
+ + - +
Interface for using filesystems
Definition: IIOManager.cs:11
+
Handles saving and loading WatchdogReattachInformation
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
+
-Go to the documentation of this file.
1 using System;
3 
5 {
10  {
14  public IDmbProvider Dmb { get; set; }
15 
19  public ReattachInformation() { }
20 
26  public ReattachInformation(Models.ReattachInformation copy, IDmbProvider dmb) : base(copy)
27  {
28  Dmb = dmb ?? throw new ArgumentNullException(nameof(dmb));
29  }
30  }
31 }
+Go to the documentation of this file.
1 using System;
4 
6 {
11  {
15  public IDmbProvider Dmb { get; set; }
16 
20  public ReattachInformation() { }
21 
27  public ReattachInformation(Models.ReattachInformation copy, IDmbProvider dmb) : base(copy)
28  {
29  Dmb = dmb ?? throw new ArgumentNullException(nameof(dmb));
30  }
31  }
32 }
+ -
IDmbProvider Dmb
The IDmbProvider used by DreamDaemon
-
ReattachInformation(Models.ReattachInformation copy, IDmbProvider dmb)
Construct a ReattachInformation from a given copy and dmb
+
IDmbProvider Dmb
The IDmbProvider used by DreamDaemon
+ +
ReattachInformation(Models.ReattachInformation copy, IDmbProvider dmb)
Construct a ReattachInformation from a given copy and dmb
-
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
+
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
-
Parameters necessary for duplicating a ISessionController session
+
Parameters necessary for duplicating a ISessionController session
- +
-Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Microsoft.Extensions.Logging;
3 using Microsoft.Extensions.Options;
4 using System;
10 
12 {
15  {
20 
24  readonly ILoggerFactory loggerFactory;
25 
30 
34  readonly IByondTopicSender byondTopicSender;
35 
40 
45 
50 
61  public WatchdogFactory(IServerControl serverControl, ILoggerFactory loggerFactory, IDatabaseContextFactory databaseContextFactory, IByondTopicSender byondTopicSender, IJobManager jobManager, IAsyncDelayer asyncDelayer, IOptions<GeneralConfiguration> generalConfigurationOptions)
62  {
63  this.serverControl = serverControl ?? throw new ArgumentNullException(nameof(serverControl));
64  this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
65  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
66  this.byondTopicSender = byondTopicSender ?? throw new ArgumentNullException(nameof(byondTopicSender));
67  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
68  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
69  generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
70  }
71 
73  public IWatchdog CreateWatchdog(IChat chat, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IEventConsumer eventConsumer, ISessionControllerFactory sessionControllerFactory, Api.Models.Instance instance, DreamDaemonSettings settings)
74  {
76  return new ExperimentalWatchdog(chat, sessionControllerFactory, dmbFactory, reattachInfoHandler, databaseContextFactory, byondTopicSender, eventConsumer, jobManager, serverControl, asyncDelayer, loggerFactory.CreateLogger<ExperimentalWatchdog>(), settings, instance, settings.AutoStart.Value);
77 
78  return new BasicWatchdog(chat, sessionControllerFactory, dmbFactory, reattachInfoHandler, databaseContextFactory, byondTopicSender, eventConsumer, jobManager, serverControl, asyncDelayer, loggerFactory.CreateLogger<BasicWatchdog>(), settings, instance, settings.AutoStart.Value);
79  }
80  }
81 }
Manages the runtime of Jobs
Definition: IJobManager.cs:12
+Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Microsoft.Extensions.Logging;
3 using Microsoft.Extensions.Options;
4 using System;
11 using Tgstation.Server.Host.IO;
13 
15 {
18  {
22  protected IServerControl ServerControl { get; }
23 
27  protected ILoggerFactory LoggerFactory { get; }
28 
33 
37  protected IByondTopicSender ByondTopicSender { get; }
38 
42  protected IJobManager JobManager { get; }
43 
47  protected IAsyncDelayer AsyncDelayer { get; }
48 
53 
64  public WatchdogFactory(IServerControl serverControl, ILoggerFactory loggerFactory, IDatabaseContextFactory databaseContextFactory, IByondTopicSender byondTopicSender, IJobManager jobManager, IAsyncDelayer asyncDelayer, IOptions<GeneralConfiguration> generalConfigurationOptions)
65  {
66  ServerControl = serverControl ?? throw new ArgumentNullException(nameof(serverControl));
67  LoggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
68  DatabaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
69  ByondTopicSender = byondTopicSender ?? throw new ArgumentNullException(nameof(byondTopicSender));
70  JobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
71  AsyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
72  GeneralConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
73  }
74 
77  IChat chat,
78  IDmbFactory dmbFactory,
79  IReattachInfoHandler reattachInfoHandler,
80  IEventConsumer eventConsumer,
81  ISessionControllerFactory sessionControllerFactory,
82  IIOManager ioManager,
83  Api.Models.Instance instance,
84  DreamDaemonSettings settings)
85  {
87  return new ExperimentalWatchdog(
88  chat,
89  sessionControllerFactory,
90  dmbFactory,
91  reattachInfoHandler,
94  eventConsumer,
95  JobManager,
98  LoggerFactory.CreateLogger<ExperimentalWatchdog>(),
99  settings,
100  instance,
101  settings.AutoStart.Value);
102 
103  return CreateNonExperimentalWatchdog(chat, dmbFactory, reattachInfoHandler, eventConsumer, sessionControllerFactory, ioManager, instance, settings);
104  }
105 
118  protected virtual IWatchdog CreateNonExperimentalWatchdog(
119  IChat chat,
120  IDmbFactory dmbFactory,
121  IReattachInfoHandler reattachInfoHandler,
122  IEventConsumer eventConsumer,
123  ISessionControllerFactory sessionControllerFactory,
124  IIOManager ioManager,
125  Api.Models.Instance instance,
126  DreamDaemonSettings settings)
127  => new BasicWatchdog(
128  chat,
129  sessionControllerFactory,
130  dmbFactory,
131  reattachInfoHandler,
134  eventConsumer,
135  JobManager,
137  AsyncDelayer,
138  LoggerFactory.CreateLogger<BasicWatchdog>(),
139  settings,
140  instance,
141  settings.AutoStart.Value);
142  }
143 }
ILoggerFactory LoggerFactory
The ILoggerFactory for the WatchdogFactory
-
readonly IByondTopicSender byondTopicSender
The IByondTopicSender for the WatchdogFactory
- +
Consumes EventTypes and takes the appropriate actions
-
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
-
readonly IJobManager jobManager
The IJobManager for the WatchdogFactory
-
readonly GeneralConfiguration generalConfiguration
The GeneralConfiguration for the WatchdogFactory
+
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
+ + -
IWatchdog CreateWatchdog(IChat chat, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IEventConsumer eventConsumer, ISessionControllerFactory sessionControllerFactory, Api.Models.Instance instance, DreamDaemonSettings settings)
Creates a IWatchdog
bool? AutoStart
If DreamDaemon starts when it's Instance starts
For managing connected chat services
Definition: IChat.cs:13
-
A IWatchdog that tries to manage 2 servers at once for maximum uptime.
-
readonly IServerControl serverControl
The IServerControl for the WatchdogFactory
+
A IWatchdog that tries to manage 2 servers at once for maximum uptime.
- - - - + +
virtual IWatchdog CreateNonExperimentalWatchdog(IChat chat, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IEventConsumer eventConsumer, ISessionControllerFactory sessionControllerFactory, IIOManager ioManager, Api.Models.Instance instance, DreamDaemonSettings settings)
Create a IWatchdog that isn't the ExperimentalWatchdog.
+ + +
bool UseExperimentalWatchdog
If the Components.Watchdog.ExperimentalWatchdog should be used.
-
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the WatchdogFactory
+ +
IServerControl ServerControl
The IServerControl for the WatchdogFactory
+
IWatchdog CreateWatchdog(IChat chat, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IEventConsumer eventConsumer, ISessionControllerFactory sessionControllerFactory, IIOManager ioManager, Api.Models.Instance instance, DreamDaemonSettings settings)
Creates a IWatchdog
+
Manages the runtime of Jobs
Definition: IJobManager.cs:13
-
WatchdogFactory(IServerControl serverControl, ILoggerFactory loggerFactory, IDatabaseContextFactory databaseContextFactory, IByondTopicSender byondTopicSender, IJobManager jobManager, IAsyncDelayer asyncDelayer, IOptions< GeneralConfiguration > generalConfigurationOptions)
Construct a WatchdogFactory
+ +
WatchdogFactory(IServerControl serverControl, ILoggerFactory loggerFactory, IDatabaseContextFactory databaseContextFactory, IByondTopicSender byondTopicSender, IJobManager jobManager, IAsyncDelayer asyncDelayer, IOptions< GeneralConfiguration > generalConfigurationOptions)
Construct a WatchdogFactory
-
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the WatchdogFactory
- -
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the WatchdogFactory
+
Interface for using filesystems
Definition: IIOManager.cs:11
+ +
IByondTopicSender ByondTopicSender
The IByondTopicSender for the WatchdogFactory
Handles saving and loading WatchdogReattachInformation
+
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
Represents a service that may take an updated Host assembly and run it, stopping the current assembly...
+
-Go to the documentation of this file.
1 using System;
2 using System.Globalization;
4 
6 {
11  {
15  public ReattachInformation Alpha { get; set; }
16 
20  public ReattachInformation Bravo { get; set; }
21 
26 
33  public WatchdogReattachInformation(Models.WatchdogReattachInformation copy, IDmbProvider dmbAlpha, IDmbProvider dmbBravo) : base(copy)
34  {
35  if (copy.Alpha != null)
36  Alpha = new ReattachInformation(copy.Alpha, dmbAlpha);
37  if (copy.Bravo != null)
38  Bravo = new ReattachInformation(copy.Bravo, dmbBravo);
39  }
40 
42  public override string ToString() => String.Format(CultureInfo.InvariantCulture, "Alpha: {0}, Bravo {1}", Alpha, Bravo);
43  }
44 }
+Go to the documentation of this file.
1 using System;
2 using System.Globalization;
5 
7 {
12  {
16  public ReattachInformation Alpha { get; set; }
17 
21  public ReattachInformation Bravo { get; set; }
22 
27 
34  public WatchdogReattachInformation(Models.WatchdogReattachInformation copy, IDmbProvider dmbAlpha, IDmbProvider dmbBravo) : base(copy)
35  {
36  if (copy.Alpha != null)
37  Alpha = new ReattachInformation(copy.Alpha, dmbAlpha);
38  if (copy.Bravo != null)
39  Bravo = new ReattachInformation(copy.Bravo, dmbBravo);
40  }
41 
43  public override string ToString() => String.Format(CultureInfo.InvariantCulture, "Alpha: {0}, Bravo {1}", Alpha, Bravo);
44  }
45 }
+ - -
ReattachInformation Alpha
ReattachInformation for the Alpha session
- + +
ReattachInformation Alpha
ReattachInformation for the Alpha session
+ -
WatchdogReattachInformation(Models.WatchdogReattachInformation copy, IDmbProvider dmbAlpha, IDmbProvider dmbBravo)
Construct a WatchdogReattachInformation from a given copy with a given dmbAlpha and dmbBravo
+
WatchdogReattachInformation(Models.WatchdogReattachInformation copy, IDmbProvider dmbAlpha, IDmbProvider dmbBravo)
Construct a WatchdogReattachInformation from a given copy with a given dmbAlpha and dmbBravo
+ -
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
-
ReattachInformation Bravo
ReattachInformation for the Bravo session
+
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
+
ReattachInformation Bravo
ReattachInformation for the Bravo session
-
Parameters necessary for duplicating a ISessionController session
+
Parameters necessary for duplicating a ISessionController session
diff --git a/_configuration_8cs_source.html b/_configuration_8cs_source.html index 5d114aa459..8b226531e7 100644 --- a/_configuration_8cs_source.html +++ b/_configuration_8cs_source.html @@ -71,74 +71,75 @@ $(function() {
Configuration.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using System;
3 using System.Collections.Generic;
4 using System.Globalization;
5 using System.IO;
6 using System.Linq;
7 using System.Security.Cryptography;
8 using System.Text;
9 using System.Threading;
10 using System.Threading.Tasks;
13 using Tgstation.Server.Host.IO;
15 
17 {
20  {
21  const string CodeModificationsSubdirectory = "CodeModifications";
22  const string EventScriptsSubdirectory = "EventScripts";
23  const string GameStaticFilesSubdirectory = "GameStaticFiles";
24 
28  const string StaticIgnoreFile = ".tgsignore";
29 
30  const string CodeModificationsHeadFile = "HeadInclude.dm";
31  const string CodeModificationsTailFile = "TailInclude.dm";
32 
33  static readonly IReadOnlyDictionary<EventType, string> EventTypeScriptFileNameMap = new Dictionary<EventType, string>
34  {
35  { EventType.CompileStart, "PreCompile" },
36  { EventType.CompileComplete, "PostCompile" },
37  { EventType.RepoPreSynchronize, "PreSynchronize" }
38  };
39 
44 
49 
54 
59 
64 
69 
73  readonly ILogger<Configuration> logger;
74 
78  readonly SemaphoreSlim semaphore;
79 
91  {
92  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
93  this.synchronousIOManager = synchronousIOManager ?? throw new ArgumentNullException(nameof(synchronousIOManager));
94  this.symlinkFactory = symlinkFactory ?? throw new ArgumentNullException(nameof(symlinkFactory));
95  this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor));
96  this.postWriteHandler = postWriteHandler ?? throw new ArgumentNullException(nameof(postWriteHandler));
97  this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
98  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
99 
100  semaphore = new SemaphoreSlim(1);
101  }
102 
104  public void Dispose() => semaphore.Dispose();
105 
111 
117  async Task EnsureDirectories(CancellationToken cancellationToken)
118  {
119  async Task ValidateStaticFolder()
120  {
121  await ioManager.CreateDirectory(GameStaticFilesSubdirectory, cancellationToken).ConfigureAwait(false);
122  var staticIgnorePath = StaticIgnorePath();
123  if(!await ioManager.FileExists(staticIgnorePath, cancellationToken).ConfigureAwait(false))
124  await ioManager.WriteAllBytes(staticIgnorePath, Array.Empty<byte>(), cancellationToken).ConfigureAwait(false);
125  }
126 
127  await Task.WhenAll(ioManager.CreateDirectory(CodeModificationsSubdirectory, cancellationToken), ioManager.CreateDirectory(EventScriptsSubdirectory, cancellationToken), ValidateStaticFolder()).ConfigureAwait(false);
128  }
129 
131  public async Task<ServerSideModifications> CopyDMFilesTo(string dmeFile, string destination, CancellationToken cancellationToken)
132  {
133  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
134  {
135  await EnsureDirectories(cancellationToken).ConfigureAwait(false);
136 
137  // just assume no other fs race conditions here
138  var dmeExistsTask = ioManager.FileExists(ioManager.ConcatPath(CodeModificationsSubdirectory, dmeFile), cancellationToken);
141  var copyTask = ioManager.CopyDirectory(CodeModificationsSubdirectory, destination, null, cancellationToken);
142 
143  await Task.WhenAll(dmeExistsTask, headFileExistsTask, tailFileExistsTask, copyTask).ConfigureAwait(false);
144 
145  if (!dmeExistsTask.Result && !headFileExistsTask.Result && !tailFileExistsTask.Result)
146  return null;
147 
148  if (dmeExistsTask.Result)
149  return new ServerSideModifications(null, null, true);
150 
151  if (!headFileExistsTask.Result && !tailFileExistsTask.Result)
152  return null;
153 
154  string IncludeLine(string filePath) => String.Format(CultureInfo.InvariantCulture, "#include \"{0}\"", filePath);
155 
156  return new ServerSideModifications(headFileExistsTask.Result ? IncludeLine(CodeModificationsHeadFile) : null, tailFileExistsTask.Result ? IncludeLine(CodeModificationsTailFile) : null, false);
157  }
158  }
159 
160  string ValidateConfigRelativePath(string configurationRelativePath)
161  {
162  var nullOrEmptyCheck = String.IsNullOrEmpty(configurationRelativePath);
163  if (nullOrEmptyCheck)
164  configurationRelativePath = ".";
165  if (configurationRelativePath[0] == Path.DirectorySeparatorChar || configurationRelativePath[0] == Path.AltDirectorySeparatorChar)
166  configurationRelativePath = '.' + configurationRelativePath;
167  var resolved = ioManager.ResolvePath(configurationRelativePath);
168  var local = !nullOrEmptyCheck ? ioManager.ResolvePath(".") : null;
169  if (!nullOrEmptyCheck && resolved.Length < local.Length) // .. fuccbois
170  throw new InvalidOperationException("Attempted to access file outside of configuration manager!");
171  return resolved;
172  }
173 
175  public async Task<IReadOnlyList<ConfigurationFile>> ListDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
176  {
177  await EnsureDirectories(cancellationToken).ConfigureAwait(false);
178  var path = ValidateConfigRelativePath(configurationRelativePath);
179 
180  if (configurationRelativePath == null)
181  configurationRelativePath = "/";
182 
183  List<ConfigurationFile> result = new List<ConfigurationFile>();
184 
185  void ListImpl()
186  {
187  var enumerator = synchronousIOManager.GetDirectories(path, cancellationToken);
188  try
189  {
190  result.AddRange(enumerator.Select(x => new ConfigurationFile
191  {
192  IsDirectory = true,
193  Path = ioManager.ConcatPath(configurationRelativePath, x),
194  }));
195  }
196  catch (IOException e)
197  {
198  logger.LogDebug("IOException while writing {0}: {1}", path, e);
199  result = null;
200  return;
201  }
202 
203  enumerator = synchronousIOManager.GetFiles(path, cancellationToken);
204  result.AddRange(enumerator.Select(x => new ConfigurationFile
205  {
206  IsDirectory = false,
207  Path = ioManager.ConcatPath(configurationRelativePath, x),
208  }));
209  }
210 
211  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
212  if (systemIdentity == null)
213  ListImpl();
214  else
215  await systemIdentity.RunImpersonated(ListImpl, cancellationToken).ConfigureAwait(false);
216 
217  return result;
218  }
219 
221  public async Task<ConfigurationFile> Read(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
222  {
223  await EnsureDirectories(cancellationToken).ConfigureAwait(false);
224  var path = ValidateConfigRelativePath(configurationRelativePath);
225 
226  ConfigurationFile result = null;
227 
228  void ReadImpl()
229  {
230  lock (this)
231  try
232  {
233  var content = synchronousIOManager.ReadFile(path);
234  string sha1String;
235 #pragma warning disable CA5350 // Do not use insecure cryptographic algorithm SHA1.
236  using (var sha1 = new SHA1Managed())
237 #pragma warning restore CA5350 // Do not use insecure cryptographic algorithm SHA1.
238  sha1String = String.Join(String.Empty, sha1.ComputeHash(content).Select(b => b.ToString("x2", CultureInfo.InvariantCulture)));
239  result = new ConfigurationFile
240  {
241  Content = content,
242  IsDirectory = false,
243  LastReadHash = sha1String,
244  AccessDenied = false,
245  Path = configurationRelativePath
246  };
247  }
248  catch (UnauthorizedAccessException)
249  {
250  // this happens on windows, dunno about linux
251  bool isDirectory;
252  try
253  {
254  isDirectory = synchronousIOManager.IsDirectory(path);
255  }
256  catch
257  {
258  isDirectory = false;
259  }
260 
261  result = new ConfigurationFile
262  {
263  Path = configurationRelativePath
264  };
265  if (!isDirectory)
266  result.AccessDenied = true;
267  else
268  result.IsDirectory = true;
269  }
270  }
271 
272  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
273  if (systemIdentity == null)
274  await Task.Factory.StartNew(ReadImpl, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
275  else
276  await systemIdentity.RunImpersonated(ReadImpl, cancellationToken).ConfigureAwait(false);
277 
278  return result;
279  }
280 
282  public async Task SymlinkStaticFilesTo(string destination, CancellationToken cancellationToken)
283  {
284  async Task<IReadOnlyList<string>> GetIgnoreFiles()
285  {
286  var ignoreFileBytes = await ioManager.ReadAllBytes(StaticIgnorePath(), cancellationToken).ConfigureAwait(false);
287  var ignoreFileText = Encoding.UTF8.GetString(ignoreFileBytes);
288 
289  var results = new List<string> { StaticIgnoreFile };
290 
291  // we don't want to lose trailing whitespace on linux
292  using (var reader = new StringReader(ignoreFileText))
293  {
294  cancellationToken.ThrowIfCancellationRequested();
295  var line = await reader.ReadLineAsync().ConfigureAwait(false);
296  if (!String.IsNullOrEmpty(line))
297  results.Add(line);
298  }
299 
300  return results;
301  }
302 
303  IReadOnlyList<string> ignoreFiles;
304 
305  async Task SymlinkBase(bool files)
306  {
307  Task<IReadOnlyList<string>> task;
308  if (files)
309  task = ioManager.GetFiles(GameStaticFilesSubdirectory, cancellationToken);
310  else
311  task = ioManager.GetDirectories(GameStaticFilesSubdirectory, cancellationToken);
312  var entries = await task.ConfigureAwait(false);
313 
314  await Task.WhenAll(entries.Select(async x =>
315  {
316  var fileName = ioManager.GetFileName(x);
317 
318  // need to normalize
319  bool ignored;
320  if (platformIdentifier.IsWindows)
321  ignored = ignoreFiles.Any(y => fileName.ToUpperInvariant() == y.ToUpperInvariant());
322  else
323  ignored = ignoreFiles.Any(y => fileName == y);
324 
325  if (ignored)
326  {
327  logger.LogTrace("Ignoring static file {0}...", fileName);
328  return;
329  }
330 
331  var destPath = ioManager.ConcatPath(destination, fileName);
332  logger.LogTrace("Symlinking {0} to {1}...", x, destPath);
333  var fileExistsTask = ioManager.FileExists(destPath, cancellationToken);
334  if (await ioManager.DirectoryExists(destPath, cancellationToken).ConfigureAwait(false))
335  await ioManager.DeleteDirectory(destPath, cancellationToken).ConfigureAwait(false);
336  var fileExists = await fileExistsTask.ConfigureAwait(false);
337  if (fileExists)
338  await ioManager.DeleteFile(destPath, cancellationToken).ConfigureAwait(false);
339  await symlinkFactory.CreateSymbolicLink(ioManager.ResolvePath(x), ioManager.ResolvePath(destPath), cancellationToken).ConfigureAwait(false);
340  })).ConfigureAwait(false);
341  }
342 
343  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
344  {
345  await EnsureDirectories(cancellationToken).ConfigureAwait(false);
346  ignoreFiles = await GetIgnoreFiles().ConfigureAwait(false);
347  await Task.WhenAll(SymlinkBase(true), SymlinkBase(false)).ConfigureAwait(false);
348  }
349  }
350 
352  public async Task<ConfigurationFile> Write(string configurationRelativePath, ISystemIdentity systemIdentity, byte[] data, string previousHash, CancellationToken cancellationToken)
353  {
354  await EnsureDirectories(cancellationToken).ConfigureAwait(false);
355  var path = ValidateConfigRelativePath(configurationRelativePath);
356 
357  ConfigurationFile result = null;
358 
359  void WriteImpl()
360  {
361  lock (this)
362  try
363  {
364  var fileHash = previousHash;
365  var success = synchronousIOManager.WriteFileChecked(path, data, ref fileHash, cancellationToken);
366  if (!success)
367  return;
368  if (data != null)
369  postWriteHandler.HandleWrite(path);
370  result = new ConfigurationFile
371  {
372  Content = data,
373  IsDirectory = false,
374  LastReadHash = fileHash,
375  AccessDenied = false,
376  Path = configurationRelativePath
377  };
378  }
379  catch (UnauthorizedAccessException)
380  {
381  // this happens on windows, dunno about linux
382  bool isDirectory;
383  try
384  {
385  isDirectory = synchronousIOManager.IsDirectory(path);
386  }
387  catch
388  {
389  isDirectory = false;
390  }
391 
392  result = new ConfigurationFile
393  {
394  Path = configurationRelativePath
395  };
396  if (!isDirectory)
397  result.AccessDenied = true;
398  else
399  result.IsDirectory = true;
400  }
401  }
402 
403  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
404  if (systemIdentity == null)
405  await Task.Factory.StartNew(WriteImpl, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
406  else
407  await systemIdentity.RunImpersonated(WriteImpl, cancellationToken).ConfigureAwait(false);
408 
409  return result;
410  }
411 
413  public async Task<bool> CreateDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
414  {
415  await EnsureDirectories(cancellationToken).ConfigureAwait(false);
416  var path = ValidateConfigRelativePath(configurationRelativePath);
417 
418  bool? result = null;
419  void DoCreate() => result = synchronousIOManager.CreateDirectory(path, cancellationToken);
420 
421  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
422  if (systemIdentity == null)
423  await Task.Factory.StartNew(DoCreate, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
424  else
425  await systemIdentity.RunImpersonated(DoCreate, cancellationToken).ConfigureAwait(false);
426 
427  return result.Value;
428  }
429 
431  public Task StartAsync(CancellationToken cancellationToken) => EnsureDirectories(cancellationToken);
432 
434  public Task StopAsync(CancellationToken cancellationToken) => EnsureDirectories(cancellationToken);
435 
437  public async Task<bool> HandleEvent(EventType eventType, IEnumerable<string> parameters, CancellationToken cancellationToken)
438  {
439  await EnsureDirectories(cancellationToken).ConfigureAwait(false);
440 
441  if (!EventTypeScriptFileNameMap.TryGetValue(eventType, out var scriptName))
442  return true;
443 
444  // always execute in serial
445  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
446  {
447  var files = await ioManager.GetFilesWithExtension(EventScriptsSubdirectory, platformIdentifier.ScriptFileExtension, cancellationToken).ConfigureAwait(false);
448  var resolvedScriptsDir = ioManager.ResolvePath(EventScriptsSubdirectory);
449 
450  foreach (var I in files.Select(x => ioManager.GetFileName(x)).Where(x => x.StartsWith(scriptName, StringComparison.Ordinal)))
451  using (var script = processExecutor.LaunchProcess(ioManager.ConcatPath(resolvedScriptsDir, I), resolvedScriptsDir, String.Join(' ', parameters), noShellExecute: true))
452  using (cancellationToken.Register(() => script.Terminate()))
453  {
454  var exitCode = await script.Lifetime.ConfigureAwait(false);
455  cancellationToken.ThrowIfCancellationRequested();
456  if (exitCode != 0)
457  return false;
458  }
459  }
460 
461  return true;
462  }
463 
465  public async Task<bool> DeleteDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
466  {
467  await EnsureDirectories(cancellationToken).ConfigureAwait(false);
468  var path = ValidateConfigRelativePath(configurationRelativePath);
469 
470  var result = false;
471  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
472  {
473  void CheckDeleteImpl() => result = synchronousIOManager.DeleteDirectory(path);
474 
475  if (systemIdentity != null)
476  await systemIdentity.RunImpersonated(CheckDeleteImpl, cancellationToken).ConfigureAwait(false);
477  else
478  CheckDeleteImpl();
479  }
480 
481  return result;
482  }
483  }
484 }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
+Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using System;
3 using System.Collections.Generic;
4 using System.Globalization;
5 using System.IO;
6 using System.Linq;
7 using System.Security.Cryptography;
8 using System.Text;
9 using System.Threading;
10 using System.Threading.Tasks;
13 using Tgstation.Server.Host.IO;
16 
18 {
21  {
22  const string CodeModificationsSubdirectory = "CodeModifications";
23  const string EventScriptsSubdirectory = "EventScripts";
24  const string GameStaticFilesSubdirectory = "GameStaticFiles";
25 
29  const string StaticIgnoreFile = ".tgsignore";
30 
31  const string CodeModificationsHeadFile = "HeadInclude.dm";
32  const string CodeModificationsTailFile = "TailInclude.dm";
33 
34  static readonly IReadOnlyDictionary<EventType, string> EventTypeScriptFileNameMap = new Dictionary<EventType, string>
35  {
36  { EventType.CompileStart, "PreCompile" },
37  { EventType.CompileComplete, "PostCompile" },
38  { EventType.RepoPreSynchronize, "PreSynchronize" }
39  };
40 
45 
50 
55 
60 
65 
70 
74  readonly ILogger<Configuration> logger;
75 
79  readonly SemaphoreSlim semaphore;
80 
91  public Configuration(
98  ILogger<Configuration> logger)
99  {
100  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
101  this.synchronousIOManager = synchronousIOManager ?? throw new ArgumentNullException(nameof(synchronousIOManager));
102  this.symlinkFactory = symlinkFactory ?? throw new ArgumentNullException(nameof(symlinkFactory));
103  this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor));
104  this.postWriteHandler = postWriteHandler ?? throw new ArgumentNullException(nameof(postWriteHandler));
105  this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
106  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
107 
108  semaphore = new SemaphoreSlim(1);
109  }
110 
112  public void Dispose() => semaphore.Dispose();
113 
119 
125  async Task EnsureDirectories(CancellationToken cancellationToken)
126  {
127  async Task ValidateStaticFolder()
128  {
129  await ioManager.CreateDirectory(GameStaticFilesSubdirectory, cancellationToken).ConfigureAwait(false);
130  var staticIgnorePath = StaticIgnorePath();
131  if(!await ioManager.FileExists(staticIgnorePath, cancellationToken).ConfigureAwait(false))
132  await ioManager.WriteAllBytes(staticIgnorePath, Array.Empty<byte>(), cancellationToken).ConfigureAwait(false);
133  }
134 
135  await Task.WhenAll(ioManager.CreateDirectory(CodeModificationsSubdirectory, cancellationToken), ioManager.CreateDirectory(EventScriptsSubdirectory, cancellationToken), ValidateStaticFolder()).ConfigureAwait(false);
136  }
137 
139  public async Task<ServerSideModifications> CopyDMFilesTo(string dmeFile, string destination, CancellationToken cancellationToken)
140  {
141  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
142  {
143  await EnsureDirectories(cancellationToken).ConfigureAwait(false);
144 
145  // just assume no other fs race conditions here
146  var dmeExistsTask = ioManager.FileExists(ioManager.ConcatPath(CodeModificationsSubdirectory, dmeFile), cancellationToken);
149  var copyTask = ioManager.CopyDirectory(CodeModificationsSubdirectory, destination, null, cancellationToken);
150 
151  await Task.WhenAll(dmeExistsTask, headFileExistsTask, tailFileExistsTask, copyTask).ConfigureAwait(false);
152 
153  if (!dmeExistsTask.Result && !headFileExistsTask.Result && !tailFileExistsTask.Result)
154  return null;
155 
156  if (dmeExistsTask.Result)
157  return new ServerSideModifications(null, null, true);
158 
159  if (!headFileExistsTask.Result && !tailFileExistsTask.Result)
160  return null;
161 
162  string IncludeLine(string filePath) => String.Format(CultureInfo.InvariantCulture, "#include \"{0}\"", filePath);
163 
164  return new ServerSideModifications(headFileExistsTask.Result ? IncludeLine(CodeModificationsHeadFile) : null, tailFileExistsTask.Result ? IncludeLine(CodeModificationsTailFile) : null, false);
165  }
166  }
167 
168  string ValidateConfigRelativePath(string configurationRelativePath)
169  {
170  var nullOrEmptyCheck = String.IsNullOrEmpty(configurationRelativePath);
171  if (nullOrEmptyCheck)
172  configurationRelativePath = ".";
173  if (configurationRelativePath[0] == Path.DirectorySeparatorChar || configurationRelativePath[0] == Path.AltDirectorySeparatorChar)
174  configurationRelativePath = '.' + configurationRelativePath;
175  var resolved = ioManager.ResolvePath(configurationRelativePath);
176  var local = !nullOrEmptyCheck ? ioManager.ResolvePath(".") : null;
177  if (!nullOrEmptyCheck && resolved.Length < local.Length) // .. fuccbois
178  throw new InvalidOperationException("Attempted to access file outside of configuration manager!");
179  return resolved;
180  }
181 
183  public async Task<IReadOnlyList<ConfigurationFile>> ListDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
184  {
185  await EnsureDirectories(cancellationToken).ConfigureAwait(false);
186  var path = ValidateConfigRelativePath(configurationRelativePath);
187 
188  if (configurationRelativePath == null)
189  configurationRelativePath = "/";
190 
191  List<ConfigurationFile> result = new List<ConfigurationFile>();
192 
193  void ListImpl()
194  {
195  var enumerator = synchronousIOManager.GetDirectories(path, cancellationToken);
196  try
197  {
198  result.AddRange(enumerator.Select(x => new ConfigurationFile
199  {
200  IsDirectory = true,
201  Path = ioManager.ConcatPath(configurationRelativePath, x),
202  }));
203  }
204  catch (IOException e)
205  {
206  logger.LogDebug("IOException while writing {0}: {1}", path, e);
207  result = null;
208  return;
209  }
210 
211  enumerator = synchronousIOManager.GetFiles(path, cancellationToken);
212  result.AddRange(enumerator.Select(x => new ConfigurationFile
213  {
214  IsDirectory = false,
215  Path = ioManager.ConcatPath(configurationRelativePath, x),
216  }));
217  }
218 
219  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
220  if (systemIdentity == null)
221  ListImpl();
222  else
223  await systemIdentity.RunImpersonated(ListImpl, cancellationToken).ConfigureAwait(false);
224 
225  return result;
226  }
227 
229  public async Task<ConfigurationFile> Read(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
230  {
231  await EnsureDirectories(cancellationToken).ConfigureAwait(false);
232  var path = ValidateConfigRelativePath(configurationRelativePath);
233 
234  ConfigurationFile result = null;
235 
236  void ReadImpl()
237  {
238  lock (this)
239  try
240  {
241  var content = synchronousIOManager.ReadFile(path);
242  string sha1String;
243 #pragma warning disable CA5350 // Do not use insecure cryptographic algorithm SHA1.
244  using (var sha1 = new SHA1Managed())
245 #pragma warning restore CA5350 // Do not use insecure cryptographic algorithm SHA1.
246  sha1String = String.Join(String.Empty, sha1.ComputeHash(content).Select(b => b.ToString("x2", CultureInfo.InvariantCulture)));
247  result = new ConfigurationFile
248  {
249  Content = content,
250  IsDirectory = false,
251  LastReadHash = sha1String,
252  AccessDenied = false,
253  Path = configurationRelativePath
254  };
255  }
256  catch (UnauthorizedAccessException)
257  {
258  // this happens on windows, dunno about linux
259  bool isDirectory;
260  try
261  {
262  isDirectory = synchronousIOManager.IsDirectory(path);
263  }
264  catch
265  {
266  isDirectory = false;
267  }
268 
269  result = new ConfigurationFile
270  {
271  Path = configurationRelativePath
272  };
273  if (!isDirectory)
274  result.AccessDenied = true;
275  else
276  result.IsDirectory = true;
277  }
278  }
279 
280  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
281  if (systemIdentity == null)
282  await Task.Factory.StartNew(ReadImpl, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
283  else
284  await systemIdentity.RunImpersonated(ReadImpl, cancellationToken).ConfigureAwait(false);
285 
286  return result;
287  }
288 
290  public async Task SymlinkStaticFilesTo(string destination, CancellationToken cancellationToken)
291  {
292  async Task<IReadOnlyList<string>> GetIgnoreFiles()
293  {
294  var ignoreFileBytes = await ioManager.ReadAllBytes(StaticIgnorePath(), cancellationToken).ConfigureAwait(false);
295  var ignoreFileText = Encoding.UTF8.GetString(ignoreFileBytes);
296 
297  var results = new List<string> { StaticIgnoreFile };
298 
299  // we don't want to lose trailing whitespace on linux
300  using (var reader = new StringReader(ignoreFileText))
301  {
302  cancellationToken.ThrowIfCancellationRequested();
303  var line = await reader.ReadLineAsync().ConfigureAwait(false);
304  if (!String.IsNullOrEmpty(line))
305  results.Add(line);
306  }
307 
308  return results;
309  }
310 
311  IReadOnlyList<string> ignoreFiles;
312 
313  async Task SymlinkBase(bool files)
314  {
315  Task<IReadOnlyList<string>> task;
316  if (files)
317  task = ioManager.GetFiles(GameStaticFilesSubdirectory, cancellationToken);
318  else
319  task = ioManager.GetDirectories(GameStaticFilesSubdirectory, cancellationToken);
320  var entries = await task.ConfigureAwait(false);
321 
322  await Task.WhenAll(entries.Select(async x =>
323  {
324  var fileName = ioManager.GetFileName(x);
325 
326  // need to normalize
327  bool ignored;
328  if (platformIdentifier.IsWindows)
329  ignored = ignoreFiles.Any(y => fileName.ToUpperInvariant() == y.ToUpperInvariant());
330  else
331  ignored = ignoreFiles.Any(y => fileName == y);
332 
333  if (ignored)
334  {
335  logger.LogTrace("Ignoring static file {0}...", fileName);
336  return;
337  }
338 
339  var destPath = ioManager.ConcatPath(destination, fileName);
340  logger.LogTrace("Symlinking {0} to {1}...", x, destPath);
341  var fileExistsTask = ioManager.FileExists(destPath, cancellationToken);
342  if (await ioManager.DirectoryExists(destPath, cancellationToken).ConfigureAwait(false))
343  await ioManager.DeleteDirectory(destPath, cancellationToken).ConfigureAwait(false);
344  var fileExists = await fileExistsTask.ConfigureAwait(false);
345  if (fileExists)
346  await ioManager.DeleteFile(destPath, cancellationToken).ConfigureAwait(false);
347  await symlinkFactory.CreateSymbolicLink(ioManager.ResolvePath(x), ioManager.ResolvePath(destPath), cancellationToken).ConfigureAwait(false);
348  })).ConfigureAwait(false);
349  }
350 
351  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
352  {
353  await EnsureDirectories(cancellationToken).ConfigureAwait(false);
354  ignoreFiles = await GetIgnoreFiles().ConfigureAwait(false);
355  await Task.WhenAll(SymlinkBase(true), SymlinkBase(false)).ConfigureAwait(false);
356  }
357  }
358 
360  public async Task<ConfigurationFile> Write(string configurationRelativePath, ISystemIdentity systemIdentity, byte[] data, string previousHash, CancellationToken cancellationToken)
361  {
362  await EnsureDirectories(cancellationToken).ConfigureAwait(false);
363  var path = ValidateConfigRelativePath(configurationRelativePath);
364 
365  ConfigurationFile result = null;
366 
367  void WriteImpl()
368  {
369  lock (this)
370  try
371  {
372  var fileHash = previousHash;
373  var success = synchronousIOManager.WriteFileChecked(path, data, ref fileHash, cancellationToken);
374  if (!success)
375  return;
376  if (data != null)
377  postWriteHandler.HandleWrite(path);
378  result = new ConfigurationFile
379  {
380  Content = data,
381  IsDirectory = false,
382  LastReadHash = fileHash,
383  AccessDenied = false,
384  Path = configurationRelativePath
385  };
386  }
387  catch (UnauthorizedAccessException)
388  {
389  // this happens on windows, dunno about linux
390  bool isDirectory;
391  try
392  {
393  isDirectory = synchronousIOManager.IsDirectory(path);
394  }
395  catch
396  {
397  isDirectory = false;
398  }
399 
400  result = new ConfigurationFile
401  {
402  Path = configurationRelativePath
403  };
404  if (!isDirectory)
405  result.AccessDenied = true;
406  else
407  result.IsDirectory = true;
408  }
409  }
410 
411  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
412  if (systemIdentity == null)
413  await Task.Factory.StartNew(WriteImpl, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
414  else
415  await systemIdentity.RunImpersonated(WriteImpl, cancellationToken).ConfigureAwait(false);
416 
417  return result;
418  }
419 
421  public async Task<bool> CreateDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
422  {
423  await EnsureDirectories(cancellationToken).ConfigureAwait(false);
424  var path = ValidateConfigRelativePath(configurationRelativePath);
425 
426  bool? result = null;
427  void DoCreate() => result = synchronousIOManager.CreateDirectory(path, cancellationToken);
428 
429  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
430  if (systemIdentity == null)
431  await Task.Factory.StartNew(DoCreate, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
432  else
433  await systemIdentity.RunImpersonated(DoCreate, cancellationToken).ConfigureAwait(false);
434 
435  return result.Value;
436  }
437 
439  public Task StartAsync(CancellationToken cancellationToken) => EnsureDirectories(cancellationToken);
440 
442  public Task StopAsync(CancellationToken cancellationToken) => EnsureDirectories(cancellationToken);
443 
445  public async Task<bool> HandleEvent(EventType eventType, IEnumerable<string> parameters, CancellationToken cancellationToken)
446  {
447  await EnsureDirectories(cancellationToken).ConfigureAwait(false);
448 
449  if (!EventTypeScriptFileNameMap.TryGetValue(eventType, out var scriptName))
450  return true;
451 
452  // always execute in serial
453  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
454  {
455  var files = await ioManager.GetFilesWithExtension(EventScriptsSubdirectory, platformIdentifier.ScriptFileExtension, cancellationToken).ConfigureAwait(false);
456  var resolvedScriptsDir = ioManager.ResolvePath(EventScriptsSubdirectory);
457 
458  foreach (var I in files.Select(x => ioManager.GetFileName(x)).Where(x => x.StartsWith(scriptName, StringComparison.Ordinal)))
459  using (var script = processExecutor.LaunchProcess(ioManager.ConcatPath(resolvedScriptsDir, I), resolvedScriptsDir, String.Join(' ', parameters), noShellExecute: true))
460  using (cancellationToken.Register(() => script.Terminate()))
461  {
462  var exitCode = await script.Lifetime.ConfigureAwait(false);
463  cancellationToken.ThrowIfCancellationRequested();
464  if (exitCode != 0)
465  return false;
466  }
467  }
468 
469  return true;
470  }
471 
473  public async Task<bool> DeleteDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
474  {
475  await EnsureDirectories(cancellationToken).ConfigureAwait(false);
476  var path = ValidateConfigRelativePath(configurationRelativePath);
477 
478  var result = false;
479  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
480  {
481  void CheckDeleteImpl() => result = synchronousIOManager.DeleteDirectory(path);
482 
483  if (systemIdentity != null)
484  await systemIdentity.RunImpersonated(CheckDeleteImpl, cancellationToken).ConfigureAwait(false);
485  else
486  CheckDeleteImpl();
487  }
488 
489  return result;
490  }
491  }
492 }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory, removes and does not enter any symlinks encounterd.
string StaticIgnorePath()
Get the proper path to StaticIgnoreFile
- -
readonly ISynchronousIOManager synchronousIOManager
The ISynchronousIOManager for Configuration
- -
async Task< bool > DeleteDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
Attempt to delete an empty directory at configurationRelativePath
+ +
readonly ISynchronousIOManager synchronousIOManager
The ISynchronousIOManager for Configuration
+ + +
async Task< bool > DeleteDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
Attempt to delete an empty directory at configurationRelativePath
Handles changing file modes/permissions after writing
-
async Task< ServerSideModifications > CopyDMFilesTo(string dmeFile, string destination, CancellationToken cancellationToken)
Copies all files in the CodeModifications directory to destination
-
async Task EnsureDirectories(CancellationToken cancellationToken)
Ensures standard configuration directories exist
+
async Task< ServerSideModifications > CopyDMFilesTo(string dmeFile, string destination, CancellationToken cancellationToken)
Copies all files in the CodeModifications directory to destination
+
async Task EnsureDirectories(CancellationToken cancellationToken)
Ensures standard configuration directories exist
Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content
-
async Task< bool > CreateDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
Create an empty directory at configurationRelativePath
-
async Task< ConfigurationFile > Write(string configurationRelativePath, ISystemIdentity systemIdentity, byte[] data, string previousHash, CancellationToken cancellationToken)
Writes to a given configurationRelativePath
+
async Task< bool > CreateDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
Create an empty directory at configurationRelativePath
+
async Task< ConfigurationFile > Write(string configurationRelativePath, ISystemIdentity systemIdentity, byte[] data, string previousHash, CancellationToken cancellationToken)
Writes to a given configurationRelativePath
-
Represents a user on the current System.Runtime.InteropServices.OSPlatform
+
Represents a user on the current global::System.Runtime.InteropServices.OSPlatform
Task CopyDirectory(string src, string dest, IEnumerable< string > ignore, CancellationToken cancellationToken)
Copies a directory from src to dest
Task< IReadOnlyList< string > > GetDirectories(string path, CancellationToken cancellationToken)
Returns directory names in a given path
- -
Configuration(IIOManager ioManager, ISynchronousIOManager synchronousIOManager, ISymlinkFactory symlinkFactory, IProcessExecutor processExecutor, IPostWriteHandler postWriteHandler, IPlatformIdentifier platformIdentifier, ILogger< Configuration > logger)
Construct Configuration
-
async Task< IReadOnlyList< ConfigurationFile > > ListDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
Get ConfigurationFile for all items in a given configurationRelativePath
+
Configuration(IIOManager ioManager, ISynchronousIOManager synchronousIOManager, ISymlinkFactory symlinkFactory, IProcessExecutor processExecutor, IPostWriteHandler postWriteHandler, IPlatformIdentifier platformIdentifier, ILogger< Configuration > logger)
Construct Configuration
+
async Task< IReadOnlyList< ConfigurationFile > > ListDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
Get ConfigurationFile for all items in a given configurationRelativePath
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
-
static readonly IReadOnlyDictionary< EventType, string > EventTypeScriptFileNameMap
+
static readonly IReadOnlyDictionary< EventType, string > EventTypeScriptFileNameMap
bool? IsDirectory
If Path represents a directory
-
readonly IProcessExecutor processExecutor
The IProcessExecutor for Configuration
+
readonly IProcessExecutor processExecutor
The IProcessExecutor for Configuration
Task CreateDirectory(string path, CancellationToken cancellationToken)
Create a directory at path
string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
-
readonly ILogger< Configuration > logger
The ILogger for Configuration
-
async Task< bool > HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
Handle a given eventType
+
readonly ILogger< Configuration > logger
The ILogger for Configuration
+
async Task< bool > HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
Handle a given eventType
byte [] ReadFile(string path)
Read the bytes of a file at a given path
-
const string StaticIgnoreFile
Name of the ignore file in GameStaticFilesSubdirectory
+
const string StaticIgnoreFile
Name of the ignore file in GameStaticFilesSubdirectory
-
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for Configuration
+
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for Configuration
For accessing the disk in a synchronous manner
Task< bool > FileExists(string path, CancellationToken cancellationToken)
Check that the file at path exists
-
string ValidateConfigRelativePath(string configurationRelativePath)
-
readonly ISymlinkFactory symlinkFactory
The ISymlinkFactory for Configuration
+
string ValidateConfigRelativePath(string configurationRelativePath)
+
readonly ISymlinkFactory symlinkFactory
The ISymlinkFactory for Configuration
Task RunImpersonated(Action action, CancellationToken cancellationToken)
Runs a given action in the context of the ISystemIdentity
- -
readonly IIOManager ioManager
The IIOManager for Configuration
-
async Task< ConfigurationFile > Read(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
Reads a given configurationRelativePath
+ +
readonly IIOManager ioManager
The IIOManager for Configuration
+
async Task< ConfigurationFile > Read(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
Reads a given configurationRelativePath
IEnumerable< string > GetDirectories(string path, CancellationToken cancellationToken)
Enumerate directories in a given path
-
readonly SemaphoreSlim semaphore
The SemaphoreSlim for Configuration
+
readonly SemaphoreSlim semaphore
The SemaphoreSlim for Configuration
Represents a game configuration file. Create and delete actions uncerimonuously overwrite/delete file...
-
readonly IPostWriteHandler postWriteHandler
The IPostWriteHandler for Configuration
+
readonly IPostWriteHandler postWriteHandler
The IPostWriteHandler for Configuration
IEnumerable< string > GetFiles(string path, CancellationToken cancellationToken)
Enumerate files in a given path
bool IsDirectory(string path)
Checks if a given path is a directory
- +
Task< IReadOnlyList< string > > GetFiles(string path, CancellationToken cancellationToken)
Returns file names in a given path
Interface for using filesystems
Definition: IIOManager.cs:11
- -
async Task SymlinkStaticFilesTo(string destination, CancellationToken cancellationToken)
Symlinks all directories in the GameData directory to destination
-
For identifying the current platform
+ +
async Task SymlinkStaticFilesTo(string destination, CancellationToken cancellationToken)
Symlinks all directories in the GameData directory to destination
bool? AccessDenied
If access to the ConfigurationFile file was denied for the operation
Task< byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
Returns all the contents of a file at path as a byte array
Task DeleteFile(string path, CancellationToken cancellationToken)
Deletes a file at path
+
For identifying the current platform
Task< bool > DirectoryExists(string path, CancellationToken cancellationToken)
Check that the directory at path exists
static async Task< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore
- +
string ConcatPath(params string[] paths)
Combines an array of strings into a path
- + + diff --git a/_configuration_controller_8cs_source.html b/_configuration_controller_8cs_source.html index 34c1e57f24..33fa448b12 100644 --- a/_configuration_controller_8cs_source.html +++ b/_configuration_controller_8cs_source.html @@ -71,49 +71,50 @@ $(function() {
ConfigurationController.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Collections.Generic;
5 using System.IO;
6 using System.Net;
7 using System.Threading;
8 using System.Threading.Tasks;
9 using Tgstation.Server.Api;
13 using Tgstation.Server.Host.IO;
16 
18 {
22  [Route(Routes.Configuration)]
23  public sealed class ConfigurationController : ApiController
24  {
29 
34 
43  public ConfigurationController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, IIOManager ioManager, ILogger<ConfigurationController> logger) : base(databaseContext, authenticationContextFactory, logger, true, true)
44  {
45  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
46  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
47  }
48 
55  bool ForbidDueToModeConflicts(string path, out ISystemIdentity systemIdentityToUse)
56  {
58  {
59  systemIdentityToUse = null;
60  return true;
61  }
62 
63  systemIdentityToUse = Instance.ConfigurationType == ConfigurationType.SystemIdentityWrite ? AuthenticationContext.SystemIdentity : null;
64  return false;
65  }
66 
76  [HttpPost]
77  [TgsAuthorize(ConfigurationRights.Write)]
78  [ProducesResponseType(typeof(ConfigurationFile), 200)]
79  [ProducesResponseType(typeof(ConfigurationFile), 201)]
80  [ProducesResponseType(501)]
81  public async Task<IActionResult> Update([FromBody] ConfigurationFile model, CancellationToken cancellationToken)
82  {
83  if (model == null)
84  throw new ArgumentNullException(nameof(model));
85  if (ForbidDueToModeConflicts(model.Path, out var systemIdentity))
86  return Forbid();
87 
89  try
90  {
91  var newFile = await config.Write(model.Path, systemIdentity, model.Content, model.LastReadHash, cancellationToken).ConfigureAwait(false);
92  if (newFile == null)
93  return Conflict(new ErrorMessage
94  {
95  Message = "This file has been updated since you last viewed it!"
96  });
97 
98  newFile.Content = null;
99 
100  return model.LastReadHash == null ? (IActionResult)StatusCode((int)HttpStatusCode.Created, newFile) : Json(newFile);
101  }
102  catch(IOException e)
103  {
104  Logger.LogInformation("IOException while updating file {0}: {1}", model.Path, e);
105  return Conflict(new ErrorMessage
106  {
107  Message = e.Message
108  });
109  }
110  catch (NotImplementedException)
111  {
112  return StatusCode((int)HttpStatusCode.NotImplemented);
113  }
114  }
115 
124  [HttpGet(Routes.File + "/{*filePath}")]
125  [TgsAuthorize(ConfigurationRights.Read)]
126  [ProducesResponseType(typeof(ConfigurationFile), 200)]
127  [ProducesResponseType(410)]
128  [ProducesResponseType(501)]
129  public async Task<IActionResult> File(string filePath, CancellationToken cancellationToken)
130  {
131  if (ForbidDueToModeConflicts(filePath, out var systemIdentity))
132  return Forbid();
133 
134  try
135  {
136  var result = await instanceManager.GetInstance(Instance).Configuration.Read(filePath, systemIdentity, cancellationToken).ConfigureAwait(false);
137  if (result == null)
138  return StatusCode((int)HttpStatusCode.Gone);
139 
140  return Json(result);
141  }
142  catch (IOException e)
143  {
144  Logger.LogInformation("IOException while reading file {0}: {1}", filePath, e);
145  return Conflict(new ErrorMessage
146  {
147  Message = e.Message
148  });
149  }
150  catch (NotImplementedException)
151  {
152  return StatusCode((int)HttpStatusCode.NotImplemented);
153  }
154  }
155 
164  [HttpGet(Routes.List + "/{*directoryPath}")]
165  [TgsAuthorize(ConfigurationRights.List)]
166  [ProducesResponseType(typeof(IReadOnlyList<ConfigurationFile>), 200)]
167  [ProducesResponseType(410)]
168  [ProducesResponseType(501)]
169  public async Task<IActionResult> Directory(string directoryPath, CancellationToken cancellationToken)
170  {
171  if (ForbidDueToModeConflicts(directoryPath, out var systemIdentity))
172  return Forbid();
173 
174  try
175  {
176  var result = await instanceManager.GetInstance(Instance).Configuration.ListDirectory(directoryPath, systemIdentity, cancellationToken).ConfigureAwait(false);
177  if (result == null)
178  return StatusCode((int)HttpStatusCode.Gone);
179 
180  return Json(result);
181  }
182  catch (NotImplementedException)
183  {
184  return StatusCode((int)HttpStatusCode.NotImplemented);
185  }
186  catch (UnauthorizedAccessException)
187  {
188  return Forbid();
189  }
190  }
191 
199  [HttpGet(Routes.List)]
200  [TgsAuthorize(ConfigurationRights.List)]
201  [ProducesResponseType(typeof(IReadOnlyList<ConfigurationFile>), 200)]
202  [ProducesResponseType(410)]
203  [ProducesResponseType(501)]
204  public Task<IActionResult> List(CancellationToken cancellationToken) => Directory(null, cancellationToken);
205 
215  [HttpPut]
216  [TgsAuthorize(ConfigurationRights.Write)]
217  [ProducesResponseType(typeof(ConfigurationFile), 200)]
218  [ProducesResponseType(typeof(ConfigurationFile), 201)]
219  [ProducesResponseType(501)]
220  public async Task<IActionResult> Create([FromBody] ConfigurationFile model, CancellationToken cancellationToken)
221  {
222  if (model == null)
223  throw new ArgumentNullException(nameof(model));
224 
225  if (ForbidDueToModeConflicts(model.Path, out var systemIdentity))
226  return Forbid();
227 
228  try
229  {
230  model.IsDirectory = true;
231  return await instanceManager.GetInstance(Instance).Configuration.CreateDirectory(model.Path, systemIdentity, cancellationToken).ConfigureAwait(false) ? (IActionResult)Json(model) : StatusCode((int)HttpStatusCode.Created, model);
232  }
233  catch (IOException e)
234  {
235  Logger.LogInformation("IOException while creating directory {0}: {1}", model.Path, e);
236  return Conflict(new ErrorMessage
237  {
238  Message = e.Message
239  });
240  }
241  catch (NotImplementedException)
242  {
243  return StatusCode((int)HttpStatusCode.NotImplemented);
244  }
245  catch (UnauthorizedAccessException)
246  {
247  return Forbid();
248  }
249  }
250 
259  [HttpDelete]
260  [TgsAuthorize(ConfigurationRights.Delete)]
261  [ProducesResponseType(200)]
262  [ProducesResponseType(501)]
263  public async Task<IActionResult> Delete([FromBody] ConfigurationFile directory, CancellationToken cancellationToken)
264  {
265  if (directory == null)
266  throw new ArgumentNullException(nameof(directory));
267 
268  if (ForbidDueToModeConflicts(directory.Path, out var systemIdentity))
269  return Forbid();
270 
271  try
272  {
273  return await instanceManager.GetInstance(Instance).Configuration.DeleteDirectory(directory.Path, systemIdentity, cancellationToken).ConfigureAwait(false) ? (IActionResult)Ok() : Conflict(new ErrorMessage
274  {
275  Message = "Directory not empty!"
276  });
277  }
278  catch (NotImplementedException)
279  {
280  return StatusCode((int)HttpStatusCode.NotImplemented);
281  }
282  catch (UnauthorizedAccessException)
283  {
284  return Forbid();
285  }
286  }
287  }
288 }
- +Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Collections.Generic;
5 using System.IO;
6 using System.Net;
7 using System.Threading;
8 using System.Threading.Tasks;
9 using Tgstation.Server.Api;
14 using Tgstation.Server.Host.IO;
17 
19 {
23  [Route(Routes.Configuration)]
24  public sealed class ConfigurationController : ApiController
25  {
30 
35 
44  public ConfigurationController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, IIOManager ioManager, ILogger<ConfigurationController> logger) : base(databaseContext, authenticationContextFactory, logger, true, true)
45  {
46  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
47  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
48  }
49 
56  bool ForbidDueToModeConflicts(string path, out ISystemIdentity systemIdentityToUse)
57  {
59  {
60  systemIdentityToUse = null;
61  return true;
62  }
63 
64  systemIdentityToUse = Instance.ConfigurationType == ConfigurationType.SystemIdentityWrite ? AuthenticationContext.SystemIdentity : null;
65  return false;
66  }
67 
77  [HttpPost]
78  [TgsAuthorize(ConfigurationRights.Write)]
79  [ProducesResponseType(typeof(ConfigurationFile), 200)]
80  [ProducesResponseType(typeof(ConfigurationFile), 201)]
81  [ProducesResponseType(501)]
82  public async Task<IActionResult> Update([FromBody] ConfigurationFile model, CancellationToken cancellationToken)
83  {
84  if (model == null)
85  throw new ArgumentNullException(nameof(model));
86  if (ForbidDueToModeConflicts(model.Path, out var systemIdentity))
87  return Forbid();
88 
90  try
91  {
92  var newFile = await config.Write(model.Path, systemIdentity, model.Content, model.LastReadHash, cancellationToken).ConfigureAwait(false);
93  if (newFile == null)
94  return Conflict(new ErrorMessage
95  {
96  Message = "This file has been updated since you last viewed it!"
97  });
98 
99  newFile.Content = null;
100 
101  return model.LastReadHash == null ? (IActionResult)StatusCode((int)HttpStatusCode.Created, newFile) : Json(newFile);
102  }
103  catch(IOException e)
104  {
105  Logger.LogInformation("IOException while updating file {0}: {1}", model.Path, e);
106  return Conflict(new ErrorMessage
107  {
108  Message = e.Message
109  });
110  }
111  catch (NotImplementedException)
112  {
113  return StatusCode((int)HttpStatusCode.NotImplemented);
114  }
115  }
116 
125  [HttpGet(Routes.File + "/{*filePath}")]
126  [TgsAuthorize(ConfigurationRights.Read)]
127  [ProducesResponseType(typeof(ConfigurationFile), 200)]
128  [ProducesResponseType(410)]
129  [ProducesResponseType(501)]
130  public async Task<IActionResult> File(string filePath, CancellationToken cancellationToken)
131  {
132  if (ForbidDueToModeConflicts(filePath, out var systemIdentity))
133  return Forbid();
134 
135  try
136  {
137  var result = await instanceManager.GetInstance(Instance).Configuration.Read(filePath, systemIdentity, cancellationToken).ConfigureAwait(false);
138  if (result == null)
139  return StatusCode((int)HttpStatusCode.Gone);
140 
141  return Json(result);
142  }
143  catch (IOException e)
144  {
145  Logger.LogInformation("IOException while reading file {0}: {1}", filePath, e);
146  return Conflict(new ErrorMessage
147  {
148  Message = e.Message
149  });
150  }
151  catch (NotImplementedException)
152  {
153  return StatusCode((int)HttpStatusCode.NotImplemented);
154  }
155  }
156 
165  [HttpGet(Routes.List + "/{*directoryPath}")]
166  [TgsAuthorize(ConfigurationRights.List)]
167  [ProducesResponseType(typeof(IReadOnlyList<ConfigurationFile>), 200)]
168  [ProducesResponseType(410)]
169  [ProducesResponseType(501)]
170  public async Task<IActionResult> Directory(string directoryPath, CancellationToken cancellationToken)
171  {
172  if (ForbidDueToModeConflicts(directoryPath, out var systemIdentity))
173  return Forbid();
174 
175  try
176  {
177  var result = await instanceManager.GetInstance(Instance).Configuration.ListDirectory(directoryPath, systemIdentity, cancellationToken).ConfigureAwait(false);
178  if (result == null)
179  return StatusCode((int)HttpStatusCode.Gone);
180 
181  return Json(result);
182  }
183  catch (NotImplementedException)
184  {
185  return StatusCode((int)HttpStatusCode.NotImplemented);
186  }
187  catch (UnauthorizedAccessException)
188  {
189  return Forbid();
190  }
191  }
192 
200  [HttpGet(Routes.List)]
201  [TgsAuthorize(ConfigurationRights.List)]
202  [ProducesResponseType(typeof(IReadOnlyList<ConfigurationFile>), 200)]
203  [ProducesResponseType(410)]
204  [ProducesResponseType(501)]
205  public Task<IActionResult> List(CancellationToken cancellationToken) => Directory(null, cancellationToken);
206 
216  [HttpPut]
217  [TgsAuthorize(ConfigurationRights.Write)]
218  [ProducesResponseType(typeof(ConfigurationFile), 200)]
219  [ProducesResponseType(typeof(ConfigurationFile), 201)]
220  [ProducesResponseType(501)]
221  public async Task<IActionResult> Create([FromBody] ConfigurationFile model, CancellationToken cancellationToken)
222  {
223  if (model == null)
224  throw new ArgumentNullException(nameof(model));
225 
226  if (ForbidDueToModeConflicts(model.Path, out var systemIdentity))
227  return Forbid();
228 
229  try
230  {
231  model.IsDirectory = true;
232  return await instanceManager.GetInstance(Instance).Configuration.CreateDirectory(model.Path, systemIdentity, cancellationToken).ConfigureAwait(false) ? (IActionResult)Json(model) : StatusCode((int)HttpStatusCode.Created, model);
233  }
234  catch (IOException e)
235  {
236  Logger.LogInformation("IOException while creating directory {0}: {1}", model.Path, e);
237  return Conflict(new ErrorMessage
238  {
239  Message = e.Message
240  });
241  }
242  catch (NotImplementedException)
243  {
244  return StatusCode((int)HttpStatusCode.NotImplemented);
245  }
246  catch (UnauthorizedAccessException)
247  {
248  return Forbid();
249  }
250  }
251 
260  [HttpDelete]
261  [TgsAuthorize(ConfigurationRights.Delete)]
262  [ProducesResponseType(200)]
263  [ProducesResponseType(501)]
264  public async Task<IActionResult> Delete([FromBody] ConfigurationFile directory, CancellationToken cancellationToken)
265  {
266  if (directory == null)
267  throw new ArgumentNullException(nameof(directory));
268 
269  if (ForbidDueToModeConflicts(directory.Path, out var systemIdentity))
270  return Forbid();
271 
272  try
273  {
274  return await instanceManager.GetInstance(Instance).Configuration.DeleteDirectory(directory.Path, systemIdentity, cancellationToken).ConfigureAwait(false) ? (IActionResult)Ok() : Conflict(new ErrorMessage
275  {
276  Message = "Directory not empty!"
277  });
278  }
279  catch (NotImplementedException)
280  {
281  return StatusCode((int)HttpStatusCode.NotImplemented);
282  }
283  catch (UnauthorizedAccessException)
284  {
285  return Forbid();
286  }
287  }
288  }
289 }
ConfigurationRights
Rights for Models.ConfigurationFile
- +
const string Configuration
The Models.ConfigurationFile controller
Definition: Routes.cs:49
Task< IActionResult > List(CancellationToken cancellationToken)
Get the contents of the root configuration directory.
IInstance GetInstance(Models.Instance metadata)
Get the IInstance associated with given metadata
-
Represents a user on the current System.Runtime.InteropServices.OSPlatform
+
Represents a user on the current global::System.Runtime.InteropServices.OSPlatform
-
bool ForbidDueToModeConflicts(string path, out ISystemIdentity systemIdentityToUse)
If a ForbidResult should be returned from actions due to conflicts with one or both of the Api....
-
readonly IInstanceManager instanceManager
The IInstanceManager for the ConfigurationController
+
bool ForbidDueToModeConflicts(string path, out ISystemIdentity systemIdentityToUse)
If a ForbidResult should be returned from actions due to conflicts with one or both of the Api....
+
readonly IInstanceManager instanceManager
The IInstanceManager for the ConfigurationController
const string File
To be paired with Configuration for accessing Models.ConfigurationFiles
Definition: Routes.cs:54
-
async Task< IActionResult > Delete([FromBody] ConfigurationFile directory, CancellationToken cancellationToken)
Deletes an empty directory
+
async Task< IActionResult > Delete([FromBody] ConfigurationFile directory, CancellationToken cancellationToken)
Deletes an empty directory
ConfigurationType
The type of configuration allowed on an Instance
-
async Task< IActionResult > Create([FromBody] ConfigurationFile model, CancellationToken cancellationToken)
Create a configuration directory.
-
ConfigurationController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, IIOManager ioManager, ILogger< ConfigurationController > logger)
Construct a UserController
+
async Task< IActionResult > Create([FromBody] ConfigurationFile model, CancellationToken cancellationToken)
Create a configuration directory.
+
ConfigurationController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, IIOManager ioManager, ILogger< ConfigurationController > logger)
Construct a UserController
- +
Routes to a server actions
Definition: Routes.cs:9
-
readonly IIOManager ioManager
The IIOManager for the ConfigurationController
+
readonly IIOManager ioManager
The IIOManager for the ConfigurationController
+
string Message
A human readable description of the error
Definition: ErrorMessage.cs:13
-
IConfiguration Configuration
The IConfiguration for the IInstance
Definition: IInstance.cs:42
+
IConfiguration Configuration
The IConfiguration for the IInstance
Definition: IInstance.cs:43
Represents a game configuration file. Create and delete actions uncerimonuously overwrite/delete file...
-
async Task< IActionResult > File(string filePath, CancellationToken cancellationToken)
Get the contents of a file at a filePath
+
async Task< IActionResult > File(string filePath, CancellationToken cancellationToken)
Get the contents of a file at a filePath
ConfigurationType? ConfigurationType
If ConfigurationFile can be used on the Instance
Definition: Instance.cs:38
ILogger Logger
The ILogger for the ApiController
Metadata about a server instance
Definition: Instance.cs:9
-
async Task< IActionResult > Update([FromBody] ConfigurationFile model, CancellationToken cancellationToken)
Write to a configuration file.
+
async Task< IActionResult > Update([FromBody] ConfigurationFile model, CancellationToken cancellationToken)
Write to a configuration file.
bool PathContainsParentAccess(string path)
Check if a path contains the '..' parent directory accessor
const string List
The postfix for list operations
Definition: Routes.cs:84
Interface for using filesystems
Definition: IIOManager.cs:11
-
async Task< IActionResult > Directory(string directoryPath, CancellationToken cancellationToken)
Get the contents of a directory at a directoryPath
+
async Task< IActionResult > Directory(string directoryPath, CancellationToken cancellationToken)
Get the contents of a directory at a directoryPath
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+
diff --git a/_console_8cs_source.html b/_console_8cs_source.html index 4eb4b2f215..b2db1d3777 100644 --- a/_console_8cs_source.html +++ b/_console_8cs_source.html @@ -71,11 +71,11 @@ $(function() {
Console.cs
-Go to the documentation of this file.
1 using System;
2 using System.Text;
3 using System.Threading;
4 using System.Threading.Tasks;
5 
7 {
9  sealed class Console : IConsole, IDisposable
10  {
12  public bool Available => Environment.UserInteractive;
13 
15  public CancellationToken CancelKeyPress => cancelKeyCts.Token;
16 
20  readonly CancellationTokenSource cancelKeyCts;
21 
25  bool disposed;
26 
30  public Console()
31  {
32  cancelKeyCts = new CancellationTokenSource();
33  System.Console.CancelKeyPress += (sender, e) =>
34  {
35  lock (cancelKeyCts)
36  {
37  if (!disposed)
38  cancelKeyCts.Cancel();
39  }
40  };
41  }
42 
44  public void Dispose()
45  {
46  lock (cancelKeyCts)
47  {
48  cancelKeyCts.Dispose();
49  disposed = true;
50  }
51  }
52 
54  {
55  if (!Available)
56  throw new InvalidOperationException("Console unavailable");
57  }
58 
60  public Task PressAnyKeyAsync(CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
61  {
63  System.Console.Read();
64  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
65 
67  public Task<string> ReadLineAsync(bool usePasswordChar, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
68  {
69  // TODO: Make this better: https://stackoverflow.com/questions/9479573/how-to-interrupt-console-readline
71  if (!usePasswordChar)
72  return System.Console.ReadLine();
73 
74  var passwordBuilder = new StringBuilder();
75  do
76  {
77  var keyDescription = System.Console.ReadKey(true);
78  if (keyDescription.Key == ConsoleKey.Enter)
79  break;
80  else if (keyDescription.Key == ConsoleKey.Backspace)
81  {
82  if (passwordBuilder.Length > 0)
83  {
84  --passwordBuilder.Length;
85  System.Console.Write("\b \b");
86  }
87  }
88  else if (keyDescription.KeyChar != '\u0000')
89  {
90  // KeyChar == '\u0000' if the key pressed does not correspond to a printable character, e.g. F1, Pause-Break, etc
91  passwordBuilder.Append(keyDescription.KeyChar);
92  System.Console.Write('*');
93  }
94  }
95  while (!cancellationToken.IsCancellationRequested);
96 
97  cancellationToken.ThrowIfCancellationRequested();
98  System.Console.WriteLine();
99  return passwordBuilder.ToString();
100  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
101 
103  public Task WriteAsync(string text, bool newLine, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
104  {
105  CheckAvailable();
106  if (text == null)
107  {
108  if (!newLine)
109  throw new InvalidOperationException("Cannot write null text without a new line!");
110  System.Console.WriteLine();
111  }
112  else if (newLine)
113  System.Console.WriteLine(text);
114  else
115  System.Console.Write(text);
116  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
117  }
118 }
readonly CancellationTokenSource cancelKeyCts
The CancellationTokenSource for CancelKeyPress.
Definition: Console.cs:20
+Go to the documentation of this file.
1 using System;
2 using System.Text;
3 using System.Threading;
4 using System.Threading.Tasks;
5 
7 {
9  sealed class Console : IConsole, IDisposable
10  {
12  public bool Available => Environment.UserInteractive;
13 
15  public CancellationToken CancelKeyPress => cancelKeyCts.Token;
16 
20  readonly CancellationTokenSource cancelKeyCts;
21 
25  bool disposed;
26 
30  public Console()
31  {
32  cancelKeyCts = new CancellationTokenSource();
33  global::System.Console.CancelKeyPress += (sender, e) =>
34  {
35  lock (cancelKeyCts)
36  {
37  if (!disposed)
38  cancelKeyCts.Cancel();
39  }
40  };
41  }
42 
44  public void Dispose()
45  {
46  lock (cancelKeyCts)
47  {
48  cancelKeyCts.Dispose();
49  disposed = true;
50  }
51  }
52 
54  {
55  if (!Available)
56  throw new InvalidOperationException("Console unavailable");
57  }
58 
60  public Task PressAnyKeyAsync(CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
61  {
63  global::System.Console.Read();
64  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
65 
67  public Task<string> ReadLineAsync(bool usePasswordChar, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
68  {
69  // TODO: Make this better: https://stackoverflow.com/questions/9479573/how-to-interrupt-console-readline
71  if (!usePasswordChar)
72  return global::System.Console.ReadLine();
73 
74  var passwordBuilder = new StringBuilder();
75  do
76  {
77  var keyDescription = global::System.Console.ReadKey(true);
78  if (keyDescription.Key == ConsoleKey.Enter)
79  break;
80  else if (keyDescription.Key == ConsoleKey.Backspace)
81  {
82  if (passwordBuilder.Length > 0)
83  {
84  --passwordBuilder.Length;
85  global::System.Console.Write("\b \b");
86  }
87  }
88  else if (keyDescription.KeyChar != '\u0000')
89  {
90  // KeyChar == '\u0000' if the key pressed does not correspond to a printable character, e.g. F1, Pause-Break, etc
91  passwordBuilder.Append(keyDescription.KeyChar);
92  global::System.Console.Write('*');
93  }
94  }
95  while (!cancellationToken.IsCancellationRequested);
96 
97  cancellationToken.ThrowIfCancellationRequested();
98  global::System.Console.WriteLine();
99  return passwordBuilder.ToString();
100  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
101 
103  public Task WriteAsync(string text, bool newLine, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
104  {
105  CheckAvailable();
106  if (text == null)
107  {
108  if (!newLine)
109  throw new InvalidOperationException("Cannot write null text without a new line!");
110  global::System.Console.WriteLine();
111  }
112  else if (newLine)
113  global::System.Console.WriteLine(text);
114  else
115  global::System.Console.Write(text);
116  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
117  }
118 }
readonly CancellationTokenSource cancelKeyCts
The CancellationTokenSource for CancelKeyPress.
Definition: Console.cs:20
-
Abstraction for System.Console
Definition: IConsole.cs:9
+
Abstraction for global::System.Console
Definition: IConsole.cs:9
CancellationToken CancelKeyPress
Definition: Console.cs:15
bool disposed
If the Console was disposed;
Definition: Console.cs:25
diff --git a/_credentials_provider_8cs_source.html b/_credentials_provider_8cs_source.html index 7a0faaebd8..454bddfadb 100644 --- a/_credentials_provider_8cs_source.html +++ b/_credentials_provider_8cs_source.html @@ -71,16 +71,16 @@ $(function() {
CredentialsProvider.cs
-Go to the documentation of this file.
1 using LibGit2Sharp;
2 using LibGit2Sharp.Handlers;
3 using Microsoft.Extensions.Logging;
4 using System;
6 
8 {
11  {
15  readonly ILogger<CredentialsProvider> logger;
16 
21  public CredentialsProvider(ILogger<CredentialsProvider> logger)
22  {
23  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
24  }
25 
27  public CredentialsHandler GenerateHandler(string username, string password) => (a, b, supportedCredentialTypes) =>
28  {
29  var hasCreds = username != null;
30  var supportsUserPass = supportedCredentialTypes.HasFlag(SupportedCredentialTypes.UsernamePassword);
31  var supportsAnonymous = supportedCredentialTypes.HasFlag(SupportedCredentialTypes.Default);
32 
33  logger.LogTrace("Credentials requested. Present: {0}. Supports anonymous: {1}. Supports user/pass: {2}", hasCreds, supportsAnonymous, supportsUserPass);
34  if (supportsUserPass)
35  {
36  if (hasCreds)
37  return new UsernamePasswordCredentials
38  {
39  Username = username,
40  Password = password
41  };
42  }
43 
44  if (supportsAnonymous)
45  return new DefaultCredentials();
46 
47  if (hasCreds)
48  throw new JobException("Remote does not support anonymous authentication!");
49 
50  throw new JobException("Server does not support anonymous or username/password authentication!");
51  };
52  }
53 }
CredentialsHandler GenerateHandler(string username, string password)
Generate a CredentialsHandler from a given username and password
+Go to the documentation of this file.
1 using LibGit2Sharp;
2 using LibGit2Sharp.Handlers;
3 using Microsoft.Extensions.Logging;
4 using System;
6 
8 {
11  {
15  readonly ILogger<CredentialsProvider> logger;
16 
21  public CredentialsProvider(ILogger<CredentialsProvider> logger)
22  {
23  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
24  }
25 
27  public CredentialsHandler GenerateHandler(string username, string password) => (a, b, supportedCredentialTypes) =>
28  {
29  var hasCreds = username != null;
30  var supportsUserPass = supportedCredentialTypes.HasFlag(SupportedCredentialTypes.UsernamePassword);
31  var supportsAnonymous = supportedCredentialTypes.HasFlag(SupportedCredentialTypes.Default);
32 
33  logger.LogTrace("Credentials requested. Present: {0}. Supports anonymous: {1}. Supports user/pass: {2}", hasCreds, supportsAnonymous, supportsUserPass);
34  if (supportsUserPass)
35  {
36  if (hasCreds)
37  return new UsernamePasswordCredentials
38  {
39  Username = username,
40  Password = password
41  };
42  }
43 
44  if (supportsAnonymous)
45  return new DefaultCredentials();
46 
47  if (hasCreds)
48  throw new JobException("Remote does not support anonymous authentication!");
49 
50  throw new JobException("Server does not support anonymous or username/password authentication!");
51  };
52  }
53 }
CredentialsHandler GenerateHandler(string username, string password)
Generate a CredentialsHandler from a given username and password
CredentialsProvider(ILogger< CredentialsProvider > logger)
Construct a CredentialsProvider
- +
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
+
readonly ILogger< CredentialsProvider > logger
The ILogger for the CredentialsProvider
-
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
diff --git a/_d_b_connection_factory_8cs_source.html b/_d_b_connection_factory_8cs_source.html deleted file mode 100644 index e855b0809b..0000000000 --- a/_d_b_connection_factory_8cs_source.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - -tgstation-server: src/Tgstation.Server.Host/Core/DBConnectionFactory.cs Source File - - - - - - - - - -
-
- - - - - - - -
-
tgstation-server -
-
The /tg/station 13 server suite
-
-
- - - - - - - - -
-
- - -
- -
- - -
-
-
-
DBConnectionFactory.cs
-
-
-Go to the documentation of this file.
1 using MySql.Data.MySqlClient;
2 using System;
3 using System.Data.Common;
4 using System.Data.SqlClient;
5 using System.Globalization;
7 
9 {
12  {
14  public DbConnection CreateConnection(string connectionString, DatabaseType databaseType)
15  {
16  if (connectionString == null)
17  throw new ArgumentNullException(nameof(connectionString));
18 
19  switch (databaseType)
20  {
21  case DatabaseType.MariaDB:
22  case DatabaseType.MySql:
23  return new MySqlConnection
24  {
25  ConnectionString = connectionString
26  };
27  case DatabaseType.SqlServer:
28  return new SqlConnection
29  {
30  ConnectionString = connectionString
31  };
32  default:
33  throw new ArgumentOutOfRangeException(nameof(databaseType), databaseType, "Invalid DatabaseType!");
34  }
35  }
36  }
37 }
- - - -
DbConnection CreateConnection(string connectionString, DatabaseType databaseType)
Create a DbConnection
- -
DatabaseType
Type of database to user
Definition: DatabaseType.cs:6
- - - -
- - - - diff --git a/_database_configuration_8cs.html b/_database_configuration_8cs.html index 3973d1f548..b525f605cb 100644 --- a/_database_configuration_8cs.html +++ b/_database_configuration_8cs.html @@ -80,7 +80,7 @@ $(function() {

Classes

class  Tgstation.Server.Host.Configuration.DatabaseConfigurationConfiguration options for the Models.DatabaseContext<TParentContext> More...
Configuration options for the Database.DatabaseContext<TParentContext> More...
  - +

diff --git a/_database_configuration_8cs_source.html b/_database_configuration_8cs_source.html index 44b243e696..88667b8c2c 100644 --- a/_database_configuration_8cs_source.html +++ b/_database_configuration_8cs_source.html @@ -76,8 +76,8 @@ $(function() {
bool ResetAdminPassword
If the admin user should be enabled and have it's password reset
-
string MySqlServerVersion
The string form of the System.Version of a target MySQL/MariaDB server
-
Configuration options for the Models.DatabaseContext<TParentContext>
+
string MySqlServerVersion
The string form of the global::System.Version of a target MySQL/MariaDB server
+
Configuration options for the Database.DatabaseContext<TParentContext>
DatabaseType
Type of database to user
Definition: DatabaseType.cs:6
bool DropDatabase
If the database should be deleted on application startup. Should not be used in production!
diff --git a/_tgs_open_api_filters_8cs.html b/_database_connection_factory_8cs.html similarity index 79% rename from _tgs_open_api_filters_8cs.html rename to _database_connection_factory_8cs.html index 355f61eb77..5b3432af1e 100644 --- a/_tgs_open_api_filters_8cs.html +++ b/_database_connection_factory_8cs.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Controllers/TgsOpenApiFilters.cs File Reference +tgstation-server: src/Tgstation.Server.Host/Database/DatabaseConnectionFactory.cs File Reference @@ -63,7 +63,7 @@ $(function() {
@@ -71,16 +71,15 @@ $(function() { Classes | Namespaces
-
TgsOpenApiFilters.cs File Reference
+
DatabaseConnectionFactory.cs File Reference
diff --git a/_database_connection_factory_8cs_source.html b/_database_connection_factory_8cs_source.html new file mode 100644 index 0000000000..28d3466ab1 --- /dev/null +++ b/_database_connection_factory_8cs_source.html @@ -0,0 +1,92 @@ + + + + + + + +tgstation-server: src/Tgstation.Server.Host/Database/DatabaseConnectionFactory.cs Source File + + + + + + + + + +
+
+ + + + + + + +
+
tgstation-server +
+
The /tg/station 13 server suite
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
DatabaseConnectionFactory.cs
+
+
+Go to the documentation of this file.
1 using MySql.Data.MySqlClient;
2 using System;
3 using System.Data.Common;
4 using System.Data.SqlClient;
6 
8 {
11  {
13  public DbConnection CreateConnection(string connectionString, DatabaseType databaseType)
14  {
15  if (connectionString == null)
16  throw new ArgumentNullException(nameof(connectionString));
17 
18  switch (databaseType)
19  {
20  case DatabaseType.MariaDB:
21  case DatabaseType.MySql:
22  return new MySqlConnection
23  {
24  ConnectionString = connectionString
25  };
26  case DatabaseType.SqlServer:
27  return new SqlConnection
28  {
29  ConnectionString = connectionString
30  };
31  default:
32  throw new ArgumentOutOfRangeException(nameof(databaseType), databaseType, "Invalid DatabaseType!");
33  }
34  }
35  }
36 }
+
DbConnection CreateConnection(string connectionString, DatabaseType databaseType)
Create a DbConnection
+ + +
DatabaseType
Type of database to user
Definition: DatabaseType.cs:6
+ + + + + +
+ + + + diff --git a/_database_context_8cs.html b/_database_context_8cs.html index 38bc1cda8e..67b8336318 100644 --- a/_database_context_8cs.html +++ b/_database_context_8cs.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Models/DatabaseContext.cs File Reference +tgstation-server: src/Tgstation.Server.Host/Database/DatabaseContext.cs File Reference @@ -63,7 +63,7 @@ $(function() {
@@ -79,7 +79,7 @@ $(function() { - +

Classes

class  Tgstation.Server.Host.Models.DatabaseContext< TParentContext >
class  Tgstation.Server.Host.Database.DatabaseContext< TParentContext >
 
- +

@@ -90,7 +90,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
namespace  Tgstation.Server.Host.Database
 
diff --git a/_database_context_8cs_source.html b/_database_context_8cs_source.html index 4bdc22dc7f..9a629b5930 100644 --- a/_database_context_8cs_source.html +++ b/_database_context_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Models/DatabaseContext.cs Source File +tgstation-server: src/Tgstation.Server.Host/Database/DatabaseContext.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,50 +71,51 @@ $(function() {
DatabaseContext.cs
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using Microsoft.EntityFrameworkCore.Infrastructure;
3 using Microsoft.EntityFrameworkCore.Migrations;
4 using Microsoft.Extensions.DependencyInjection;
5 using Microsoft.Extensions.Logging;
6 using Microsoft.Extensions.Options;
7 using System;
8 using System.Globalization;
9 using System.Linq;
10 using System.Threading;
11 using System.Threading.Tasks;
14 
16 {
18  #pragma warning disable CA1506 // TODO: Decomplexify
19  abstract class DatabaseContext<TParentContext> : DbContext, IDatabaseContext where TParentContext : DbContext
20  {
22  public DbSet<User> Users { get; set; }
23 
25  public DbSet<Instance> Instances { get; set; }
26 
28  public DbSet<CompileJob> CompileJobs { get; set; }
29 
31  public DbSet<RevisionInformation> RevisionInformations { get; set; }
32 
34  public DbSet<DreamMakerSettings> DreamMakerSettings { get; set; }
35 
37  public DbSet<ChatBot> ChatBots { get; set; }
38 
40  public DbSet<DreamDaemonSettings> DreamDaemonSettings { get; set; }
41 
43  public DbSet<RepositorySettings> RepositorySettings { get; set; }
44 
46  public DbSet<InstanceUser> InstanceUsers { get; set; }
47 
49  public DbSet<ChatChannel> ChatChannels { get; set; }
50 
52  public DbSet<Job> Jobs { get; set; }
53 
55  public DbSet<ReattachInformation> ReattachInformations { get; set; }
56 
58  public DbSet<WatchdogReattachInformation> WatchdogReattachInformations { get; set; }
59 
63  public DbSet<TestMerge> TestMerges { get; set; }
64 
68  public DbSet<RevInfoTestMerge> RevInfoTestMerges { get; set; }
69 
73  protected ILogger Logger { get; }
74 
79 
84 
92  public DatabaseContext(DbContextOptions<TParentContext> dbContextOptions, IOptions<DatabaseConfiguration> databaseConfigurationOptions, IDatabaseSeeder databaseSeeder, ILogger logger) : base(dbContextOptions)
93  {
94  DatabaseConfiguration = databaseConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(databaseConfigurationOptions));
95  this.databaseSeeder = databaseSeeder ?? throw new ArgumentNullException(nameof(databaseSeeder));
96  Logger = logger ?? throw new ArgumentNullException(nameof(logger));
97  }
98 
100  protected override void OnModelCreating(ModelBuilder modelBuilder)
101  {
102  Logger.LogTrace("Building entity framework context...");
103  base.OnModelCreating(modelBuilder);
104 
105  var userModel = modelBuilder.Entity<User>();
106  userModel.HasIndex(x => x.CanonicalName).IsUnique();
107  userModel.HasMany(x => x.TestMerges).WithOne(x => x.MergedBy).OnDelete(DeleteBehavior.Restrict);
108 
109  modelBuilder.Entity<InstanceUser>().HasIndex(x => new { x.UserId, x.InstanceId }).IsUnique();
110 
111  modelBuilder.Entity<TestMerge>().HasMany(x => x.RevisonInformations).WithOne(x => x.TestMerge).OnDelete(DeleteBehavior.Cascade);
112 
113  var revInfo = modelBuilder.Entity<RevisionInformation>();
114  revInfo.HasMany(x => x.CompileJobs).WithOne(x => x.RevisionInformation).OnDelete(DeleteBehavior.Cascade);
115  revInfo.HasMany(x => x.ActiveTestMerges).WithOne(x => x.RevisionInformation).OnDelete(DeleteBehavior.Cascade);
116  revInfo.HasOne(x => x.PrimaryTestMerge).WithOne(x => x.PrimaryRevisionInformation).OnDelete(DeleteBehavior.Restrict);
117  revInfo.HasIndex(x => new { x.InstanceId, x.CommitSha }).IsUnique();
118 
119  modelBuilder.Entity<CompileJob>().HasIndex(x => x.DirectoryName);
120 
121  modelBuilder.Entity<Job>().HasOne<CompileJob>().WithOne(x => x.Job).OnDelete(DeleteBehavior.Restrict);
122 
123  var chatChannel = modelBuilder.Entity<ChatChannel>();
124  chatChannel.HasIndex(x => new { x.ChatSettingsId, x.IrcChannel }).IsUnique();
125  chatChannel.HasIndex(x => new { x.ChatSettingsId, x.DiscordChannelId }).IsUnique();
126  chatChannel.HasOne(x => x.ChatSettings).WithMany(x => x.Channels).HasForeignKey(x => x.ChatSettingsId).OnDelete(DeleteBehavior.Cascade);
127 
128  modelBuilder.Entity<ChatBot>().HasIndex(x => x.Name).IsUnique();
129 
130  var instanceModel = modelBuilder.Entity<Instance>();
131  instanceModel.HasIndex(x => x.Path).IsUnique();
132  instanceModel.HasMany(x => x.ChatSettings).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
133  instanceModel.HasOne(x => x.DreamDaemonSettings).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
134  instanceModel.HasOne(x => x.DreamMakerSettings).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
135  instanceModel.HasOne(x => x.RepositorySettings).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
136  instanceModel.HasMany(x => x.RevisionInformations).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
137  instanceModel.HasMany(x => x.InstanceUsers).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
138  instanceModel.HasMany(x => x.Jobs).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
139  instanceModel.HasOne(x => x.WatchdogReattachInformation).WithOne().OnDelete(DeleteBehavior.Cascade);
140  }
141 
143  public async Task Initialize(CancellationToken cancellationToken)
144  {
146  {
147  Logger.LogCritical("DropDatabase configuration option set! Dropping any existing database...");
148  await Database.EnsureDeletedAsync(cancellationToken).ConfigureAwait(false);
149  }
150 
151  var migrations = await Database.GetAppliedMigrationsAsync(cancellationToken).ConfigureAwait(false);
152  var wasEmpty = !migrations.Any();
153 
154  if (wasEmpty || (await Database.GetPendingMigrationsAsync(cancellationToken).ConfigureAwait(false)).Any())
155  {
156  Logger.LogInformation("Migrating database...");
157  await Database.MigrateAsync(cancellationToken).ConfigureAwait(false);
158  }
159  else
160  Logger.LogDebug("No migrations to apply.");
161 
162  wasEmpty |= (await Users.CountAsync(cancellationToken).ConfigureAwait(false)) == 0;
163 
164  if (wasEmpty)
165  {
166  Logger.LogInformation("Seeding database...");
167  await databaseSeeder.SeedDatabase(this, cancellationToken).ConfigureAwait(false);
168  }
170  {
171  Logger.LogWarning("Enabling and resetting admin password due to configuration!");
172  await databaseSeeder.ResetAdminPassword(this, cancellationToken).ConfigureAwait(false);
173  }
174  }
175 
177  public Task Save(CancellationToken cancellationToken) => SaveChangesAsync(cancellationToken);
178 
183  protected abstract bool UseMySQLMigrations();
184 
186  public async Task SchemaDowngradeForServerVersion(Version version, CancellationToken cancellationToken)
187  {
188  if (version == null)
189  throw new ArgumentNullException(nameof(version));
190  if (version < new Version(4, 0))
191  throw new ArgumentOutOfRangeException(nameof(version), version, "Not a valid V4 version!");
192 
193  string targetMigration = null;
194 
195  // Update this with new migrations as they are made
196  // Always use the MS class
197  if (version < new Version(4, 0, 2))
198  targetMigration = nameof(MSReattachCompileJobRequired);
199 
200  if (targetMigration == null)
201  return;
202 
203  if (UseMySQLMigrations())
204  targetMigration = String.Format(CultureInfo.InvariantCulture, "MY{0}", targetMigration.Substring(2));
205 
206  // even though it clearly implements it in the DatabaseFacade definition this won't work without casting (╯ಠ益ಠ)╯︵ ┻━┻
207  var dbServiceProvider = ((IInfrastructure<IServiceProvider>)Database).Instance;
208  var migrator = dbServiceProvider.GetRequiredService<IMigrator>();
209 
210  Logger.LogInformation("Migrating down to version {0}. Target: {1}", version, targetMigration);
211  try
212  {
213  await migrator.MigrateAsync(targetMigration, cancellationToken).ConfigureAwait(false);
214  }
215  catch (Exception e)
216  {
217  Logger.LogCritical("Failed to migrate! Exception: {0}", e);
218  }
219  }
220  }
221 }
-
DbSet< TestMerge > TestMerges
The TestMerges in the DatabaseContext<TParentContext>
+Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using Microsoft.EntityFrameworkCore.Infrastructure;
3 using Microsoft.EntityFrameworkCore.Migrations;
4 using Microsoft.Extensions.DependencyInjection;
5 using Microsoft.Extensions.Logging;
6 using Microsoft.Extensions.Options;
7 using System;
8 using System.Globalization;
9 using System.Linq;
10 using System.Threading;
11 using System.Threading.Tasks;
15 
17 {
19  #pragma warning disable CA1506 // TODO: Decomplexify
20  abstract class DatabaseContext<TParentContext> : DbContext, IDatabaseContext where TParentContext : DbContext
21  {
23  public DbSet<User> Users { get; set; }
24 
26  public DbSet<Instance> Instances { get; set; }
27 
29  public DbSet<CompileJob> CompileJobs { get; set; }
30 
32  public DbSet<RevisionInformation> RevisionInformations { get; set; }
33 
35  public DbSet<DreamMakerSettings> DreamMakerSettings { get; set; }
36 
38  public DbSet<ChatBot> ChatBots { get; set; }
39 
41  public DbSet<DreamDaemonSettings> DreamDaemonSettings { get; set; }
42 
44  public DbSet<RepositorySettings> RepositorySettings { get; set; }
45 
47  public DbSet<InstanceUser> InstanceUsers { get; set; }
48 
50  public DbSet<ChatChannel> ChatChannels { get; set; }
51 
53  public DbSet<Job> Jobs { get; set; }
54 
56  public DbSet<ReattachInformation> ReattachInformations { get; set; }
57 
59  public DbSet<WatchdogReattachInformation> WatchdogReattachInformations { get; set; }
60 
64  public DbSet<TestMerge> TestMerges { get; set; }
65 
69  public DbSet<RevInfoTestMerge> RevInfoTestMerges { get; set; }
70 
74  protected ILogger Logger { get; }
75 
80 
85 
93  public DatabaseContext(DbContextOptions<TParentContext> dbContextOptions, IOptions<DatabaseConfiguration> databaseConfigurationOptions, IDatabaseSeeder databaseSeeder, ILogger logger) : base(dbContextOptions)
94  {
95  DatabaseConfiguration = databaseConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(databaseConfigurationOptions));
96  this.databaseSeeder = databaseSeeder ?? throw new ArgumentNullException(nameof(databaseSeeder));
97  Logger = logger ?? throw new ArgumentNullException(nameof(logger));
98  }
99 
101  protected override void OnModelCreating(ModelBuilder modelBuilder)
102  {
103  Logger.LogTrace("Building entity framework context...");
104  base.OnModelCreating(modelBuilder);
105 
106  var userModel = modelBuilder.Entity<User>();
107  userModel.HasIndex(x => x.CanonicalName).IsUnique();
108  userModel.HasMany(x => x.TestMerges).WithOne(x => x.MergedBy).OnDelete(DeleteBehavior.Restrict);
109 
110  modelBuilder.Entity<InstanceUser>().HasIndex(x => new { x.UserId, x.InstanceId }).IsUnique();
111 
112  modelBuilder.Entity<TestMerge>().HasMany(x => x.RevisonInformations).WithOne(x => x.TestMerge).OnDelete(DeleteBehavior.Cascade);
113 
114  var revInfo = modelBuilder.Entity<RevisionInformation>();
115  revInfo.HasMany(x => x.CompileJobs).WithOne(x => x.RevisionInformation).OnDelete(DeleteBehavior.Cascade);
116  revInfo.HasMany(x => x.ActiveTestMerges).WithOne(x => x.RevisionInformation).OnDelete(DeleteBehavior.Cascade);
117  revInfo.HasOne(x => x.PrimaryTestMerge).WithOne(x => x.PrimaryRevisionInformation).OnDelete(DeleteBehavior.Restrict);
118  revInfo.HasIndex(x => new { x.InstanceId, x.CommitSha }).IsUnique();
119 
120  modelBuilder.Entity<CompileJob>().HasIndex(x => x.DirectoryName);
121 
122  modelBuilder.Entity<Job>().HasOne<CompileJob>().WithOne(x => x.Job).OnDelete(DeleteBehavior.Restrict);
123 
124  var chatChannel = modelBuilder.Entity<ChatChannel>();
125  chatChannel.HasIndex(x => new { x.ChatSettingsId, x.IrcChannel }).IsUnique();
126  chatChannel.HasIndex(x => new { x.ChatSettingsId, x.DiscordChannelId }).IsUnique();
127  chatChannel.HasOne(x => x.ChatSettings).WithMany(x => x.Channels).HasForeignKey(x => x.ChatSettingsId).OnDelete(DeleteBehavior.Cascade);
128 
129  modelBuilder.Entity<ChatBot>().HasIndex(x => x.Name).IsUnique();
130 
131  var instanceModel = modelBuilder.Entity<Instance>();
132  instanceModel.HasIndex(x => x.Path).IsUnique();
133  instanceModel.HasMany(x => x.ChatSettings).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
134  instanceModel.HasOne(x => x.DreamDaemonSettings).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
135  instanceModel.HasOne(x => x.DreamMakerSettings).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
136  instanceModel.HasOne(x => x.RepositorySettings).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
137  instanceModel.HasMany(x => x.RevisionInformations).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
138  instanceModel.HasMany(x => x.InstanceUsers).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
139  instanceModel.HasMany(x => x.Jobs).WithOne(x => x.Instance).OnDelete(DeleteBehavior.Cascade);
140  instanceModel.HasOne(x => x.WatchdogReattachInformation).WithOne().OnDelete(DeleteBehavior.Cascade);
141  }
142 
144  public async Task Initialize(CancellationToken cancellationToken)
145  {
147  {
148  Logger.LogCritical("DropDatabase configuration option set! Dropping any existing database...");
149  await Database.EnsureDeletedAsync(cancellationToken).ConfigureAwait(false);
150  }
151 
152  var migrations = await Database.GetAppliedMigrationsAsync(cancellationToken).ConfigureAwait(false);
153  var wasEmpty = !migrations.Any();
154 
155  if (wasEmpty || (await Database.GetPendingMigrationsAsync(cancellationToken).ConfigureAwait(false)).Any())
156  {
157  Logger.LogInformation("Migrating database...");
158  await Database.MigrateAsync(cancellationToken).ConfigureAwait(false);
159  }
160  else
161  Logger.LogDebug("No migrations to apply.");
162 
163  wasEmpty |= (await Users.CountAsync(cancellationToken).ConfigureAwait(false)) == 0;
164 
165  if (wasEmpty)
166  {
167  Logger.LogInformation("Seeding database...");
168  await databaseSeeder.SeedDatabase(this, cancellationToken).ConfigureAwait(false);
169  }
171  {
172  Logger.LogWarning("Enabling and resetting admin password due to configuration!");
173  await databaseSeeder.ResetAdminPassword(this, cancellationToken).ConfigureAwait(false);
174  }
175  }
176 
178  public Task Save(CancellationToken cancellationToken) => SaveChangesAsync(cancellationToken);
179 
184  protected abstract bool UseMySQLMigrations();
185 
187  public async Task SchemaDowngradeForServerVersion(Version version, CancellationToken cancellationToken)
188  {
189  if (version == null)
190  throw new ArgumentNullException(nameof(version));
191  if (version < new Version(4, 0))
192  throw new ArgumentOutOfRangeException(nameof(version), version, "Not a valid V4 version!");
193 
194  string targetMigration = null;
195 
196  // Update this with new migrations as they are made
197  // Always use the MS class
198  if (version < new Version(4, 0, 2))
199  targetMigration = nameof(MSReattachCompileJobRequired);
200 
201  if (targetMigration == null)
202  return;
203 
204  if (UseMySQLMigrations())
205  targetMigration = String.Format(CultureInfo.InvariantCulture, "MY{0}", targetMigration.Substring(2));
206 
207  // even though it clearly implements it in the DatabaseFacade definition this won't work without casting (╯ಠ益ಠ)╯︵ ┻━┻
208  var dbServiceProvider = ((IInfrastructure<IServiceProvider>)Database).Instance;
209  var migrator = dbServiceProvider.GetRequiredService<IMigrator>();
210 
211  Logger.LogInformation("Migrating down to version {0}. Target: {1}", version, targetMigration);
212  try
213  {
214  await migrator.MigrateAsync(targetMigration, cancellationToken).ConfigureAwait(false);
215  }
216  catch (Exception e)
217  {
218  Logger.LogCritical("Failed to migrate! Exception: {0}", e);
219  }
220  }
221  }
222 }
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
+
ILogger Logger
The ILogger for the DatabaseContext<TParentContext>
- -
DbSet< ReattachInformation > ReattachInformations
-
abstract bool UseMySQLMigrations()
If the MY_ class of migrations should be used instead of the MS_ class
- - -
Task ResetAdminPassword(IDatabaseContext databaseContext, CancellationToken cancellationToken)
Changes the admin password in IDatabaseContext back to it's default and enables the account
-
For initially seeding a database
- -
DbSet< RevisionInformation > RevisionInformations
-
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
+
For initially seeding a database
+
DatabaseContext(DbContextOptions< TParentContext > dbContextOptions, IOptions< DatabaseConfiguration > databaseConfigurationOptions, IDatabaseSeeder databaseSeeder, ILogger logger)
Construct a DatabaseContext<TParentContext>
+ +
abstract bool UseMySQLMigrations()
If the MY_ class of migrations should be used instead of the MS_ class
+
DbSet< WatchdogReattachInformation > WatchdogReattachInformations
+ + +
DbSet< ReattachInformation > ReattachInformations
+
DbSet< RevisionInformation > RevisionInformations
- -
async Task Initialize(CancellationToken cancellationToken)
Creates and migrates the IDatabaseContext
+ + +
async Task Initialize(CancellationToken cancellationToken)
Creates and migrates the IDatabaseContext
bool ResetAdminPassword
If the admin user should be enabled and have it's password reset
-
override void OnModelCreating(ModelBuilder modelBuilder)
-
async Task SchemaDowngradeForServerVersion(Version version, CancellationToken cancellationToken)
Attempt to downgrade the schema to the migration used for a given server version
+
DbSet< RevInfoTestMerge > RevInfoTestMerges
The RevInfoTestMerges om the DatabaseContext<TParentContext>
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
+
async Task SchemaDowngradeForServerVersion(Version version, CancellationToken cancellationToken)
Attempt to downgrade the schema to the migration used for a given server version
- - +
Task ResetAdminPassword(IDatabaseContext databaseContext, CancellationToken cancellationToken)
Changes the admin password in IDatabaseContext back to it's default and enables the account
Marks the CompileJobs of ReattachInformations as non-nullable for MSSQL
-
DatabaseContext(DbContextOptions< TParentContext > dbContextOptions, IOptions< DatabaseConfiguration > databaseConfigurationOptions, IDatabaseSeeder databaseSeeder, ILogger logger)
Construct a DatabaseContext<TParentContext>
+ -
Configuration options for the Models.DatabaseContext<TParentContext>
-
DbSet< RevInfoTestMerge > RevInfoTestMerges
The RevInfoTestMerges om the DatabaseContext<TParentContext>
+
Configuration options for the Database.DatabaseContext<TParentContext>
-
DbSet< WatchdogReattachInformation > WatchdogReattachInformations
+
bool DropDatabase
If the database should be deleted on application startup. Should not be used in production!
-
readonly IDatabaseSeeder databaseSeeder
The IDatabaseSeeder for the DatabaseContext<TParentContext>
-
ILogger Logger
The ILogger for the DatabaseContext<TParentContext>
+
readonly IDatabaseSeeder databaseSeeder
The IDatabaseSeeder for the DatabaseContext<TParentContext>
+
Task SeedDatabase(IDatabaseContext databaseContext, CancellationToken cancellationToken)
Initially seed a given databaseContext
+ +
override void OnModelCreating(ModelBuilder modelBuilder)
- -
Task SeedDatabase(IDatabaseContext databaseContext, CancellationToken cancellationToken)
Initially seed a given databaseContext
+ + +
DbSet< TestMerge > TestMerges
The TestMerges in the DatabaseContext<TParentContext>
diff --git a/_database_context_factory_8cs.html b/_database_context_factory_8cs.html index 695e55f26f..06d6e0d391 100644 --- a/_database_context_factory_8cs.html +++ b/_database_context_factory_8cs.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/DatabaseContextFactory.cs File Reference +tgstation-server: src/Tgstation.Server.Host/Database/DatabaseContextFactory.cs File Reference @@ -63,7 +63,7 @@ $(function() {
@@ -79,7 +79,7 @@ $(function() { - +

Classes

class  Tgstation.Server.Host.Core.DatabaseContextFactory
class  Tgstation.Server.Host.Database.DatabaseContextFactory
 
- +

@@ -90,7 +90,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
namespace  Tgstation.Server.Host.Database
 
diff --git a/_database_context_factory_8cs_source.html b/_database_context_factory_8cs_source.html index cb77bb2256..63b7adee19 100644 --- a/_database_context_factory_8cs_source.html +++ b/_database_context_factory_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/DatabaseContextFactory.cs Source File +tgstation-server: src/Tgstation.Server.Host/Database/DatabaseContextFactory.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,17 +71,13 @@ $(function() {
DatabaseContextFactory.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.DependencyInjection;
2 using System;
3 using System.Threading.Tasks;
5 
7 {
10  {
14  readonly IServiceScopeFactory scopeFactory;
15 
20  public DatabaseContextFactory(IServiceScopeFactory scopeFactory)
21  {
22  this.scopeFactory = scopeFactory ?? throw new ArgumentNullException(nameof(scopeFactory));
23 
24  using (var scope = scopeFactory.CreateScope())
25  scope.ServiceProvider.GetRequiredService<IDatabaseContext>();
26  }
27 
29  public async Task UseContext(Func<IDatabaseContext, Task> operation)
30  {
31  if (operation == null)
32  throw new ArgumentNullException(nameof(operation));
33 
34  using (var scope = scopeFactory.CreateScope())
35  await operation(scope.ServiceProvider.GetRequiredService<IDatabaseContext>()).ConfigureAwait(false);
36  }
37  }
38 }
- -
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
-
DatabaseContextFactory(IServiceScopeFactory scopeFactory)
Construct a DatabaseContextFactory
- - -
readonly IServiceScopeFactory scopeFactory
The IServiceScopeFactory for the DatabaseContextFactory
-
async Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
- - - +Go to the documentation of this file.
1 using Microsoft.Extensions.DependencyInjection;
2 using System;
3 using System.Threading.Tasks;
4 
6 {
9  {
13  readonly IServiceScopeFactory scopeFactory;
14 
19  public DatabaseContextFactory(IServiceScopeFactory scopeFactory)
20  {
21  this.scopeFactory = scopeFactory ?? throw new ArgumentNullException(nameof(scopeFactory));
22 
23  using (var scope = scopeFactory.CreateScope())
24  scope.ServiceProvider.GetRequiredService<IDatabaseContext>();
25  }
26 
28  public async Task UseContext(Func<IDatabaseContext, Task> operation)
29  {
30  if (operation == null)
31  throw new ArgumentNullException(nameof(operation));
32 
33  using (var scope = scopeFactory.CreateScope())
34  await operation(scope.ServiceProvider.GetRequiredService<IDatabaseContext>()).ConfigureAwait(false);
35  }
36  }
37 }
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
+ + +
async Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
+
readonly IServiceScopeFactory scopeFactory
The IServiceScopeFactory for the DatabaseContextFactory
+
DatabaseContextFactory(IServiceScopeFactory scopeFactory)
Construct a DatabaseContextFactory
+
@@ -79,7 +79,7 @@ $(function() { - +

Classes

class  Tgstation.Server.Host.Models.DatabaseSeeder
class  Tgstation.Server.Host.Database.DatabaseSeeder
 
- +

@@ -90,7 +90,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
namespace  Tgstation.Server.Host.Database
 
diff --git a/_database_seeder_8cs_source.html b/_database_seeder_8cs_source.html index 868e210c7e..aa76256440 100644 --- a/_database_seeder_8cs_source.html +++ b/_database_seeder_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Models/DatabaseSeeder.cs Source File +tgstation-server: src/Tgstation.Server.Host/Database/DatabaseSeeder.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,27 +71,28 @@ $(function() {
DatabaseSeeder.cs
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using System;
3 using System.Linq;
4 using System.Threading;
5 using System.Threading.Tasks;
8 
10 {
13  {
18 
23  public DatabaseSeeder(ICryptographySuite cryptographySuite) => this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite));
24 
29  void SeedAdminUser(IDatabaseContext databaseContext)
30  {
31  var admin = new User
32  {
34  CreatedAt = DateTimeOffset.Now,
36  Name = Api.Models.User.AdminName,
37  CanonicalName = Api.Models.User.AdminName.ToUpperInvariant(),
38  Enabled = true,
39  };
40  cryptographySuite.SetUserPassword(admin, Api.Models.User.DefaultAdminPassword, true);
41  databaseContext.Users.Add(admin);
42  }
43 
45  public async Task SeedDatabase(IDatabaseContext databaseContext, CancellationToken cancellationToken)
46  {
47  SeedAdminUser(databaseContext);
48  await databaseContext.Save(cancellationToken).ConfigureAwait(false);
49  }
50 
52  public async Task ResetAdminPassword(IDatabaseContext databaseContext, CancellationToken cancellationToken)
53  {
54  var admin = await databaseContext.Users.Where(x => x.CanonicalName == Api.Models.User.AdminName.ToUpperInvariant()).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
55  if (admin == default)
56  SeedAdminUser(databaseContext);
57  else
58  {
59  admin.Enabled = true;
60  cryptographySuite.SetUserPassword(admin, Api.Models.User.DefaultAdminPassword, false);
61  }
62 
63  await databaseContext.Save(cancellationToken).ConfigureAwait(false);
64  }
65  }
66 }
-
async Task ResetAdminPassword(IDatabaseContext databaseContext, CancellationToken cancellationToken)
Changes the admin password in IDatabaseContext back to it's default and enables the account
- -
readonly ICryptographySuite cryptographySuite
The ICryptographySuite for the DatabaseContext<TParentContext>
+Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using System;
3 using System.Linq;
4 using System.Threading;
5 using System.Threading.Tasks;
9 
11 {
14  {
19 
25  {
26  this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite));
27  }
28 
33  void SeedAdminUser(IDatabaseContext databaseContext)
34  {
35  var admin = new User
36  {
38  CreatedAt = DateTimeOffset.Now,
40  Name = Api.Models.User.AdminName,
41  CanonicalName = Api.Models.User.AdminName.ToUpperInvariant(),
42  Enabled = true,
43  };
44  cryptographySuite.SetUserPassword(admin, Api.Models.User.DefaultAdminPassword, true);
45  databaseContext.Users.Add(admin);
46  }
47 
49  public async Task SeedDatabase(IDatabaseContext databaseContext, CancellationToken cancellationToken)
50  {
51  SeedAdminUser(databaseContext);
52  await databaseContext.Save(cancellationToken).ConfigureAwait(false);
53  }
54 
56  public async Task ResetAdminPassword(IDatabaseContext databaseContext, CancellationToken cancellationToken)
57  {
58  var admin = await databaseContext.Users.Where(x => x.CanonicalName == Api.Models.User.AdminName.ToUpperInvariant()).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
59  if (admin == default)
60  SeedAdminUser(databaseContext);
61  else
62  {
63  admin.Enabled = true;
64  cryptographySuite.SetUserPassword(admin, Api.Models.User.DefaultAdminPassword, false);
65  }
66 
67  await databaseContext.Save(cancellationToken).ConfigureAwait(false);
68  }
69  }
70 }
+
readonly ICryptographySuite cryptographySuite
The ICryptographySuite for the DatabaseContext<TParentContext>
-
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
-
For initially seeding a database
-
DbSet< User > Users
The Users in the IDatabaseContext
+
For initially seeding a database
+ +
async Task SeedDatabase(IDatabaseContext databaseContext, CancellationToken cancellationToken)
Initially seed a given databaseContext
AdministrationRights
Rights for Models.Administration
-
async Task SeedDatabase(IDatabaseContext databaseContext, CancellationToken cancellationToken)
Initially seed a given databaseContext
Contains various cryptographic functions
-
DatabaseSeeder(ICryptographySuite cryptographySuite)
Construct a DatabaseSeeder
+ +
async Task ResetAdminPassword(IDatabaseContext databaseContext, CancellationToken cancellationToken)
Changes the admin password in IDatabaseContext back to it's default and enables the account
InstanceManagerRights
Rights for managing Models.Instances
-
void SeedAdminUser(IDatabaseContext databaseContext)
Add a default admin User to a given databaseContext
+
DatabaseSeeder(ICryptographySuite cryptographySuite)
Construct a DatabaseSeeder
void SetUserPassword(User user, string newPassword, bool newUser)
Sets a User.PasswordHash for a given user
- +
DbSet< User > Users
The Users in the IDatabaseContext
+
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
+
void SeedAdminUser(IDatabaseContext databaseContext)
Add a default admin User to a given databaseContext
+
diff --git a/_dead_session_controller_8cs_source.html b/_dead_session_controller_8cs_source.html index 684de69c70..d6b02980c0 100644 --- a/_dead_session_controller_8cs_source.html +++ b/_dead_session_controller_8cs_source.html @@ -71,30 +71,38 @@ $(function() {
DeadSessionController.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
6 {
11  {
13  public Task<LaunchResult> LaunchResult { get; }
14 
16  public bool IsPrimary => false;
17 
19  public bool TerminationWasRequested => false;
20 
22  public ApiValidationStatus ApiValidationStatus => throw new NotSupportedException();
23 
25  public IDmbProvider Dmb { get; }
26 
28  public ushort? Port => null;
29 
31  public bool ClosePortOnReboot
32  {
33  get => false;
34  set => throw new NotSupportedException();
35  }
36 
38  public RebootState RebootState => throw new NotSupportedException();
39 
41  public Task OnReboot { get; }
42 
44  public Task<int> Lifetime { get; }
45 
49  bool disposed;
50 
55  public DeadSessionController(IDmbProvider dmbProvider)
56  {
57  Dmb = dmbProvider ?? throw new ArgumentNullException(nameof(dmbProvider));
58  LaunchResult = Task.FromResult(new LaunchResult
59  {
60  StartupTime = TimeSpan.FromSeconds(0)
61  });
62  Lifetime = Task.FromResult(-1);
63  OnReboot = new TaskCompletionSource<object>().Task;
64  }
65 
67  public void Dispose()
68  {
69  lock (this)
70  {
71  if (disposed)
72  return;
73  disposed = true;
74  }
75 
76  Dmb.Dispose();
77  }
78 
80  public void EnableCustomChatCommands() => throw new NotSupportedException();
81 
83  public ReattachInformation Release() => throw new NotSupportedException();
84 
86  public void ResetRebootState() => throw new NotSupportedException();
87 
89  public Task<string> SendCommand(string command, CancellationToken cancellationToken) => throw new NotSupportedException();
90 
92  public void SetHighPriority() => throw new NotSupportedException();
93 
95  public Task<bool> SetPort(ushort newPort, CancellationToken cancellatonToken) => throw new NotSupportedException();
96 
98  public Task<bool> SetRebootState(RebootState newRebootState, CancellationToken cancellationToken) => throw new NotSupportedException();
99  }
100 }
- +Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
12  {
14  public Task<LaunchResult> LaunchResult { get; }
15 
17  public bool IsPrimary => false;
18 
20  public bool TerminationWasRequested => false;
21 
23  public ApiValidationStatus ApiValidationStatus => throw new NotSupportedException();
24 
26  public IDmbProvider Dmb { get; }
27 
29  public ushort? Port => null;
30 
32  public bool ClosePortOnReboot
33  {
34  get => false;
35  set => throw new NotSupportedException();
36  }
37 
39  public RebootState RebootState => throw new NotSupportedException();
40 
42  public Task OnReboot { get; }
43 
45  public Task<int> Lifetime { get; }
46 
50  bool disposed;
51 
56  public DeadSessionController(IDmbProvider dmbProvider)
57  {
58  Dmb = dmbProvider ?? throw new ArgumentNullException(nameof(dmbProvider));
59  LaunchResult = Task.FromResult(new LaunchResult
60  {
61  StartupTime = TimeSpan.FromSeconds(0)
62  });
63  Lifetime = Task.FromResult(-1);
64  OnReboot = new TaskCompletionSource<object>().Task;
65  }
66 
68  public void Dispose()
69  {
70  lock (this)
71  {
72  if (disposed)
73  return;
74  disposed = true;
75  }
76 
77  Dmb.Dispose();
78  }
79 
81  public void EnableCustomChatCommands() => throw new NotSupportedException();
82 
84  public ReattachInformation Release() => throw new NotSupportedException();
85 
87  public void ResetRebootState() => throw new NotSupportedException();
88 
90  public Task<string> SendCommand(string command, CancellationToken cancellationToken) => throw new NotSupportedException();
91 
93  public void SetHighPriority() => throw new NotSupportedException();
94 
96  public Task<bool> SetPort(ushort newPort, CancellationToken cancellatonToken) => throw new NotSupportedException();
97 
99  public Task<bool> SetRebootState(RebootState newRebootState, CancellationToken cancellationToken) => throw new NotSupportedException();
100 
102  public void ReplaceDmbProvider(IDmbProvider newProvider) => throw new NotSupportedException();
103 
105  public void Suspend() => throw new NotSupportedException();
106 
108  public void Resume() => throw new NotSupportedException();
109  }
110 }
+
Represents the result of trying to start a DD process
Definition: LaunchResult.cs:9
- + + +
void ReplaceDmbProvider(IDmbProvider newProvider)
Replace Dmb with a given newProvider , disposing the old one.
+
Task< bool > SetPort(ushort newPort, CancellationToken cancellatonToken)
Causes the world to start listening on a newPort
-
Handles communication with a DreamDaemon IProcess
-
ReattachInformation Release()
Releases the IProcess without terminating it. Also calls System.IDisposable.Dispose
+
Handles communication with a DreamDaemon IProcess
+
ReattachInformation Release()
Releases the IProcess without terminating it. Also calls global::System.IDisposable....
Task< string > SendCommand(string command, CancellationToken cancellationToken)
Sends a command to DreamDaemon through /world/Topic()
-
void SetHighPriority()
Set's the owned System.Diagnostics.Process.PriorityClass to System.Diagnostics.ProcessPriorityClass....
- -
void ResetRebootState()
Changes RebootState to Components.Watchdog.RebootState.Normal without telling the DMAPI
- +
void SetHighPriority()
Set's the owned global::System.Diagnostics.Process.PriorityClass to global::System....
+ +
void ResetRebootState()
Changes RebootState to Watchdog.RebootState.Normal without telling the DMAPI
+
Task< bool > SetRebootState(RebootState newRebootState, CancellationToken cancellationToken)
Attempts to change the current RebootState to newRebootState
- - + + +
void EnableCustomChatCommands()
Enables the reading of custom chat commands from the ISessionController
- - -
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
-
DeadSessionController(IDmbProvider dmbProvider)
Construct a DeadSessionController
-
bool disposed
If the DeadSessionController was Disposed
+ + + + +
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
+
DeadSessionController(IDmbProvider dmbProvider)
Construct a DeadSessionController
+
bool disposed
If the DeadSessionController was Disposed
+
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
-
Parameters necessary for duplicating a ISessionController session
+
Parameters necessary for duplicating a ISessionController session
+
ApiValidationStatus
Status of DMAPI validation
diff --git a/_default_i_o_manager_8cs_source.html b/_default_i_o_manager_8cs_source.html index 035aa9edf1..6415945909 100644 --- a/_default_i_o_manager_8cs_source.html +++ b/_default_i_o_manager_8cs_source.html @@ -71,22 +71,22 @@ $(function() {
DefaultIOManager.cs
-Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Globalization;
4 using System.IO;
5 using System.IO.Compression;
6 using System.Linq;
7 using System.Net;
8 using System.Threading;
9 using System.Threading.Tasks;
10 
12 {
17  {
21  public const int DefaultBufferSize = 4096;
22 
29  static async Task NormalizeAndDelete(DirectoryInfo dir, CancellationToken cancellationToken)
30  {
31  var tasks = new List<Task>();
32 
33  foreach (var subDir in dir.EnumerateDirectories())
34  {
35  cancellationToken.ThrowIfCancellationRequested();
36 
37  // if below succeeds this is probably a symlink
38  if (!subDir.Attributes.HasFlag(FileAttributes.Directory) || subDir.Attributes.HasFlag(FileAttributes.ReparsePoint))
39  subDir.Delete();
40  else
41  tasks.Add(NormalizeAndDelete(subDir, cancellationToken));
42  }
43 
44  foreach (var file in dir.EnumerateFiles())
45  {
46  cancellationToken.ThrowIfCancellationRequested();
47  file.Attributes = FileAttributes.Normal;
48  file.Delete();
49  }
50 
51  await Task.WhenAll(tasks).ConfigureAwait(false);
52  cancellationToken.ThrowIfCancellationRequested();
53  dir.Delete(true);
54  }
55 
61  static FileStream OpenWriteStream(string path) => new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite, DefaultBufferSize, true);
62 
71  IEnumerable<Task> CopyDirectoryImpl(string src, string dest, IEnumerable<string> ignore, CancellationToken cancellationToken)
72  {
73  var dir = new DirectoryInfo(src);
74  var atLeastOneSubDir = false;
75  foreach (var I in dir.EnumerateDirectories())
76  {
77  if (ignore != null && ignore.Contains(I.Name))
78  continue;
79  foreach (var J in CopyDirectoryImpl(I.FullName, Path.Combine(dest, I.Name), null, cancellationToken))
80  {
81  atLeastOneSubDir = true;
82  yield return J;
83  }
84  }
85 
86  async Task CopyThisDirectory()
87  {
88  if (!atLeastOneSubDir)
89  await CreateDirectory(dest, cancellationToken).ConfigureAwait(false); // save on createdir calls
90 
91  var tasks = new List<Task>();
92 
93  await dir.EnumerateFiles().ToAsyncEnumerable().ForEachAsync(fileInfo =>
94  {
95  if (ignore != null && ignore.Contains(fileInfo.Name))
96  return;
97  tasks.Add(CopyFile(fileInfo.FullName, Path.Combine(dest, fileInfo.Name), cancellationToken));
98  }).ConfigureAwait(false);
99 
100  await Task.WhenAll(tasks).ConfigureAwait(false);
101  }
102 
103  yield return CopyThisDirectory();
104  }
105 
107  public async Task CopyDirectory(string src, string dest, IEnumerable<string> ignore, CancellationToken cancellationToken)
108  {
109  if (dest == null)
110  throw new ArgumentNullException(nameof(src));
111  if (dest == null)
112  throw new ArgumentNullException(nameof(src));
113 
114  src = ResolvePath(src);
115  dest = ResolvePath(dest);
116  foreach (var directoryCopy in CopyDirectoryImpl(src, dest, ignore, cancellationToken))
117  await directoryCopy.ConfigureAwait(false);
118  }
119 
121  public string ConcatPath(params string[] paths)
122  {
123  if (paths == null)
124  throw new ArgumentNullException(nameof(paths));
125  return Path.Combine(paths);
126  }
127 
129  public async Task CopyFile(string src, string dest, CancellationToken cancellationToken)
130  {
131  if (src == null)
132  throw new ArgumentNullException(nameof(src));
133  if (dest == null)
134  throw new ArgumentNullException(nameof(dest));
135  using (var srcStream = new FileStream(ResolvePath(src), FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete, DefaultBufferSize, true))
136  using (var destStream = new FileStream(ResolvePath(dest), FileMode.Create, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete, DefaultBufferSize, true))
137  await srcStream.CopyToAsync(destStream, 81920, cancellationToken).ConfigureAwait(false);
138  }
139 
141  public Task CreateDirectory(string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => Directory.CreateDirectory(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
142 
144  public async Task DeleteDirectory(string path, CancellationToken cancellationToken)
145  {
146  path = ResolvePath(path);
147  var di = new DirectoryInfo(path);
148  if (!di.Exists)
149  return;
150  await NormalizeAndDelete(di, cancellationToken).ConfigureAwait(false);
151  }
152 
154  public Task DeleteFile(string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => File.Delete(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
155 
157  public Task<bool> FileExists(string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => File.Exists(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
158 
160  public Task<bool> DirectoryExists(string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => Directory.Exists(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
161 
163  public string GetDirectoryName(string path) => Path.GetDirectoryName(path ?? throw new ArgumentNullException(nameof(path)));
164 
166  public string GetFileName(string path) => Path.GetFileName(path ?? throw new ArgumentNullException(nameof(path)));
167 
169  public string GetFileNameWithoutExtension(string path) => Path.GetFileNameWithoutExtension(path ?? throw new ArgumentNullException(nameof(path)));
170 
172  public Task<List<string>> GetFilesWithExtension(string path, string extension, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
173  {
174  path = ResolvePath(path);
175  if (extension == null)
176  throw new ArgumentNullException(extension);
177  var results = new List<string>();
178  foreach (var I in Directory.EnumerateFiles(path, String.Format(CultureInfo.InvariantCulture, "*.{0}", extension), SearchOption.TopDirectoryOnly))
179  {
180  cancellationToken.ThrowIfCancellationRequested();
181  results.Add(I);
182  }
183 
184  return results;
185  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
186 
188  public Task MoveFile(string source, string destination, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
189  {
190  if (destination == null)
191  throw new ArgumentNullException(nameof(destination));
192  source = ResolvePath(source ?? throw new ArgumentNullException(nameof(source)));
193  destination = ResolvePath(destination);
194  File.Move(source, destination);
195  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
196 
198  public Task MoveDirectory(string source, string destination, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
199  {
200  if (destination == null)
201  throw new ArgumentNullException(nameof(destination));
202  source = ResolvePath(source ?? throw new ArgumentNullException(nameof(source)));
203  destination = ResolvePath(destination);
204  Directory.Move(source, destination);
205  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
206 
208  public async Task<byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
209  {
210  path = ResolvePath(path);
211  using (var file = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete, DefaultBufferSize, true))
212  {
213  byte[] buf;
214  buf = new byte[file.Length];
215  await file.ReadAsync(buf, 0, (int)file.Length, cancellationToken).ConfigureAwait(false);
216  return buf;
217  }
218  }
219 
221  public virtual string ResolvePath(string path) => Path.GetFullPath(path ?? throw new ArgumentNullException(nameof(path)));
222 
224  public async Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
225  {
226  path = ResolvePath(path);
227  using (var file = OpenWriteStream(path))
228  await file.WriteAsync(contents, 0, contents.Length, cancellationToken).ConfigureAwait(false);
229  }
230 
232  public Task<IReadOnlyList<string>> GetDirectories(string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
233  {
234  path = ResolvePath(path);
235  var results = new List<string>();
236  cancellationToken.ThrowIfCancellationRequested();
237  foreach (var I in Directory.EnumerateDirectories(path))
238  {
239  results.Add(I);
240  cancellationToken.ThrowIfCancellationRequested();
241  }
242 
243  return (IReadOnlyList<string>)results;
244  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
245 
247  public Task<IReadOnlyList<string>> GetFiles(string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
248  {
249  path = ResolvePath(path);
250  var results = new List<string>();
251  cancellationToken.ThrowIfCancellationRequested();
252  foreach (var I in Directory.EnumerateFiles(path))
253  {
254  results.Add(I);
255  cancellationToken.ThrowIfCancellationRequested();
256  }
257 
258  return (IReadOnlyList<string>)results;
259  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
260 
262  public async Task<byte[]> DownloadFile(Uri url, CancellationToken cancellationToken)
263  {
264  // DownloadDataTaskAsync can't be cancelled and is shittily written, don't use it
265  using (var wc = new WebClient())
266  {
267  var tcs = new TaskCompletionSource<byte[]>();
268  wc.DownloadDataCompleted += (a, b) =>
269  {
270  if (b.Error != null)
271  tcs.TrySetException(b.Error);
272  else if (b.Cancelled)
273  tcs.TrySetCanceled();
274  else
275  tcs.TrySetResult(b.Result);
276  };
277  wc.DownloadDataAsync(url);
278  using (cancellationToken.Register(() =>
279  {
280  wc.CancelAsync();
281  tcs.TrySetCanceled();
282  }))
283  return await tcs.Task.ConfigureAwait(false);
284  }
285  }
286 
288  public Task ZipToDirectory(string path, byte[] zipFileBytes, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
289  {
290  path = ResolvePath(path);
291  if (zipFileBytes == null)
292  throw new ArgumentNullException(nameof(zipFileBytes));
293 
294  using (var ms = new MemoryStream(zipFileBytes))
295  using (var archive = new ZipArchive(ms, ZipArchiveMode.Read))
296  archive.ExtractToDirectory(path);
297  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
298 
300  public bool PathContainsParentAccess(string path) => path?.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }).Any(x => x == "..") ?? throw new ArgumentNullException(nameof(path));
301  }
302 }
async Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content
-
string ConcatPath(params string[] paths)
Combines an array of strings into a path
+Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Globalization;
4 using System.IO;
5 using System.IO.Compression;
6 using System.Linq;
7 using System.Net;
8 using System.Threading;
9 using System.Threading.Tasks;
10 
12 {
17  {
21  public const int DefaultBufferSize = 4096;
22 
29  static async Task NormalizeAndDelete(DirectoryInfo dir, CancellationToken cancellationToken)
30  {
31  var tasks = new List<Task>();
32 
33  // check if we are a symbolic link
34  if (!dir.Attributes.HasFlag(FileAttributes.Directory) || dir.Attributes.HasFlag(FileAttributes.ReparsePoint))
35  {
36  dir.Delete();
37  return;
38  }
39 
40  foreach (var subDir in dir.EnumerateDirectories())
41  {
42  cancellationToken.ThrowIfCancellationRequested();
43  tasks.Add(NormalizeAndDelete(subDir, cancellationToken));
44  }
45 
46  foreach (var file in dir.EnumerateFiles())
47  {
48  cancellationToken.ThrowIfCancellationRequested();
49  file.Attributes = FileAttributes.Normal;
50  file.Delete();
51  }
52 
53  await Task.WhenAll(tasks).ConfigureAwait(false);
54  cancellationToken.ThrowIfCancellationRequested();
55  dir.Delete(true);
56  }
57 
63  static FileStream OpenWriteStream(string path) => new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite, DefaultBufferSize, true);
64 
73  IEnumerable<Task> CopyDirectoryImpl(string src, string dest, IEnumerable<string> ignore, CancellationToken cancellationToken)
74  {
75  var dir = new DirectoryInfo(src);
76  var atLeastOneSubDir = false;
77  foreach (var I in dir.EnumerateDirectories())
78  {
79  if (ignore != null && ignore.Contains(I.Name))
80  continue;
81  foreach (var J in CopyDirectoryImpl(I.FullName, Path.Combine(dest, I.Name), null, cancellationToken))
82  {
83  atLeastOneSubDir = true;
84  yield return J;
85  }
86  }
87 
88  async Task CopyThisDirectory()
89  {
90  if (!atLeastOneSubDir)
91  await CreateDirectory(dest, cancellationToken).ConfigureAwait(false); // save on createdir calls
92 
93  var tasks = new List<Task>();
94 
95  await dir.EnumerateFiles().ToAsyncEnumerable().ForEachAsync(fileInfo =>
96  {
97  if (ignore != null && ignore.Contains(fileInfo.Name))
98  return;
99  tasks.Add(CopyFile(fileInfo.FullName, Path.Combine(dest, fileInfo.Name), cancellationToken));
100  }).ConfigureAwait(false);
101 
102  await Task.WhenAll(tasks).ConfigureAwait(false);
103  }
104 
105  yield return CopyThisDirectory();
106  }
107 
109  public async Task CopyDirectory(string src, string dest, IEnumerable<string> ignore, CancellationToken cancellationToken)
110  {
111  if (dest == null)
112  throw new ArgumentNullException(nameof(src));
113  if (dest == null)
114  throw new ArgumentNullException(nameof(src));
115 
116  src = ResolvePath(src);
117  dest = ResolvePath(dest);
118  foreach (var directoryCopy in CopyDirectoryImpl(src, dest, ignore, cancellationToken))
119  await directoryCopy.ConfigureAwait(false);
120  }
121 
123  public string ConcatPath(params string[] paths)
124  {
125  if (paths == null)
126  throw new ArgumentNullException(nameof(paths));
127  return Path.Combine(paths);
128  }
129 
131  public async Task CopyFile(string src, string dest, CancellationToken cancellationToken)
132  {
133  if (src == null)
134  throw new ArgumentNullException(nameof(src));
135  if (dest == null)
136  throw new ArgumentNullException(nameof(dest));
137  using (var srcStream = new FileStream(ResolvePath(src), FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete, DefaultBufferSize, true))
138  using (var destStream = new FileStream(ResolvePath(dest), FileMode.Create, FileAccess.Write, FileShare.ReadWrite | FileShare.Delete, DefaultBufferSize, true))
139  await srcStream.CopyToAsync(destStream, 81920, cancellationToken).ConfigureAwait(false);
140  }
141 
143  public Task CreateDirectory(string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => Directory.CreateDirectory(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
144 
146  public async Task DeleteDirectory(string path, CancellationToken cancellationToken)
147  {
148  path = ResolvePath(path);
149  var di = new DirectoryInfo(path);
150  if (!di.Exists)
151  return;
152  await NormalizeAndDelete(di, cancellationToken).ConfigureAwait(false);
153  }
154 
156  public Task DeleteFile(string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => File.Delete(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
157 
159  public Task<bool> FileExists(string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => File.Exists(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
160 
162  public Task<bool> DirectoryExists(string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() => Directory.Exists(ResolvePath(path)), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
163 
165  public string GetDirectoryName(string path) => Path.GetDirectoryName(path ?? throw new ArgumentNullException(nameof(path)));
166 
168  public string GetFileName(string path) => Path.GetFileName(path ?? throw new ArgumentNullException(nameof(path)));
169 
171  public string GetFileNameWithoutExtension(string path) => Path.GetFileNameWithoutExtension(path ?? throw new ArgumentNullException(nameof(path)));
172 
174  public Task<List<string>> GetFilesWithExtension(string path, string extension, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
175  {
176  path = ResolvePath(path);
177  if (extension == null)
178  throw new ArgumentNullException(extension);
179  var results = new List<string>();
180  foreach (var I in Directory.EnumerateFiles(path, String.Format(CultureInfo.InvariantCulture, "*.{0}", extension), SearchOption.TopDirectoryOnly))
181  {
182  cancellationToken.ThrowIfCancellationRequested();
183  results.Add(I);
184  }
185 
186  return results;
187  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
188 
190  public Task MoveFile(string source, string destination, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
191  {
192  if (destination == null)
193  throw new ArgumentNullException(nameof(destination));
194  source = ResolvePath(source ?? throw new ArgumentNullException(nameof(source)));
195  destination = ResolvePath(destination);
196  File.Move(source, destination);
197  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
198 
200  public Task MoveDirectory(string source, string destination, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
201  {
202  if (destination == null)
203  throw new ArgumentNullException(nameof(destination));
204  source = ResolvePath(source ?? throw new ArgumentNullException(nameof(source)));
205  destination = ResolvePath(destination);
206  Directory.Move(source, destination);
207  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
208 
210  public async Task<byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
211  {
212  path = ResolvePath(path);
213  using (var file = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete, DefaultBufferSize, true))
214  {
215  byte[] buf;
216  buf = new byte[file.Length];
217  await file.ReadAsync(buf, 0, (int)file.Length, cancellationToken).ConfigureAwait(false);
218  return buf;
219  }
220  }
221 
223  public virtual string ResolvePath(string path) => Path.GetFullPath(path ?? throw new ArgumentNullException(nameof(path)));
224 
226  public async Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
227  {
228  path = ResolvePath(path);
229  using (var file = OpenWriteStream(path))
230  await file.WriteAsync(contents, 0, contents.Length, cancellationToken).ConfigureAwait(false);
231  }
232 
234  public Task<IReadOnlyList<string>> GetDirectories(string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
235  {
236  path = ResolvePath(path);
237  var results = new List<string>();
238  cancellationToken.ThrowIfCancellationRequested();
239  foreach (var I in Directory.EnumerateDirectories(path))
240  {
241  results.Add(I);
242  cancellationToken.ThrowIfCancellationRequested();
243  }
244 
245  return (IReadOnlyList<string>)results;
246  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
247 
249  public Task<IReadOnlyList<string>> GetFiles(string path, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
250  {
251  path = ResolvePath(path);
252  var results = new List<string>();
253  cancellationToken.ThrowIfCancellationRequested();
254  foreach (var I in Directory.EnumerateFiles(path))
255  {
256  results.Add(I);
257  cancellationToken.ThrowIfCancellationRequested();
258  }
259 
260  return (IReadOnlyList<string>)results;
261  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
262 
264  public async Task<byte[]> DownloadFile(Uri url, CancellationToken cancellationToken)
265  {
266  // DownloadDataTaskAsync can't be cancelled and is shittily written, don't use it
267  using (var wc = new WebClient())
268  {
269  var tcs = new TaskCompletionSource<byte[]>();
270  wc.DownloadDataCompleted += (a, b) =>
271  {
272  if (b.Error != null)
273  tcs.TrySetException(b.Error);
274  else if (b.Cancelled)
275  tcs.TrySetCanceled();
276  else
277  tcs.TrySetResult(b.Result);
278  };
279  wc.DownloadDataAsync(url);
280  using (cancellationToken.Register(() =>
281  {
282  wc.CancelAsync();
283  tcs.TrySetCanceled();
284  }))
285  return await tcs.Task.ConfigureAwait(false);
286  }
287  }
288 
290  public Task ZipToDirectory(string path, byte[] zipFileBytes, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
291  {
292  path = ResolvePath(path);
293  if (zipFileBytes == null)
294  throw new ArgumentNullException(nameof(zipFileBytes));
295 
296  using (var ms = new MemoryStream(zipFileBytes))
297  using (var archive = new ZipArchive(ms, ZipArchiveMode.Read))
298  archive.ExtractToDirectory(path);
299  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
300 
302  public bool PathContainsParentAccess(string path) => path?.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }).Any(x => x == "..") ?? throw new ArgumentNullException(nameof(path));
303  }
304 }
async Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content
+
string ConcatPath(params string[] paths)
Combines an array of strings into a path
Task< bool > DirectoryExists(string path, CancellationToken cancellationToken)
Check that the directory at path exists
-
async Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
-
async Task CopyFile(string src, string dest, CancellationToken cancellationToken)
Copy a file from src to dest
+
async Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory, removes and does not enter any symlinks encounterd.
+
async Task CopyFile(string src, string dest, CancellationToken cancellationToken)
Copy a file from src to dest
Task MoveFile(string source, string destination, CancellationToken cancellationToken)
Moves a file at source to destination
string GetDirectoryName(string path)
Gets the directory portion of a given path
static async Task NormalizeAndDelete(DirectoryInfo dir, CancellationToken cancellationToken)
Recursively empty a directory
Task ZipToDirectory(string path, byte[] zipFileBytes, CancellationToken cancellationToken)
Extract a set of zipFileBytes to a given path
-
async Task CopyDirectory(string src, string dest, IEnumerable< string > ignore, CancellationToken cancellationToken)
Copies a directory from src to dest
+
async Task CopyDirectory(string src, string dest, IEnumerable< string > ignore, CancellationToken cancellationToken)
Copies a directory from src to dest
Task< bool > FileExists(string path, CancellationToken cancellationToken)
Check that the file at path exists
-
async Task< byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
Returns all the contents of a file at path as a byte array
+
async Task< byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
Returns all the contents of a file at path as a byte array
string GetFileNameWithoutExtension(string path)
Gets the file name portion of a path with
-
IEnumerable< Task > CopyDirectoryImpl(string src, string dest, IEnumerable< string > ignore, CancellationToken cancellationToken)
Copies a directory from src to dest
+
IEnumerable< Task > CopyDirectoryImpl(string src, string dest, IEnumerable< string > ignore, CancellationToken cancellationToken)
Copies a directory from src to dest
Task< List< string > > GetFilesWithExtension(string path, string extension, CancellationToken cancellationToken)
Gets a list of files in path with the given extension
-
async Task< byte[]> DownloadFile(Uri url, CancellationToken cancellationToken)
Downloads a file from url
+
async Task< byte[]> DownloadFile(Uri url, CancellationToken cancellationToken)
Downloads a file from url
Task< IReadOnlyList< string > > GetFiles(string path, CancellationToken cancellationToken)
Returns file names in a given path
Task MoveDirectory(string source, string destination, CancellationToken cancellationToken)
Moves a directory at source to destination
IIOManager that resolves paths to Environment.CurrentDirectory
diff --git a/_design_time_db_context_factory_helpers_8cs.html b/_design_time_db_context_factory_helpers_8cs.html index b0e9596729..301bc4ccc5 100644 --- a/_design_time_db_context_factory_helpers_8cs.html +++ b/_design_time_db_context_factory_helpers_8cs.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Models/Migrations/DesignTimeDbContextFactoryHelpers.cs File Reference +tgstation-server: src/Tgstation.Server.Host/Database/Design/DesignTimeDbContextFactoryHelpers.cs File Reference @@ -63,7 +63,7 @@ $(function() {
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

class  Tgstation.Server.Host.Models.Migrations.DesignTimeDbContextFactoryHelpers
 Contains helpers for creating design time DatabaseContext<TParentContext>s More...
class  Tgstation.Server.Host.Database.Design.DesignTimeDbContextFactoryHelpers
 Contains helpers for creating design time DatabaseContext<TParentContext>s More...
 
- + - +

@@ -91,9 +91,9 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
namespace  Tgstation.Server.Host.Database
 
namespace  Tgstation.Server.Host.Models.Migrations
namespace  Tgstation.Server.Host.Database.Design
 
diff --git a/_design_time_db_context_factory_helpers_8cs_source.html b/_design_time_db_context_factory_helpers_8cs_source.html index e4a2c3da3d..7418109283 100644 --- a/_design_time_db_context_factory_helpers_8cs_source.html +++ b/_design_time_db_context_factory_helpers_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Models/Migrations/DesignTimeDbContextFactoryHelpers.cs Source File +tgstation-server: src/Tgstation.Server.Host/Database/Design/DesignTimeDbContextFactoryHelpers.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,20 +71,20 @@ $(function() {
DesignTimeDbContextFactoryHelpers.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Configuration;
2 using Microsoft.Extensions.Options;
5 using Tgstation.Server.Host.IO;
6 
8 {
13  {
17  const string RootJson = "appsettings.json";
18 
22  const string DevJson = "appsettings.Development.json";
23 
28  public static IOptions<DatabaseConfiguration> GetDbContextOptions()
29  {
30  var builder = new ConfigurationBuilder();
31  var assemblyInfoProvider = new AssemblyInformationProvider();
32  var ioManager = new DefaultIOManager();
33  builder.SetBasePath(ioManager.GetDirectoryName(assemblyInfoProvider.Path));
34  builder.AddJsonFile(RootJson);
35  builder.AddJsonFile(DevJson);
36  var configuration = builder.Build();
37  return Options.Create(configuration.GetSection(DatabaseConfiguration.Section).Get<DatabaseConfiguration>());
38  }
39  }
40 }
static IOptions< DatabaseConfiguration > GetDbContextOptions()
Get the IOptions<TOptions> for the DatabaseConfiguration
- -
Contains helpers for creating design time DatabaseContext<TParentContext>s
+Go to the documentation of this file.
1 using Microsoft.Extensions.Configuration;
2 using Microsoft.Extensions.Options;
4 using Tgstation.Server.Host.IO;
6 
8 {
13  {
17  const string RootJson = "appsettings.json";
18 
22  const string DevJson = "appsettings.Development.json";
23 
28  public static IOptions<DatabaseConfiguration> GetDbContextOptions()
29  {
30  var builder = new ConfigurationBuilder();
31  var assemblyInfoProvider = new AssemblyInformationProvider();
32  var ioManager = new DefaultIOManager();
33  builder.SetBasePath(ioManager.GetDirectoryName(assemblyInfoProvider.Path));
34  builder.AddJsonFile(RootJson);
35  builder.AddJsonFile(DevJson);
36  var configuration = builder.Build();
37  return Options.Create(configuration.GetSection(DatabaseConfiguration.Section).Get<DatabaseConfiguration>());
38  }
39  }
40 }
+ +
const string RootJson
Path to the json file to use for migrations configuration
const string Section
The key for the Microsoft.Extensions.Configuration.IConfigurationSection the DatabaseConfiguration re...
- -
const string DevJson
Path to the development json file to use for migrations configuration
-
Configuration options for the Models.DatabaseContext<TParentContext>
+
Configuration options for the Database.DatabaseContext<TParentContext>
+
IIOManager that resolves paths to Environment.CurrentDirectory
+
Contains helpers for creating design time DatabaseContext<TParentContext>s
-
const string RootJson
Path to the json file to use for migrations configuration
- +
static IOptions< DatabaseConfiguration > GetDbContextOptions()
Get the IOptions<TOptions> for the DatabaseConfiguration
+
const string DevJson
Path to the development json file to use for migrations configuration
diff --git a/_dmb_factory_8cs.html b/_dmb_factory_8cs.html index fa127f4c53..2378b54a80 100644 --- a/_dmb_factory_8cs.html +++ b/_dmb_factory_8cs.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Components/Compiler/DmbFactory.cs File Reference +tgstation-server: src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs File Reference @@ -63,7 +63,7 @@ $(function() {
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

class  Tgstation.Server.Host.Components.Compiler.DmbFactory
 Standard IDmbFactory More...
class  Tgstation.Server.Host.Components.Deployment.DmbFactory
 Standard IDmbFactory More...
 
- +

@@ -93,7 +93,7 @@ Namespaces

 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Compiler
namespace  Tgstation.Server.Host.Components.Deployment
 
diff --git a/_dmb_factory_8cs_source.html b/_dmb_factory_8cs_source.html index c436301406..6877a58645 100644 --- a/_dmb_factory_8cs_source.html +++ b/_dmb_factory_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Components/Compiler/DmbFactory.cs Source File +tgstation-server: src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,51 +71,51 @@ $(function() {
DmbFactory.cs
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 using System.Threading;
7 using System.Threading.Tasks;
9 using Tgstation.Server.Host.IO;
11 
13 {
18  {
20  public Task OnNewerDmb
21  {
22  get
23  {
24  lock (this)
25  return newerDmbTcs.Task;
26  }
27  }
28 
30  public bool DmbAvailable => nextDmbProvider != null;
31 
36 
41 
45  readonly ILogger<DmbFactory> logger;
46 
50  readonly Api.Models.Instance instance;
51 
55  readonly CancellationTokenSource cleanupCts;
56 
60  readonly IDictionary<long, int> jobLockCounts;
61 
66 
70  TaskCompletionSource<object> newerDmbTcs;
71 
76 
85  {
86  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
87  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
88  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
89  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
90 
91  cleanupTask = Task.CompletedTask;
92  newerDmbTcs = new TaskCompletionSource<object>();
93  cleanupCts = new CancellationTokenSource();
94  jobLockCounts = new Dictionary<long, int>();
95  }
96 
98  public void Dispose() => cleanupCts.Dispose(); // we don't dispose nextDmbProvider here, since it might be the only thing we have
99 
105  {
106  async Task HandleCleanup()
107  {
108  var deleteJob = ioManager.DeleteDirectory(job.DirectoryName.ToString(), cleanupCts.Token);
109  Task otherTask;
110 
111  // lock (this) //already locked below
112  otherTask = cleanupTask;
113  await Task.WhenAll(otherTask, deleteJob).ConfigureAwait(false);
114  }
115 
116  lock (this)
117  if (!jobLockCounts.TryGetValue(job.Id, out var currentVal) || currentVal == 1)
118  {
119  jobLockCounts.Remove(job.Id);
120  logger.LogDebug("Cleaning compile job {0} => {1}", job.Id, job.DirectoryName);
121  cleanupTask = HandleCleanup();
122  }
123  else
124  {
125  var decremented = --jobLockCounts[job.Id];
126  logger.LogTrace("Compile job {0} lock count now: {1}", job.Id, decremented);
127  }
128  }
129 
131  public async Task LoadCompileJob(CompileJob job, CancellationToken cancellationToken)
132  {
133  if (job == null)
134  throw new ArgumentNullException(nameof(job));
135 
136  var newProvider = await FromCompileJob(job, cancellationToken).ConfigureAwait(false);
137  if (newProvider == null)
138  return;
139  lock (this)
140  {
141  nextDmbProvider?.Dispose();
142  nextDmbProvider = newProvider;
143  newerDmbTcs.SetResult(nextDmbProvider);
144  newerDmbTcs = new TaskCompletionSource<object>();
145  }
146  }
147 
149  public IDmbProvider LockNextDmb(int lockCount)
150  {
151  if (!DmbAvailable)
152  throw new InvalidOperationException("No .dmb available!");
153  if (lockCount < 0)
154  throw new ArgumentOutOfRangeException(nameof(lockCount), lockCount, "lockCount must be greater than or equal to 0!");
155  lock (this)
156  {
157  var jobId = nextDmbProvider.CompileJob.Id;
158  var incremented = jobLockCounts[jobId] += lockCount;
159  logger.LogTrace("Compile job {0} lock count now: {1}", jobId, incremented);
160  return nextDmbProvider;
161  }
162  }
163 
165  public Task StartAsync(CancellationToken cancellationToken) => databaseContextFactory.UseContext(async (db) =>
166  {
167  // where complete clause not necessary, only successful COMPILEjobs get in the db
168  var cj = await db.CompileJobs.Where(x => x.Job.Instance.Id == instance.Id)
169  .OrderByDescending(x => x.Job.StoppedAt).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
170  if (cj == default(CompileJob))
171  return;
172  await LoadCompileJob(cj, cancellationToken).ConfigureAwait(false);
173 
174  // we dont do CleanUnusedCompileJobs here because the watchdog may have plans for them yet
175  });
176 
178  public async Task StopAsync(CancellationToken cancellationToken)
179  {
180  using (cancellationToken.Register(() => cleanupCts.Cancel()))
181  await cleanupTask.ConfigureAwait(false);
182  }
183 
185  #pragma warning disable CA1506 // TODO: Decomplexify
186  public async Task<IDmbProvider> FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken)
187  {
188  if (compileJob == null)
189  throw new ArgumentNullException(nameof(compileJob));
190 
191  // ensure we have the entire compile job tree
192  await databaseContextFactory.UseContext(async db => compileJob = await db.CompileJobs.Where(x => x.Id == compileJob.Id)
193  .Include(x => x.Job).ThenInclude(x => x.StartedBy)
194  .Include(x => x.RevisionInformation).ThenInclude(x => x.PrimaryTestMerge).ThenInclude(x => x.MergedBy)
195  .Include(x => x.RevisionInformation).ThenInclude(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).ThenInclude(x => x.MergedBy)
196  .FirstAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false); // can't wait to see that query
197 
198  logger.LogTrace("Loading compile job {0}...", compileJob.Id);
199  var providerSubmitted = false;
200  var newProvider = new DmbProvider(compileJob, ioManager, () =>
201  {
202  if (providerSubmitted)
203  CleanJob(compileJob);
204  });
205 
206  try
207  {
208  var primaryCheckTask = ioManager.FileExists(ioManager.ConcatPath(newProvider.PrimaryDirectory, newProvider.DmbName), cancellationToken);
209  var secondaryCheckTask = ioManager.FileExists(ioManager.ConcatPath(newProvider.PrimaryDirectory, newProvider.DmbName), cancellationToken);
210 
211  if (!(await primaryCheckTask.ConfigureAwait(false) && await secondaryCheckTask.ConfigureAwait(false)))
212  {
213  logger.LogWarning("Error loading compile job, .dmb missing!");
214  return null; // omae wa mou shinderu
215  }
216 
217  lock (this)
218  {
219  if (!jobLockCounts.TryGetValue(compileJob.Id, out int value))
220  {
221  value = 1;
222  jobLockCounts.Add(compileJob.Id, 1);
223  }
224  else
225  jobLockCounts[compileJob.Id] = ++value;
226 
227  logger.LogTrace("Compile job {0} lock count now: {1}", compileJob.Id, value);
228 
229  providerSubmitted = true;
230  return newProvider;
231  }
232  }
233  finally
234  {
235  if (!providerSubmitted)
236  newProvider.Dispose();
237  }
238  }
239  #pragma warning restore CA1506
240 
242  #pragma warning disable CA1506 // TODO: Decomplexify
243  public async Task CleanUnusedCompileJobs(CompileJob exceptThisOne, CancellationToken cancellationToken)
244  {
245  List<long> jobIdsToSkip;
246 
247  // don't clean locked directories
248  lock (this)
249  jobIdsToSkip = jobLockCounts.Select(x => x.Key).ToList();
250 
251  List<string> jobUidsToNotErase = null;
252 
253  // find the uids of locked directories
254  await databaseContextFactory.UseContext(async db =>
255  {
256  jobUidsToNotErase = await db.CompileJobs.Where(x => x.Job.Instance.Id == instance.Id && jobIdsToSkip.Contains(x.Id)).Select(x => x.DirectoryName.Value.ToString().ToUpperInvariant()).ToListAsync(cancellationToken).ConfigureAwait(false);
257  }).ConfigureAwait(false);
258 
259  // add the other exemption
260  if (exceptThisOne != null)
261  jobUidsToNotErase.Add(exceptThisOne.DirectoryName.Value.ToString().ToUpperInvariant());
262 
263  // cleanup
264  await ioManager.CreateDirectory(".", cancellationToken).ConfigureAwait(false);
265  var directories = await ioManager.GetDirectories(".", cancellationToken).ConfigureAwait(false);
266  int deleting = 0;
267  var tasks = directories.Select(async x =>
268  {
269  var nameOnly = ioManager.GetFileName(x);
270  if (jobUidsToNotErase.Contains(nameOnly.ToUpperInvariant()))
271  return;
272  try
273  {
274  ++deleting;
275  await ioManager.DeleteDirectory(x, cancellationToken).ConfigureAwait(false);
276  }
277  catch (OperationCanceledException)
278  {
279  throw;
280  }
281  catch (Exception e)
282  {
283  logger.LogWarning("Error deleting directory {0}! Exception: {1}", x, e);
284  }
285  }).ToList();
286  if (deleting > 0)
287  {
288  logger.LogDebug("Cleaning {0} unused game folders...", deleting);
289  await Task.WhenAll().ConfigureAwait(false);
290  }
291  }
292  #pragma warning restore CA1506
293  }
294 }
-
IDmbProvider nextDmbProvider
The latest DmbProvider
Definition: DmbFactory.cs:75
-
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
-
Task cleanupTask
Task representing calls to CleanJob(CompileJob)
Definition: DmbFactory.cs:65
-
CompileJob CompileJob
The CompileJob of the .dmb
Definition: IDmbProvider.cs:29
+Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 using System.Threading;
7 using System.Threading.Tasks;
9 using Tgstation.Server.Host.IO;
11 
13 {
18  {
20  public Task OnNewerDmb
21  {
22  get
23  {
24  lock (this)
25  return newerDmbTcs.Task;
26  }
27  }
28 
30  public bool DmbAvailable => nextDmbProvider != null;
31 
36 
41 
45  readonly ILogger<DmbFactory> logger;
46 
50  readonly Api.Models.Instance instance;
51 
55  readonly CancellationTokenSource cleanupCts;
56 
60  readonly IDictionary<long, int> jobLockCounts;
61 
66 
70  TaskCompletionSource<object> newerDmbTcs;
71 
76 
85  {
86  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
87  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
88  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
89  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
90 
91  cleanupTask = Task.CompletedTask;
92  newerDmbTcs = new TaskCompletionSource<object>();
93  cleanupCts = new CancellationTokenSource();
94  jobLockCounts = new Dictionary<long, int>();
95  }
96 
98  public void Dispose() => cleanupCts.Dispose(); // we don't dispose nextDmbProvider here, since it might be the only thing we have
99 
105  {
106  async Task HandleCleanup()
107  {
108  var deleteJob = ioManager.DeleteDirectory(job.DirectoryName.ToString(), cleanupCts.Token);
109  Task otherTask;
110 
111  // lock (this) //already locked below
112  otherTask = cleanupTask;
113  await Task.WhenAll(otherTask, deleteJob).ConfigureAwait(false);
114  }
115 
116  lock (this)
117  if (!jobLockCounts.TryGetValue(job.Id, out var currentVal) || currentVal == 1)
118  {
119  jobLockCounts.Remove(job.Id);
120  logger.LogDebug("Cleaning compile job {0} => {1}", job.Id, job.DirectoryName);
121  cleanupTask = HandleCleanup();
122  }
123  else
124  {
125  var decremented = --jobLockCounts[job.Id];
126  logger.LogTrace("Compile job {0} lock count now: {1}", job.Id, decremented);
127  }
128  }
129 
131  public async Task LoadCompileJob(CompileJob job, CancellationToken cancellationToken)
132  {
133  if (job == null)
134  throw new ArgumentNullException(nameof(job));
135 
136  var newProvider = await FromCompileJob(job, cancellationToken).ConfigureAwait(false);
137  if (newProvider == null)
138  return;
139  lock (this)
140  {
141  nextDmbProvider?.Dispose();
142  nextDmbProvider = newProvider;
143  newerDmbTcs.SetResult(nextDmbProvider);
144  newerDmbTcs = new TaskCompletionSource<object>();
145  }
146  }
147 
149  public IDmbProvider LockNextDmb(int lockCount)
150  {
151  if (!DmbAvailable)
152  throw new InvalidOperationException("No .dmb available!");
153  if (lockCount < 0)
154  throw new ArgumentOutOfRangeException(nameof(lockCount), lockCount, "lockCount must be greater than or equal to 0!");
155  lock (this)
156  {
157  var jobId = nextDmbProvider.CompileJob.Id;
158  var incremented = jobLockCounts[jobId] += lockCount;
159  logger.LogTrace("Compile job {0} lock count now: {1}", jobId, incremented);
160  return nextDmbProvider;
161  }
162  }
163 
165  public Task StartAsync(CancellationToken cancellationToken) => databaseContextFactory.UseContext(async (db) =>
166  {
167  // where complete clause not necessary, only successful COMPILEjobs get in the db
168  var cj = await db.CompileJobs.Where(x => x.Job.Instance.Id == instance.Id)
169  .OrderByDescending(x => x.Job.StoppedAt).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
170  if (cj == default(CompileJob))
171  return;
172  await LoadCompileJob(cj, cancellationToken).ConfigureAwait(false);
173 
174  // we dont do CleanUnusedCompileJobs here because the watchdog may have plans for them yet
175  });
176 
178  public async Task StopAsync(CancellationToken cancellationToken)
179  {
180  using (cancellationToken.Register(() => cleanupCts.Cancel()))
181  await cleanupTask.ConfigureAwait(false);
182  }
183 
185  #pragma warning disable CA1506 // TODO: Decomplexify
186  public async Task<IDmbProvider> FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken)
187  {
188  if (compileJob == null)
189  throw new ArgumentNullException(nameof(compileJob));
190 
191  // ensure we have the entire compile job tree
192  await databaseContextFactory.UseContext(async db => compileJob = await db.CompileJobs.Where(x => x.Id == compileJob.Id)
193  .Include(x => x.Job).ThenInclude(x => x.StartedBy)
194  .Include(x => x.RevisionInformation).ThenInclude(x => x.PrimaryTestMerge).ThenInclude(x => x.MergedBy)
195  .Include(x => x.RevisionInformation).ThenInclude(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).ThenInclude(x => x.MergedBy)
196  .FirstAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false); // can't wait to see that query
197 
198  logger.LogTrace("Loading compile job {0}...", compileJob.Id);
199  var providerSubmitted = false;
200  var newProvider = new DmbProvider(compileJob, ioManager, () =>
201  {
202  if (providerSubmitted)
203  CleanJob(compileJob);
204  });
205 
206  try
207  {
208  var primaryCheckTask = ioManager.FileExists(ioManager.ConcatPath(newProvider.PrimaryDirectory, newProvider.DmbName), cancellationToken);
209  var secondaryCheckTask = ioManager.FileExists(ioManager.ConcatPath(newProvider.PrimaryDirectory, newProvider.DmbName), cancellationToken);
210 
211  if (!(await primaryCheckTask.ConfigureAwait(false) && await secondaryCheckTask.ConfigureAwait(false)))
212  {
213  logger.LogWarning("Error loading compile job, .dmb missing!");
214  return null; // omae wa mou shinderu
215  }
216 
217  lock (this)
218  {
219  if (!jobLockCounts.TryGetValue(compileJob.Id, out int value))
220  {
221  value = 1;
222  jobLockCounts.Add(compileJob.Id, 1);
223  }
224  else
225  jobLockCounts[compileJob.Id] = ++value;
226 
227  logger.LogTrace("Compile job {0} lock count now: {1}", compileJob.Id, value);
228 
229  providerSubmitted = true;
230  return newProvider;
231  }
232  }
233  finally
234  {
235  if (!providerSubmitted)
236  newProvider.Dispose();
237  }
238  }
239  #pragma warning restore CA1506
240 
242  #pragma warning disable CA1506 // TODO: Decomplexify
243  public async Task CleanUnusedCompileJobs(CompileJob exceptThisOne, CancellationToken cancellationToken)
244  {
245  List<long> jobIdsToSkip;
246 
247  // don't clean locked directories
248  lock (this)
249  jobIdsToSkip = jobLockCounts.Select(x => x.Key).ToList();
250 
251  List<string> jobUidsToNotErase = null;
252 
253  // find the uids of locked directories
254  await databaseContextFactory.UseContext(async db =>
255  {
256  jobUidsToNotErase = await db.CompileJobs.Where(x => x.Job.Instance.Id == instance.Id && jobIdsToSkip.Contains(x.Id)).Select(x => x.DirectoryName.Value.ToString().ToUpperInvariant()).ToListAsync(cancellationToken).ConfigureAwait(false);
257  }).ConfigureAwait(false);
258 
259  // add the other exemption
260  if (exceptThisOne != null)
261  jobUidsToNotErase.Add(exceptThisOne.DirectoryName.Value.ToString().ToUpperInvariant());
262 
263  // cleanup
264  await ioManager.CreateDirectory(".", cancellationToken).ConfigureAwait(false);
265  var directories = await ioManager.GetDirectories(".", cancellationToken).ConfigureAwait(false);
266  int deleting = 0;
267  var tasks = directories.Select(async x =>
268  {
269  var nameOnly = ioManager.GetFileName(x);
270  if (jobUidsToNotErase.Contains(nameOnly.ToUpperInvariant()))
271  return;
272  try
273  {
274  ++deleting;
275  await ioManager.DeleteDirectory(x, cancellationToken).ConfigureAwait(false);
276  }
277  catch (OperationCanceledException)
278  {
279  throw;
280  }
281  catch (Exception e)
282  {
283  logger.LogWarning("Error deleting directory {0}! Exception: {1}", x, e);
284  }
285  }).ToList();
286  if (deleting > 0)
287  {
288  logger.LogDebug("Cleaning {0} unused game folders...", deleting);
289  await Task.WhenAll().ConfigureAwait(false);
290  }
291  }
292  #pragma warning restore CA1506
293  }
294 }
CompileJob CompileJob
The CompileJob of the .dmb
Definition: IDmbProvider.cs:29
+
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory, removes and does not enter any symlinks encounterd.
+
IDmbProvider nextDmbProvider
The latest DmbProvider
Definition: DmbFactory.cs:75
long Id
The ID of the entity.
Definition: EntityId.cs:11
- - -
Task StartAsync(CancellationToken cancellationToken)
- +
async Task StopAsync(CancellationToken cancellationToken)
Definition: DmbFactory.cs:178
+ +
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the DmbFactory
Definition: DmbFactory.cs:35
+ +
DmbFactory(IDatabaseContextFactory databaseContextFactory, IIOManager ioManager, ILogger< DmbFactory > logger, Api.Models.Instance instance)
Construct a DmbFactory
Definition: DmbFactory.cs:84
+
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
Task< IReadOnlyList< string > > GetDirectories(string path, CancellationToken cancellationToken)
Returns directory names in a given path
-
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
-
async Task StopAsync(CancellationToken cancellationToken)
Definition: DmbFactory.cs:178
-
readonly IIOManager ioManager
The IIOManager for the DmbFactory
Definition: DmbFactory.cs:40
Guid? DirectoryName
The Game folder the results were compiled into
Definition: CompileJob.cs:27
+
void CleanJob(CompileJob job)
Delete the Api.Models.Internal.CompileJob.DirectoryName of job
Definition: DmbFactory.cs:104
Task CreateDirectory(string path, CancellationToken cancellationToken)
Create a directory at path
- - - -
async Task< IDmbProvider > FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken)
Gets a IDmbProvider for a given CompileJob
Definition: DmbFactory.cs:186
+ +
TaskCompletionSource< object > newerDmbTcs
TaskCompletionSource<TResult> resulting in the latest DmbProvider yet to exist
Definition: DmbFactory.cs:70
string GetFileName(string path)
Gets the file name portion of a path
+
readonly IDictionary< long, int > jobLockCounts
Map of CompileJob.JobIds to locks on them.
Definition: DmbFactory.cs:60
Task< bool > FileExists(string path, CancellationToken cancellationToken)
Check that the file at path exists
-
DmbFactory(IDatabaseContextFactory databaseContextFactory, IIOManager ioManager, ILogger< DmbFactory > logger, Api.Models.Instance instance)
Construct a DmbFactory
Definition: DmbFactory.cs:84
-
async Task CleanUnusedCompileJobs(CompileJob exceptThisOne, CancellationToken cancellationToken)
Deletes all compile jobs that are inactive in the Game folder exceptThisOne
Definition: DmbFactory.cs:243
- -
readonly CancellationTokenSource cleanupCts
The CancellationTokenSource for cleanupTask
Definition: DmbFactory.cs:55
-
readonly ILogger< DmbFactory > logger
The ILogger for the DmbFactory
Definition: DmbFactory.cs:45
-
readonly IDictionary< long, int > jobLockCounts
Map of CompileJob.JobIds to locks on them.
Definition: DmbFactory.cs:60
-
readonly Api.Models.Instance instance
The Api.Models.Instance for the DmbFactory
Definition: DmbFactory.cs:50
-
void CleanJob(CompileJob job)
Delete the Api.Models.Internal.CompileJob.DirectoryName of job
Definition: DmbFactory.cs:104
-
IDmbProvider LockNextDmb(int lockCount)
Gets the next IDmbProvider
Definition: DmbFactory.cs:149
-
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the DmbFactory
Definition: DmbFactory.cs:35
+
readonly IIOManager ioManager
The IIOManager for the DmbFactory
Definition: DmbFactory.cs:40
+ + +
readonly CancellationTokenSource cleanupCts
The CancellationTokenSource for cleanupTask
Definition: DmbFactory.cs:55
+ + +
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
+
async Task CleanUnusedCompileJobs(CompileJob exceptThisOne, CancellationToken cancellationToken)
Deletes all compile jobs that are inactive in the Game folder exceptThisOne
Definition: DmbFactory.cs:243
+
async Task< IDmbProvider > FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken)
Gets a IDmbProvider for a given CompileJob
Definition: DmbFactory.cs:186
-
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
-
TaskCompletionSource< object > newerDmbTcs
TaskCompletionSource<TResult> resulting in the latest DmbProvider yet to exist
Definition: DmbFactory.cs:70
-
async Task LoadCompileJob(CompileJob job, CancellationToken cancellationToken)
Load a new job into the ICompileJobConsumer
Definition: DmbFactory.cs:131
-
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
+
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
Interface for using filesystems
Definition: IIOManager.cs:11
- +
async Task LoadCompileJob(CompileJob job, CancellationToken cancellationToken)
Load a new job into the ICompileJobConsumer
Definition: DmbFactory.cs:131
+ +
IDmbProvider LockNextDmb(int lockCount)
Gets the next IDmbProvider
Definition: DmbFactory.cs:149
+
readonly ILogger< DmbFactory > logger
The ILogger for the DmbFactory
Definition: DmbFactory.cs:45
string ConcatPath(params string[] paths)
Combines an array of strings into a path
+ +
readonly Api.Models.Instance instance
The Api.Models.Instance for the DmbFactory
Definition: DmbFactory.cs:50
+
Task cleanupTask
Task representing calls to CleanJob(CompileJob)
Definition: DmbFactory.cs:65
+
Task StartAsync(CancellationToken cancellationToken)
diff --git a/_dmb_provider_8cs_source.html b/_dmb_provider_8cs_source.html index fce5d1473f..f1f304a048 100644 --- a/_dmb_provider_8cs_source.html +++ b/_dmb_provider_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Components/Compiler/DmbProvider.cs Source File +tgstation-server: src/Tgstation.Server.Host/Components/Deployment/DmbProvider.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,31 +71,31 @@ $(function() {
DmbProvider.cs
-Go to the documentation of this file.
1 using System;
2 using Tgstation.Server.Host.IO;
4 
6 {
8  sealed class DmbProvider : IDmbProvider
9  {
11  public string DmbName => String.Concat(CompileJob.DmeName, DreamMaker.DmbExtension);
12 
15 
18 
22  public CompileJob CompileJob { get; }
23 
28 
32  Action onDispose;
33 
40  public DmbProvider(CompileJob compileJob, IIOManager ioManager, Action onDispose)
41  {
42  CompileJob = compileJob ?? throw new ArgumentNullException(nameof(compileJob));
43  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
44  this.onDispose = onDispose ?? throw new ArgumentNullException(nameof(onDispose));
45  }
46 
48  public void Dispose() => onDispose?.Invoke();
49 
51  public void KeepAlive() => onDispose = null;
52  }
53 }
- +Go to the documentation of this file.
1 using System;
2 using Tgstation.Server.Host.IO;
4 
6 {
8  sealed class DmbProvider : IDmbProvider
9  {
11  public string DmbName => String.Concat(CompileJob.DmeName, DreamMaker.DmbExtension);
12 
15 
18 
22  public CompileJob CompileJob { get; }
23 
28 
32  Action onDispose;
33 
40  public DmbProvider(CompileJob compileJob, IIOManager ioManager, Action onDispose)
41  {
42  CompileJob = compileJob ?? throw new ArgumentNullException(nameof(compileJob));
43  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
44  this.onDispose = onDispose ?? throw new ArgumentNullException(nameof(onDispose));
45  }
46 
48  public void Dispose() => onDispose?.Invoke();
49 
51  public void KeepAlive() => onDispose = null;
52  }
53 }
+ +
string DmeName
The .dme file used for compilation
Definition: CompileJob.cs:15
- - -
const string BDirectoryName
Name of the secondary directory used for compilation
Definition: DreamMaker.cs:31
- +
Guid? DirectoryName
The Game folder the results were compiled into
Definition: CompileJob.cs:27
+
string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
-
const string ADirectoryName
Name of the primary directory used for compilation
Definition: DreamMaker.cs:26
- -
DmbProvider(CompileJob compileJob, IIOManager ioManager, Action onDispose)
Construct a DmbProvider
Definition: DmbProvider.cs:40
-
Action onDispose
The Action to run when Dispose is called
Definition: DmbProvider.cs:32
-
const string DmbExtension
Extension for .dmbs
Definition: DreamMaker.cs:36
-
readonly IIOManager ioManager
The IIOManager for the DmbProvider
Definition: DmbProvider.cs:27
- +
void KeepAlive()
Disposing the IDmbProvider won't cause a cleanup of the working directory
+
DmbProvider(CompileJob compileJob, IIOManager ioManager, Action onDispose)
Construct a DmbProvider
Definition: DmbProvider.cs:40
+
const string ADirectoryName
Name of the primary directory used for compilation
Definition: DreamMaker.cs:27
+
readonly IIOManager ioManager
The IIOManager for the DmbProvider
Definition: DmbProvider.cs:27
+
const string DmbExtension
Extension for .dmbs
Definition: DreamMaker.cs:37
+
Action onDispose
The Action to run when Dispose is called
Definition: DmbProvider.cs:32
-
void KeepAlive()
Disposing the IDmbProvider won't cause a cleanup of the working directory
-
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
+
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
Interface for using filesystems
Definition: IIOManager.cs:11
+ +
string ConcatPath(params string[] paths)
Combines an array of strings into a path
+
const string BDirectoryName
Name of the secondary directory used for compilation
Definition: DreamMaker.cs:32
diff --git a/_dream_daemon_controller_8cs_source.html b/_dream_daemon_controller_8cs_source.html index 5e783802d4..f45284410b 100644 --- a/_dream_daemon_controller_8cs_source.html +++ b/_dream_daemon_controller_8cs_source.html @@ -71,12 +71,11 @@ $(function() {
DreamDaemonController.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.EntityFrameworkCore;
3 using Microsoft.Extensions.Logging;
4 using System;
5 using System.Linq;
6 using System.Linq.Expressions;
7 using System.Net;
8 using System.Reflection;
9 using System.Threading;
10 using System.Threading.Tasks;
11 using Tgstation.Server.Api;
19 
21 {
25  [Route(Routes.DreamDaemon)]
26  public sealed class DreamDaemonController : ApiController
27  {
32 
37 
46  public DreamDaemonController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, IInstanceManager instanceManager, ILogger<DreamDaemonController> logger) : base(databaseContext, authenticationContextFactory, logger, true, true)
47  {
48  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
49  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
50  }
51 
59  [HttpPut]
60  [TgsAuthorize(DreamDaemonRights.Start)]
61  [ProducesResponseType(typeof(Api.Models.Job), 202)]
62  [ProducesResponseType(410)]
63  public async Task<IActionResult> Create(CancellationToken cancellationToken)
64  {
65  // alias for launching DD
66  var instance = instanceManager.GetInstance(Instance);
67 
68  if (instance.Watchdog.Running)
69  return StatusCode((int)HttpStatusCode.Gone);
70 
71  var job = new Models.Job
72  {
73  Description = "Launch DreamDaemon",
74  CancelRight = (ulong)DreamDaemonRights.Shutdown,
75  CancelRightsType = RightsType.DreamDaemon,
77  StartedBy = AuthenticationContext.User
78  };
79  await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressHandler, innerCt) => instance.Watchdog.Launch(innerCt), cancellationToken).ConfigureAwait(false);
80  return Accepted(job.ToApi());
81  }
82 
89  [HttpGet]
90  [TgsAuthorize(DreamDaemonRights.ReadMetadata | DreamDaemonRights.ReadRevision)]
91  [ProducesResponseType(typeof(DreamDaemon), 200)]
92  [ProducesResponseType(410)]
93  public Task<IActionResult> Read(CancellationToken cancellationToken) => ReadImpl(null, cancellationToken);
94 
101  async Task<IActionResult> ReadImpl(DreamDaemonSettings settings, CancellationToken cancellationToken)
102  {
103  var instance = instanceManager.GetInstance(Instance);
104  var dd = instance.Watchdog;
105 
106  var metadata = (AuthenticationContext.GetRight(RightsType.DreamDaemon) & (ulong)DreamDaemonRights.ReadMetadata) != 0;
107  var revision = (AuthenticationContext.GetRight(RightsType.DreamDaemon) & (ulong)DreamDaemonRights.ReadRevision) != 0;
108 
109  if (settings == null)
110  {
111  settings = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).Select(x => x.DreamDaemonSettings).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
112  if (settings == default)
113  return StatusCode((int)HttpStatusCode.Gone);
114  }
115 
116  var result = new DreamDaemon();
117  if (metadata)
118  {
119  var alphaActive = dd.AlphaIsActive;
120  var llp = dd.LastLaunchParameters;
121  var rstate = dd.RebootState;
122  result.AutoStart = settings.AutoStart;
123  result.CurrentPort = alphaActive ? llp?.PrimaryPort : llp?.SecondaryPort;
124  result.CurrentSecurity = llp?.SecurityLevel;
125  result.CurrentAllowWebclient = llp?.AllowWebClient;
126  result.PrimaryPort = settings.PrimaryPort;
127  result.AllowWebClient = settings.AllowWebClient;
128  result.Running = dd.Running;
129  result.SecondaryPort = settings.SecondaryPort;
130  result.SecurityLevel = settings.SecurityLevel;
131  result.SoftRestart = rstate == RebootState.Restart;
132  result.SoftShutdown = rstate == RebootState.Shutdown;
133  result.StartupTimeout = settings.StartupTimeout;
134  }
135 
136  if (revision)
137  {
138  var latestCompileJob = instance.LatestCompileJob();
139  result.ActiveCompileJob = (dd.ActiveCompileJob ?? latestCompileJob)?.ToApi();
140  if (latestCompileJob?.Id != result.ActiveCompileJob?.Id)
141  result.StagedCompileJob = latestCompileJob?.ToApi();
142  }
143 
144  return Json(result);
145  }
146 
153  [HttpDelete("{id}")]
154  [TgsAuthorize(DreamDaemonRights.Shutdown)]
155  [ProducesResponseType(200)]
156  public async Task<IActionResult> Delete(CancellationToken cancellationToken)
157  {
158  var instance = instanceManager.GetInstance(Instance);
159  await instance.Watchdog.Terminate(false, cancellationToken).ConfigureAwait(false);
160  return Ok();
161  }
162 
171  [HttpPost]
172  [TgsAuthorize(DreamDaemonRights.SetAutoStart | DreamDaemonRights.SetPorts | DreamDaemonRights.SetSecurity | DreamDaemonRights.SetWebClient | DreamDaemonRights.SoftRestart | DreamDaemonRights.SoftShutdown | DreamDaemonRights.Start | DreamDaemonRights.SetStartupTimeout)]
173  [ProducesResponseType(typeof(DreamDaemon), 200)]
174  [ProducesResponseType(410)]
175  #pragma warning disable CA1506 // TODO: Decomplexify
176  public async Task<IActionResult> Update([FromBody] DreamDaemon model, CancellationToken cancellationToken)
177  {
178  if (model == null)
179  throw new ArgumentNullException(nameof(model));
180 
181  if (model.PrimaryPort == 0)
182  return BadRequest(new ErrorMessage { Message = "Primary port cannot be 0!" });
183 
184  if (model.SecurityLevel == DreamDaemonSecurity.Ultrasafe)
185  return BadRequest(new ErrorMessage { Message = "This version of TGS does not support the ultrasafe DreamDaemon configuration!" });
186 
187  // alias for changing DD settings
188  var current = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).Select(x => x.DreamDaemonSettings).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
189 
190  if (current == default)
191  return StatusCode((int)HttpStatusCode.Gone);
192 
193  var userRights = (DreamDaemonRights)AuthenticationContext.GetRight(RightsType.DreamDaemon);
194 
195  bool CheckModified<T>(Expression<Func<Api.Models.Internal.DreamDaemonSettings, T>> expression, DreamDaemonRights requiredRight)
196  {
197  var memberSelectorExpression = (MemberExpression)expression.Body;
198  var property = (PropertyInfo)memberSelectorExpression.Member;
199 
200  var newVal = property.GetValue(model);
201  if (newVal == null)
202  return false;
203  if (!userRights.HasFlag(requiredRight) && property.GetValue(current) != newVal)
204  return true;
205 
206  property.SetValue(current, newVal);
207  return false;
208  }
209 
210  var oldSoftRestart = current.SoftRestart;
211  var oldSoftShutdown = current.SoftShutdown;
212 
213  if (CheckModified(x => x.AllowWebClient, DreamDaemonRights.SetWebClient)
214  || CheckModified(x => x.AutoStart, DreamDaemonRights.SetAutoStart)
215  || CheckModified(x => x.PrimaryPort, DreamDaemonRights.SetPorts)
216  || CheckModified(x => x.SecondaryPort, DreamDaemonRights.SetPorts)
217  || CheckModified(x => x.SecurityLevel, DreamDaemonRights.SetSecurity)
218  || CheckModified(x => x.SoftRestart, DreamDaemonRights.SoftRestart)
219  || CheckModified(x => x.SoftShutdown, DreamDaemonRights.SoftShutdown)
220  || CheckModified(x => x.StartupTimeout, DreamDaemonRights.SetStartupTimeout))
221  return Forbid();
222 
223  if (current.PrimaryPort == current.SecondaryPort)
224  return BadRequest(new ErrorMessage { Message = "Primary port and secondary port cannot be the same!" });
225 
227 
228  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
229 
230  // run this second because current may be modified by it
231  await wd.ChangeSettings(current, cancellationToken).ConfigureAwait(false);
232 
233  if (!oldSoftRestart.Value && current.SoftRestart.Value)
234  await wd.Restart(true, cancellationToken).ConfigureAwait(false);
235  else if (!oldSoftShutdown.Value && current.SoftShutdown.Value)
236  await wd.Terminate(true, cancellationToken).ConfigureAwait(false);
237  else if ((oldSoftRestart.Value && !current.SoftRestart.Value) || (oldSoftShutdown.Value && !current.SoftShutdown.Value))
238  await wd.ResetRebootState(cancellationToken).ConfigureAwait(false);
239 
240  return await ReadImpl(current, cancellationToken).ConfigureAwait(false);
241  }
242  #pragma warning restore CA1506
243 
250  [HttpPatch]
251  [TgsAuthorize(DreamDaemonRights.Restart)]
252  [ProducesResponseType(typeof(Api.Models.Job), 202)]
253  public async Task<IActionResult> Restart(CancellationToken cancellationToken)
254  {
255  var job = new Models.Job
256  {
257  Instance = Instance,
258  CancelRightsType = RightsType.DreamDaemon,
259  CancelRight = (ulong)DreamDaemonRights.Shutdown,
260  StartedBy = AuthenticationContext.User,
261  Description = "Restart Watchdog"
262  };
263 
265 
266  await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressReporter, ct) => watchdog.Restart(false, ct), cancellationToken).ConfigureAwait(false);
267  return Accepted(job.ToApi());
268  }
269  }
270 }
async Task< IActionResult > Delete(CancellationToken cancellationToken)
Stops the Watchdog if it's running.
- -
Manages the runtime of Jobs
Definition: IJobManager.cs:12
+Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.EntityFrameworkCore;
3 using Microsoft.Extensions.Logging;
4 using System;
5 using System.Linq;
6 using System.Linq.Expressions;
7 using System.Net;
8 using System.Reflection;
9 using System.Threading;
10 using System.Threading.Tasks;
11 using Tgstation.Server.Api;
20 
22 {
26  [Route(Routes.DreamDaemon)]
27  public sealed class DreamDaemonController : ApiController
28  {
33 
38 
47  public DreamDaemonController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, IInstanceManager instanceManager, ILogger<DreamDaemonController> logger) : base(databaseContext, authenticationContextFactory, logger, true, true)
48  {
49  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
50  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
51  }
52 
60  [HttpPut]
61  [TgsAuthorize(DreamDaemonRights.Start)]
62  [ProducesResponseType(typeof(Api.Models.Job), 202)]
63  [ProducesResponseType(410)]
64  public async Task<IActionResult> Create(CancellationToken cancellationToken)
65  {
66  // alias for launching DD
67  var instance = instanceManager.GetInstance(Instance);
68 
69  if (instance.Watchdog.Running)
70  return StatusCode((int)HttpStatusCode.Gone);
71 
72  var job = new Models.Job
73  {
74  Description = "Launch DreamDaemon",
75  CancelRight = (ulong)DreamDaemonRights.Shutdown,
76  CancelRightsType = RightsType.DreamDaemon,
78  StartedBy = AuthenticationContext.User
79  };
80  await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressHandler, innerCt) => instance.Watchdog.Launch(innerCt), cancellationToken).ConfigureAwait(false);
81  return Accepted(job.ToApi());
82  }
83 
90  [HttpGet]
91  [TgsAuthorize(DreamDaemonRights.ReadMetadata | DreamDaemonRights.ReadRevision)]
92  [ProducesResponseType(typeof(DreamDaemon), 200)]
93  [ProducesResponseType(410)]
94  public Task<IActionResult> Read(CancellationToken cancellationToken) => ReadImpl(null, cancellationToken);
95 
102  async Task<IActionResult> ReadImpl(DreamDaemonSettings settings, CancellationToken cancellationToken)
103  {
104  var instance = instanceManager.GetInstance(Instance);
105  var dd = instance.Watchdog;
106 
107  var metadata = (AuthenticationContext.GetRight(RightsType.DreamDaemon) & (ulong)DreamDaemonRights.ReadMetadata) != 0;
108  var revision = (AuthenticationContext.GetRight(RightsType.DreamDaemon) & (ulong)DreamDaemonRights.ReadRevision) != 0;
109 
110  if (settings == null)
111  {
112  settings = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).Select(x => x.DreamDaemonSettings).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
113  if (settings == default)
114  return StatusCode((int)HttpStatusCode.Gone);
115  }
116 
117  var result = new DreamDaemon();
118  if (metadata)
119  {
120  var alphaActive = dd.AlphaIsActive;
121  var llp = dd.LastLaunchParameters;
122  var rstate = dd.RebootState;
123  result.AutoStart = settings.AutoStart;
124  result.CurrentPort = alphaActive ? llp?.PrimaryPort : llp?.SecondaryPort;
125  result.CurrentSecurity = llp?.SecurityLevel;
126  result.CurrentAllowWebclient = llp?.AllowWebClient;
127  result.PrimaryPort = settings.PrimaryPort;
128  result.AllowWebClient = settings.AllowWebClient;
129  result.Running = dd.Running;
130  result.SecondaryPort = settings.SecondaryPort;
131  result.SecurityLevel = settings.SecurityLevel;
132  result.SoftRestart = rstate == RebootState.Restart;
133  result.SoftShutdown = rstate == RebootState.Shutdown;
134  result.StartupTimeout = settings.StartupTimeout;
135  }
136 
137  if (revision)
138  {
139  var latestCompileJob = instance.LatestCompileJob();
140  result.ActiveCompileJob = (dd.ActiveCompileJob ?? latestCompileJob)?.ToApi();
141  if (latestCompileJob?.Id != result.ActiveCompileJob?.Id)
142  result.StagedCompileJob = latestCompileJob?.ToApi();
143  }
144 
145  return Json(result);
146  }
147 
154  [HttpDelete]
155  [TgsAuthorize(DreamDaemonRights.Shutdown)]
156  [ProducesResponseType(200)]
157  public async Task<IActionResult> Delete(CancellationToken cancellationToken)
158  {
159  var instance = instanceManager.GetInstance(Instance);
160  await instance.Watchdog.Terminate(false, cancellationToken).ConfigureAwait(false);
161  return Ok();
162  }
163 
172  [HttpPost]
173  [TgsAuthorize(DreamDaemonRights.SetAutoStart | DreamDaemonRights.SetPorts | DreamDaemonRights.SetSecurity | DreamDaemonRights.SetWebClient | DreamDaemonRights.SoftRestart | DreamDaemonRights.SoftShutdown | DreamDaemonRights.Start | DreamDaemonRights.SetStartupTimeout)]
174  [ProducesResponseType(typeof(DreamDaemon), 200)]
175  [ProducesResponseType(410)]
176  #pragma warning disable CA1506 // TODO: Decomplexify
177  public async Task<IActionResult> Update([FromBody] DreamDaemon model, CancellationToken cancellationToken)
178  {
179  if (model == null)
180  throw new ArgumentNullException(nameof(model));
181 
182  if (model.PrimaryPort == 0)
183  return BadRequest(new ErrorMessage { Message = "Primary port cannot be 0!" });
184 
185  if (model.SecurityLevel == DreamDaemonSecurity.Ultrasafe)
186  return BadRequest(new ErrorMessage { Message = "This version of TGS does not support the ultrasafe DreamDaemon configuration!" });
187 
188  // alias for changing DD settings
189  var current = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).Select(x => x.DreamDaemonSettings).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
190 
191  if (current == default)
192  return StatusCode((int)HttpStatusCode.Gone);
193 
194  var userRights = (DreamDaemonRights)AuthenticationContext.GetRight(RightsType.DreamDaemon);
195 
196  bool CheckModified<T>(Expression<Func<Api.Models.Internal.DreamDaemonSettings, T>> expression, DreamDaemonRights requiredRight)
197  {
198  var memberSelectorExpression = (MemberExpression)expression.Body;
199  var property = (PropertyInfo)memberSelectorExpression.Member;
200 
201  var newVal = property.GetValue(model);
202  if (newVal == null)
203  return false;
204  if (!userRights.HasFlag(requiredRight) && property.GetValue(current) != newVal)
205  return true;
206 
207  property.SetValue(current, newVal);
208  return false;
209  }
210 
211  var oldSoftRestart = current.SoftRestart;
212  var oldSoftShutdown = current.SoftShutdown;
213 
214  if (CheckModified(x => x.AllowWebClient, DreamDaemonRights.SetWebClient)
215  || CheckModified(x => x.AutoStart, DreamDaemonRights.SetAutoStart)
216  || CheckModified(x => x.PrimaryPort, DreamDaemonRights.SetPorts)
217  || CheckModified(x => x.SecondaryPort, DreamDaemonRights.SetPorts)
218  || CheckModified(x => x.SecurityLevel, DreamDaemonRights.SetSecurity)
219  || CheckModified(x => x.SoftRestart, DreamDaemonRights.SoftRestart)
220  || CheckModified(x => x.SoftShutdown, DreamDaemonRights.SoftShutdown)
221  || CheckModified(x => x.StartupTimeout, DreamDaemonRights.SetStartupTimeout))
222  return Forbid();
223 
224  if (current.PrimaryPort == current.SecondaryPort)
225  return BadRequest(new ErrorMessage { Message = "Primary port and secondary port cannot be the same!" });
226 
228 
229  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
230 
231  // run this second because current may be modified by it
232  await wd.ChangeSettings(current, cancellationToken).ConfigureAwait(false);
233 
234  if (!oldSoftRestart.Value && current.SoftRestart.Value)
235  await wd.Restart(true, cancellationToken).ConfigureAwait(false);
236  else if (!oldSoftShutdown.Value && current.SoftShutdown.Value)
237  await wd.Terminate(true, cancellationToken).ConfigureAwait(false);
238  else if ((oldSoftRestart.Value && !current.SoftRestart.Value) || (oldSoftShutdown.Value && !current.SoftShutdown.Value))
239  await wd.ResetRebootState(cancellationToken).ConfigureAwait(false);
240 
241  return await ReadImpl(current, cancellationToken).ConfigureAwait(false);
242  }
243  #pragma warning restore CA1506
244 
251  [HttpPatch]
252  [TgsAuthorize(DreamDaemonRights.Restart)]
253  [ProducesResponseType(typeof(Api.Models.Job), 202)]
254  public async Task<IActionResult> Restart(CancellationToken cancellationToken)
255  {
256  var job = new Models.Job
257  {
258  Instance = Instance,
259  CancelRightsType = RightsType.DreamDaemon,
260  CancelRight = (ulong)DreamDaemonRights.Shutdown,
261  StartedBy = AuthenticationContext.User,
262  Description = "Restart Watchdog"
263  };
264 
266 
267  await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressReporter, ct) => watchdog.Restart(false, ct), cancellationToken).ConfigureAwait(false);
268  return Accepted(job.ToApi());
269  }
270  }
271 }
async Task< IActionResult > Delete(CancellationToken cancellationToken)
Stops the Watchdog if it's running.
+
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
- +
ushort? PrimaryPort
The first port DreamDaemon uses. This should be the publically advertised port
@@ -84,45 +83,47 @@ $(function() {
IInstance GetInstance(Models.Instance metadata)
Get the IInstance associated with given metadata
- -
async Task< IActionResult > Update([FromBody] DreamDaemon model, CancellationToken cancellationToken)
Update watchdog settings to be applied at next server reboot.
-
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
+
async Task< IActionResult > Update([FromBody] DreamDaemon model, CancellationToken cancellationToken)
Update watchdog settings to be applied at next server reboot.
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
bool? AutoStart
If DreamDaemon starts when it's Instance starts
-
Task RegisterOperation(Job job, Func< Job, IDatabaseContext, Action< int >, CancellationToken, Task > operation, CancellationToken cancellationToken)
Registers a given Job and begins running it
- -
async Task< IActionResult > ReadImpl(DreamDaemonSettings settings, CancellationToken cancellationToken)
Implementation of Read(CancellationToken)
-
async Task< IActionResult > Restart(CancellationToken cancellationToken)
Creates a Api.Models.Job to restart the Watchdog. It will start if it wasn't already running.
+ +
async Task< IActionResult > ReadImpl(DreamDaemonSettings settings, CancellationToken cancellationToken)
Implementation of Read(CancellationToken)
+
async Task< IActionResult > Restart(CancellationToken cancellationToken)
Creates a Api.Models.Job to restart the Watchdog. It will start if it wasn't already running.
Routes to a server actions
Definition: Routes.cs:9
DreamDaemonRights
Rights for Models.DreamDaemon
-
async Task< IActionResult > Create(CancellationToken cancellationToken)
Launches the watchdog.
+ + +
async Task< IActionResult > Create(CancellationToken cancellationToken)
Launches the watchdog.
- -
DreamDaemonController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, IInstanceManager instanceManager, ILogger< DreamDaemonController > logger)
Construct a DreamDaemonController
+
DreamDaemonController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, IInstanceManager instanceManager, ILogger< DreamDaemonController > logger)
Construct a DreamDaemonController
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
- +
const string DreamDaemon
The Models.DreamDaemon controller
Definition: Routes.cs:44
-
readonly IInstanceManager instanceManager
The IInstanceManager for the DreamMakerController
+
readonly IInstanceManager instanceManager
The IInstanceManager for the DreamMakerController
-
readonly IJobManager jobManager
The IJobManager for the DreamMakerController
+
readonly IJobManager jobManager
The IJobManager for the DreamMakerController
-
IWatchdog Watchdog
The IWatchdog for the IInstance
Definition: IInstance.cs:32
+
IWatchdog Watchdog
The IWatchdog for the IInstance
Definition: IInstance.cs:33
Metadata about a server instance
Definition: Instance.cs:9
+
Manages the runtime of Jobs
Definition: IJobManager.cs:13
+
DreamDaemonSecurity
DreamDaemon's security level
Represents an instance of BYOND's DreamDaemon game server. Create action starts the server....
Definition: DreamDaemon.cs:8
bool? AllowWebClient
If the BYOND web client can be used to connect to the game server
Task Terminate(bool graceful, CancellationToken cancellationToken)
Stops the watchdog
+
Task RegisterOperation(Job job, Func< Job, IDatabaseContext, Action< int >, CancellationToken, Task > operation, CancellationToken cancellationToken)
Registers a given Job and begins running it
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
Task< IActionResult > Read(CancellationToken cancellationToken)
Get the watchdog status.
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
+
DreamDaemonSecurity? SecurityLevel
The DreamDaemonSecurity level of DreamDaemon
Models.Instance Instance
The Instance for the operation
diff --git a/_dream_maker_controller_8cs_source.html b/_dream_maker_controller_8cs_source.html index 6d0e43c69f..8d47af811f 100644 --- a/_dream_maker_controller_8cs_source.html +++ b/_dream_maker_controller_8cs_source.html @@ -71,54 +71,55 @@ $(function() {
DreamMakerController.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.EntityFrameworkCore;
3 using Microsoft.Extensions.Logging;
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Net;
8 using System.Threading;
9 using System.Threading.Tasks;
10 using Tgstation.Server.Api;
17 
19 {
23  [Route(Routes.DreamMaker)]
24  #pragma warning disable CA1506 // TODO: Decomplexify
25  public sealed class DreamMakerController : ApiController
26  {
31 
36 
45  public DreamMakerController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, IInstanceManager instanceManager, ILogger<DreamMakerController> logger) : base(databaseContext, authenticationContextFactory, logger, true, true)
46  {
47  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
48  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
49  }
50 
57  [HttpGet]
58  [TgsAuthorize(DreamMakerRights.Read)]
59  [ProducesResponseType(typeof(DreamMaker), 200)]
60  public async Task<IActionResult> Read(CancellationToken cancellationToken)
61  {
62  var instance = instanceManager.GetInstance(Instance);
63  var dreamMakerSettings = await DatabaseContext.DreamMakerSettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
64  return Json(dreamMakerSettings.ToApi());
65  }
66 
75  [HttpGet("{id}")]
76  [TgsAuthorize(DreamMakerRights.CompileJobs)]
77  [ProducesResponseType(typeof(Api.Models.CompileJob), 200)]
78  [ProducesResponseType(404)]
79  public async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
80  {
81  var compileJob = await DatabaseContext.CompileJobs
82  .Where(x => x.Id == id && x.Job.Instance.Id == Instance.Id)
83  .Include(x => x.Job).ThenInclude(x => x.StartedBy)
84  .Include(x => x.RevisionInformation).ThenInclude(x => x.PrimaryTestMerge).ThenInclude(x => x.MergedBy)
85  .Include(x => x.RevisionInformation).ThenInclude(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).ThenInclude(x => x.MergedBy)
86  .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
87  if (compileJob == default)
88  return NotFound();
89  return Json(compileJob.ToApi());
90  }
91 
98  [HttpGet(Routes.List)]
99  [TgsAuthorize(DreamMakerRights.CompileJobs)]
100  [ProducesResponseType(typeof(List<EntityId>), 200)]
101  public async Task<IActionResult> List(CancellationToken cancellationToken)
102  {
103  var compileJobs = await DatabaseContext.CompileJobs.Where(x => x.Job.Instance.Id == Instance.Id).OrderByDescending(x => x.Job.StoppedAt).Select(x => new EntityId
104  {
105  Id = x.Id
106  }).ToListAsync(cancellationToken).ConfigureAwait(false);
107  return Json(compileJobs);
108  }
109 
116  [HttpPut]
117  [TgsAuthorize(DreamMakerRights.Compile)]
118  [ProducesResponseType(typeof(Api.Models.Job), 202)]
119  public async Task<IActionResult> Create(CancellationToken cancellationToken)
120  {
121  var job = new Models.Job
122  {
123  Description = "Compile active repository code",
124  StartedBy = AuthenticationContext.User,
125  CancelRightsType = RightsType.DreamMaker,
126  CancelRight = (ulong)DreamMakerRights.CancelCompile,
128  };
129  await jobManager.RegisterOperation(job, instanceManager.GetInstance(Instance).CompileProcess, cancellationToken).ConfigureAwait(false);
130  return Accepted(job.ToApi());
131  }
132 
141  [HttpPost]
142  [TgsAuthorize(DreamMakerRights.SetDme | DreamMakerRights.SetApiValidationPort | DreamMakerRights.SetApiValidationPort)]
143  [ProducesResponseType(typeof(DreamMaker), 200)]
144  [ProducesResponseType(200)]
145  [ProducesResponseType(410)]
146  public async Task<IActionResult> Update([FromBody] DreamMaker model, CancellationToken cancellationToken)
147  {
148  if (model == null)
149  throw new ArgumentNullException(nameof(model));
150 
151  if (model.ApiValidationPort == 0)
152  return BadRequest(new ErrorMessage { Message = "API Validation port cannot be 0!" });
153 
154  if (model.ApiValidationSecurityLevel == DreamDaemonSecurity.Ultrasafe)
155  return BadRequest(new ErrorMessage { Message = "This version of TGS does not support the ultrasafe DreamDaemon configuration!" });
156 
157  var hostModel = await DatabaseContext.DreamMakerSettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
158  if (hostModel == null)
159  return StatusCode((int)HttpStatusCode.Gone);
160 
161  if (model.ProjectName != null)
162  {
164  return Forbid();
165  if (model.ProjectName.Length == 0)
166  hostModel.ProjectName = null;
167  else
168  hostModel.ProjectName = model.ProjectName;
169  }
170 
171  if (model.ApiValidationPort.HasValue)
172  {
173  if (!AuthenticationContext.InstanceUser.DreamMakerRights.Value.HasFlag(DreamMakerRights.SetApiValidationPort))
174  return Forbid();
175  hostModel.ApiValidationPort = model.ApiValidationPort;
176  }
177 
178  if (model.ApiValidationSecurityLevel.HasValue)
179  {
180  if (!AuthenticationContext.InstanceUser.DreamMakerRights.Value.HasFlag(DreamMakerRights.SetSecurityLevel))
181  return Forbid();
182  hostModel.ApiValidationSecurityLevel = model.ApiValidationSecurityLevel;
183  }
184 
185  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
186 
187  if ((AuthenticationContext.GetRight(RightsType.DreamMaker) & (ulong)DreamMakerRights.Read) == 0)
188  return Ok();
189 
190  return await Read(cancellationToken).ConfigureAwait(false);
191  }
192  }
193 }
-
Manages the runtime of Jobs
Definition: IJobManager.cs:12
+Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.EntityFrameworkCore;
3 using Microsoft.Extensions.Logging;
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Net;
8 using System.Threading;
9 using System.Threading.Tasks;
10 using Tgstation.Server.Api;
18 
20 {
24  [Route(Routes.DreamMaker)]
25  #pragma warning disable CA1506 // TODO: Decomplexify
26  public sealed class DreamMakerController : ApiController
27  {
32 
37 
46  public DreamMakerController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, IInstanceManager instanceManager, ILogger<DreamMakerController> logger) : base(databaseContext, authenticationContextFactory, logger, true, true)
47  {
48  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
49  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
50  }
51 
58  [HttpGet]
59  [TgsAuthorize(DreamMakerRights.Read)]
60  [ProducesResponseType(typeof(DreamMaker), 200)]
61  public async Task<IActionResult> Read(CancellationToken cancellationToken)
62  {
63  var instance = instanceManager.GetInstance(Instance);
64  var dreamMakerSettings = await DatabaseContext.DreamMakerSettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
65  return Json(dreamMakerSettings.ToApi());
66  }
67 
76  [HttpGet("{id}")]
77  [TgsAuthorize(DreamMakerRights.CompileJobs)]
78  [ProducesResponseType(typeof(Api.Models.CompileJob), 200)]
79  [ProducesResponseType(404)]
80  public async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
81  {
82  var compileJob = await DatabaseContext.CompileJobs
83  .Where(x => x.Id == id && x.Job.Instance.Id == Instance.Id)
84  .Include(x => x.Job).ThenInclude(x => x.StartedBy)
85  .Include(x => x.RevisionInformation).ThenInclude(x => x.PrimaryTestMerge).ThenInclude(x => x.MergedBy)
86  .Include(x => x.RevisionInformation).ThenInclude(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).ThenInclude(x => x.MergedBy)
87  .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
88  if (compileJob == default)
89  return NotFound();
90  return Json(compileJob.ToApi());
91  }
92 
99  [HttpGet(Routes.List)]
100  [TgsAuthorize(DreamMakerRights.CompileJobs)]
101  [ProducesResponseType(typeof(List<EntityId>), 200)]
102  public async Task<IActionResult> List(CancellationToken cancellationToken)
103  {
104  var compileJobs = await DatabaseContext.CompileJobs.Where(x => x.Job.Instance.Id == Instance.Id).OrderByDescending(x => x.Job.StoppedAt).Select(x => new EntityId
105  {
106  Id = x.Id
107  }).ToListAsync(cancellationToken).ConfigureAwait(false);
108  return Json(compileJobs);
109  }
110 
117  [HttpPut]
118  [TgsAuthorize(DreamMakerRights.Compile)]
119  [ProducesResponseType(typeof(Api.Models.Job), 202)]
120  public async Task<IActionResult> Create(CancellationToken cancellationToken)
121  {
122  var job = new Models.Job
123  {
124  Description = "Compile active repository code",
125  StartedBy = AuthenticationContext.User,
126  CancelRightsType = RightsType.DreamMaker,
127  CancelRight = (ulong)DreamMakerRights.CancelCompile,
129  };
130  await jobManager.RegisterOperation(job, instanceManager.GetInstance(Instance).CompileProcess, cancellationToken).ConfigureAwait(false);
131  return Accepted(job.ToApi());
132  }
133 
142  [HttpPost]
143  [TgsAuthorize(DreamMakerRights.SetDme | DreamMakerRights.SetApiValidationPort | DreamMakerRights.SetApiValidationPort)]
144  [ProducesResponseType(typeof(DreamMaker), 200)]
145  [ProducesResponseType(200)]
146  [ProducesResponseType(410)]
147  public async Task<IActionResult> Update([FromBody] DreamMaker model, CancellationToken cancellationToken)
148  {
149  if (model == null)
150  throw new ArgumentNullException(nameof(model));
151 
152  if (model.ApiValidationPort == 0)
153  return BadRequest(new ErrorMessage { Message = "API Validation port cannot be 0!" });
154 
155  if (model.ApiValidationSecurityLevel == DreamDaemonSecurity.Ultrasafe)
156  return BadRequest(new ErrorMessage { Message = "This version of TGS does not support the ultrasafe DreamDaemon configuration!" });
157 
158  var hostModel = await DatabaseContext.DreamMakerSettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
159  if (hostModel == null)
160  return StatusCode((int)HttpStatusCode.Gone);
161 
162  if (model.ProjectName != null)
163  {
165  return Forbid();
166  if (model.ProjectName.Length == 0)
167  hostModel.ProjectName = null;
168  else
169  hostModel.ProjectName = model.ProjectName;
170  }
171 
172  if (model.ApiValidationPort.HasValue)
173  {
174  if (!AuthenticationContext.InstanceUser.DreamMakerRights.Value.HasFlag(DreamMakerRights.SetApiValidationPort))
175  return Forbid();
176  hostModel.ApiValidationPort = model.ApiValidationPort;
177  }
178 
179  if (model.ApiValidationSecurityLevel.HasValue)
180  {
181  if (!AuthenticationContext.InstanceUser.DreamMakerRights.Value.HasFlag(DreamMakerRights.SetSecurityLevel))
182  return Forbid();
183  hostModel.ApiValidationSecurityLevel = model.ApiValidationSecurityLevel;
184  }
185 
186  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
187 
188  if ((AuthenticationContext.GetRight(RightsType.DreamMaker) & (ulong)DreamMakerRights.Read) == 0)
189  return Ok();
190 
191  return await Read(cancellationToken).ConfigureAwait(false);
192  }
193  }
194 }
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
-
readonly IInstanceManager instanceManager
The IInstanceManager for the DreamMakerController
+
readonly IInstanceManager instanceManager
The IInstanceManager for the DreamMakerController
- +
Represents the state of the DreamMaker compiler. Create action starts a new compile....
Definition: DreamMaker.cs:8
long Id
The ID of the entity.
Definition: EntityId.cs:11
-
async Task< IActionResult > List(CancellationToken cancellationToken)
List all Api.Models.CompileJob EntityIds for the instance.
+
async Task< IActionResult > List(CancellationToken cancellationToken)
List all Api.Models.CompileJob EntityIds for the instance.
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
-
ApiController for managing the deployment system.
-
DbSet< DreamMakerSettings > DreamMakerSettings
+
ApiController for managing the deployment system.
-
async Task< IActionResult > Create(CancellationToken cancellationToken)
Begin deploying repository code.
+
async Task< IActionResult > Create(CancellationToken cancellationToken)
Begin deploying repository code.
IInstance GetInstance(Models.Instance metadata)
Get the IInstance associated with given metadata
-
async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Get a Api.Models.CompileJob specified by a given id .
-
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
-
Task CompileProcess(Job job, IDatabaseContext databaseContext, Action< int > progressReporter, CancellationToken cancellationToken)
Run the compile job and insert it into the database. Meant to be called by a Core....
+
async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Get a Api.Models.CompileJob specified by a given id .
+
Task CompileProcess(Job job, IDatabaseContext databaseContext, Action< int > progressReporter, CancellationToken cancellationToken)
Run the compile job and insert it into the database. Meant to be called by a Jobs....
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
-
async Task< IActionResult > Read(CancellationToken cancellationToken)
Read current DreamMaker status.
+
async Task< IActionResult > Read(CancellationToken cancellationToken)
Read current DreamMaker status.
-
Task RegisterOperation(Job job, Func< Job, IDatabaseContext, Action< int >, CancellationToken, Task > operation, CancellationToken cancellationToken)
Registers a given Job and begins running it
- +
Routes to a server actions
Definition: Routes.cs:9
-
async Task< IActionResult > Update([FromBody] DreamMaker model, CancellationToken cancellationToken)
Update deployment settings.
+
DbSet< DreamMakerSettings > DreamMakerSettings
+ +
async Task< IActionResult > Update([FromBody] DreamMaker model, CancellationToken cancellationToken)
Update deployment settings.
DreamMakerRights? DreamMakerRights
The Rights.DreamMakerRights of the InstanceUser
Definition: InstanceUser.cs:39
const string DreamMaker
The Models.DreamMaker controller
Definition: Routes.cs:74
DreamMakerRights
Rights for Models.DreamMaker
- -
DreamMakerController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, IInstanceManager instanceManager, ILogger< DreamMakerController > logger)
Construct a DreamMakerController
-
readonly IJobManager jobManager
The IJobManager for the DreamMakerController
+
DreamMakerController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, IInstanceManager instanceManager, ILogger< DreamMakerController > logger)
Construct a DreamMakerController
+
readonly IJobManager jobManager
The IJobManager for the DreamMakerController
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
Metadata about a server instance
Definition: Instance.cs:9
+
Manages the runtime of Jobs
Definition: IJobManager.cs:13
+
DreamDaemonSecurity
DreamDaemon's security level
const string List
The postfix for list operations
Definition: Routes.cs:84
+ +
Task RegisterOperation(Job job, Func< Job, IDatabaseContext, Action< int >, CancellationToken, Task > operation, CancellationToken cancellationToken)
Registers a given Job and begins running it
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- +
diff --git a/_event_consumer_8cs_source.html b/_event_consumer_8cs_source.html index d896b3f7f6..5937076767 100644 --- a/_event_consumer_8cs_source.html +++ b/_event_consumer_8cs_source.html @@ -82,7 +82,7 @@ $(function() { - +
Task< bool > HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
Handle a given eventType
void SetWatchdog(IWatchdog watchdog)
Set the watchdog for the EventConsumer
diff --git a/_experimental_watchdog_8cs_source.html b/_experimental_watchdog_8cs_source.html index 0d71f8cd49..b64882ab7f 100644 --- a/_experimental_watchdog_8cs_source.html +++ b/_experimental_watchdog_8cs_source.html @@ -71,102 +71,104 @@ $(function() {
ExperimentalWatchdog.cs
-Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Microsoft.Extensions.Logging;
3 using Newtonsoft.Json;
4 using System;
5 using System.Diagnostics;
6 using System.Globalization;
7 using System.Threading;
8 using System.Threading.Tasks;
13 
15 {
20  {
24  const int AlphaBravoStartupSeperationInterval = 10; // TODO: Make this configurable
25 
27  public override bool AlphaIsActive => alphaIsActive;
28 
30  public override Models.CompileJob ActiveCompileJob => (AlphaIsActive ? alphaServer : bravoServer)?.Dmb.CompileJob;
31 
34 
39 
44 
49 
67  public ExperimentalWatchdog(IChat chat, ISessionControllerFactory sessionControllerFactory, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IDatabaseContextFactory databaseContextFactory, IByondTopicSender byondTopicSender, IEventConsumer eventConsumer, IJobManager jobManager, IServerControl serverControl, IAsyncDelayer asyncDelayer, ILogger<ExperimentalWatchdog> logger, DreamDaemonLaunchParameters initialLaunchParameters, Api.Models.Instance instance, bool autoStart)
68  : base(
69  chat,
70  sessionControllerFactory,
71  dmbFactory,
76  jobManager,
77  serverControl,
78  asyncDelayer,
79  logger,
80  initialLaunchParameters,
81  instance,
82  autoStart)
83  {
84  alphaIsActive = true;
85  }
86 
94  #pragma warning disable CA1502 // TODO: Decomplexify
95  async Task HandlerMonitorWakeup(MonitorActivationReason activationReason, MonitorState monitorState, CancellationToken cancellationToken)
96  {
97  Logger.LogDebug("Monitor activation. Reason: {0}", activationReason);
98 
99  // this is where the bulk of the watchdog handling code lives and is fraught with lambdas, sorry not sorry
100  // I'll do my best to walk you through it
101 
102  // returns true if the inactive server can't be used immediately
103  // also sets monitor to restart if the above holds
104  bool FullRestartDeadInactive()
105  {
106  if (monitorState.RebootingInactiveServer || monitorState.InactiveServerCritFail)
107  {
108  Logger.LogInformation("Inactive server is {0}! Restarting monitor...", monitorState.InactiveServerCritFail ? "critically failed" : "still rebooting");
109  monitorState.NextAction = MonitorAction.Restart; // will dispose server
110  return true;
111  }
112 
113  return false;
114  }
115 
116  // trys to set inactive server's port to the public game port
117  // doesn't handle closing active server's port
118  // returns true on success and swaps inactiveserver and activeserver also sets LastLaunchParameters to ActiveLaunchParameters
119  // on failure, sets monitor to restart
120  async Task<bool> MakeInactiveActive()
121  {
122  Logger.LogDebug("Setting inactive server to port {0}...", ActiveLaunchParameters.PrimaryPort.Value);
123  var result = await monitorState.InactiveServer.SetPort(ActiveLaunchParameters.PrimaryPort.Value, cancellationToken).ConfigureAwait(false);
124 
125  if (!result)
126  {
127  Logger.LogWarning("Failed to activate inactive server! Restarting monitor...");
128  monitorState.NextAction = MonitorAction.Restart; // will dispose server
129  return false;
130  }
131 
132  // inactive server should always be using active launch parameters
134 
135  var tmp = monitorState.ActiveServer;
136  monitorState.ActiveServer = monitorState.InactiveServer;
137  monitorState.InactiveServer = tmp;
139  monitorState.ActiveServer.EnableCustomChatCommands();
140  return true;
141  }
142 
143  // Kills and tries to launch inactive server with the latest dmb
144  // falls back to current dmb on failure
145  // Sets critfail on inactive server failing that
146  // returns false if the backup dmb was used successfully, true otherwise
147  async Task UpdateAndRestartInactiveServer(bool breakAfter)
148  {
149  ActiveParametersUpdated = new TaskCompletionSource<object>();
150  monitorState.InactiveServer.Dispose(); // kill or recycle it
151  var desiredNextAction = breakAfter ? MonitorAction.Break : MonitorAction.Continue;
152  monitorState.NextAction = desiredNextAction;
153 
154  Logger.LogInformation("Rebooting inactive server...");
155  var newDmb = DmbFactory.LockNextDmb(1);
156  try
157  {
158  monitorState.InactiveServer = await SessionControllerFactory.LaunchNew(ActiveLaunchParameters, newDmb, null, false, !monitorState.ActiveServer.IsPrimary, false, cancellationToken).ConfigureAwait(false);
159  monitorState.InactiveServer.SetHighPriority();
160  }
161  catch (OperationCanceledException)
162  {
163  throw;
164  }
165  catch (Exception e)
166  {
167  Logger.LogError("Error occurred while recreating server! Attempting backup strategy of running DMB of running server! Exception: {0}", e.ToString());
168 
169  // ahh jeez, what do we do here?
170  // this is our fault, so it should never happen but
171  // idk maybe a database error while handling the newest dmb?
172  // either way try to start it using the active server's dmb as a backup
173  try
174  {
175  var dmbBackup = await DmbFactory.FromCompileJob(monitorState.ActiveServer.Dmb.CompileJob, cancellationToken).ConfigureAwait(false);
176 
177  if (dmbBackup == null) // NANI!?
178  throw new JobException("Creating backup DMB provider failed!"); // just give up, if THAT compile job is failing then the ActiveServer is gonna crash soon too or already has
179 
180  monitorState.InactiveServer = await SessionControllerFactory.LaunchNew(ActiveLaunchParameters, dmbBackup, null, false, !monitorState.ActiveServer.IsPrimary, false, cancellationToken).ConfigureAwait(false);
181  monitorState.InactiveServer.SetHighPriority();
182  await Chat.SendWatchdogMessage("Staging newest DMB on inactive server failed: {0} Falling back to previous dmb...", cancellationToken).ConfigureAwait(false);
183  }
184  catch (OperationCanceledException)
185  {
186  throw;
187  }
188  catch (Exception e2)
189  {
190  // fuuuuucckkk
191  Logger.LogError("Backup strategy failed! Monitor will restart when active server reboots! Exception: {0}", e2.ToString());
192  monitorState.InactiveServerCritFail = true;
193  await Chat.SendWatchdogMessage("Attempted reboot of inactive server failed. Watchdog will reset when active server fails or exits", cancellationToken).ConfigureAwait(false);
194  return;
195  }
196  }
197 
198  Logger.LogInformation("Successfully relaunched inactive server!");
199  monitorState.RebootingInactiveServer = true;
200  }
201 
202  string ExitWord(ISessionController controller) => controller.TerminationWasRequested ? "exited" : "crashed";
203 
204  // reason handling
205  switch (activationReason)
206  {
207  case MonitorActivationReason.ActiveServerCrashed:
208  if (monitorState.ActiveServer.RebootState == Watchdog.RebootState.Shutdown)
209  {
210  // the time for graceful shutdown is now
211  await Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Active server {0}! Exiting due to graceful termination request...", ExitWord(monitorState.ActiveServer)), cancellationToken).ConfigureAwait(false);
213  monitorState.NextAction = MonitorAction.Exit;
214  break;
215  }
216 
217  if (FullRestartDeadInactive())
218  {
219  // tell chat about it and go ahead
220  await Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Active server {0}! Inactive server unable to online!", ExitWord(monitorState.ActiveServer)), cancellationToken).ConfigureAwait(false);
221 
222  // we've already been set to restart
223  break;
224  }
225 
226  // tell chat about it
227  await Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Active server {0}! Onlining inactive server...", ExitWord(monitorState.ActiveServer)), cancellationToken).ConfigureAwait(false);
228 
229  // try to activate the inactive server
230  if (!await MakeInactiveActive().ConfigureAwait(false))
231  break; // failing that, we've already been set to restart
232 
233  // bring up another inactive server
234  await UpdateAndRestartInactiveServer(true).ConfigureAwait(false);
235  break;
236  case MonitorActivationReason.InactiveServerCrashed:
237  // just announce and try to bring it back
238  await Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Inactive server {0}! Rebooting...", ExitWord(monitorState.InactiveServer)), cancellationToken).ConfigureAwait(false);
239  await UpdateAndRestartInactiveServer(false).ConfigureAwait(false);
240  break;
241  case MonitorActivationReason.ActiveServerRebooted:
242  // ideal goal: active server just closed its port
243  // tell inactive server to open it's port and that's now the active server
244  var rebootState = monitorState.ActiveServer.RebootState;
245  monitorState.ActiveServer.ResetRebootState(); // the DMAPI has already done this internally
246 
247  if (FullRestartDeadInactive() && rebootState != Watchdog.RebootState.Shutdown)
248  break; // full restart if the inactive server is being fucky
249 
250  // what matters here is the RebootState
251  var restartOnceSwapped = false;
252 
253  switch (rebootState)
254  {
255  case Watchdog.RebootState.Normal:
256  // life as normal
257  break;
258  case Watchdog.RebootState.Restart:
259  // reboot the current active server once the inactive one activates
260  restartOnceSwapped = true;
261  break;
262  case Watchdog.RebootState.Shutdown:
263  // graceful shutdown time
264  await Chat.SendWatchdogMessage("Active server rebooted! Exiting due to graceful termination request...", cancellationToken).ConfigureAwait(false);
266  monitorState.NextAction = MonitorAction.Exit;
267  return;
268  default:
269  throw new InvalidOperationException($"Invalid reboot state: {rebootState}");
270  }
271 
272  // are both servers now running the same CompileJob?
273  var sameCompileJob = monitorState.InactiveServer.Dmb.CompileJob.Id == monitorState.ActiveServer.Dmb.CompileJob.Id;
274 
275  if (!sameCompileJob || ActiveLaunchParameters != LastLaunchParameters)
276  restartOnceSwapped = true; // need a new launch to update either settings or compile job
277 
278  if (restartOnceSwapped)
279  /*
280  * we need to manually restart active server
281  * just kill it here, easier that way
282  */
283  monitorState.ActiveServer.Dispose();
284 
285  var activeServerStillHasPortOpen = !restartOnceSwapped && !monitorState.ActiveServer.ClosePortOnReboot;
286 
287  if (activeServerStillHasPortOpen)
288  /* we didn't want active server to swap for some reason and it still has it's port open
289  * just continue as normal
290  */
291  break;
292 
293  if (!await MakeInactiveActive().ConfigureAwait(false))
294  break; // monitor will restart
295 
296  // servers now swapped
297  // enable this now if inactive server is not still valid
298  monitorState.ActiveServer.ClosePortOnReboot = restartOnceSwapped;
299 
300  if (!restartOnceSwapped)
301  /*
302  * now try to reopen it on the private port
303  * failing that, just reboot it
304  */
305  restartOnceSwapped = !await monitorState.InactiveServer.SetPort(ActiveLaunchParameters.SecondaryPort.Value, cancellationToken).ConfigureAwait(false);
306 
307  // break either way because any issues past this point would be solved by the reboot
308  if (restartOnceSwapped) // for one reason or another
309  await UpdateAndRestartInactiveServer(true).ConfigureAwait(false); // update and reboot
310  else
311  monitorState.NextAction = MonitorAction.Skip; // only skip checking inactive server rebooted, it's guaranteed InactiveServerStartup complete wouldn't fire this iteration
312  break;
313  case MonitorActivationReason.InactiveServerRebooted:
314  // just don't let the active server close it's port if the inactive server isn't ready
315  monitorState.RebootingInactiveServer = true;
316  monitorState.InactiveServer.ResetRebootState();
317  monitorState.ActiveServer.ClosePortOnReboot = false;
318  monitorState.NextAction = MonitorAction.Continue;
319  break;
320  case MonitorActivationReason.InactiveServerStartupComplete:
321  // opposite of above case
322  monitorState.RebootingInactiveServer = false;
323  monitorState.ActiveServer.ClosePortOnReboot = true;
324  monitorState.NextAction = MonitorAction.Continue;
325  break;
326  case MonitorActivationReason.NewDmbAvailable:
327  case MonitorActivationReason.ActiveLaunchParametersUpdated:
328  // just reload the inactive server and wait for a swap to apply the changes
329  await UpdateAndRestartInactiveServer(true).ConfigureAwait(false);
330  break;
331  default:
332  Trace.Assert(false, String.Format(CultureInfo.InvariantCulture, "Invalid monitor activation reason: {0}!", activationReason));
333  break;
334  }
335  }
336  #pragma warning restore CA1502
337 
341  protected override void DisposeAndNullControllers()
342  {
343  alphaServer?.Dispose();
344  alphaServer = null;
345  bravoServer?.Dispose();
346  bravoServer = null;
347  Running = false;
348  }
349 
351  #pragma warning disable CA1502 // TODO: Decomplexify
352  protected override async Task MonitorLifetimes(CancellationToken cancellationToken)
353  {
354  Logger.LogTrace("Entered MonitorLifetimes");
355 
356  // this function is responsible for calling HandlerMonitorWakeup when necessary and manitaining the MonitorState
357  var iteration = 1;
358  for (var monitorState = new MonitorState(); monitorState.NextAction != MonitorAction.Exit; ++iteration)
359  {
360  // always start out with continue
361  monitorState.NextAction = MonitorAction.Continue;
362 
363  // dump some info to the logs
364  Logger.LogDebug("Iteration {0} of monitor loop", iteration);
365  try
366  {
367  if (AlphaIsActive)
368  Logger.LogDebug("Alpha is the active server");
369  else
370  Logger.LogDebug("Bravo is the active server");
371 
372  if (monitorState.RebootingInactiveServer)
373  Logger.LogDebug("Inactive server is rebooting");
374 
375  // update the monitor state with the inactive/active servers
376  monitorState.ActiveServer = AlphaIsActive ? alphaServer : bravoServer;
377  monitorState.InactiveServer = AlphaIsActive ? bravoServer : alphaServer;
378 
379  if (monitorState.ActiveServer.ClosePortOnReboot)
380  Logger.LogDebug("Active server will close port on reboot");
381  if (monitorState.InactiveServer.ClosePortOnReboot)
382  Logger.LogDebug("Inactive server will close port on reboot");
383 
384  Logger.LogDebug("Active server Compile Job ID: {0}", monitorState.ActiveServer.Dmb.CompileJob.Id);
385  Logger.LogDebug("Inactive server Compile Job ID: {0}", monitorState.InactiveServer.Dmb.CompileJob.Id);
386 
387  // load the activation tasks into local variables
388  Task activeServerLifetime = monitorState.ActiveServer.Lifetime;
389  Task inactiveServerLifetime = monitorState.InactiveServer.Lifetime;
390  var activeServerReboot = monitorState.ActiveServer.OnReboot;
391  var inactiveServerReboot = monitorState.InactiveServer.OnReboot;
392  Task inactiveServerStartup = monitorState.RebootingInactiveServer ? monitorState.InactiveServer.LaunchResult : null;
393  Task activeLaunchParametersChanged = ActiveParametersUpdated.Task;
394  var newDmbAvailable = DmbFactory.OnNewerDmb;
395 
396  // cancel waiting if requested
397  var cancelTcs = new TaskCompletionSource<object>();
398  using (cancellationToken.Register(() => cancelTcs.SetCanceled()))
399  {
400  var toWaitOn = Task.WhenAny(activeServerLifetime, inactiveServerLifetime, activeServerReboot, inactiveServerReboot, newDmbAvailable, cancelTcs.Task, activeLaunchParametersChanged);
401  if (monitorState.RebootingInactiveServer)
402  toWaitOn = Task.WhenAny(toWaitOn, inactiveServerStartup);
403 
404  // wait for something to happen
405  await toWaitOn.ConfigureAwait(false);
406  cancellationToken.ThrowIfCancellationRequested();
407  }
408 
409  var chatTask = Task.CompletedTask;
410  using (await SemaphoreSlimContext.Lock(Semaphore, cancellationToken).ConfigureAwait(false))
411  {
412  // always run HandleMonitorWakeup from the context of the semaphore lock
413  // multiple things may have happened, handle them one at a time
414  for (var moreActivationsToProcess = true; moreActivationsToProcess && (monitorState.NextAction == MonitorAction.Continue || monitorState.NextAction == MonitorAction.Skip);)
415  {
416  MonitorActivationReason activationReason = default; // this will always be assigned before being used
417 
418  // process the tasks in this order and call HandlerMonitorWakup for each
419  bool CheckActivationReason(ref Task task, MonitorActivationReason testActivationReason)
420  {
421  var taskCompleted = task?.IsCompleted == true;
422  task = null;
423  if (monitorState.NextAction == MonitorAction.Skip)
424  monitorState.NextAction = MonitorAction.Continue;
425  else if (taskCompleted)
426  {
427  activationReason = testActivationReason;
428  return true;
429  }
430 
431  return false;
432  }
433 
434  if (CheckActivationReason(ref activeServerLifetime, MonitorActivationReason.ActiveServerCrashed)
435  || CheckActivationReason(ref inactiveServerLifetime, MonitorActivationReason.InactiveServerCrashed)
436  || CheckActivationReason(ref activeServerReboot, MonitorActivationReason.ActiveServerRebooted)
437  || CheckActivationReason(ref inactiveServerReboot, MonitorActivationReason.InactiveServerRebooted)
438  || CheckActivationReason(ref inactiveServerStartup, MonitorActivationReason.InactiveServerStartupComplete)
439  || CheckActivationReason(ref newDmbAvailable, MonitorActivationReason.NewDmbAvailable)
440  || CheckActivationReason(ref activeLaunchParametersChanged, MonitorActivationReason.ActiveLaunchParametersUpdated))
441  await HandlerMonitorWakeup(activationReason, monitorState, cancellationToken).ConfigureAwait(false);
442  else
443  moreActivationsToProcess = false;
444  }
445 
446  // writeback alphaServer and bravoServer from monitor state in case they changesd
447  alphaServer = AlphaIsActive ? monitorState.ActiveServer : monitorState.InactiveServer;
448  bravoServer = !AlphaIsActive ? monitorState.ActiveServer : monitorState.InactiveServer;
449  }
450 
451  // full reboot required
452  if (monitorState.NextAction == MonitorAction.Restart)
453  {
454  Logger.LogDebug("Next state action is to restart");
456  chatTask = Chat.SendWatchdogMessage("Restarting entirely due to complications...", cancellationToken);
457 
458  for (var retryAttempts = 1; monitorState.NextAction == MonitorAction.Restart; ++retryAttempts)
459  {
460  Exception launchException = null;
461  using (await SemaphoreSlimContext.Lock(Semaphore, cancellationToken).ConfigureAwait(false))
462  try
463  {
464  // use LaunchImplNoLock without announcements or restarting the monitor
465  await LaunchImplNoLock(false, false, null, cancellationToken).ConfigureAwait(false);
466  if (Running)
467  {
468  Logger.LogDebug("Relaunch successful, resetting monitor state...");
469  monitorState = new MonitorState(); // clean the slate and continue
470  }
471  }
472  catch (OperationCanceledException)
473  {
474  throw;
475  }
476  catch (Exception e)
477  {
478  launchException = e;
479  }
480 
481  await chatTask.ConfigureAwait(false);
482  if (!Running)
483  {
484  if (launchException == null)
485  Logger.LogWarning("Failed to automatically restart the watchdog! Attempt: {0}", retryAttempts);
486  else
487  Logger.LogWarning("Failed to automatically restart the watchdog! Attempt: {0}, Exception: {1}", retryAttempts, launchException);
488  var retryDelay = Math.Min(Math.Pow(2, retryAttempts), 3600); // max of one hour, increasing by a power of 2 each time
489  chatTask = Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Failed to restart watchdog (Attempt: {0}), retrying in {1} seconds...", retryAttempts, retryDelay), cancellationToken);
490  await Task.WhenAll(AsyncDelayer.Delay(TimeSpan.FromSeconds(retryDelay), cancellationToken), chatTask).ConfigureAwait(false);
491  }
492  }
493  }
494  }
495  catch (OperationCanceledException)
496  {
497  Logger.LogDebug("Monitor cancelled");
498  break;
499  }
500  catch (Exception e)
501  {
502  // really, this should NEVER happen
503  Logger.LogError("Monitor crashed! Iteration: {0}, State: {1}, Exception: {2}", iteration, JsonConvert.SerializeObject(monitorState), e);
504  await Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Monitor crashed, this should NEVER happen! Please report this, full details in logs! Restarting monitor... Error: {0}", e.Message), cancellationToken).ConfigureAwait(false);
505  }
506  }
507 
508  Logger.LogTrace("Monitor exiting...");
509  }
510  #pragma warning restore CA1502
511 
513  #pragma warning disable CA1502 // TODO: Decomplexify
514  protected override async Task InitControllers(Action callBeforeRecurse, Task chatTask, WatchdogReattachInformation reattachInfo, CancellationToken cancellationToken)
515  {
516  // good ole sanity, should never fucking trigger but i don't trust myself even though I should
517  // TODO: Unit test this instead?
518  if (alphaServer != null || bravoServer != null)
519  throw new InvalidOperationException("Entered LaunchNoLock with one or more of the servers not being null!");
520 
521  // don't need a new dmb if reattaching
522  var doesntNeedNewDmb = reattachInfo?.Alpha != null && reattachInfo?.Bravo != null;
523  var dmbToUse = doesntNeedNewDmb ? null : DmbFactory.LockNextDmb(2);
524 
525  // if this try catches something, both servers are killed
526  try
527  {
528  // start the alpha server task, either by launch a new process or attaching to an existing one
529  // The tasks returned are mainly for writing interop files to the directories among other things and should generally never fail
530  // The tasks pertaining to server startup times are in the ISessionControllers
531  Task<ISessionController> alphaServerTask;
532  if (!doesntNeedNewDmb)
533  alphaServerTask = SessionControllerFactory.LaunchNew(ActiveLaunchParameters, dmbToUse, null, true, true, false, cancellationToken);
534  else
535  alphaServerTask = SessionControllerFactory.Reattach(reattachInfo.Alpha, cancellationToken);
536 
537  // retrieve the session controller
538  var startTime = DateTimeOffset.Now;
539  alphaServer = await alphaServerTask.ConfigureAwait(false);
540 
541  // failed reattaches will return null
543 
544  // extra delay for total ordering
545  var now = DateTimeOffset.Now;
546  var delay = now - startTime;
547 
548  // definitely not if reattaching though
549  if (reattachInfo == null && delay.TotalSeconds < AlphaBravoStartupSeperationInterval)
550  await AsyncDelayer.Delay(startTime.AddSeconds(AlphaBravoStartupSeperationInterval) - now, cancellationToken).ConfigureAwait(false);
551 
552  // now bring bravo up
553  if (!doesntNeedNewDmb)
554  bravoServer = await SessionControllerFactory.LaunchNew(ActiveLaunchParameters, dmbToUse, null, false, false, false, cancellationToken).ConfigureAwait(false);
555  else
556  bravoServer = await SessionControllerFactory.Reattach(reattachInfo.Bravo, cancellationToken).ConfigureAwait(false);
557 
558  // failed reattaches will return null
560 
561  // possiblity of null servers due to failed reattaches
562  if (alphaServer == null || bravoServer == null)
563  {
564  await chatTask.ConfigureAwait(false);
565  var bothServersDead = alphaServer == null && bravoServer == null;
566  if (bothServersDead
567  || (alphaServer == null && reattachInfo.AlphaIsActive)
568  || (bravoServer == null && !reattachInfo.AlphaIsActive))
569  {
570  // we lost the active server, just restart entirely
572  const string FailReattachMessage = "Unable to properly reattach to active server! Restarting...";
573  Logger.LogWarning(FailReattachMessage);
574  Logger.LogDebug(bothServersDead ? "Also could not reattach to inactive server!" : "Inactive server was reattached successfully!");
575  chatTask = Chat.SendWatchdogMessage(FailReattachMessage, cancellationToken);
576  callBeforeRecurse();
577  await LaunchImplNoLock(true, false, null, cancellationToken).ConfigureAwait(false);
578  await chatTask.ConfigureAwait(false);
579  return;
580  }
581 
582  // we still have the active server but the other one is dead to us, hand it off to the monitor to restart
583  const string InactiveReattachFailureMessage = "Unable to reattach to inactive server. Leaving for monitor to reboot...";
584  chatTask = Chat.SendWatchdogMessage(InactiveReattachFailureMessage, cancellationToken);
585  Logger.LogWarning(InactiveReattachFailureMessage);
586 
587  if (reattachInfo.AlphaIsActive)
589  else
591  }
592 
593  var alphaLrt = CheckLaunchResult(alphaServer, "Alpha", cancellationToken);
594  var bravoLrt = CheckLaunchResult(bravoServer, "Bravo", cancellationToken);
595 
596  // this task completes when both serers have finished booting
597  var allTask = Task.WhenAll(alphaLrt, bravoLrt);
598 
599  await allTask.ConfigureAwait(false);
600 
601  // both servers are now running, alpha is the active server(unless reattach), huzzah
602  alphaIsActive = reattachInfo?.AlphaIsActive ?? true;
603 
604  var activeServer = AlphaIsActive ? alphaServer : bravoServer;
605  activeServer.EnableCustomChatCommands();
606  activeServer.ClosePortOnReboot = true;
607  }
608  catch
609  {
610  if (dmbToUse != null)
611  {
612  // we locked 2 dmbs
613  if (bravoServer == null)
614  {
615  // bravo didn't get control of his
616  dmbToUse.Dispose();
617  if (alphaServer == null)
618  dmbToUse.Dispose(); // alpha didn't get control of his
619  }
620  }
621  else if (doesntNeedNewDmb) // we have reattachInfo
622  if (bravoServer == null)
623  {
624  // bravo didn't get control of his
625  reattachInfo.Bravo?.Dmb.Dispose();
626  if (alphaServer == null)
627  reattachInfo.Alpha?.Dmb.Dispose(); // alpha didn't get control of his
628  }
629 
630  // kill the controllers
632  throw;
633  }
634  }
635  #pragma warning restore CA1502
636 
639 
643  {
645  Alpha = alphaServer?.Release(),
646  Bravo = bravoServer?.Release()
647  };
648  }
649 }
-
bool InactiveServerCritFail
If the inactive server is in an unrecoverable state
Definition: MonitorState.cs:18
-
Manages the runtime of Jobs
Definition: IJobManager.cs:12
-
readonly bool autoStart
If the WatchdogBase should LaunchImplNoLock(bool, bool, WatchdogReattachInformation,...
+Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Microsoft.Extensions.Logging;
3 using Newtonsoft.Json;
4 using System;
5 using System.Diagnostics;
6 using System.Globalization;
7 using System.Threading;
8 using System.Threading.Tasks;
15 
17 {
22  {
26  const int AlphaBravoStartupSeperationInterval = 10; // TODO: Make this configurable
27 
29  public override bool AlphaIsActive => alphaIsActive;
30 
32  public override Models.CompileJob ActiveCompileJob => (AlphaIsActive ? alphaServer : bravoServer)?.Dmb.CompileJob;
33 
36 
41 
46 
51 
69  public ExperimentalWatchdog(IChat chat, ISessionControllerFactory sessionControllerFactory, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IDatabaseContextFactory databaseContextFactory, IByondTopicSender byondTopicSender, IEventConsumer eventConsumer, IJobManager jobManager, IServerControl serverControl, IAsyncDelayer asyncDelayer, ILogger<ExperimentalWatchdog> logger, DreamDaemonLaunchParameters initialLaunchParameters, Api.Models.Instance instance, bool autoStart)
70  : base(
71  chat,
72  sessionControllerFactory,
73  dmbFactory,
78  jobManager,
79  serverControl,
80  asyncDelayer,
81  logger,
82  initialLaunchParameters,
83  instance,
84  autoStart)
85  {
86  alphaIsActive = true;
87  }
88 
96  #pragma warning disable CA1502 // TODO: Decomplexify
97  async Task HandlerMonitorWakeup(MonitorActivationReason activationReason, MonitorState monitorState, CancellationToken cancellationToken)
98  {
99  Logger.LogDebug("Monitor activation. Reason: {0}", activationReason);
100 
101  // this is where the bulk of the watchdog handling code lives and is fraught with lambdas, sorry not sorry
102  // I'll do my best to walk you through it
103 
104  // returns true if the inactive server can't be used immediately
105  // also sets monitor to restart if the above holds
106  bool FullRestartDeadInactive()
107  {
108  if (monitorState.RebootingInactiveServer || monitorState.InactiveServerCritFail)
109  {
110  Logger.LogInformation("Inactive server is {0}! Restarting monitor...", monitorState.InactiveServerCritFail ? "critically failed" : "still rebooting");
111  monitorState.NextAction = MonitorAction.Restart; // will dispose server
112  return true;
113  }
114 
115  return false;
116  }
117 
118  // trys to set inactive server's port to the public game port
119  // doesn't handle closing active server's port
120  // returns true on success and swaps inactiveserver and activeserver also sets LastLaunchParameters to ActiveLaunchParameters
121  // on failure, sets monitor to restart
122  async Task<bool> MakeInactiveActive()
123  {
124  Logger.LogDebug("Setting inactive server to port {0}...", ActiveLaunchParameters.PrimaryPort.Value);
125  var result = await monitorState.InactiveServer.SetPort(ActiveLaunchParameters.PrimaryPort.Value, cancellationToken).ConfigureAwait(false);
126 
127  if (!result)
128  {
129  Logger.LogWarning("Failed to activate inactive server! Restarting monitor...");
130  monitorState.NextAction = MonitorAction.Restart; // will dispose server
131  return false;
132  }
133 
134  // inactive server should always be using active launch parameters
136 
137  var tmp = monitorState.ActiveServer;
138  monitorState.ActiveServer = monitorState.InactiveServer;
139  monitorState.InactiveServer = tmp;
141  monitorState.ActiveServer.EnableCustomChatCommands();
142  return true;
143  }
144 
145  // Kills and tries to launch inactive server with the latest dmb
146  // falls back to current dmb on failure
147  // Sets critfail on inactive server failing that
148  // returns false if the backup dmb was used successfully, true otherwise
149  async Task UpdateAndRestartInactiveServer(bool breakAfter)
150  {
151  ActiveParametersUpdated = new TaskCompletionSource<object>();
152  monitorState.InactiveServer.Dispose(); // kill or recycle it
153  var desiredNextAction = breakAfter ? MonitorAction.Break : MonitorAction.Continue;
154  monitorState.NextAction = desiredNextAction;
155 
156  Logger.LogInformation("Rebooting inactive server...");
157  var newDmb = DmbFactory.LockNextDmb(1);
158  try
159  {
160  monitorState.InactiveServer = await SessionControllerFactory.LaunchNew(ActiveLaunchParameters, newDmb, null, false, !monitorState.ActiveServer.IsPrimary, false, cancellationToken).ConfigureAwait(false);
161  monitorState.InactiveServer.SetHighPriority();
162  }
163  catch (OperationCanceledException)
164  {
165  throw;
166  }
167  catch (Exception e)
168  {
169  Logger.LogError("Error occurred while recreating server! Attempting backup strategy of running DMB of running server! Exception: {0}", e.ToString());
170 
171  // ahh jeez, what do we do here?
172  // this is our fault, so it should never happen but
173  // idk maybe a database error while handling the newest dmb?
174  // either way try to start it using the active server's dmb as a backup
175  try
176  {
177  var dmbBackup = await DmbFactory.FromCompileJob(monitorState.ActiveServer.Dmb.CompileJob, cancellationToken).ConfigureAwait(false);
178 
179  if (dmbBackup == null) // NANI!?
180  throw new JobException("Creating backup DMB provider failed!"); // just give up, if THAT compile job is failing then the ActiveServer is gonna crash soon too or already has
181 
182  monitorState.InactiveServer = await SessionControllerFactory.LaunchNew(ActiveLaunchParameters, dmbBackup, null, false, !monitorState.ActiveServer.IsPrimary, false, cancellationToken).ConfigureAwait(false);
183  monitorState.InactiveServer.SetHighPriority();
184  await Chat.SendWatchdogMessage("Staging newest DMB on inactive server failed: {0} Falling back to previous dmb...", cancellationToken).ConfigureAwait(false);
185  }
186  catch (OperationCanceledException)
187  {
188  throw;
189  }
190  catch (Exception e2)
191  {
192  // fuuuuucckkk
193  Logger.LogError("Backup strategy failed! Monitor will restart when active server reboots! Exception: {0}", e2.ToString());
194  monitorState.InactiveServerCritFail = true;
195  await Chat.SendWatchdogMessage("Attempted reboot of inactive server failed. Watchdog will reset when active server fails or exits", cancellationToken).ConfigureAwait(false);
196  return;
197  }
198  }
199 
200  Logger.LogInformation("Successfully relaunched inactive server!");
201  monitorState.RebootingInactiveServer = true;
202  }
203 
204  string ExitWord(ISessionController controller) => controller.TerminationWasRequested ? "exited" : "crashed";
205 
206  // reason handling
207  switch (activationReason)
208  {
209  case MonitorActivationReason.ActiveServerCrashed:
210  if (monitorState.ActiveServer.RebootState == Watchdog.RebootState.Shutdown)
211  {
212  // the time for graceful shutdown is now
213  await Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Active server {0}! Exiting due to graceful termination request...", ExitWord(monitorState.ActiveServer)), cancellationToken).ConfigureAwait(false);
215  monitorState.NextAction = MonitorAction.Exit;
216  break;
217  }
218 
219  if (FullRestartDeadInactive())
220  {
221  // tell chat about it and go ahead
222  await Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Active server {0}! Inactive server unable to online!", ExitWord(monitorState.ActiveServer)), cancellationToken).ConfigureAwait(false);
223 
224  // we've already been set to restart
225  break;
226  }
227 
228  // tell chat about it
229  await Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Active server {0}! Onlining inactive server...", ExitWord(monitorState.ActiveServer)), cancellationToken).ConfigureAwait(false);
230 
231  // try to activate the inactive server
232  if (!await MakeInactiveActive().ConfigureAwait(false))
233  break; // failing that, we've already been set to restart
234 
235  // bring up another inactive server
236  await UpdateAndRestartInactiveServer(true).ConfigureAwait(false);
237  break;
238  case MonitorActivationReason.InactiveServerCrashed:
239  // just announce and try to bring it back
240  await Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Inactive server {0}! Rebooting...", ExitWord(monitorState.InactiveServer)), cancellationToken).ConfigureAwait(false);
241  await UpdateAndRestartInactiveServer(false).ConfigureAwait(false);
242  break;
243  case MonitorActivationReason.ActiveServerRebooted:
244  // ideal goal: active server just closed its port
245  // tell inactive server to open it's port and that's now the active server
246  var rebootState = monitorState.ActiveServer.RebootState;
247  monitorState.ActiveServer.ResetRebootState(); // the DMAPI has already done this internally
248 
249  if (FullRestartDeadInactive() && rebootState != Watchdog.RebootState.Shutdown)
250  break; // full restart if the inactive server is being fucky
251 
252  // what matters here is the RebootState
253  var restartOnceSwapped = false;
254 
255  switch (rebootState)
256  {
257  case Watchdog.RebootState.Normal:
258  // life as normal
259  break;
260  case Watchdog.RebootState.Restart:
261  // reboot the current active server once the inactive one activates
262  restartOnceSwapped = true;
263  break;
264  case Watchdog.RebootState.Shutdown:
265  // graceful shutdown time
266  await Chat.SendWatchdogMessage("Active server rebooted! Exiting due to graceful termination request...", cancellationToken).ConfigureAwait(false);
268  monitorState.NextAction = MonitorAction.Exit;
269  return;
270  default:
271  throw new InvalidOperationException($"Invalid reboot state: {rebootState}");
272  }
273 
274  // are both servers now running the same CompileJob?
275  var sameCompileJob = monitorState.InactiveServer.Dmb.CompileJob.Id == monitorState.ActiveServer.Dmb.CompileJob.Id;
276 
277  if (!sameCompileJob || ActiveLaunchParameters != LastLaunchParameters)
278  restartOnceSwapped = true; // need a new launch to update either settings or compile job
279 
280  if (restartOnceSwapped)
281  /*
282  * we need to manually restart active server
283  * just kill it here, easier that way
284  */
285  monitorState.ActiveServer.Dispose();
286 
287  var activeServerStillHasPortOpen = !restartOnceSwapped && !monitorState.ActiveServer.ClosePortOnReboot;
288 
289  if (activeServerStillHasPortOpen)
290  /* we didn't want active server to swap for some reason and it still has it's port open
291  * just continue as normal
292  */
293  break;
294 
295  if (!await MakeInactiveActive().ConfigureAwait(false))
296  break; // monitor will restart
297 
298  // servers now swapped
299  // enable this now if inactive server is not still valid
300  monitorState.ActiveServer.ClosePortOnReboot = restartOnceSwapped;
301 
302  if (!restartOnceSwapped)
303  /*
304  * now try to reopen it on the private port
305  * failing that, just reboot it
306  */
307  restartOnceSwapped = !await monitorState.InactiveServer.SetPort(ActiveLaunchParameters.SecondaryPort.Value, cancellationToken).ConfigureAwait(false);
308 
309  // break either way because any issues past this point would be solved by the reboot
310  if (restartOnceSwapped) // for one reason or another
311  await UpdateAndRestartInactiveServer(true).ConfigureAwait(false); // update and reboot
312  else
313  monitorState.NextAction = MonitorAction.Skip; // only skip checking inactive server rebooted, it's guaranteed InactiveServerStartup complete wouldn't fire this iteration
314  break;
315  case MonitorActivationReason.InactiveServerRebooted:
316  // just don't let the active server close it's port if the inactive server isn't ready
317  monitorState.RebootingInactiveServer = true;
318  monitorState.InactiveServer.ResetRebootState();
319  monitorState.ActiveServer.ClosePortOnReboot = false;
320  monitorState.NextAction = MonitorAction.Continue;
321  break;
322  case MonitorActivationReason.InactiveServerStartupComplete:
323  // opposite of above case
324  monitorState.RebootingInactiveServer = false;
325  monitorState.ActiveServer.ClosePortOnReboot = true;
326  monitorState.NextAction = MonitorAction.Continue;
327  break;
328  case MonitorActivationReason.NewDmbAvailable:
329  case MonitorActivationReason.ActiveLaunchParametersUpdated:
330  // just reload the inactive server and wait for a swap to apply the changes
331  await UpdateAndRestartInactiveServer(true).ConfigureAwait(false);
332  break;
333  default:
334  Trace.Assert(false, String.Format(CultureInfo.InvariantCulture, "Invalid monitor activation reason: {0}!", activationReason));
335  break;
336  }
337  }
338  #pragma warning restore CA1502
339 
343  protected override void DisposeAndNullControllers()
344  {
345  alphaServer?.Dispose();
346  alphaServer = null;
347  bravoServer?.Dispose();
348  bravoServer = null;
349  Running = false;
350  }
351 
353  #pragma warning disable CA1502 // TODO: Decomplexify
354  protected override async Task MonitorLifetimes(CancellationToken cancellationToken)
355  {
356  Logger.LogTrace("Entered MonitorLifetimes");
357 
358  // this function is responsible for calling HandlerMonitorWakeup when necessary and manitaining the MonitorState
359  var iteration = 1;
360  for (var monitorState = new MonitorState(); monitorState.NextAction != MonitorAction.Exit; ++iteration)
361  {
362  // always start out with continue
363  monitorState.NextAction = MonitorAction.Continue;
364 
365  // dump some info to the logs
366  Logger.LogDebug("Iteration {0} of monitor loop", iteration);
367  try
368  {
369  if (AlphaIsActive)
370  Logger.LogDebug("Alpha is the active server");
371  else
372  Logger.LogDebug("Bravo is the active server");
373 
374  if (monitorState.RebootingInactiveServer)
375  Logger.LogDebug("Inactive server is rebooting");
376 
377  // update the monitor state with the inactive/active servers
378  monitorState.ActiveServer = AlphaIsActive ? alphaServer : bravoServer;
379  monitorState.InactiveServer = AlphaIsActive ? bravoServer : alphaServer;
380 
381  if (monitorState.ActiveServer.ClosePortOnReboot)
382  Logger.LogDebug("Active server will close port on reboot");
383  if (monitorState.InactiveServer.ClosePortOnReboot)
384  Logger.LogDebug("Inactive server will close port on reboot");
385 
386  Logger.LogDebug("Active server Compile Job ID: {0}", monitorState.ActiveServer.Dmb.CompileJob.Id);
387  Logger.LogDebug("Inactive server Compile Job ID: {0}", monitorState.InactiveServer.Dmb.CompileJob.Id);
388 
389  // load the activation tasks into local variables
390  Task activeServerLifetime = monitorState.ActiveServer.Lifetime;
391  Task inactiveServerLifetime = monitorState.InactiveServer.Lifetime;
392  var activeServerReboot = monitorState.ActiveServer.OnReboot;
393  var inactiveServerReboot = monitorState.InactiveServer.OnReboot;
394  Task inactiveServerStartup = monitorState.RebootingInactiveServer ? monitorState.InactiveServer.LaunchResult : null;
395  Task activeLaunchParametersChanged = ActiveParametersUpdated.Task;
396  var newDmbAvailable = DmbFactory.OnNewerDmb;
397 
398  // cancel waiting if requested
399  var cancelTcs = new TaskCompletionSource<object>();
400  using (cancellationToken.Register(() => cancelTcs.SetCanceled()))
401  {
402  var toWaitOn = Task.WhenAny(activeServerLifetime, inactiveServerLifetime, activeServerReboot, inactiveServerReboot, newDmbAvailable, cancelTcs.Task, activeLaunchParametersChanged);
403  if (monitorState.RebootingInactiveServer)
404  toWaitOn = Task.WhenAny(toWaitOn, inactiveServerStartup);
405 
406  // wait for something to happen
407  await toWaitOn.ConfigureAwait(false);
408  cancellationToken.ThrowIfCancellationRequested();
409  }
410 
411  var chatTask = Task.CompletedTask;
412  using (await SemaphoreSlimContext.Lock(Semaphore, cancellationToken).ConfigureAwait(false))
413  {
414  // always run HandleMonitorWakeup from the context of the semaphore lock
415  // multiple things may have happened, handle them one at a time
416  for (var moreActivationsToProcess = true; moreActivationsToProcess && (monitorState.NextAction == MonitorAction.Continue || monitorState.NextAction == MonitorAction.Skip);)
417  {
418  MonitorActivationReason activationReason = default; // this will always be assigned before being used
419 
420  // process the tasks in this order and call HandlerMonitorWakup for each
421  bool CheckActivationReason(ref Task task, MonitorActivationReason testActivationReason)
422  {
423  var taskCompleted = task?.IsCompleted == true;
424  task = null;
425  if (monitorState.NextAction == MonitorAction.Skip)
426  monitorState.NextAction = MonitorAction.Continue;
427  else if (taskCompleted)
428  {
429  activationReason = testActivationReason;
430  return true;
431  }
432 
433  return false;
434  }
435 
436  if (CheckActivationReason(ref activeServerLifetime, MonitorActivationReason.ActiveServerCrashed)
437  || CheckActivationReason(ref inactiveServerLifetime, MonitorActivationReason.InactiveServerCrashed)
438  || CheckActivationReason(ref activeServerReboot, MonitorActivationReason.ActiveServerRebooted)
439  || CheckActivationReason(ref inactiveServerReboot, MonitorActivationReason.InactiveServerRebooted)
440  || CheckActivationReason(ref inactiveServerStartup, MonitorActivationReason.InactiveServerStartupComplete)
441  || CheckActivationReason(ref newDmbAvailable, MonitorActivationReason.NewDmbAvailable)
442  || CheckActivationReason(ref activeLaunchParametersChanged, MonitorActivationReason.ActiveLaunchParametersUpdated))
443  {
444  Logger.LogTrace("Monitor activation: {0}", activationReason);
445  await HandlerMonitorWakeup(activationReason, monitorState, cancellationToken).ConfigureAwait(false);
446  }
447  else
448  moreActivationsToProcess = false;
449  }
450 
451  // writeback alphaServer and bravoServer from monitor state in case they changesd
452  alphaServer = AlphaIsActive ? monitorState.ActiveServer : monitorState.InactiveServer;
453  bravoServer = !AlphaIsActive ? monitorState.ActiveServer : monitorState.InactiveServer;
454  }
455 
456  // full reboot required
457  if (monitorState.NextAction == MonitorAction.Restart)
458  {
459  Logger.LogDebug("Next state action is to restart");
461  chatTask = Chat.SendWatchdogMessage("Restarting entirely due to complications...", cancellationToken);
462 
463  for (var retryAttempts = 1; monitorState.NextAction == MonitorAction.Restart; ++retryAttempts)
464  {
465  Exception launchException = null;
466  using (await SemaphoreSlimContext.Lock(Semaphore, cancellationToken).ConfigureAwait(false))
467  try
468  {
469  // use LaunchImplNoLock without announcements or restarting the monitor
470  await LaunchImplNoLock(false, false, null, cancellationToken).ConfigureAwait(false);
471  if (Running)
472  {
473  Logger.LogDebug("Relaunch successful, resetting monitor state...");
474  monitorState = new MonitorState(); // clean the slate and continue
475  }
476  }
477  catch (OperationCanceledException)
478  {
479  throw;
480  }
481  catch (Exception e)
482  {
483  launchException = e;
484  }
485 
486  await chatTask.ConfigureAwait(false);
487  if (!Running)
488  {
489  if (launchException == null)
490  Logger.LogWarning("Failed to automatically restart the watchdog! Attempt: {0}", retryAttempts);
491  else
492  Logger.LogWarning("Failed to automatically restart the watchdog! Attempt: {0}, Exception: {1}", retryAttempts, launchException);
493  var retryDelay = Math.Min(Math.Pow(2, retryAttempts), 3600); // max of one hour, increasing by a power of 2 each time
494  chatTask = Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Failed to restart watchdog (Attempt: {0}), retrying in {1} seconds...", retryAttempts, retryDelay), cancellationToken);
495  await Task.WhenAll(AsyncDelayer.Delay(TimeSpan.FromSeconds(retryDelay), cancellationToken), chatTask).ConfigureAwait(false);
496  }
497  }
498  }
499  }
500  catch (OperationCanceledException)
501  {
502  Logger.LogDebug("Monitor cancelled");
503  break;
504  }
505  catch (Exception e)
506  {
507  // really, this should NEVER happen
508  Logger.LogError("Monitor crashed! Iteration: {0}, State: {1}, Exception: {2}", iteration, JsonConvert.SerializeObject(monitorState), e);
509  await Chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Monitor crashed, this should NEVER happen! Please report this, full details in logs! Restarting monitor... Error: {0}", e.Message), cancellationToken).ConfigureAwait(false);
510  }
511  }
512 
513  Logger.LogTrace("Monitor exiting...");
514  }
515  #pragma warning restore CA1502
516 
518  #pragma warning disable CA1502 // TODO: Decomplexify
519  protected override async Task InitControllers(Action callBeforeRecurse, Task chatTask, WatchdogReattachInformation reattachInfo, CancellationToken cancellationToken)
520  {
521  Debug.Assert(alphaServer == null && bravoServer == null, "Entered LaunchNoLock with one or more of the servers not being null!");
522 
523  // don't need a new dmb if reattaching
524  var doesntNeedNewDmb = reattachInfo?.Alpha != null && reattachInfo?.Bravo != null;
525  var dmbToUse = doesntNeedNewDmb ? null : DmbFactory.LockNextDmb(2);
526 
527  // if this try catches something, both servers are killed
528  try
529  {
530  // start the alpha server task, either by launch a new process or attaching to an existing one
531  // The tasks returned are mainly for writing interop files to the directories among other things and should generally never fail
532  // The tasks pertaining to server startup times are in the ISessionControllers
533  Task<ISessionController> alphaServerTask;
534  if (!doesntNeedNewDmb)
535  alphaServerTask = SessionControllerFactory.LaunchNew(ActiveLaunchParameters, dmbToUse, null, true, true, false, cancellationToken);
536  else
537  alphaServerTask = SessionControllerFactory.Reattach(reattachInfo.Alpha, cancellationToken);
538 
539  // retrieve the session controller
540  var startTime = DateTimeOffset.Now;
541  alphaServer = await alphaServerTask.ConfigureAwait(false);
542 
543  // failed reattaches will return null
545 
546  // extra delay for total ordering
547  var now = DateTimeOffset.Now;
548  var delay = now - startTime;
549 
550  // definitely not if reattaching though
551  if (reattachInfo == null && delay.TotalSeconds < AlphaBravoStartupSeperationInterval)
552  await AsyncDelayer.Delay(startTime.AddSeconds(AlphaBravoStartupSeperationInterval) - now, cancellationToken).ConfigureAwait(false);
553 
554  // now bring bravo up
555  if (!doesntNeedNewDmb)
556  bravoServer = await SessionControllerFactory.LaunchNew(ActiveLaunchParameters, dmbToUse, null, false, false, false, cancellationToken).ConfigureAwait(false);
557  else
558  bravoServer = await SessionControllerFactory.Reattach(reattachInfo.Bravo, cancellationToken).ConfigureAwait(false);
559 
560  // failed reattaches will return null
562 
563  // possiblity of null servers due to failed reattaches
564  if (alphaServer == null || bravoServer == null)
565  {
566  await chatTask.ConfigureAwait(false);
567  var bothServersDead = alphaServer == null && bravoServer == null;
568  if (bothServersDead
569  || (alphaServer == null && reattachInfo.AlphaIsActive)
570  || (bravoServer == null && !reattachInfo.AlphaIsActive))
571  {
572  // we lost the active server, just restart entirely
574  const string FailReattachMessage = "Unable to properly reattach to active server! Restarting...";
575  Logger.LogWarning(FailReattachMessage);
576  Logger.LogDebug(bothServersDead ? "Also could not reattach to inactive server!" : "Inactive server was reattached successfully!");
577  chatTask = Chat.SendWatchdogMessage(FailReattachMessage, cancellationToken);
578  callBeforeRecurse();
579  await LaunchImplNoLock(true, false, null, cancellationToken).ConfigureAwait(false);
580  await chatTask.ConfigureAwait(false);
581  return;
582  }
583 
584  // we still have the active server but the other one is dead to us, hand it off to the monitor to restart
585  const string InactiveReattachFailureMessage = "Unable to reattach to inactive server. Leaving for monitor to reboot...";
586  chatTask = Chat.SendWatchdogMessage(InactiveReattachFailureMessage, cancellationToken);
587  Logger.LogWarning(InactiveReattachFailureMessage);
588 
589  if (reattachInfo.AlphaIsActive)
591  else
593  }
594 
595  var alphaLrt = CheckLaunchResult(alphaServer, "Alpha", cancellationToken);
596  var bravoLrt = CheckLaunchResult(bravoServer, "Bravo", cancellationToken);
597 
598  // this task completes when both serers have finished booting
599  var allTask = Task.WhenAll(alphaLrt, bravoLrt);
600 
601  await allTask.ConfigureAwait(false);
602 
603  // both servers are now running, alpha is the active server(unless reattach), huzzah
604  alphaIsActive = reattachInfo?.AlphaIsActive ?? true;
605 
606  var activeServer = AlphaIsActive ? alphaServer : bravoServer;
607  activeServer.EnableCustomChatCommands();
608  activeServer.ClosePortOnReboot = true;
609  }
610  catch
611  {
612  if (dmbToUse != null)
613  {
614  // we locked 2 dmbs
615  if (bravoServer == null)
616  {
617  // bravo didn't get control of his
618  dmbToUse.Dispose();
619  if (alphaServer == null)
620  dmbToUse.Dispose(); // alpha didn't get control of his
621  }
622  }
623  else if (doesntNeedNewDmb) // we have reattachInfo
624  if (bravoServer == null)
625  {
626  // bravo didn't get control of his
627  reattachInfo.Bravo?.Dmb.Dispose();
628  if (alphaServer == null)
629  reattachInfo.Alpha?.Dmb.Dispose(); // alpha didn't get control of his
630  }
631 
632  // kill the controllers
634  throw;
635  }
636  }
637  #pragma warning restore CA1502
638 
641 
645  {
647  Alpha = alphaServer?.Release(),
648  Bravo = bravoServer?.Release()
649  };
650  }
651 }
bool InactiveServerCritFail
If the inactive server is in an unrecoverable state
Definition: MonitorState.cs:18
+
CompileJob CompileJob
The CompileJob of the .dmb
Definition: IDmbProvider.cs:29
+
readonly bool autoStart
If the WatchdogBase should LaunchImplNoLock(bool, bool, WatchdogReattachInformation,...
-
const int AlphaBravoStartupSeperationInterval
The time in seconds to wait from starting alphaServer to start bravoServer. Does not take responsiven...
+
const int AlphaBravoStartupSeperationInterval
The time in seconds to wait from starting alphaServer to start bravoServer. Does not take responsiven...
- - + +
ushort? PrimaryPort
The first port DreamDaemon uses. This should be the publically advertised port
-
CompileJob CompileJob
The CompileJob of the .dmb
Definition: IDmbProvider.cs:29
long Id
The ID of the entity.
Definition: EntityId.cs:11
- - -
async Task LaunchImplNoLock(bool startMonitor, bool announce, WatchdogReattachInformation reattachInfo, CancellationToken cancellationToken)
Launches the watchdog.
-
MonitorAction NextAction
The next MonitorAction to take in ExperimentalWatchdog.MonitorLifetimes(System.Threading....
Definition: MonitorState.cs:23
+ +
async Task LaunchImplNoLock(bool startMonitor, bool announce, WatchdogReattachInformation reattachInfo, CancellationToken cancellationToken)
Launches the watchdog.
+
MonitorAction NextAction
The next MonitorAction to take in ExperimentalWatchdog.MonitorLifetimes(global::System....
Definition: MonitorState.cs:23
- + +
Consumes EventTypes and takes the appropriate actions
- -
ExperimentalWatchdog(IChat chat, ISessionControllerFactory sessionControllerFactory, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IDatabaseContextFactory databaseContextFactory, IByondTopicSender byondTopicSender, IEventConsumer eventConsumer, IJobManager jobManager, IServerControl serverControl, IAsyncDelayer asyncDelayer, ILogger< ExperimentalWatchdog > logger, DreamDaemonLaunchParameters initialLaunchParameters, Api.Models.Instance instance, bool autoStart)
Initializes a new instance of the ExperimentalWatchdog class.
- -
SemaphoreSlim Semaphore
The SemaphoreSlim for the WatchdogBase.
Definition: WatchdogBase.cs:55
+ + +
ExperimentalWatchdog(IChat chat, ISessionControllerFactory sessionControllerFactory, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IDatabaseContextFactory databaseContextFactory, IByondTopicSender byondTopicSender, IEventConsumer eventConsumer, IJobManager jobManager, IServerControl serverControl, IAsyncDelayer asyncDelayer, ILogger< ExperimentalWatchdog > logger, DreamDaemonLaunchParameters initialLaunchParameters, Api.Models.Instance instance, bool autoStart)
Initializes a new instance of the ExperimentalWatchdog class.
+ +
SemaphoreSlim Semaphore
The SemaphoreSlim for the WatchdogBase.
Definition: WatchdogBase.cs:58
+
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
void EnableCustomChatCommands()
Enables the reading of custom chat commands from the ISessionController
override ISessionController GetActiveController()
Get the active ISessionController.
-
bool ClosePortOnReboot
If the port should be rotated off when the world reboots
-
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
+
bool ClosePortOnReboot
If the port should be rotated off when the world reboots
Task SendWatchdogMessage(string message, CancellationToken cancellationToken)
Send a chat message to configured watchdog channels
Definition: Chat.cs:514
- -
readonly IByondTopicSender byondTopicSender
The IByondTopicSender for the ExperimentalWatchdog
+ +
readonly IByondTopicSender byondTopicSender
The IByondTopicSender for the ExperimentalWatchdog
-
readonly IJobManager jobManager
The IJobManager for the ExperimentalWatchdog
+
readonly IJobManager jobManager
The IJobManager for the ExperimentalWatchdog
For managing connected chat services
Definition: IChat.cs:13
ISessionController CreateDeadSession(IDmbProvider dmbProvider)
Creates a ISessionController that appears to have started and died with exit code -1
- + -
readonly IReattachInfoHandler reattachInfoHandler
The IReattachInfoHandler for the WatchdogBase
Definition: WatchdogBase.cs:90
+
readonly IReattachInfoHandler reattachInfoHandler
The IReattachInfoHandler for the WatchdogBase
Definition: WatchdogBase.cs:93
-
Handles communication with a DreamDaemon IProcess
-
bool IsPrimary
If the IDmbProvider.PrimaryDirectory of Dmb is being used
- -
void SetHighPriority()
Set's the owned System.Diagnostics.Process.PriorityClass to System.Diagnostics.ProcessPriorityClass....
-
A IWatchdog that tries to manage 2 servers at once for maximum uptime.
-
bool TerminationWasRequested
If the DreamDaemon instance sent a
+
Handles communication with a DreamDaemon IProcess
+
bool IsPrimary
If the IDmbProvider.PrimaryDirectory of Dmb is being used
+ +
A IWatchdog that tries to manage 2 servers at once for maximum uptime.
+
bool TerminationWasRequested
If the DreamDaemon instance sent a
-
bool RebootingInactiveServer
If the inactive server is being rebooted
Definition: MonitorState.cs:13
- -
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the ExperimentalWatchdog
Definition: WatchdogBase.cs:95
-
async Task< ISessionController > LaunchNew(DreamDaemonLaunchParameters launchParameters, IDmbProvider dmbProvider, IByondExecutableLock currentByondLock, bool primaryPort, bool primaryDirectory, bool apiValidate, CancellationToken cancellationToken)
Create a ISessionController from a freshly launch DreamDaemon instance
-
TaskCompletionSource< object > ActiveParametersUpdated
TaskCompletionSource<TResult> that completes when ActiveLaunchParameters are changed and we are Runni...
Definition: WatchdogBase.cs:50
-
async Task< IDmbProvider > FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken)
Gets a IDmbProvider for a given CompileJob
Definition: DmbFactory.cs:186
-
override async Task InitControllers(Action callBeforeRecurse, Task chatTask, WatchdogReattachInformation reattachInfo, CancellationToken cancellationToken)
Starts all ISessionControllers.
- -
ReattachInformation Alpha
ReattachInformation for the Alpha session
+
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the ExperimentalWatchdog
Definition: WatchdogBase.cs:98
+
async Task< ISessionController > LaunchNew(DreamDaemonLaunchParameters launchParameters, IDmbProvider dmbProvider, IByondExecutableLock currentByondLock, bool primaryPort, bool primaryDirectory, bool apiValidate, CancellationToken cancellationToken)
Create a ISessionController from a freshly launch DreamDaemon instance
+
TaskCompletionSource< object > ActiveParametersUpdated
TaskCompletionSource<TResult> that completes when ActiveLaunchParameters are changed and we are Runni...
Definition: WatchdogBase.cs:53
+
override async Task InitControllers(Action callBeforeRecurse, Task chatTask, WatchdogReattachInformation reattachInfo, CancellationToken cancellationToken)
Starts all ISessionControllers.
+ +
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
+
ReattachInformation Alpha
ReattachInformation for the Alpha session
Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan
MonitorActivationReason
Reasons for the monitor to wake up
-
async Task< ISessionController > Reattach(ReattachInformation reattachInformation, CancellationToken cancellationToken)
Create a ISessionController from an existing DreamDaemon instance
+
async Task< ISessionController > Reattach(ReattachInformation reattachInformation, CancellationToken cancellationToken)
Create a ISessionController from an existing DreamDaemon instance
Task< bool > SetPort(ushort newPort, CancellationToken cancellatonToken)
Causes the world to start listening on a newPort
-
IDmbProvider Dmb
The IDmbProvider used by DreamDaemon
-
ReattachInformation Release()
Releases the IProcess without terminating it. Also calls System.IDisposable.Dispose
-
override async Task MonitorLifetimes(CancellationToken cancellationToken)
The loop that watches the watchdog
+
IDmbProvider Dmb
The IDmbProvider used by DreamDaemon
+
ReattachInformation Release()
Releases the IProcess without terminating it. Also calls global::System.IDisposable....
+
override async Task MonitorLifetimes(CancellationToken cancellationToken)
The loop that watches the watchdog
- + +
ISessionController ActiveServer
The active ISessionController
Definition: MonitorState.cs:29
-
IDmbProvider LockNextDmb(int lockCount)
Gets the next IDmbProvider
Definition: DmbFactory.cs:149
+ +
void SetHighPriority()
Set's the owned global::System.Diagnostics.Process.PriorityClass to global::System....
ISessionController InactiveServer
The inactive ISessionController
Definition: MonitorState.cs:35
- -
readonly IEventConsumer eventConsumer
The IEventConsumer for the ExperimentalWatchdog
+ +
readonly IEventConsumer eventConsumer
The IEventConsumer for the ExperimentalWatchdog
+
Manages the runtime of Jobs
Definition: IJobManager.cs:13
-
async Task CheckLaunchResult(ISessionController controller, string serverName, CancellationToken cancellationToken)
Check the LaunchResult of a given controller for errors and throw a JobException if any are detected...
+ +
async Task< IDmbProvider > FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken)
Gets a IDmbProvider for a given CompileJob
Definition: DmbFactory.cs:186
+
async Task CheckLaunchResult(ISessionController controller, string serverName, CancellationToken cancellationToken)
Check the LaunchResult of a given controller for errors and throw a JobException if any are detected...
-
ILogger Logger
The ILogger for the WatchdogBase.
Definition: WatchdogBase.cs:60
- +
ILogger Logger
The ILogger for the WatchdogBase.
Definition: WatchdogBase.cs:63
+
override WatchdogReattachInformation CreateReattachInformation()
Create the WatchdogReattachInformation for the ISessionControllers.
-
readonly Api.Models.Instance instance
The Api.Models.Instance for the WatchdogBase.
Definition: WatchdogBase.cs:85
-
async Task HandlerMonitorWakeup(MonitorActivationReason activationReason, MonitorState monitorState, CancellationToken cancellationToken)
Handles the actions to take when the monitor has to "wake up"
-
ReattachInformation Bravo
ReattachInformation for the Bravo session
+
readonly Api.Models.Instance instance
The Api.Models.Instance for the WatchdogBase.
Definition: WatchdogBase.cs:88
+
async Task HandlerMonitorWakeup(MonitorActivationReason activationReason, MonitorState monitorState, CancellationToken cancellationToken)
Handles the actions to take when the monitor has to "wake up"
+
ReattachInformation Bravo
ReattachInformation for the Bravo session
MonitorAction
The action for the monitor loop to take when control is returned to it
Definition: MonitorAction.cs:6
+
IDmbProvider LockNextDmb(int lockCount)
Gets the next IDmbProvider
Definition: DmbFactory.cs:149
The (absolute) state of the ExperimentalWatchdog
Definition: MonitorState.cs:8
Handles saving and loading WatchdogReattachInformation
static async Task< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore
-
void ResetRebootState()
Changes RebootState to Components.Watchdog.RebootState.Normal without telling the DMAPI
+
void ResetRebootState()
Changes RebootState to Watchdog.RebootState.Normal without telling the DMAPI
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
-
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
- + +
Represents a service that may take an updated Host assembly and run it, stopping the current assembly...
-
override void DisposeAndNullControllers()
Call IDisposable.Dispose on alphaServer and bravoServer and set them to null
+
override void DisposeAndNullControllers()
Call IDisposable.Dispose on alphaServer and bravoServer and set them to null
-Go to the documentation of this file.
1 using Newtonsoft.Json;
2 using Newtonsoft.Json.Converters;
3 
5 {
9  public sealed class GeneralConfiguration
10  {
14  public const string Section = "General";
15 
20 
24  const int DefaultByondTopicTimeout = 5000;
25 
29  const int DefaultRestartTimeout = 10000;
30 
35 
39  public string GitHubAccessToken { get; set; }
40 
44  [JsonConverter(typeof(StringEnumConverter))]
45  public SetupWizardMode SetupWizardMode { get; set; }
46 
50  public int ByondTopicTimeout { get; set; } = DefaultByondTopicTimeout;
51 
55  public int RestartTimeout { get; set; } = DefaultRestartTimeout;
56 
60  public bool UseExperimentalWatchdog { get; set; }
61  }
62 }
string GitHubAccessToken
A GitHub personal access token to use for bypassing rate limits on requests. Requires no scopes
+Go to the documentation of this file.
1 using Newtonsoft.Json;
2 using Newtonsoft.Json.Converters;
3 
5 {
9  public sealed class GeneralConfiguration
10  {
14  public const string Section = "General";
15 
20 
24  const int DefaultByondTopicTimeout = 5000;
25 
29  const int DefaultRestartTimeout = 10000;
30 
35 
39  public string GitHubAccessToken { get; set; }
40 
44  [JsonConverter(typeof(StringEnumConverter))]
45  public SetupWizardMode SetupWizardMode { get; set; }
46 
50  public int ByondTopicTimeout { get; set; } = DefaultByondTopicTimeout;
51 
55  public int RestartTimeout { get; set; } = DefaultRestartTimeout;
56 
60  public bool UseExperimentalWatchdog { get; set; }
61 
65  public bool UseBasicWatchdogOnWindows { get; set; }
66  }
67 }
string GitHubAccessToken
A GitHub personal access token to use for bypassing rate limits on requests. Requires no scopes
SetupWizardMode
Determines if the Core.ISetupWizard will run
const string Section
The key for the Microsoft.Extensions.Configuration.IConfigurationSection the GeneralConfiguration res...
const int DefaultByondTopicTimeout
The default value for ByondTopicTimeout
@@ -79,6 +79,7 @@ $(function() {
int RestartTimeout
The timeout milliseconds for restarting the server
+
bool UseBasicWatchdogOnWindows
If the Components.Watchdog.WindowsWatchdog should not be used if it is available.
bool UseExperimentalWatchdog
If the Components.Watchdog.ExperimentalWatchdog should be used.
int ByondTopicTimeout
The timeout in milliseconds for sending and receiving topics to/from DreamDaemon. Note that a single ...
diff --git a/_home_controller_8cs_source.html b/_home_controller_8cs_source.html index cb2122475d..d127ff7b58 100644 --- a/_home_controller_8cs_source.html +++ b/_home_controller_8cs_source.html @@ -71,56 +71,57 @@ $(function() {
HomeController.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Authorization;
2 using Microsoft.AspNetCore.Http;
3 using Microsoft.AspNetCore.Mvc;
4 using Microsoft.EntityFrameworkCore;
5 using Microsoft.Extensions.Logging;
6 using Microsoft.Extensions.Options;
7 using Microsoft.Extensions.Primitives;
8 using Microsoft.Net.Http.Headers;
9 using System;
10 using System.Linq;
11 using System.Net.Mime;
12 using System.Threading;
13 using System.Threading.Tasks;
14 using Tgstation.Server.Api;
19 using Wangkanai.Detection;
20 
22 {
26  [Route(Routes.Root)]
27  public sealed class HomeController : ApiController
28  {
33 
38 
43 
48 
53 
57  readonly IBrowserResolver browserResolver;
58 
63 
77  public HomeController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ITokenFactory tokenFactory, ISystemIdentityFactory systemIdentityFactory, ICryptographySuite cryptographySuite, IApplication application, IIdentityCache identityCache, IBrowserResolver browserResolver, IOptions<ControlPanelConfiguration> controlPanelConfigurationOptions, ILogger<HomeController> logger) : base(databaseContext, authenticationContextFactory, logger, false, false)
78  {
79  this.tokenFactory = tokenFactory ?? throw new ArgumentNullException(nameof(tokenFactory));
80  this.systemIdentityFactory = systemIdentityFactory ?? throw new ArgumentNullException(nameof(systemIdentityFactory));
81  this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite));
82  this.application = application ?? throw new ArgumentNullException(nameof(application));
83  this.identityCache = identityCache ?? throw new ArgumentNullException(nameof(identityCache));
84  this.browserResolver = browserResolver ?? throw new ArgumentNullException(nameof(browserResolver));
85  controlPanelConfiguration = controlPanelConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(controlPanelConfigurationOptions));
86  }
87 
95  [HttpGet]
96  [TgsAuthorize]
97  [AllowAnonymous]
98  [ProducesResponseType(typeof(Api.Models.ServerInformation), 200)]
99  public IActionResult Home()
100  {
101  if (AuthenticationContext != null)
102  return Json(new Api.Models.ServerInformation
103  {
104  Version = application.Version,
105  ApiVersion = ApiHeaders.Version
106  });
107 
108  // if we are using a browser and the control panel, soft redirect to the app page
109  if (controlPanelConfiguration.Enable && browserResolver.Browser.Type != BrowserType.Generic)
110  {
111  Logger.LogDebug("Unauthorized browser request (User-Agent: \"{0}\"), loading control panel...", browserResolver.UserAgent);
112  return File("~/index.html", MediaTypeNames.Text.Html);
113  }
114 
115  return Unauthorized();
116  }
117 
126  [HttpPost]
127  [ProducesResponseType(typeof(Api.Models.Token), 200)]
128  [ProducesResponseType(401)]
129  [ProducesResponseType(403)]
130  #pragma warning disable CA1506 // TODO: Decomplexify
131  public async Task<IActionResult> CreateToken(CancellationToken cancellationToken)
132  {
133  if (ApiHeaders == null)
134  {
135  // Get the exact error
136  var errorMessage = "Missing API headers!";
137  try
138  {
139  var _ = new ApiHeaders(Request.GetTypedHeaders());
140  }
141  catch (InvalidOperationException ex)
142  {
143  errorMessage = ex.Message;
144  }
145 
146  Response.Headers.Add(HeaderNames.WWWAuthenticate, new StringValues("basic realm=\"Create TGS4 bearer token\""));
147 
148  return BadRequest(new Api.Models.ErrorMessage { Message = errorMessage });
149  }
150 
152  return BadRequest(new Api.Models.ErrorMessage { Message = "Cannot create a token using another token!" });
153 
154  ISystemIdentity systemIdentity;
155  try
156  {
157  // trust the system over the database because a user's name can change while still having the same SID
158  systemIdentity = await systemIdentityFactory.CreateSystemIdentity(ApiHeaders.Username, ApiHeaders.Password, cancellationToken).ConfigureAwait(false);
159  }
160  catch (NotImplementedException)
161  {
162  systemIdentity = null;
163  }
164 
165  using (systemIdentity)
166  {
167  IQueryable<User> query;
168  if (systemIdentity == null)
169  query = DatabaseContext.Users.Where(x => x.CanonicalName == ApiHeaders.Username.ToUpperInvariant());
170  else
171  query = DatabaseContext.Users.Where(x => x.SystemIdentifier == systemIdentity.Uid);
172  var user = await query.Select(x => new User
173  {
174  Id = x.Id,
175  PasswordHash = x.PasswordHash,
176  Enabled = x.Enabled,
177  Name = x.Name
178  }).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
179 
180  if (user == null)
181  return Unauthorized();
182 
183  if (systemIdentity == null)
184  {
185  var originalHash = user.PasswordHash;
187  return Unauthorized();
188  if (user.PasswordHash != originalHash)
189  {
190  Logger.LogDebug("User ID {0}'s password hash needs a refresh, updating database.", user.Id);
191  var updatedUser = new User
192  {
193  Id = user.Id
194  };
195  DatabaseContext.Users.Attach(updatedUser);
196  updatedUser.PasswordHash = user.PasswordHash;
197  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
198  }
199  }
200 
201  // check if the name changed and updoot accordingly
202  else if (systemIdentity.Username != user.Name)
203  {
204  Logger.LogDebug("User ID {0}'s system identity needs a refresh, updating database.", user.Id);
205  DatabaseContext.Users.Attach(user);
206  user.Name = systemIdentity.Username;
207  user.CanonicalName = user.Name.ToUpperInvariant();
208  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
209  }
210 
211  // Now that the bookeeping is done, tell them to fuck off if necessary
212  if (!user.Enabled.Value)
213  {
214  Logger.LogTrace("Not logging in disabled user {0}.", user.Id);
215  return Forbid();
216  }
217 
218  var token = await tokenFactory.CreateToken(user, cancellationToken).ConfigureAwait(false);
219  if (systemIdentity != null)
220  {
221  // expire the identity slightly after the auth token in case of lag
222  var identExpiry = token.ExpiresAt.Value;
223  identExpiry += tokenFactory.ValidationParameters.ClockSkew;
224  identExpiry += TimeSpan.FromSeconds(15);
225  identityCache.CacheSystemIdentity(user, systemIdentity, identExpiry);
226  }
227 
228  Logger.LogDebug("Successfully logged in user {0}!", user.Id);
229 
230  return Json(token);
231  }
232  }
233  #pragma warning restore CA1506
234  }
235 }
+Go to the documentation of this file.
1 using Microsoft.AspNetCore.Authorization;
2 using Microsoft.AspNetCore.Http;
3 using Microsoft.AspNetCore.Mvc;
4 using Microsoft.EntityFrameworkCore;
5 using Microsoft.Extensions.Logging;
6 using Microsoft.Extensions.Options;
7 using Microsoft.Extensions.Primitives;
8 using Microsoft.Net.Http.Headers;
9 using System;
10 using System.Linq;
11 using System.Net.Mime;
12 using System.Threading;
13 using System.Threading.Tasks;
14 using Tgstation.Server.Api;
20 using Wangkanai.Detection;
21 
23 {
27  [Route(Routes.Root)]
28  public sealed class HomeController : ApiController
29  {
34 
39 
44 
49 
54 
58  readonly IBrowserResolver browserResolver;
59 
64 
78  public HomeController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ITokenFactory tokenFactory, ISystemIdentityFactory systemIdentityFactory, ICryptographySuite cryptographySuite, IApplication application, IIdentityCache identityCache, IBrowserResolver browserResolver, IOptions<ControlPanelConfiguration> controlPanelConfigurationOptions, ILogger<HomeController> logger) : base(databaseContext, authenticationContextFactory, logger, false, false)
79  {
80  this.tokenFactory = tokenFactory ?? throw new ArgumentNullException(nameof(tokenFactory));
81  this.systemIdentityFactory = systemIdentityFactory ?? throw new ArgumentNullException(nameof(systemIdentityFactory));
82  this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite));
83  this.application = application ?? throw new ArgumentNullException(nameof(application));
84  this.identityCache = identityCache ?? throw new ArgumentNullException(nameof(identityCache));
85  this.browserResolver = browserResolver ?? throw new ArgumentNullException(nameof(browserResolver));
86  controlPanelConfiguration = controlPanelConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(controlPanelConfigurationOptions));
87  }
88 
96  [HttpGet]
97  [TgsAuthorize]
98  [AllowAnonymous]
99  [ProducesResponseType(typeof(Api.Models.ServerInformation), 200)]
100  public IActionResult Home()
101  {
102  if (AuthenticationContext != null)
103  return Json(new Api.Models.ServerInformation
104  {
105  Version = application.Version,
106  ApiVersion = ApiHeaders.Version
107  });
108 
109  // if we are using a browser and the control panel, soft redirect to the app page
110  if (controlPanelConfiguration.Enable && browserResolver.Browser.Type != BrowserType.Generic)
111  {
112  Logger.LogDebug("Unauthorized browser request (User-Agent: \"{0}\"), loading control panel...", browserResolver.UserAgent);
113  return File("~/index.html", MediaTypeNames.Text.Html);
114  }
115 
116  return Unauthorized();
117  }
118 
127  [HttpPost]
128  [ProducesResponseType(typeof(Api.Models.Token), 200)]
129  [ProducesResponseType(401)]
130  [ProducesResponseType(403)]
131  #pragma warning disable CA1506 // TODO: Decomplexify
132  public async Task<IActionResult> CreateToken(CancellationToken cancellationToken)
133  {
134  if (ApiHeaders == null)
135  {
136  // Get the exact error
137  var errorMessage = "Missing API headers!";
138  try
139  {
140  var _ = new ApiHeaders(Request.GetTypedHeaders());
141  }
142  catch (InvalidOperationException ex)
143  {
144  errorMessage = ex.Message;
145  }
146 
147  Response.Headers.Add(HeaderNames.WWWAuthenticate, new StringValues("basic realm=\"Create TGS4 bearer token\""));
148 
149  return BadRequest(new Api.Models.ErrorMessage { Message = errorMessage });
150  }
151 
153  return BadRequest(new Api.Models.ErrorMessage { Message = "Cannot create a token using another token!" });
154 
155  ISystemIdentity systemIdentity;
156  try
157  {
158  // trust the system over the database because a user's name can change while still having the same SID
159  systemIdentity = await systemIdentityFactory.CreateSystemIdentity(ApiHeaders.Username, ApiHeaders.Password, cancellationToken).ConfigureAwait(false);
160  }
161  catch (NotImplementedException)
162  {
163  systemIdentity = null;
164  }
165 
166  using (systemIdentity)
167  {
168  // Get the user from the database
169  IQueryable<User> query;
170  string canonicalName = ApiHeaders.Username.ToUpperInvariant();
171  if (systemIdentity == null)
172  query = DatabaseContext.Users.Where(x => x.CanonicalName == canonicalName);
173  else
174  query = DatabaseContext.Users.Where(x => x.CanonicalName == canonicalName || x.SystemIdentifier == systemIdentity.Uid);
175  var users = await query.Select(x => new User
176  {
177  Id = x.Id,
178  PasswordHash = x.PasswordHash,
179  Enabled = x.Enabled,
180  Name = x.Name
181  }).ToListAsync(cancellationToken).ConfigureAwait(false);
182 
183  // Pick the DB user first
184  var user = users
185  .OrderByDescending(dbUser => dbUser.PasswordHash != null)
186  .FirstOrDefault();
187 
188  // No user? You're not allowed
189  if (user == null)
190  return Unauthorized();
191 
192  // A system user may have had their name AND password changed to one in our DB...
193  // Or a DB user was created that had the same user/pass as a system user
194  // Dumb admins...
195  // FALLBACK TO THE DB USER HERE, DO NOT REVEAL A SYSTEM LOGIN!!!
196  // This of course, allows system users to discover TGS users in this (HIGHLY IMPROBABLE) case but that is not our fault
197  var originalHash = user.PasswordHash;
198  var isDbUser = originalHash != null;
199  bool usingSystemIdentity = systemIdentity != null && !isDbUser;
200  if (!usingSystemIdentity)
201  {
202  // DB User password check and update
204  return Unauthorized();
205  if (user.PasswordHash != originalHash)
206  {
207  Logger.LogDebug("User ID {0}'s password hash needs a refresh, updating database.", user.Id);
208  var updatedUser = new User
209  {
210  Id = user.Id
211  };
212  DatabaseContext.Users.Attach(updatedUser);
213  updatedUser.PasswordHash = user.PasswordHash;
214  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
215  }
216  }
217  else if (systemIdentity.Username != user.Name)
218  {
219  // System identity username change update
220  Logger.LogDebug("User ID {0}'s system identity needs a refresh, updating database.", user.Id);
221  DatabaseContext.Users.Attach(user);
222  user.Name = systemIdentity.Username;
223  user.CanonicalName = user.Name.ToUpperInvariant();
224  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
225  }
226 
227  // Now that the bookeeping is done, tell them to fuck off if necessary
228  if (!user.Enabled.Value)
229  {
230  Logger.LogTrace("Not logging in disabled user {0}.", user.Id);
231  return Forbid();
232  }
233 
234  var token = await tokenFactory.CreateToken(user, cancellationToken).ConfigureAwait(false);
235  if (usingSystemIdentity)
236  {
237  // expire the identity slightly after the auth token in case of lag
238  var identExpiry = token.ExpiresAt.Value;
239  identExpiry += tokenFactory.ValidationParameters.ClockSkew;
240  identExpiry += TimeSpan.FromSeconds(15);
241  identityCache.CacheSystemIdentity(user, systemIdentity, identExpiry);
242  }
243 
244  Logger.LogDebug("Successfully logged in user {0}!", user.Id);
245 
246  return Json(token);
247  }
248  }
249  #pragma warning restore CA1506
250  }
251 }
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
-
async Task< IActionResult > CreateToken(CancellationToken cancellationToken)
Attempt to authenticate a User using ApiController.ApiHeaders
- +
async Task< IActionResult > CreateToken(CancellationToken cancellationToken)
Attempt to authenticate a User using ApiController.ApiHeaders
+
bool CheckUserPassword(User user, string password)
Checks a given password matches a given user 's User.PasswordHash. This may result in User....
Task< ISystemIdentity > CreateSystemIdentity(User user, CancellationToken cancellationToken)
Create a ISystemIdentity for a given user
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
Task< Token > CreateToken(Models.User user, CancellationToken cancellationToken)
Create a Token for a given user
- -
Represents a user on the current System.Runtime.InteropServices.OSPlatform
+
Represents a user on the current global::System.Runtime.InteropServices.OSPlatform
-
IActionResult Home()
Main page of the Application
+
IActionResult Home()
Main page of the Application
string Username
The client's username
Definition: ApiHeaders.cs:92
-
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
-
HomeController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ITokenFactory tokenFactory, ISystemIdentityFactory systemIdentityFactory, ICryptographySuite cryptographySuite, IApplication application, IIdentityCache identityCache, IBrowserResolver browserResolver, IOptions< ControlPanelConfiguration > controlPanelConfigurationOptions, ILogger< HomeController > logger)
Construct a HomeController
+
HomeController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ITokenFactory tokenFactory, ISystemIdentityFactory systemIdentityFactory, ICryptographySuite cryptographySuite, IApplication application, IIdentityCache identityCache, IBrowserResolver browserResolver, IOptions< ControlPanelConfiguration > controlPanelConfigurationOptions, ILogger< HomeController > logger)
Construct a HomeController
Contains various cryptographic functions
ApiHeaders ApiHeaders
The ApiHeaders for the operation
-
readonly ICryptographySuite cryptographySuite
The ICryptographySuite for the HomeController
+
readonly ICryptographySuite cryptographySuite
The ICryptographySuite for the HomeController
+
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:17
-
readonly ControlPanelConfiguration controlPanelConfiguration
The ControlPanelConfiguration for the HomeController
+
readonly ControlPanelConfiguration controlPanelConfiguration
The ControlPanelConfiguration for the HomeController
+
string Password
The client's password
Definition: ApiHeaders.cs:97
-
readonly IApplication application
The IApplication for the HomeController
+
readonly IApplication application
The IApplication for the HomeController
Routes to a server actions
Definition: Routes.cs:9
-
Main ApiController for the Application
+
Main ApiController for the Application
+ -
readonly IIdentityCache identityCache
The IIdentityCache for the HomeController
+
readonly IIdentityCache identityCache
The IIdentityCache for the HomeController
bool IsTokenAuthentication
If the header uses password or JWT authentication
Definition: ApiHeaders.cs:102
-
const string Root
The root controller
Definition: Routes.cs:14
- +
TokenValidationParameters ValidationParameters
The TokenValidationParameters for the ITokenFactory
long Id
The ID of the User
Definition: User.cs:15
ILogger Logger
The ILogger for the ApiController
-
readonly IBrowserResolver browserResolver
The IBrowserResolver for the HomeController
+
readonly IBrowserResolver browserResolver
The IBrowserResolver for the HomeController
void CacheSystemIdentity(User user, ISystemIdentity systemIdentity, DateTimeOffset expiry)
Keep a user 's systemIdentity alive until an expiry time
-
readonly ISystemIdentityFactory systemIdentityFactory
The ISystemIdentityFactory for the HomeController
+
readonly ISystemIdentityFactory systemIdentityFactory
The ISystemIdentityFactory for the HomeController
-
readonly ITokenFactory tokenFactory
The ITokenFactory for the HomeController
-
string Uid
A unique identifier for the user
+
readonly ITokenFactory tokenFactory
The ITokenFactory for the HomeController
+
string Uid
A unique identifier for the user
+
diff --git a/_i_assembly_information_provider_8cs.html b/_i_assembly_information_provider_8cs.html index 75a043bd1a..c9cf8f2895 100644 --- a/_i_assembly_information_provider_8cs.html +++ b/_i_assembly_information_provider_8cs.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/IAssemblyInformationProvider.cs File Reference +tgstation-server: src/Tgstation.Server.Host/System/IAssemblyInformationProvider.cs File Reference @@ -63,7 +63,7 @@ $(function() {
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

interface  Tgstation.Server.Host.Core.IAssemblyInformationProvider
 For retrieving the Assembly's location. More...
interface  Tgstation.Server.Host.System.IAssemblyInformationProvider
 For retrieving the Assembly's location. More...
 
- +

@@ -91,7 +91,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
namespace  Tgstation.Server.Host.System
 
diff --git a/_i_assembly_information_provider_8cs_source.html b/_i_assembly_information_provider_8cs_source.html index ec8585a4be..b4239bfc9d 100644 --- a/_i_assembly_information_provider_8cs_source.html +++ b/_i_assembly_information_provider_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/IAssemblyInformationProvider.cs Source File +tgstation-server: src/Tgstation.Server.Host/System/IAssemblyInformationProvider.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,10 +71,10 @@ $(function() {
IAssemblyInformationProvider.cs
-Go to the documentation of this file.
1 using System.Reflection;
2 
4 {
9  {
13  string Path { get; }
14 
18  AssemblyName Name { get; }
19  }
20 }
string Path
Gets the path to the executing assembly.
- - - +Go to the documentation of this file.
1 using System.Reflection;
2 
4 {
9  {
13  string Path { get; }
14 
18  AssemblyName Name { get; }
19  }
20 }
+ + +

Classes

interface  Tgstation.Server.Host.Security.IClaimsInjector
 For injecting System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look for More...
 For injecting global::System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look for More...
 
- +

diff --git a/_i_claims_injector_8cs_source.html b/_i_claims_injector_8cs_source.html index 40bbf40a83..07333101bf 100644 --- a/_i_claims_injector_8cs_source.html +++ b/_i_claims_injector_8cs_source.html @@ -71,9 +71,9 @@ $(function() {
IClaimsInjector.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Authentication.JwtBearer;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
6 {
10  interface IClaimsInjector
11  {
18  Task InjectClaimsIntoContext(TokenValidatedContext tokenValidatedContext, CancellationToken cancellationToken);
19  }
20 }
Task InjectClaimsIntoContext(TokenValidatedContext tokenValidatedContext, CancellationToken cancellationToken)
Setup the System.Security.Claims.Claims for a given tokenValidatedContext
+Go to the documentation of this file.
1 using Microsoft.AspNetCore.Authentication.JwtBearer;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
6 {
10  interface IClaimsInjector
11  {
18  Task InjectClaimsIntoContext(TokenValidatedContext tokenValidatedContext, CancellationToken cancellationToken);
19  }
20 }
Task InjectClaimsIntoContext(TokenValidatedContext tokenValidatedContext, CancellationToken cancellationToken)
Setup the global::System.Security.Claims.Claims for a given tokenValidatedContext
-
For injecting System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look for
+
For injecting global::System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look f...
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

interface  Tgstation.Server.Host.Components.Compiler.ICompileJobConsumer
 Sink for CompileJobs More...
interface  Tgstation.Server.Host.Components.Deployment.ICompileJobConsumer
 Sink for CompileJobs More...
 
- +

@@ -93,7 +93,7 @@ Namespaces

 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Compiler
namespace  Tgstation.Server.Host.Components.Deployment
 
diff --git a/_i_compile_job_consumer_8cs_source.html b/_i_compile_job_consumer_8cs_source.html index 484cbd5285..26c5ed3a89 100644 --- a/_i_compile_job_consumer_8cs_source.html +++ b/_i_compile_job_consumer_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Components/Compiler/ICompileJobConsumer.cs Source File +tgstation-server: src/Tgstation.Server.Host/Components/Deployment/ICompileJobConsumer.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,10 +71,10 @@ $(function() {
ICompileJobConsumer.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Hosting;
2 using System;
3 using System.Threading;
4 using System.Threading.Tasks;
6 
8 {
13  {
20  Task LoadCompileJob(CompileJob job, CancellationToken cancellationToken);
21  }
22 }
Task LoadCompileJob(CompileJob job, CancellationToken cancellationToken)
Load a new job into the ICompileJobConsumer
- - +Go to the documentation of this file.
1 using Microsoft.Extensions.Hosting;
2 using System;
3 using System.Threading;
4 using System.Threading.Tasks;
6 
8 {
13  {
20  Task LoadCompileJob(CompileJob job, CancellationToken cancellationToken);
21  }
22 }
+
Task LoadCompileJob(CompileJob job, CancellationToken cancellationToken)
Load a new job into the ICompileJobConsumer
+ diff --git a/_i_configuration_8cs_source.html b/_i_configuration_8cs_source.html index 78b4c2825f..5e8d71039a 100644 --- a/_i_configuration_8cs_source.html +++ b/_i_configuration_8cs_source.html @@ -73,7 +73,7 @@ $(function() {
Go to the documentation of this file.
1 using Microsoft.Extensions.Hosting;
2 using System;
3 using System.Collections.Generic;
4 using System.Threading;
5 using System.Threading.Tasks;
8 
10 {
15  {
23  Task<ServerSideModifications> CopyDMFilesTo(string dmeFile, string destination, CancellationToken cancellationToken);
24 
31  Task SymlinkStaticFilesTo(string destination, CancellationToken cancellationToken);
32 
40  Task<IReadOnlyList<ConfigurationFile>> ListDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken);
41 
49  Task<ConfigurationFile> Read(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken);
50 
58  Task<bool> CreateDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken);
59 
67  Task<bool> DeleteDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken);
68 
78  Task<ConfigurationFile> Write(string configurationRelativePath, ISystemIdentity systemIdentity, byte[] data, string previousHash, CancellationToken cancellationToken);
79  }
80 }
Consumes EventTypes and takes the appropriate actions
-
Represents a user on the current System.Runtime.InteropServices.OSPlatform
+
Represents a user on the current global::System.Runtime.InteropServices.OSPlatform
Task< ConfigurationFile > Write(string configurationRelativePath, ISystemIdentity systemIdentity, byte[] data, string previousHash, CancellationToken cancellationToken)
Writes to a given configurationRelativePath
Task< bool > DeleteDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
Attempt to delete an empty directory at configurationRelativePath
@@ -85,7 +85,7 @@ $(function() {
Task< ConfigurationFile > Read(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
Reads a given configurationRelativePath
- +
Task< IReadOnlyList< ConfigurationFile > > ListDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
Get ConfigurationFile for all items in a given configurationRelativePath
Task SymlinkStaticFilesTo(string destination, CancellationToken cancellationToken)
Symlinks all directories in the GameData directory to destination
diff --git a/_i_console_8cs.html b/_i_console_8cs.html index 5497d3c8f7..f68cb62752 100644 --- a/_i_console_8cs.html +++ b/_i_console_8cs.html @@ -80,7 +80,7 @@ $(function() {

Classes

interface  Tgstation.Server.Host.IO.IConsole
 Abstraction for System.Console More...
 Abstraction for global::System.Console More...
 
- +

diff --git a/_i_console_8cs_source.html b/_i_console_8cs_source.html index f16da60bbb..db8ede7bb6 100644 --- a/_i_console_8cs_source.html +++ b/_i_console_8cs_source.html @@ -71,7 +71,7 @@ $(function() {
IConsole.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
5 {
9  interface IConsole
10  {
14  bool Available { get; }
15 
19  CancellationToken CancelKeyPress { get; }
20 
28  Task WriteAsync(string text, bool newLine, CancellationToken cancellationToken);
29 
35  Task PressAnyKeyAsync(CancellationToken cancellationToken);
36 
43  Task<string> ReadLineAsync(bool usePasswordChar, CancellationToken cancellationToken);
44  }
45 }
Abstraction for System.Console
Definition: IConsole.cs:9
+Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
5 {
9  interface IConsole
10  {
14  bool Available { get; }
15 
19  CancellationToken CancelKeyPress { get; }
20 
28  Task WriteAsync(string text, bool newLine, CancellationToken cancellationToken);
29 
35  Task PressAnyKeyAsync(CancellationToken cancellationToken);
36 
43  Task<string> ReadLineAsync(bool usePasswordChar, CancellationToken cancellationToken);
44  }
45 }
Abstraction for global::System.Console
Definition: IConsole.cs:9
bool Available
If the IConsole is visible to the user
Definition: IConsole.cs:14
CancellationToken CancelKeyPress
Gets a CancellationToken that triggers if Crtl+C or an equivalent is pressed.
Definition: IConsole.cs:19
Task< string > ReadLineAsync(bool usePasswordChar, CancellationToken cancellationToken)
Read a line from the IConsole
diff --git a/_i_database_connection_factory_8cs.html b/_i_database_connection_factory_8cs.html new file mode 100644 index 0000000000..bad1b76c22 --- /dev/null +++ b/_i_database_connection_factory_8cs.html @@ -0,0 +1,105 @@ + + + + + + + +tgstation-server: src/Tgstation.Server.Host/Database/IDatabaseConnectionFactory.cs File Reference + + + + + + + + + +
+
+ + + + + + + +
+
tgstation-server +
+
The /tg/station 13 server suite
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+ +
+
IDatabaseConnectionFactory.cs File Reference
+
+
+ +

Go to the source code of this file.

+ + + + + +

+Classes

interface  Tgstation.Server.Host.Database.IDatabaseConnectionFactory
 For creating raw DbConnections. More...
 
+ + + + + + + + + +

+Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Database
 
+
+ + + + diff --git a/_i_d_b_connection_factory_8cs_source.html b/_i_database_connection_factory_8cs_source.html similarity index 56% rename from _i_d_b_connection_factory_8cs_source.html rename to _i_database_connection_factory_8cs_source.html index 05f07869f7..97827d6354 100644 --- a/_i_d_b_connection_factory_8cs_source.html +++ b/_i_database_connection_factory_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/IDBConnectionFactory.cs Source File +tgstation-server: src/Tgstation.Server.Host/Database/IDatabaseConnectionFactory.cs Source File @@ -63,21 +63,21 @@ $(function() {
-
IDBConnectionFactory.cs
+
IDatabaseConnectionFactory.cs
-Go to the documentation of this file.
1 using System.Data.Common;
3 
5 {
10  {
17  DbConnection CreateConnection(string connectionString, DatabaseType databaseType);
18  }
19 }
-
DbConnection CreateConnection(string connectionString, DatabaseType databaseType)
Create a DbConnection
- +Go to the documentation of this file.
1 using System.Data.Common;
3 
5 {
10  {
17  DbConnection CreateConnection(string connectionString, DatabaseType databaseType);
18  }
19 }
DbConnection CreateConnection(string connectionString, DatabaseType databaseType)
Create a DbConnection
+
DatabaseType
Type of database to user
Definition: DatabaseType.cs:6
+
diff --git a/_i_database_context_8cs.html b/_i_database_context_8cs.html index d9e4a8d19f..baa6f5e890 100644 --- a/_i_database_context_8cs.html +++ b/_i_database_context_8cs.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Models/IDatabaseContext.cs File Reference +tgstation-server: src/Tgstation.Server.Host/Database/IDatabaseContext.cs File Reference @@ -63,7 +63,7 @@ $(function() {
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

interface  Tgstation.Server.Host.Models.IDatabaseContext
 Represents the database More...
interface  Tgstation.Server.Host.Database.IDatabaseContext
 Represents the database More...
 
- +

@@ -91,7 +91,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
namespace  Tgstation.Server.Host.Database
 
diff --git a/_i_database_context_8cs_source.html b/_i_database_context_8cs_source.html index 334e7122b5..d9f026f74d 100644 --- a/_i_database_context_8cs_source.html +++ b/_i_database_context_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Models/IDatabaseContext.cs Source File +tgstation-server: src/Tgstation.Server.Host/Database/IDatabaseContext.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,24 +71,28 @@ $(function() {
IDatabaseContext.cs
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using System;
3 using System.Threading;
4 using System.Threading.Tasks;
5 
7 {
11  public interface IDatabaseContext
12  {
16  DbSet<User> Users { get; }
17 
21  DbSet<Instance> Instances { get; }
22 
26  DbSet<InstanceUser> InstanceUsers { get; }
27 
31  DbSet<Job> Jobs { get; }
32 
36  DbSet<CompileJob> CompileJobs { get; }
37 
41  DbSet<RevisionInformation> RevisionInformations { get; }
42 
46  DbSet<DreamMakerSettings> DreamMakerSettings { get; set; }
47 
51  DbSet<DreamDaemonSettings> DreamDaemonSettings { get; set; }
52 
56  DbSet<ChatBot> ChatBots { get; set; }
57 
61  DbSet<ChatChannel> ChatChannels { get; set; }
62 
66  DbSet<RepositorySettings> RepositorySettings { get; set; }
67 
71  DbSet<ReattachInformation> ReattachInformations { get; set; }
72 
76  DbSet<WatchdogReattachInformation> WatchdogReattachInformations { get; set; }
77 
83  Task Save(CancellationToken cancellationToken);
84 
90  Task Initialize(CancellationToken cancellationToken);
91 
98  Task SchemaDowngradeForServerVersion(Version version, CancellationToken cancellationToken);
99  }
100 }
-
DbSet< Instance > Instances
The Instances in the IDatabaseContext
- +Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using System;
3 using System.Threading;
4 using System.Threading.Tasks;
6 
8 {
12  public interface IDatabaseContext
13  {
17  DbSet<User> Users { get; }
18 
22  DbSet<Instance> Instances { get; }
23 
27  DbSet<InstanceUser> InstanceUsers { get; }
28 
32  DbSet<Job> Jobs { get; }
33 
37  DbSet<CompileJob> CompileJobs { get; }
38 
42  DbSet<RevisionInformation> RevisionInformations { get; }
43 
47  DbSet<DreamMakerSettings> DreamMakerSettings { get; set; }
48 
52  DbSet<DreamDaemonSettings> DreamDaemonSettings { get; set; }
53 
57  DbSet<ChatBot> ChatBots { get; set; }
58 
62  DbSet<ChatChannel> ChatChannels { get; set; }
63 
67  DbSet<RepositorySettings> RepositorySettings { get; set; }
68 
72  DbSet<ReattachInformation> ReattachInformations { get; set; }
73 
77  DbSet<WatchdogReattachInformation> WatchdogReattachInformations { get; set; }
78 
84  Task Save(CancellationToken cancellationToken);
85 
91  Task Initialize(CancellationToken cancellationToken);
92 
99  Task SchemaDowngradeForServerVersion(Version version, CancellationToken cancellationToken);
100  }
101 }
-
DbSet< WatchdogReattachInformation > WatchdogReattachInformations
The DbSet<TEntity> for Models.WatchdogReattachInformations
-
DbSet< ReattachInformation > ReattachInformations
The DbSet<TEntity> for Models.ReattachInformations
+
DbSet< Instance > Instances
The Instances in the IDatabaseContext
+
DbSet< CompileJob > CompileJobs
The CompileJobs in the IDatabaseContext
-
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
-
DbSet< Job > Jobs
The Jobs in the IDatabaseContext
-
DbSet< User > Users
The Users in the IDatabaseContext
-
Task SchemaDowngradeForServerVersion(Version version, CancellationToken cancellationToken)
Attempt to downgrade the schema to the migration used for a given server version
-
DbSet< ChatChannel > ChatChannels
The ChatChannel in the IDatabaseContext
-
DbSet< CompileJob > CompileJobs
The CompileJobs in the IDatabaseContext
-
Task Initialize(CancellationToken cancellationToken)
Creates and migrates the IDatabaseContext
-
DbSet< RevisionInformation > RevisionInformations
The RevisionInformations in the IDatabaseContext
-
DbSet< ChatBot > ChatBots
The Models.ChatBot in the IDatabaseContext
-
DbSet< InstanceUser > InstanceUsers
The InstanceUsers in the IDatabaseContext
+
Task Initialize(CancellationToken cancellationToken)
Creates and migrates the IDatabaseContext
+
DbSet< ChatBot > ChatBots
The ChatBots in the IDatabaseContext
+ +
DbSet< ChatChannel > ChatChannels
The ChatChannel in the IDatabaseContext
+
DbSet< Job > Jobs
The Jobs in the IDatabaseContext
+
Task SchemaDowngradeForServerVersion(Version version, CancellationToken cancellationToken)
Attempt to downgrade the schema to the migration used for a given server version
+
DbSet< ReattachInformation > ReattachInformations
The DbSet<TEntity> for ReattachInformations
+
DbSet< WatchdogReattachInformation > WatchdogReattachInformations
The DbSet<TEntity> for WatchdogReattachInformations
+
DbSet< RevisionInformation > RevisionInformations
The RevisionInformations in the IDatabaseContext
+ +
DbSet< User > Users
The Users in the IDatabaseContext
+
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
+
DbSet< InstanceUser > InstanceUsers
The InstanceUsers in the IDatabaseContext
+ + +
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

interface  Tgstation.Server.Host.Core.IDatabaseContextFactory
 Factory for scoping usage of IDatabaseContexts. Meant for use by Components More...
interface  Tgstation.Server.Host.Database.IDatabaseContextFactory
 Factory for scoping usage of IDatabaseContexts. Meant for use by Components More...
 
- +

@@ -91,7 +91,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
namespace  Tgstation.Server.Host.Database
 
diff --git a/_i_database_context_factory_8cs_source.html b/_i_database_context_factory_8cs_source.html index 86bb83c2ba..b577ad6bf0 100644 --- a/_i_database_context_factory_8cs_source.html +++ b/_i_database_context_factory_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/IDatabaseContextFactory.cs Source File +tgstation-server: src/Tgstation.Server.Host/Database/IDatabaseContextFactory.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,13 +71,9 @@ $(function() {
IDatabaseContextFactory.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading.Tasks;
4 
6 {
11  {
17  Task UseContext(Func<IDatabaseContext, Task> operation);
18  }
19 }
-
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
- - -
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
- - +Go to the documentation of this file.
1 using System;
2 using System.Threading.Tasks;
3 
5 {
10  {
16  Task UseContext(Func<IDatabaseContext, Task> operation);
17  }
18 }
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
+
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
+
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

interface  Tgstation.Server.Host.Models.IDatabaseSeeder
 For initially seeding a database More...
interface  Tgstation.Server.Host.Database.IDatabaseSeeder
 For initially seeding a database More...
 
- +

@@ -91,7 +91,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
namespace  Tgstation.Server.Host.Database
 
diff --git a/_i_database_seeder_8cs_source.html b/_i_database_seeder_8cs_source.html index a8a7eb1319..22b50072c9 100644 --- a/_i_database_seeder_8cs_source.html +++ b/_i_database_seeder_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Models/IDatabaseSeeder.cs Source File +tgstation-server: src/Tgstation.Server.Host/Database/IDatabaseSeeder.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,11 +71,11 @@ $(function() {
IDatabaseSeeder.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
5 {
9  interface IDatabaseSeeder
10  {
17  Task SeedDatabase(IDatabaseContext databaseContext, CancellationToken cancellationToken);
18 
25  Task ResetAdminPassword(IDatabaseContext databaseContext, CancellationToken cancellationToken);
26  }
27 }
- -
Task ResetAdminPassword(IDatabaseContext databaseContext, CancellationToken cancellationToken)
Changes the admin password in IDatabaseContext back to it's default and enables the account
-
For initially seeding a database
-
Task SeedDatabase(IDatabaseContext databaseContext, CancellationToken cancellationToken)
Initially seed a given databaseContext
+Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
5 {
9  interface IDatabaseSeeder
10  {
17  Task SeedDatabase(IDatabaseContext databaseContext, CancellationToken cancellationToken);
18 
25  Task ResetAdminPassword(IDatabaseContext databaseContext, CancellationToken cancellationToken);
26  }
27 }
For initially seeding a database
+ +
Task ResetAdminPassword(IDatabaseContext databaseContext, CancellationToken cancellationToken)
Changes the admin password in IDatabaseContext back to it's default and enables the account
+
Task SeedDatabase(IDatabaseContext databaseContext, CancellationToken cancellationToken)
Initially seed a given databaseContext
+
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

interface  Tgstation.Server.Host.Components.Compiler.IDmbFactory
 Factory for IDmbProviders More...
interface  Tgstation.Server.Host.Components.Deployment.IDmbFactory
 Factory for IDmbProviders More...
 
- +

@@ -93,7 +93,7 @@ Namespaces

 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Compiler
namespace  Tgstation.Server.Host.Components.Deployment
 
diff --git a/_i_dmb_factory_8cs_source.html b/_i_dmb_factory_8cs_source.html index 72c7b2daae..5ea8ab4cc5 100644 --- a/_i_dmb_factory_8cs_source.html +++ b/_i_dmb_factory_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Components/Compiler/IDmbFactory.cs Source File +tgstation-server: src/Tgstation.Server.Host/Components/Deployment/IDmbFactory.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,16 +71,16 @@ $(function() {
IDmbFactory.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
11  public interface IDmbFactory
12  {
17  Task OnNewerDmb { get; }
18 
22  bool DmbAvailable { get; }
23 
29  IDmbProvider LockNextDmb(int lockCount);
30 
37  Task<IDmbProvider> FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken);
38 
45  Task CleanUnusedCompileJobs(CompileJob exceptThisOne, CancellationToken cancellationToken);
46  }
47 }
+Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
11  public interface IDmbFactory
12  {
17  Task OnNewerDmb { get; }
18 
22  bool DmbAvailable { get; }
23 
29  IDmbProvider LockNextDmb(int lockCount);
30 
37  Task<IDmbProvider> FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken);
38 
45  Task CleanUnusedCompileJobs(CompileJob exceptThisOne, CancellationToken cancellationToken);
46  }
47 }
Task OnNewerDmb
Get a Task that completes when the result of a call to LockNextDmb will be different than the previou...
Definition: IDmbFactory.cs:17
+ - -
Task CleanUnusedCompileJobs(CompileJob exceptThisOne, CancellationToken cancellationToken)
Deletes all compile jobs that are inactive in the Game folder exceptThisOne
-
IDmbProvider LockNextDmb(int lockCount)
Gets the next IDmbProvider
-
bool DmbAvailable
If LockNextDmb will succeed
Definition: IDmbFactory.cs:22
-
Task OnNewerDmb
Get a Task that completes when the result of a call to LockNextDmb will be different than the previou...
Definition: IDmbFactory.cs:17
+ + -
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
-
Task< IDmbProvider > FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken)
Gets a IDmbProvider for a given CompileJob
+
Task CleanUnusedCompileJobs(CompileJob exceptThisOne, CancellationToken cancellationToken)
Deletes all compile jobs that are inactive in the Game folder exceptThisOne
+
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
+
IDmbProvider LockNextDmb(int lockCount)
Gets the next IDmbProvider
+
Task< IDmbProvider > FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken)
Gets a IDmbProvider for a given CompileJob
diff --git a/_i_dmb_provider_8cs.html b/_i_dmb_provider_8cs.html index 5e0df9d4ca..ee2718089a 100644 --- a/_i_dmb_provider_8cs.html +++ b/_i_dmb_provider_8cs.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Components/IDmbProvider.cs File Reference +tgstation-server: src/Tgstation.Server.Host/Components/Deployment/IDmbProvider.cs File Reference @@ -63,7 +63,7 @@ $(function() {
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

interface  Tgstation.Server.Host.Components.IDmbProvider
 Provides absolute paths to the latest compiled .dmbs More...
interface  Tgstation.Server.Host.Components.Deployment.IDmbProvider
 Provides absolute paths to the latest compiled .dmbs More...
 
+ +

@@ -93,6 +93,8 @@ Namespaces

 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Deployment
 
diff --git a/_i_dmb_provider_8cs_source.html b/_i_dmb_provider_8cs_source.html index c973b42a5d..28eb9a8d93 100644 --- a/_i_dmb_provider_8cs_source.html +++ b/_i_dmb_provider_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Components/IDmbProvider.cs Source File +tgstation-server: src/Tgstation.Server.Host/Components/Deployment/IDmbProvider.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,15 +71,15 @@ $(function() {
IDmbProvider.cs
-Go to the documentation of this file.
1 using System;
3 
5 {
9  public interface IDmbProvider : IDisposable
10  {
14  string DmbName { get; }
15 
19  string PrimaryDirectory { get; }
20 
24  string SecondaryDirectory { get; }
25 
30 
34  void KeepAlive();
35  }
36 }
string DmbName
The file name of the .dmb
Definition: IDmbProvider.cs:14
+Go to the documentation of this file.
1 using System;
3 
5 {
9  public interface IDmbProvider : IDisposable
10  {
14  string DmbName { get; }
15 
19  string PrimaryDirectory { get; }
20 
24  string SecondaryDirectory { get; }
25 
30 
34  void KeepAlive();
35  }
36 }
-
string SecondaryDirectory
The secondary game directory with a trailing directory separator
Definition: IDmbProvider.cs:24
-
string PrimaryDirectory
The primary game directory with a trailing directory separator
Definition: IDmbProvider.cs:19
-
void KeepAlive()
Disposing the IDmbProvider won't cause a cleanup of the working directory
- +
string PrimaryDirectory
The primary game directory with a trailing directory separator
Definition: IDmbProvider.cs:19
+
string SecondaryDirectory
The secondary game directory with a trailing directory separator
Definition: IDmbProvider.cs:24
-
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
+ +
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
+
void KeepAlive()
Disposing the IDmbProvider won't cause a cleanup of the working directory
diff --git a/_i_dream_maker_8cs.html b/_i_dream_maker_8cs.html index 8ef3812aa9..9ba80b3009 100644 --- a/_i_dream_maker_8cs.html +++ b/_i_dream_maker_8cs.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Components/Compiler/IDreamMaker.cs File Reference +tgstation-server: src/Tgstation.Server.Host/Components/Deployment/IDreamMaker.cs File Reference @@ -63,7 +63,7 @@ $(function() {
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

interface  Tgstation.Server.Host.Components.Compiler.IDreamMaker
 For managing the compiler More...
interface  Tgstation.Server.Host.Components.Deployment.IDreamMaker
 For managing the compiler More...
 
- +

@@ -93,7 +93,7 @@ Namespaces

 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Compiler
namespace  Tgstation.Server.Host.Components.Deployment
 
diff --git a/_i_dream_maker_8cs_source.html b/_i_dream_maker_8cs_source.html index d9616f65e3..f5625549d8 100644 --- a/_i_dream_maker_8cs_source.html +++ b/_i_dream_maker_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Components/Compiler/IDreamMaker.cs Source File +tgstation-server: src/Tgstation.Server.Host/Components/Deployment/IDreamMaker.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,11 +71,11 @@ $(function() {
IDreamMaker.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
11  public interface IDreamMaker
12  {
24  Task<Models.CompileJob> Compile(Models.RevisionInformation revisionInformation, Api.Models.DreamMaker dreamMakerSettings, uint apiValidateTimeout, IRepository repository, Action<int> progressReporter, TimeSpan? estimatedDuration, CancellationToken cancellationToken);
25  }
26 }
- +Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
11  public interface IDreamMaker
12  {
24  Task<Models.CompileJob> Compile(Models.RevisionInformation revisionInformation, Api.Models.DreamMaker dreamMakerSettings, uint apiValidateTimeout, IRepository repository, Action<int> progressReporter, TimeSpan? estimatedDuration, CancellationToken cancellationToken);
25  }
26 }
Represents an on-disk git repository
Definition: IRepository.cs:11
+ -
Task< Models.CompileJob > Compile(Models.RevisionInformation revisionInformation, Api.Models.DreamMaker dreamMakerSettings, uint apiValidateTimeout, IRepository repository, Action< int > progressReporter, TimeSpan? estimatedDuration, CancellationToken cancellationToken)
Starts a compile
+
Task< Models.CompileJob > Compile(Models.RevisionInformation revisionInformation, Api.Models.DreamMaker dreamMakerSettings, uint apiValidateTimeout, IRepository repository, Action< int > progressReporter, TimeSpan? estimatedDuration, CancellationToken cancellationToken)
Starts a compile
diff --git a/_i_i_o_manager_8cs_source.html b/_i_i_o_manager_8cs_source.html index 1ec261af44..4d3b7a2483 100644 --- a/_i_i_o_manager_8cs_source.html +++ b/_i_i_o_manager_8cs_source.html @@ -71,7 +71,7 @@ $(function() {
IIOManager.cs
-Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Threading;
4 using System.Threading.Tasks;
5 
7 {
11  public interface IIOManager
12  {
18  string ResolvePath(string path);
19 
25  string GetFileName(string path);
26 
32  string GetFileNameWithoutExtension(string path);
33 
39  bool PathContainsParentAccess(string path);
40 
49  Task CopyDirectory(string src, string dest, IEnumerable<string> ignore, CancellationToken cancellationToken);
50 
57  Task<bool> FileExists(string path, CancellationToken cancellationToken);
58 
65  Task<bool> DirectoryExists(string path, CancellationToken cancellationToken);
66 
73  Task<byte[]> ReadAllBytes(string path, CancellationToken cancellationToken);
74 
81  Task<IReadOnlyList<string>> GetDirectories(string path, CancellationToken cancellationToken);
82 
89  Task<IReadOnlyList<string>> GetFiles(string path, CancellationToken cancellationToken);
90 
98  Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken);
99 
107  Task CopyFile(string src, string dest, CancellationToken cancellationToken);
108 
114  string GetDirectoryName(string path);
115 
123  Task<List<string>> GetFilesWithExtension(string path, string extension, CancellationToken cancellationToken);
124 
131  Task DeleteFile(string path, CancellationToken cancellationToken);
132 
139  Task CreateDirectory(string path, CancellationToken cancellationToken);
140 
147  Task DeleteDirectory(string path, CancellationToken cancellationToken);
148 
154  string ConcatPath(params string[] paths);
155 
163  Task MoveFile(string source, string destination, CancellationToken cancellationToken);
164 
172  Task MoveDirectory(string source, string destination, CancellationToken cancellationToken);
173 
180  Task<byte[]> DownloadFile(Uri url, CancellationToken cancellationToken);
181 
189  Task ZipToDirectory(string path, byte[] zipFileBytes, CancellationToken cancellationToken);
190  }
191 }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
+Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Threading;
4 using System.Threading.Tasks;
5 
7 {
11  public interface IIOManager
12  {
18  string ResolvePath(string path);
19 
25  string GetFileName(string path);
26 
32  string GetFileNameWithoutExtension(string path);
33 
39  bool PathContainsParentAccess(string path);
40 
49  Task CopyDirectory(string src, string dest, IEnumerable<string> ignore, CancellationToken cancellationToken);
50 
57  Task<bool> FileExists(string path, CancellationToken cancellationToken);
58 
65  Task<bool> DirectoryExists(string path, CancellationToken cancellationToken);
66 
73  Task<byte[]> ReadAllBytes(string path, CancellationToken cancellationToken);
74 
81  Task<IReadOnlyList<string>> GetDirectories(string path, CancellationToken cancellationToken);
82 
89  Task<IReadOnlyList<string>> GetFiles(string path, CancellationToken cancellationToken);
90 
98  Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken);
99 
107  Task CopyFile(string src, string dest, CancellationToken cancellationToken);
108 
114  string GetDirectoryName(string path);
115 
123  Task<List<string>> GetFilesWithExtension(string path, string extension, CancellationToken cancellationToken);
124 
131  Task DeleteFile(string path, CancellationToken cancellationToken);
132 
139  Task CreateDirectory(string path, CancellationToken cancellationToken);
140 
147  Task DeleteDirectory(string path, CancellationToken cancellationToken);
148 
154  string ConcatPath(params string[] paths);
155 
163  Task MoveFile(string source, string destination, CancellationToken cancellationToken);
164 
172  Task MoveDirectory(string source, string destination, CancellationToken cancellationToken);
173 
180  Task<byte[]> DownloadFile(Uri url, CancellationToken cancellationToken);
181 
189  Task ZipToDirectory(string path, byte[] zipFileBytes, CancellationToken cancellationToken);
190  }
191 }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory, removes and does not enter any symlinks encounterd.
Task MoveDirectory(string source, string destination, CancellationToken cancellationToken)
Moves a directory at source to destination
Task< List< string > > GetFilesWithExtension(string path, string extension, CancellationToken cancellationToken)
Gets a list of files in path with the given extension
Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content
diff --git a/_i_identity_cache_8cs.html b/_i_identity_cache_8cs.html index 3c1fd7bbad..33ffb3358e 100644 --- a/_i_identity_cache_8cs.html +++ b/_i_identity_cache_8cs.html @@ -80,7 +80,7 @@ $(function() {

Classes

interface  Tgstation.Server.Host.Security.IIdentityCache
 For caching ISystemIdentitys More...
 For caching ISystemIdentitys More...
 
- +

diff --git a/_i_identity_cache_8cs_source.html b/_i_identity_cache_8cs_source.html index 3d2f1daae9..114051ede3 100644 --- a/_i_identity_cache_8cs_source.html +++ b/_i_identity_cache_8cs_source.html @@ -71,7 +71,7 @@ $(function() {
IIdentityCache.cs
-Go to the documentation of this file.
1 using System;
3 
5 {
9  public interface IIdentityCache
10  {
17  void CacheSystemIdentity(User user, ISystemIdentity systemIdentity, DateTimeOffset expiry);
18 
25  }
26 }
Represents a user on the current System.Runtime.InteropServices.OSPlatform
+Go to the documentation of this file.
1 using System;
3 
5 {
9  public interface IIdentityCache
10  {
17  void CacheSystemIdentity(User user, ISystemIdentity systemIdentity, DateTimeOffset expiry);
18 
25  }
26 }
Represents a user on the current global::System.Runtime.InteropServices.OSPlatform
ISystemIdentity LoadCachedIdentity(User user)
Attempt to load a cached ISystemIdentity
diff --git a/_i_instance_8cs_source.html b/_i_instance_8cs_source.html index 180e67e292..16a1c4b8d7 100644 --- a/_i_instance_8cs_source.html +++ b/_i_instance_8cs_source.html @@ -71,33 +71,34 @@ $(function() {
IInstance.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Hosting;
2 using System;
3 using System.Threading;
4 using System.Threading.Tasks;
11 
13 {
17  public interface IInstance : IHostedService, IDisposable
18  {
23 
28 
33 
37  IChat Chat { get; }
38 
43 
49 
54  void Rename(string newName);
55 
61  Task SetAutoUpdateInterval(uint newInterval);
62 
71  Task CompileProcess(Job job, IDatabaseContext databaseContext, Action<int> progressReporter, CancellationToken cancellationToken);
72  }
73 }
- +Go to the documentation of this file.
1 using Microsoft.Extensions.Hosting;
2 using System;
3 using System.Threading;
4 using System.Threading.Tasks;
12 
14 {
18  public interface IInstance : IHostedService, IDisposable
19  {
24 
29 
34 
38  IChat Chat { get; }
39 
44 
50 
55  void Rename(string newName);
56 
62  Task SetAutoUpdateInterval(uint newInterval);
63 
72  Task CompileProcess(Job job, IDatabaseContext databaseContext, Action<int> progressReporter, CancellationToken cancellationToken);
73  }
74 }
- + -
Task CompileProcess(Job job, IDatabaseContext databaseContext, Action< int > progressReporter, CancellationToken cancellationToken)
Run the compile job and insert it into the database. Meant to be called by a Core....
+
Task CompileProcess(Job job, IDatabaseContext databaseContext, Action< int > progressReporter, CancellationToken cancellationToken)
Run the compile job and insert it into the database. Meant to be called by a Jobs....
For managing connected chat services
Definition: IChat.cs:13
-
For interacting with the instance services
Definition: IInstance.cs:17
+ +
For interacting with the instance services
Definition: IInstance.cs:18
void Rename(string newName)
Rename the IInstance
-
IWatchdog Watchdog
The IWatchdog for the IInstance
Definition: IInstance.cs:32
+
IWatchdog Watchdog
The IWatchdog for the IInstance
Definition: IInstance.cs:33
- + - +
CompileJob LatestCompileJob()
The latest staged CompileJob
Task SetAutoUpdateInterval(uint newInterval)
Change the Api.Models.Instance.AutoUpdateInterval for the IInstance
+
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
diff --git a/_i_instance_factory_8cs_source.html b/_i_instance_factory_8cs_source.html index 4682cfb21e..6b3fd3170d 100644 --- a/_i_instance_factory_8cs_source.html +++ b/_i_instance_factory_8cs_source.html @@ -73,7 +73,7 @@ $(function() {
Go to the documentation of this file.
1 using Microsoft.Extensions.Hosting;
2 
4 {
9  {
15  IInstance CreateInstance(Models.Instance metadata);
16  }
17 }
IInstance CreateInstance(Models.Instance metadata)
Create an IInstance
-
For interacting with the instance services
Definition: IInstance.cs:17
+
For interacting with the instance services
Definition: IInstance.cs:18
diff --git a/_i_instance_manager_8cs_source.html b/_i_instance_manager_8cs_source.html index 91d83cf3ef..b6e6b1e2e3 100644 --- a/_i_instance_manager_8cs_source.html +++ b/_i_instance_manager_8cs_source.html @@ -77,7 +77,7 @@ $(function() {
Task OfflineInstance(Models.Instance metadata, User user, CancellationToken cancellationToken)
Offline an IInstance
Task OnlineInstance(Models.Instance metadata, CancellationToken cancellationToken)
Online an IInstance
-
For interacting with the instance services
Definition: IInstance.cs:17
+
For interacting with the instance services
Definition: IInstance.cs:18
diff --git a/_i_job_manager_8cs.html b/_i_job_manager_8cs.html index 51ae5e6d27..27c106ddfb 100644 --- a/_i_job_manager_8cs.html +++ b/_i_job_manager_8cs.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/IJobManager.cs File Reference +tgstation-server: src/Tgstation.Server.Host/Jobs/IJobManager.cs File Reference @@ -63,7 +63,7 @@ $(function() {
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

interface  Tgstation.Server.Host.Core.IJobManager
 Manages the runtime of Jobs More...
interface  Tgstation.Server.Host.Jobs.IJobManager
 Manages the runtime of Jobs More...
 
- +

@@ -91,7 +91,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
namespace  Tgstation.Server.Host.Jobs
 
diff --git a/_i_job_manager_8cs_source.html b/_i_job_manager_8cs_source.html index d291524569..9f41ca82e7 100644 --- a/_i_job_manager_8cs_source.html +++ b/_i_job_manager_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/IJobManager.cs Source File +tgstation-server: src/Tgstation.Server.Host/Jobs/IJobManager.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,20 +71,21 @@ $(function() {
IJobManager.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Hosting;
2 using System;
3 using System.Threading;
4 using System.Threading.Tasks;
6 
8 {
12  public interface IJobManager : IHostedService
13  {
19  int? JobProgress(Job job);
20 
28  Task RegisterOperation(Job job, Func<Job, IDatabaseContext, Action<int>, CancellationToken, Task> operation, CancellationToken cancellationToken);
29 
38 #pragma warning disable CA1068 // CancellationToken parameters must come last https://github.com/dotnet/roslyn-analyzers/issues/1816
39  Task WaitForJobCompletion(Job job, User canceller, CancellationToken jobCancellationToken, CancellationToken cancellationToken);
40 #pragma warning restore CA1068 // CancellationToken parameters must come last
41 
50  Task<bool> CancelJob(Job job, User user, bool blocking, CancellationToken cancellationToken);
51  }
52 }
-
Manages the runtime of Jobs
Definition: IJobManager.cs:12
- -
Task RegisterOperation(Job job, Func< Job, IDatabaseContext, Action< int >, CancellationToken, Task > operation, CancellationToken cancellationToken)
Registers a given Job and begins running it
- +Go to the documentation of this file.
1 using Microsoft.Extensions.Hosting;
2 using System;
3 using System.Threading;
4 using System.Threading.Tasks;
7 
9 {
13  public interface IJobManager : IHostedService
14  {
20  int? JobProgress(Job job);
21 
29  Task RegisterOperation(Job job, Func<Job, IDatabaseContext, Action<int>, CancellationToken, Task> operation, CancellationToken cancellationToken);
30 
39 #pragma warning disable CA1068 // CancellationToken parameters must come last https://github.com/dotnet/roslyn-analyzers/issues/1816
40  Task WaitForJobCompletion(Job job, User canceller, CancellationToken jobCancellationToken, CancellationToken cancellationToken);
41 #pragma warning restore CA1068 // CancellationToken parameters must come last
42 
51  Task<bool> CancelJob(Job job, User user, bool blocking, CancellationToken cancellationToken);
52  }
53 }
+
int? JobProgress(Job job)
Get the Api.Models.Job.Progress for a job
+
Task< bool > CancelJob(Job job, User user, bool blocking, CancellationToken cancellationToken)
Cancels a give job
-
Task< bool > CancelJob(Job job, User user, bool blocking, CancellationToken cancellationToken)
Cancels a give job
+ +
Manages the runtime of Jobs
Definition: IJobManager.cs:13
+ -
Task WaitForJobCompletion(Job job, User canceller, CancellationToken jobCancellationToken, CancellationToken cancellationToken)
Wait for a given job to complete
+
Task WaitForJobCompletion(Job job, User canceller, CancellationToken jobCancellationToken, CancellationToken cancellationToken)
Wait for a given job to complete
+
Task RegisterOperation(Job job, Func< Job, IDatabaseContext, Action< int >, CancellationToken, Task > operation, CancellationToken cancellationToken)
Registers a given Job and begins running it
+ -
int? JobProgress(Job job)
Get the Api.Models.Job.Progress for a job
-Go to the documentation of this file.
2 
4 {
9  {
14  void RegisterProcess(IProcess process);
15  }
16 }
- -
Abstraction over a System.Diagnostics.Process
Definition: IProcess.cs:9
+Go to the documentation of this file.
2 
4 {
9  {
14  void RegisterProcess(IProcess process);
15  }
16 }
+ +
Abstraction over a global::System.Diagnostics.Process
Definition: IProcess.cs:8
void RegisterProcess(IProcess process)
Register a given process for network prompt reaping
On Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort()....
diff --git a/_i_platform_identifier_8cs.html b/_i_platform_identifier_8cs.html index cb531bc420..d3090e50f9 100644 --- a/_i_platform_identifier_8cs.html +++ b/_i_platform_identifier_8cs.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/IPlatformIdentifier.cs File Reference +tgstation-server: src/Tgstation.Server.Host/System/IPlatformIdentifier.cs File Reference @@ -63,7 +63,7 @@ $(function() {
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

interface  Tgstation.Server.Host.Core.IPlatformIdentifier
 For identifying the current platform More...
interface  Tgstation.Server.Host.System.IPlatformIdentifier
 For identifying the current platform More...
 
- +

@@ -91,7 +91,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
namespace  Tgstation.Server.Host.System
 
diff --git a/_i_platform_identifier_8cs_source.html b/_i_platform_identifier_8cs_source.html index cfc0bf4e43..719eeb4019 100644 --- a/_i_platform_identifier_8cs_source.html +++ b/_i_platform_identifier_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/IPlatformIdentifier.cs Source File +tgstation-server: src/Tgstation.Server.Host/System/IPlatformIdentifier.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,10 +71,10 @@ $(function() {
IPlatformIdentifier.cs
-Go to the documentation of this file.
2 {
6  public interface IPlatformIdentifier
7  {
11  bool IsWindows { get; }
12 
16  string ScriptFileExtension { get; }
17  }
18 }
-
bool IsWindows
If the current platform is a Windows platform
-
string ScriptFileExtension
The extension of executable script files for the system
-
For identifying the current platform
+Go to the documentation of this file.
2 {
6  public interface IPlatformIdentifier
7  {
11  bool IsWindows { get; }
12 
16  string ScriptFileExtension { get; }
17  }
18 }
+
string ScriptFileExtension
The extension of executable script files for the system
+
For identifying the current platform
+
bool IsWindows
If the current platform is a Windows platform
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

interface  Tgstation.Server.Host.Core.IProcess
 Abstraction over a System.Diagnostics.Process More...
interface  Tgstation.Server.Host.System.IProcess
 Abstraction over a global::System.Diagnostics.Process More...
 
- +

@@ -91,7 +91,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
namespace  Tgstation.Server.Host.System
 
diff --git a/_i_process_8cs_source.html b/_i_process_8cs_source.html index 13dcd40d83..5d2e708842 100644 --- a/_i_process_8cs_source.html +++ b/_i_process_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/IProcess.cs Source File +tgstation-server: src/Tgstation.Server.Host/System/IProcess.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,15 +71,15 @@ $(function() {
IProcess.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading.Tasks;
3 
5 {
9  interface IProcess : IProcessBase
10  {
14  int Id { get; }
15 
19  Task Startup { get; }
20 
25  string GetErrorOutput();
26 
31  string GetStandardOutput();
32 
37  string GetCombinedOutput();
38 
42  void Terminate();
43  }
44 }
string GetStandardOutput()
Get the stdout output of the IProcess
-
Task Startup
The Task representing the time until the IProcess becomes "idle"
Definition: IProcess.cs:19
- -
string GetErrorOutput()
Get the stderr output of the IProcess
-
void Terminate()
Terminates the process
-
Abstraction over a System.Diagnostics.Process
Definition: IProcess.cs:9
-
string GetCombinedOutput()
Get the stderr and stdout output of the IProcess
-
Represents process lifetime
Definition: IProcessBase.cs:9
- +Go to the documentation of this file.
1 using System.Threading.Tasks;
2 
4 {
8  interface IProcess : IProcessBase
9  {
13  int Id { get; }
14 
18  Task Startup { get; }
19 
24  string GetErrorOutput();
25 
30  string GetStandardOutput();
31 
36  string GetCombinedOutput();
37 
41  void Terminate();
42  }
43 }
string GetStandardOutput()
Get the stdout output of the IProcess
+ + +
Abstraction over a global::System.Diagnostics.Process
Definition: IProcess.cs:8
+
string GetErrorOutput()
Get the stderr output of the IProcess
+
Represents process lifetime
Definition: IProcessBase.cs:9
+
Task Startup
The Task representing the time until the IProcess becomes "idle"
Definition: IProcess.cs:18
+
void Terminate()
Terminates the process
+
string GetCombinedOutput()
Get the stderr and stdout output of the IProcess
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

interface  Tgstation.Server.Host.Core.IProcessBase
 Represents process lifetime More...
interface  Tgstation.Server.Host.System.IProcessBase
 Represents process lifetime More...
 
- +

@@ -91,7 +91,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
namespace  Tgstation.Server.Host.System
 
diff --git a/_i_process_base_8cs_source.html b/_i_process_base_8cs_source.html index 30844b27c3..f66671f347 100644 --- a/_i_process_base_8cs_source.html +++ b/_i_process_base_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/IProcessBase.cs Source File +tgstation-server: src/Tgstation.Server.Host/System/IProcessBase.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,11 +71,13 @@ $(function() {
IProcessBase.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading.Tasks;
3 
5 {
10  {
14  Task<int> Lifetime { get; }
15 
19  void SetHighPriority();
20  }
21 }
Task< int > Lifetime
The Task<TResult> resulting in the exit code of the process
Definition: IProcessBase.cs:14
-
void SetHighPriority()
Set's the owned System.Diagnostics.Process.PriorityClass to System.Diagnostics.ProcessPriorityClass....
- -
Represents process lifetime
Definition: IProcessBase.cs:9
+Go to the documentation of this file.
1 using System;
2 using System.Threading.Tasks;
3 
5 {
10  {
14  Task<int> Lifetime { get; }
15 
19  void SetHighPriority();
20 
24  void Suspend();
25 
29  void Resume();
30  }
31 }
Task< int > Lifetime
The Task<TResult> resulting in the exit code of the process
Definition: IProcessBase.cs:14
+ +
void Suspend()
Suspends the process.
+
void Resume()
Resumes the process.
+
void SetHighPriority()
Set's the owned global::System.Diagnostics.Process.PriorityClass to global::System....
+
Represents process lifetime
Definition: IProcessBase.cs:9
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

interface  Tgstation.Server.Host.Core.IProcessExecutor
 For launching IProcess' More...
interface  Tgstation.Server.Host.System.IProcessExecutor
 For launching IProcess' More...
 
- +

@@ -91,7 +91,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
namespace  Tgstation.Server.Host.System
 
diff --git a/_i_process_executor_8cs_source.html b/_i_process_executor_8cs_source.html index 2cb74257da..f685725686 100644 --- a/_i_process_executor_8cs_source.html +++ b/_i_process_executor_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/IProcessExecutor.cs Source File +tgstation-server: src/Tgstation.Server.Host/System/IProcessExecutor.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,11 +71,11 @@ $(function() {
IProcessExecutor.cs
-Go to the documentation of this file.
2 {
6  interface IProcessExecutor
7  {
18  IProcess LaunchProcess(string fileName, string workingDirectory, string arguments = null, bool readOutput = false, bool readError = false, bool noShellExecute = false);
19 
25  IProcess GetProcess(int id);
26  }
27 }
- -
IProcess LaunchProcess(string fileName, string workingDirectory, string arguments=null, bool readOutput=false, bool readError=false, bool noShellExecute=false)
Launch a IProcess
-
Abstraction over a System.Diagnostics.Process
Definition: IProcess.cs:9
-
IProcess GetProcess(int id)
Get a IProcess by id
+Go to the documentation of this file.
2 {
6  interface IProcessExecutor
7  {
18  IProcess LaunchProcess(string fileName, string workingDirectory, string arguments = null, bool readOutput = false, bool readError = false, bool noShellExecute = false);
19 
25  IProcess GetProcess(int id);
26  }
27 }
+
IProcess GetProcess(int id)
Get a IProcess by id
+
Abstraction over a global::System.Diagnostics.Process
Definition: IProcess.cs:8
+
IProcess LaunchProcess(string fileName, string workingDirectory, string arguments=null, bool readOutput=false, bool readError=false, bool noShellExecute=false)
Launch a IProcess
+
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
4 
6 {
11  {
15  Task<LaunchResult> LaunchResult { get; }
16 
20  bool IsPrimary { get; }
21 
26 
31 
35  IDmbProvider Dmb { get; }
36 
40  ushort? Port { get; }
41 
45  bool ClosePortOnReboot { get; set; }
46 
51 
55  Task OnReboot { get; }
56 
62 
69  Task<string> SendCommand(string command, CancellationToken cancellationToken);
70 
77  Task<bool> SetPort(ushort newPort, CancellationToken cancellatonToken);
78 
85  Task<bool> SetRebootState(RebootState newRebootState, CancellationToken cancellationToken);
86 
90  void ResetRebootState();
91 
96  }
97 }
+Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
5 
7 {
12  {
16  Task<LaunchResult> LaunchResult { get; }
17 
21  bool IsPrimary { get; }
22 
27 
32 
36  IDmbProvider Dmb { get; }
37 
41  ushort? Port { get; }
42 
46  bool ClosePortOnReboot { get; set; }
47 
52 
56  Task OnReboot { get; }
57 
63 
70  Task<string> SendCommand(string command, CancellationToken cancellationToken);
71 
78  Task<bool> SetPort(ushort newPort, CancellationToken cancellatonToken);
79 
86  Task<bool> SetRebootState(RebootState newRebootState, CancellationToken cancellationToken);
87 
91  void ResetRebootState();
92 
97 
102  void ReplaceDmbProvider(IDmbProvider newProvider);
103  }
104 }
+
Represents the result of trying to start a DD process
Definition: LaunchResult.cs:9
- + +
void EnableCustomChatCommands()
Enables the reading of custom chat commands from the ISessionController
Task< bool > SetRebootState(RebootState newRebootState, CancellationToken cancellationToken)
Attempts to change the current RebootState to newRebootState
-
bool ClosePortOnReboot
If the port should be rotated off when the world reboots
-
Handles communication with a DreamDaemon IProcess
-
bool IsPrimary
If the IDmbProvider.PrimaryDirectory of Dmb is being used
-
bool TerminationWasRequested
If the DreamDaemon instance sent a
- +
bool ClosePortOnReboot
If the port should be rotated off when the world reboots
+
Handles communication with a DreamDaemon IProcess
+
bool IsPrimary
If the IDmbProvider.PrimaryDirectory of Dmb is being used
+
bool TerminationWasRequested
If the DreamDaemon instance sent a
Task< bool > SetPort(ushort newPort, CancellationToken cancellatonToken)
Causes the world to start listening on a newPort
-
ReattachInformation Release()
Releases the IProcess without terminating it. Also calls System.IDisposable.Dispose
-
ushort? Port
The current port DreamDaemon is listening on
-
Represents process lifetime
Definition: IProcessBase.cs:9
+
void ReplaceDmbProvider(IDmbProvider newProvider)
Replace Dmb with a given newProvider , disposing the old one.
+
ReattachInformation Release()
Releases the IProcess without terminating it. Also calls global::System.IDisposable....
+
ushort? Port
The current port DreamDaemon is listening on
+ -
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
+
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
Task< string > SendCommand(string command, CancellationToken cancellationToken)
Sends a command to DreamDaemon through /world/Topic()
-
Task OnReboot
A Task that completes when the server calls /world/Reboot()
+
Task OnReboot
A Task that completes when the server calls /world/Reboot()
+
Represents process lifetime
Definition: IProcessBase.cs:9
-
void ResetRebootState()
Changes RebootState to Components.Watchdog.RebootState.Normal without telling the DMAPI
+
void ResetRebootState()
Changes RebootState to Watchdog.RebootState.Normal without telling the DMAPI
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
-
Parameters necessary for duplicating a ISessionController session
+
Parameters necessary for duplicating a ISessionController session
ApiValidationStatus
Status of DMAPI validation
diff --git a/_i_session_controller_factory_8cs_source.html b/_i_session_controller_factory_8cs_source.html index a468635e3c..3b0a190a62 100644 --- a/_i_session_controller_factory_8cs_source.html +++ b/_i_session_controller_factory_8cs_source.html @@ -71,23 +71,24 @@ $(function() {
ISessionControllerFactory.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
5 
7 {
12  {
24  Task<ISessionController> LaunchNew(DreamDaemonLaunchParameters launchParameters, IDmbProvider dmbProvider, IByondExecutableLock currentByondLock, bool primaryPort, bool primaryDirectory, bool apiValidate, CancellationToken cancellationToken);
25 
32  Task<ISessionController> Reattach(ReattachInformation reattachInformation, CancellationToken cancellationToken);
33 
40  }
41 }
Task< ISessionController > Reattach(ReattachInformation reattachInformation, CancellationToken cancellationToken)
Create a ISessionController from an existing DreamDaemon instance
+Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
6 
8 {
13  {
25  Task<ISessionController> LaunchNew(DreamDaemonLaunchParameters launchParameters, IDmbProvider dmbProvider, IByondExecutableLock currentByondLock, bool primaryPort, bool primaryDirectory, bool apiValidate, CancellationToken cancellationToken);
26 
33  Task<ISessionController> Reattach(ReattachInformation reattachInformation, CancellationToken cancellationToken);
34 
41  }
42 }
Task< ISessionController > Reattach(ReattachInformation reattachInformation, CancellationToken cancellationToken)
Create a ISessionController from an existing DreamDaemon instance
+
ISessionController CreateDeadSession(IDmbProvider dmbProvider)
Creates a ISessionController that appears to have started and died with exit code -1
-
Handles communication with a DreamDaemon IProcess
+
Handles communication with a DreamDaemon IProcess
Task< ISessionController > LaunchNew(DreamDaemonLaunchParameters launchParameters, IDmbProvider dmbProvider, IByondExecutableLock currentByondLock, bool primaryPort, bool primaryDirectory, bool apiValidate, CancellationToken cancellationToken)
Create a ISessionController from a freshly launch DreamDaemon instance
- +
Represents usage of the two primary BYOND server executables
-
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
+
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
-
Parameters necessary for duplicating a ISessionController session
+
Parameters necessary for duplicating a ISessionController session
diff --git a/_i_system_identity_8cs.html b/_i_system_identity_8cs.html index e92f4002e1..9cac647aeb 100644 --- a/_i_system_identity_8cs.html +++ b/_i_system_identity_8cs.html @@ -80,7 +80,7 @@ $(function() {

Classes

interface  Tgstation.Server.Host.Security.ISystemIdentity
 Represents a user on the current System.Runtime.InteropServices.OSPlatform More...
 Represents a user on the current global::System.Runtime.InteropServices.OSPlatform More...
 
- +

diff --git a/_i_system_identity_8cs_source.html b/_i_system_identity_8cs_source.html index c02bd66aa7..0661be539f 100644 --- a/_i_system_identity_8cs_source.html +++ b/_i_system_identity_8cs_source.html @@ -71,13 +71,13 @@ $(function() {
ISystemIdentity.cs
-Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Threading;
4 using System.Threading.Tasks;
5 
7 {
11  public interface ISystemIdentity : IDisposable
12  {
16  string Uid { get; }
17 
21  string Username { get; }
22 
28 
35  Task RunImpersonated(Action action, CancellationToken cancellationToken);
36  }
37 }
Represents a user on the current System.Runtime.InteropServices.OSPlatform
+Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
6 {
10  public interface ISystemIdentity : IDisposable
11  {
15  string Uid { get; }
16 
20  string Username { get; }
21 
27 
34  Task RunImpersonated(Action action, CancellationToken cancellationToken);
35  }
36 }
Represents a user on the current global::System.Runtime.InteropServices.OSPlatform
Task RunImpersonated(Action action, CancellationToken cancellationToken)
Runs a given action in the context of the ISystemIdentity
- +
ISystemIdentity Clone()
Clone the ISystemIdentity creating another copy that must have IDisposable.Dispose called on it
-
string Uid
A unique identifier for the user
+
string Uid
A unique identifier for the user

Classes

interface  Tgstation.Server.Host.Security.ISystemIdentityFactory
 Factory for ISystemIdentitys More...
 Factory for ISystemIdentitys More...
 
- +

diff --git a/_identity_cache_8cs_source.html b/_identity_cache_8cs_source.html index b52c19625a..69fda34a6a 100644 --- a/_identity_cache_8cs_source.html +++ b/_identity_cache_8cs_source.html @@ -71,7 +71,7 @@ $(function() {
IdentityCache.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
7 
9 {
12  {
17 
21  readonly ILogger<IdentityCache> logger;
22 
26  readonly Dictionary<long, IdentityCacheObject> cachedIdentities;
27 
33  public IdentityCache(IAsyncDelayer asyncDelayer, ILogger<IdentityCache> logger)
34  {
35  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
36  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
37 
38  cachedIdentities = new Dictionary<long, IdentityCacheObject>();
39  }
40 
42  public void Dispose()
43  {
44  logger.LogTrace("Disposing...");
45  foreach (var I in cachedIdentities.Select(x => x.Value).ToList())
46  I.Dispose();
47  }
48 
50  public void CacheSystemIdentity(User user, ISystemIdentity systemIdentity, DateTimeOffset expiry)
51  {
52  if (user == null)
53  throw new ArgumentNullException(nameof(user));
54  if (systemIdentity == null)
55  throw new ArgumentNullException(nameof(systemIdentity));
56  lock (cachedIdentities)
57  {
58  var uid = systemIdentity.Uid;
59  logger.LogDebug("Caching system identity {0} of user {1}", uid, user.Id);
60 
61  if (cachedIdentities.TryGetValue(user.Id, out var identCache))
62  {
63  logger.LogTrace("Expiring previously cached identity...");
64  identCache.Dispose(); // also clears it out
65  }
66 
67  identCache = new IdentityCacheObject(systemIdentity.Clone(), asyncDelayer, () =>
68  {
69  logger.LogDebug("Expiring system identity cache for user {1}", uid, user.Id);
70  lock (cachedIdentities)
71  cachedIdentities.Remove(user.Id);
72  }, expiry);
73  cachedIdentities.Add(user.Id, identCache);
74  }
75  }
76 
79  {
80  if (user == null)
81  throw new ArgumentNullException(nameof(user));
82  lock (cachedIdentities)
83  if (cachedIdentities.TryGetValue(user.Id, out var identity))
84  return identity.SystemIdentity.Clone();
85  throw new InvalidOperationException("Cached system identity has expired!");
86  }
87  }
88 }
Represents a user on the current System.Runtime.InteropServices.OSPlatform
+Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using System;
3 using System.Collections.Generic;
4 using System.Linq;
7 
9 {
12  {
17 
21  readonly ILogger<IdentityCache> logger;
22 
26  readonly Dictionary<long, IdentityCacheObject> cachedIdentities;
27 
33  public IdentityCache(IAsyncDelayer asyncDelayer, ILogger<IdentityCache> logger)
34  {
35  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
36  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
37 
38  cachedIdentities = new Dictionary<long, IdentityCacheObject>();
39  }
40 
42  public void Dispose()
43  {
44  logger.LogTrace("Disposing...");
45  foreach (var I in cachedIdentities.Select(x => x.Value).ToList())
46  I.Dispose();
47  }
48 
50  public void CacheSystemIdentity(User user, ISystemIdentity systemIdentity, DateTimeOffset expiry)
51  {
52  if (user == null)
53  throw new ArgumentNullException(nameof(user));
54  if (systemIdentity == null)
55  throw new ArgumentNullException(nameof(systemIdentity));
56  lock (cachedIdentities)
57  {
58  var uid = systemIdentity.Uid;
59  logger.LogDebug("Caching system identity {0} of user {1}", uid, user.Id);
60 
61  if (cachedIdentities.TryGetValue(user.Id, out var identCache))
62  {
63  logger.LogTrace("Expiring previously cached identity...");
64  identCache.Dispose(); // also clears it out
65  }
66 
67  identCache = new IdentityCacheObject(systemIdentity.Clone(), asyncDelayer, () =>
68  {
69  logger.LogDebug("Expiring system identity cache for user {1}", uid, user.Id);
70  lock (cachedIdentities)
71  cachedIdentities.Remove(user.Id);
72  }, expiry);
73  cachedIdentities.Add(user.Id, identCache);
74  }
75  }
76 
79  {
80  if (user == null)
81  throw new ArgumentNullException(nameof(user));
82  lock (cachedIdentities)
83  if (cachedIdentities.TryGetValue(user.Id, out var identity))
84  return identity.SystemIdentity.Clone();
85  throw new InvalidOperationException("Cached system identity has expired!");
86  }
87  }
88 }
Represents a user on the current global::System.Runtime.InteropServices.OSPlatform
readonly Dictionary< long, IdentityCacheObject > cachedIdentities
The map of Api.Models.Internal.User.Ids to IdentityCacheObjects
@@ -91,7 +91,7 @@ $(function() {
For keeping a specific ISystemIdentity alive for a period of time
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the IdentityCache
-
string Uid
A unique identifier for the user
+
string Uid
A unique identifier for the user
diff --git a/_identity_cache_object_8cs.html b/_identity_cache_object_8cs.html index 613eb5e8d6..6b204bc706 100644 --- a/_identity_cache_object_8cs.html +++ b/_identity_cache_object_8cs.html @@ -80,7 +80,7 @@ $(function() {

Classes

class  Tgstation.Server.Host.Security.IdentityCacheObject
 For keeping a specific ISystemIdentity alive for a period of time More...
 For keeping a specific ISystemIdentity alive for a period of time More...
 
- +

diff --git a/_identity_cache_object_8cs_source.html b/_identity_cache_object_8cs_source.html index d7d1888f7f..05ee33f59c 100644 --- a/_identity_cache_object_8cs_source.html +++ b/_identity_cache_object_8cs_source.html @@ -74,7 +74,7 @@ $(function() { Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
12  {
17 
21  readonly CancellationTokenSource cancellationTokenSource;
22 
26  readonly Task task;
27 
35  public IdentityCacheObject(ISystemIdentity systemIdentity, IAsyncDelayer asyncDelayer, Action onExpiry, DateTimeOffset expiry)
36  {
37  SystemIdentity = systemIdentity ?? throw new ArgumentNullException(nameof(systemIdentity));
38 
39  if (asyncDelayer == null)
40  throw new ArgumentNullException(nameof(asyncDelayer));
41 
42  if (onExpiry == null)
43  throw new ArgumentNullException(nameof(onExpiry));
44  var now = DateTimeOffset.Now;
45  if (expiry < now)
46  throw new ArgumentOutOfRangeException(nameof(expiry), expiry, "expiry must be greater than DateTimeOffset.Now!");
47 
48  cancellationTokenSource = new CancellationTokenSource();
49 
50  async Task DisposeOnExipiry(CancellationToken cancellationToken)
51  {
52  using (SystemIdentity)
53  try
54  {
55  await asyncDelayer.Delay(expiry - now, cancellationToken).ConfigureAwait(false);
56  }
57  finally
58  {
59  onExpiry();
60  }
61  }
62 
63  task = DisposeOnExipiry(cancellationTokenSource.Token);
64  }
65 
67  public void Dispose()
68  {
69  cancellationTokenSource.Cancel();
70  try
71  {
72  task.GetAwaiter().GetResult();
73  }
74  catch (OperationCanceledException) { }
75  cancellationTokenSource.Dispose();
76  }
77  }
78 }
readonly Task task
The Task to clean up SystemIdentity
IdentityCacheObject(ISystemIdentity systemIdentity, IAsyncDelayer asyncDelayer, Action onExpiry, DateTimeOffset expiry)
Construct an IdentityCache
ISystemIdentity SystemIdentity
The ISystemIdentity the IdentityCache manages
-
Represents a user on the current System.Runtime.InteropServices.OSPlatform
+
Represents a user on the current global::System.Runtime.InteropServices.OSPlatform
diff --git a/_instance_controller_8cs_source.html b/_instance_controller_8cs_source.html index 594f98e748..eb2e5b4d34 100644 --- a/_instance_controller_8cs_source.html +++ b/_instance_controller_8cs_source.html @@ -71,85 +71,86 @@ $(function() {
InstanceController.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.EntityFrameworkCore;
3 using Microsoft.Extensions.Logging;
4 using System;
5 using System.Collections.Generic;
6 using System.Globalization;
7 using System.IO;
8 using System.Linq;
9 using System.Linq.Expressions;
10 using System.Net;
11 using System.Reflection;
12 using System.Threading;
13 using System.Threading.Tasks;
14 using Tgstation.Server.Api;
19 using Tgstation.Server.Host.IO;
22 
24 {
28  [Route(Routes.InstanceManager)]
29  #pragma warning disable CA1506 // TODO: Decomplexify
30  public sealed class InstanceController : ApiController
31  {
35  const string InstanceAttachFileName = "TGS4_ALLOW_INSTANCE_ATTACH";
36 
37  const string MoveInstanceJobPrefix = "Move instance ID ";
38 
43 
48 
53 
58 
63 
75  public InstanceController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, IInstanceManager instanceManager, IIOManager ioManager, IApplication application, IPlatformIdentifier platformIdentifier, ILogger<InstanceController> logger) : base(databaseContext, authenticationContextFactory, logger, false, true)
76  {
77  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
78  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
79  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
80  this.application = application ?? throw new ArgumentNullException(nameof(application));
81  this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
82  }
83 
84  void NormalizeModelPath(Api.Models.Instance model, out string absolutePath)
85  {
86  if (model.Path == null)
87  {
88  absolutePath = null;
89  return;
90  }
91 
92  absolutePath = ioManager.ResolvePath(model.Path);
94  model.Path = absolutePath.ToUpperInvariant();
95  else
96  model.Path = absolutePath;
97  }
98 
99  Models.InstanceUser InstanceAdminUser() => new Models.InstanceUser
100  {
101  ByondRights = (ByondRights)~0U,
108  UserId = AuthenticationContext.User.Id
109  };
110 
119  [HttpPut]
120  [TgsAuthorize(InstanceManagerRights.Create)]
121  [ProducesResponseType(typeof(Api.Models.Instance), 200)]
122  [ProducesResponseType(typeof(Api.Models.Instance), 201)]
123  public async Task<IActionResult> Create([FromBody] Api.Models.Instance model, CancellationToken cancellationToken)
124  {
125  if (model == null)
126  throw new ArgumentNullException(nameof(model));
127 
128  if (String.IsNullOrWhiteSpace(model.Name))
129  return BadRequest(new ErrorMessage { Message = "name must not be empty!" });
130 
131  if (model.Path == null)
132  return BadRequest(new ErrorMessage { Message = "path must not be empty!" });
133 
134  NormalizeModelPath(model, out var rawPath);
135 
136  var localPath = ioManager.ResolvePath(".");
137  NormalizeModelPath(new Api.Models.Instance
138  {
139  Path = localPath
140  }, out var normalizedLocalPath);
141 
142  if (rawPath.StartsWith(normalizedLocalPath, StringComparison.Ordinal))
143  {
144  bool sameLength = rawPath.Length == normalizedLocalPath.Length;
145  char dirSeparatorChar = rawPath.ToCharArray()[normalizedLocalPath.Length];
146  if(sameLength
147  || dirSeparatorChar == Path.DirectorySeparatorChar
148  || dirSeparatorChar == Path.AltDirectorySeparatorChar)
149  return Conflict(new ErrorMessage { Message = "Instances cannot be created in the installation directory!" });
150  }
151 
152  var dirExistsTask = ioManager.DirectoryExists(model.Path, cancellationToken);
153  bool attached = false;
154  if (await ioManager.FileExists(model.Path, cancellationToken).ConfigureAwait(false) || await dirExistsTask.ConfigureAwait(false))
155  if (!await ioManager.FileExists(ioManager.ConcatPath(model.Path, InstanceAttachFileName), cancellationToken).ConfigureAwait(false))
156  return Conflict(new ErrorMessage { Message = "Path not empty!" });
157  else
158  attached = true;
159 
160  var newInstance = new Models.Instance
161  {
162  ConfigurationType = model.ConfigurationType ?? ConfigurationType.Disallowed,
164  {
165  AllowWebClient = false,
166  AutoStart = false,
167  PrimaryPort = 1337,
168  SecondaryPort = 1338,
169  SecurityLevel = DreamDaemonSecurity.Safe,
170  SoftRestart = false,
171  SoftShutdown = false,
172  StartupTimeout = 20
173  },
175  {
176  ApiValidationPort = 1339,
177  ApiValidationSecurityLevel = DreamDaemonSecurity.Safe
178  },
179  Name = model.Name,
180  Online = false,
181  Path = model.Path,
182  AutoUpdateInterval = model.AutoUpdateInterval ?? 0,
184  {
185  CommitterEmail = "tgstation-server@users.noreply.github.com",
186  CommitterName = application.VersionPrefix,
187  PushTestMergeCommits = false,
188  ShowTestMergeCommitters = false,
189  AutoUpdatesKeepTestMerges = false,
190  AutoUpdatesSynchronize = false,
191  PostTestMergeComment = false
192  },
193  InstanceUsers = new List<Models.InstanceUser> // give this user full privileges on the instance
194  {
196  }
197  };
198 
199  DatabaseContext.Instances.Add(newInstance);
200  try
201  {
202  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
203 
204  try
205  {
206  // actually reserve it now
207  await ioManager.CreateDirectory(rawPath, cancellationToken).ConfigureAwait(false);
208  await ioManager.DeleteFile(ioManager.ConcatPath(rawPath, InstanceAttachFileName), cancellationToken).ConfigureAwait(false);
209  }
210  catch
211  {
212  // oh shit delete the model
213  DatabaseContext.Instances.Remove(newInstance);
214 
215  await DatabaseContext.Save(default).ConfigureAwait(false);
216  throw;
217  }
218  }
219  catch (IOException e)
220  {
221  return Conflict(new ErrorMessage { Message = e.Message });
222  }
223  catch (DbUpdateException e)
224  {
225  return Conflict(new ErrorMessage { Message = e.Message });
226  }
227 
228  Logger.LogInformation("{0} {1} instance {2}: {3} ({4})", AuthenticationContext.User.Name, attached ? "attached" : "created", newInstance.Name, newInstance.Id, newInstance.Path);
229 
230  var api = newInstance.ToApi();
231  return attached ? (IActionResult)Json(api) : StatusCode((int)HttpStatusCode.Created, api);
232  }
233 
242  [HttpDelete("{id}")]
243  [TgsAuthorize(InstanceManagerRights.Delete)]
244  [ProducesResponseType(200)]
245  [ProducesResponseType(410)]
246  public async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
247  {
248  var originalModel = await DatabaseContext.Instances.Where(x => x.Id == id)
249  .Include(x => x.WatchdogReattachInformation)
250  .Include(x => x.WatchdogReattachInformation.Alpha)
251  .Include(x => x.WatchdogReattachInformation.Bravo)
252  .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
253  if (originalModel == default)
254  return StatusCode((int)HttpStatusCode.Gone);
255  if (originalModel.Online.Value)
256  return Conflict(new ErrorMessage
257  {
258  Message = "Cannot detach an online instance!"
259  });
260 
261  if (originalModel.WatchdogReattachInformation != null)
262  {
263  DatabaseContext.WatchdogReattachInformations.Remove(originalModel.WatchdogReattachInformation);
264  if (originalModel.WatchdogReattachInformation.Alpha != null)
265  DatabaseContext.ReattachInformations.Remove(originalModel.WatchdogReattachInformation.Alpha);
266  if (originalModel.WatchdogReattachInformation.Bravo != null)
267  DatabaseContext.ReattachInformations.Remove(originalModel.WatchdogReattachInformation.Bravo);
268  }
269 
270  DatabaseContext.Instances.Remove(originalModel);
271 
272  var attachFileName = ioManager.ConcatPath(originalModel.Path, InstanceAttachFileName);
273  await ioManager.WriteAllBytes(attachFileName, Array.Empty<byte>(), default).ConfigureAwait(false);
274  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false); // cascades everything
275  return Ok();
276  }
277 
286  [HttpPost]
287  [TgsAuthorize(InstanceManagerRights.Relocate | InstanceManagerRights.Rename | InstanceManagerRights.SetAutoUpdate | InstanceManagerRights.SetConfiguration | InstanceManagerRights.SetOnline)]
288  [ProducesResponseType(typeof(Api.Models.Instance), 200)]
289  [ProducesResponseType(410)]
290 #pragma warning disable CA1502 // TODO: Decomplexify
291  public async Task<IActionResult> Update([FromBody] Api.Models.Instance model, CancellationToken cancellationToken)
292  {
293  if (model == null)
294  throw new ArgumentNullException(nameof(model));
295 
296  var instanceQuery = DatabaseContext.Instances.Where(x => x.Id == model.Id);
297 
298  var moveJob = await instanceQuery
299  .SelectMany(x => x.Jobs).
300 #pragma warning disable CA1307 // Specify StringComparison
301  Where(x => !x.StoppedAt.HasValue && x.Description.StartsWith(MoveInstanceJobPrefix))
302 #pragma warning restore CA1307 // Specify StringComparison
303  .Select(x => new Models.Job
304  {
305  Id = x.Id
306  }).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
307 
308  if (moveJob != default)
309  await jobManager.CancelJob(moveJob, AuthenticationContext.User, true, cancellationToken).ConfigureAwait(false); // cancel it now
310 
311  var usersInstanceUserTask = instanceQuery.SelectMany(x => x.InstanceUsers).Where(x => x.UserId == AuthenticationContext.User.Id).FirstOrDefaultAsync(cancellationToken);
312 
313  var originalModel = await instanceQuery
314  .Include(x => x.RepositorySettings)
315  .Include(x => x.ChatSettings)
316  .ThenInclude(x => x.Channels)
317  .Include(x => x.DreamDaemonSettings) // need these for onlining
318  .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
319  if (originalModel == default(Models.Instance))
320  return StatusCode((int)HttpStatusCode.Gone);
321 
322  var userRights = (InstanceManagerRights)AuthenticationContext.GetRight(RightsType.InstanceManager);
323  bool CheckModified<T>(Expression<Func<Api.Models.Instance, T>> expression, InstanceManagerRights requiredRight)
324  {
325  var memberSelectorExpression = (MemberExpression)expression.Body;
326  var property = (PropertyInfo)memberSelectorExpression.Member;
327 
328  var newVal = property.GetValue(model);
329  if (newVal == null)
330  return false;
331  if (!userRights.HasFlag(requiredRight) && property.GetValue(originalModel) != newVal)
332  return true;
333 
334  property.SetValue(originalModel, newVal);
335  return false;
336  }
337 
338  string originalModelPath = null;
339  string rawPath = null;
340  if (model.Path != null)
341  {
342  NormalizeModelPath(model, out rawPath);
343 
344  if (model.Path != originalModel.Path)
345  {
346  if (!userRights.HasFlag(InstanceManagerRights.Relocate))
347  return Forbid();
348  if (originalModel.Online.Value && model.Online != true)
349  return Conflict(new ErrorMessage { Message = "Cannot relocate an online instance!" });
350 
351  var dirExistsTask = ioManager.DirectoryExists(model.Path, cancellationToken);
352  if (await ioManager.FileExists(model.Path, cancellationToken).ConfigureAwait(false) || await dirExistsTask.ConfigureAwait(false))
353  return Conflict(new ErrorMessage { Message = "Path not empty!" });
354 
355  originalModelPath = originalModel.Path;
356  originalModel.Path = model.Path;
357  }
358  }
359 
360  var oldAutoUpdateInterval = originalModel.AutoUpdateInterval.Value;
361  var originalOnline = originalModel.Online.Value;
362  var renamed = model.Name != null && originalModel.Name != model.Name;
363 
364  if (CheckModified(x => x.AutoUpdateInterval, InstanceManagerRights.SetAutoUpdate)
365  || CheckModified(x => x.ConfigurationType, InstanceManagerRights.SetConfiguration)
366  || CheckModified(x => x.Name, InstanceManagerRights.Rename)
367  || CheckModified(x => x.Online, InstanceManagerRights.SetOnline))
368  return Forbid();
369 
370  // ensure the current user has write privilege on the instance
371  var usersInstanceUser = await usersInstanceUserTask.ConfigureAwait(false);
372  if (usersInstanceUser == default)
373  {
374  var instanceAdminUser = InstanceAdminUser();
375  instanceAdminUser.InstanceId = originalModel.Id;
376  DatabaseContext.InstanceUsers.Add(instanceAdminUser);
377  }
378  else
379  usersInstanceUser.InstanceUserRights |= InstanceUserRights.WriteUsers;
380 
381  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
382 
383  if (renamed)
384  instanceManager.GetInstance(originalModel).Rename(originalModel.Name);
385 
386  var oldAutoStart = originalModel.DreamDaemonSettings.AutoStart;
387  try
388  {
389  if (originalOnline && model.Online == false)
390  await instanceManager.OfflineInstance(originalModel, AuthenticationContext.User, cancellationToken).ConfigureAwait(false);
391  else if (!originalOnline && model.Online == true)
392  {
393  // force autostart false here because we don't want any long running jobs right now
394  // remember to document this
395  originalModel.DreamDaemonSettings.AutoStart = false;
396  await instanceManager.OnlineInstance(originalModel, cancellationToken).ConfigureAwait(false);
397  }
398  }
399  catch (Exception e)
400  {
401  if(!(e is OperationCanceledException))
402  Logger.LogError("Error changing instance online state! Exception: {0}", e);
403  originalModel.Online = originalOnline;
404  originalModel.DreamDaemonSettings.AutoStart = oldAutoStart;
405  if (originalModelPath != null)
406  originalModel.Path = originalModelPath;
407  await DatabaseContext.Save(default).ConfigureAwait(false);
408  throw;
409  }
410 
411  var api = (AuthenticationContext.GetRight(RightsType.InstanceManager) & (ulong)InstanceManagerRights.Read) != 0 ? originalModel.ToApi() : new Api.Models.Instance
412  {
413  Id = originalModel.Id
414  };
415 
416  var moving = originalModelPath != null;
417  if (moving)
418  {
419  var job = new Models.Job
420  {
421  Description = String.Format(CultureInfo.InvariantCulture, MoveInstanceJobPrefix + "{0} from {1} to {2}", originalModel.Id, originalModel.Path, rawPath),
422  Instance = originalModel,
423  CancelRightsType = RightsType.InstanceManager,
424  CancelRight = (ulong)InstanceManagerRights.Relocate,
425  StartedBy = AuthenticationContext.User
426  };
427 
428  await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressHandler, ct) => instanceManager.MoveInstance(originalModel, rawPath, ct), cancellationToken).ConfigureAwait(false);
429  api.MoveJob = job.ToApi();
430  }
431 
432  if (originalModel.Online.Value && model.AutoUpdateInterval.HasValue && oldAutoUpdateInterval != model.AutoUpdateInterval)
433  await instanceManager.GetInstance(originalModel).SetAutoUpdateInterval(model.AutoUpdateInterval.Value).ConfigureAwait(false);
434 
435  return moving ? (IActionResult)Accepted(api) : Json(api);
436  }
437 #pragma warning restore CA1502
438 
445  [HttpGet(Routes.List)]
446  [TgsAuthorize(InstanceManagerRights.List | InstanceManagerRights.Read)]
447  [ProducesResponseType(typeof(IEnumerable<Api.Models.Instance>), 200)]
448  public async Task<IActionResult> List(CancellationToken cancellationToken)
449  {
450  IQueryable<Models.Instance> query = DatabaseContext.Instances;
452  query = query.Where(x => x.InstanceUsers.Any(y => y.UserId == AuthenticationContext.User.Id)).Where(x => x.InstanceUsers.Any(y => y.AnyRights));
453 
454  var moveJobTasks = query
455  .SelectMany(x => x.Jobs)
456 #pragma warning disable CA1307 // Specify StringComparison
457  .Where(x => !x.StoppedAt.HasValue && x.Description.StartsWith(MoveInstanceJobPrefix))
458 #pragma warning restore CA1307 // Specify StringComparison
459  .Include(x => x.StartedBy).ThenInclude(x => x.CreatedBy)
460  .Include(x => x.Instance)
461  .ToListAsync(cancellationToken);
462  var instances = await query.ToListAsync(cancellationToken).ConfigureAwait(false);
463  var apis = instances.Select(x => x.ToApi());
464  var moveJobs = await moveJobTasks.ConfigureAwait(false);
465  foreach(var I in moveJobs)
466  apis.Where(x => x.Id == I.Instance.Id).First().MoveJob = I.ToApi(); // if this .First() fails i will personally murder kevinz000 because I just know he is somehow responsible
467  return Json(apis);
468  }
469 
478  [HttpGet("{id}")]
479  [TgsAuthorize(InstanceManagerRights.List | InstanceManagerRights.Read)]
480  [ProducesResponseType(typeof(Api.Models.Instance), 200)]
481  [ProducesResponseType(410)]
482  public async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
483  {
484  var query = DatabaseContext.Instances.Where(x => x.Id == id);
485  var cantList = !AuthenticationContext.User.InstanceManagerRights.Value.HasFlag(InstanceManagerRights.List);
486 
487  if (cantList)
488  query = query.Include(x => x.InstanceUsers);
489 
490  var moveJobTask = query
491  .SelectMany(x => x.Jobs)
492 #pragma warning disable CA1307 // Specify StringComparison
493  .Where(x => !x.StoppedAt.HasValue && x.Description.StartsWith(MoveInstanceJobPrefix))
494 #pragma warning restore CA1307 // Specify StringComparison
495  .Include(x => x.StartedBy).ThenInclude(x => x.CreatedBy)
496  .FirstOrDefaultAsync(cancellationToken);
497  var instance = await query.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
498 
499  if (instance == null)
500  return StatusCode((int)HttpStatusCode.Gone);
501 
502  if (cantList && !instance.InstanceUsers.Any(x => x.UserId == AuthenticationContext.User.Id && x.AnyRights))
503  return Forbid();
504 
505  var api = instance.ToApi();
506  api.MoveJob = (await moveJobTask.ConfigureAwait(false))?.ToApi();
507  return Json(api);
508  }
509  }
510 }
string Name
The name of the User
Definition: User.cs:38
- +Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.EntityFrameworkCore;
3 using Microsoft.Extensions.Logging;
4 using System;
5 using System.Collections.Generic;
6 using System.Globalization;
7 using System.IO;
8 using System.Linq;
9 using System.Linq.Expressions;
10 using System.Net;
11 using System.Reflection;
12 using System.Threading;
13 using System.Threading.Tasks;
14 using Tgstation.Server.Api;
20 using Tgstation.Server.Host.IO;
25 
27 {
31  [Route(Routes.InstanceManager)]
32  #pragma warning disable CA1506 // TODO: Decomplexify
33  public sealed class InstanceController : ApiController
34  {
38  const string InstanceAttachFileName = "TGS4_ALLOW_INSTANCE_ATTACH";
39 
40  const string MoveInstanceJobPrefix = "Move instance ID ";
41 
46 
51 
56 
61 
66 
78  public InstanceController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, IInstanceManager instanceManager, IIOManager ioManager, IApplication application, IPlatformIdentifier platformIdentifier, ILogger<InstanceController> logger) : base(databaseContext, authenticationContextFactory, logger, false, true)
79  {
80  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
81  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
82  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
83  this.application = application ?? throw new ArgumentNullException(nameof(application));
84  this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
85  }
86 
87  void NormalizeModelPath(Api.Models.Instance model, out string absolutePath)
88  {
89  if (model.Path == null)
90  {
91  absolutePath = null;
92  return;
93  }
94 
95  absolutePath = ioManager.ResolvePath(model.Path);
97  model.Path = absolutePath.ToUpperInvariant();
98  else
99  model.Path = absolutePath;
100  }
101 
102  Models.InstanceUser InstanceAdminUser() => new Models.InstanceUser
103  {
104  ByondRights = (ByondRights)~0U,
111  UserId = AuthenticationContext.User.Id
112  };
113 
122  [HttpPut]
123  [TgsAuthorize(InstanceManagerRights.Create)]
124  [ProducesResponseType(typeof(Api.Models.Instance), 200)]
125  [ProducesResponseType(typeof(Api.Models.Instance), 201)]
126  public async Task<IActionResult> Create([FromBody] Api.Models.Instance model, CancellationToken cancellationToken)
127  {
128  if (model == null)
129  throw new ArgumentNullException(nameof(model));
130 
131  if (String.IsNullOrWhiteSpace(model.Name))
132  return BadRequest(new ErrorMessage { Message = "name must not be empty!" });
133 
134  if (model.Path == null)
135  return BadRequest(new ErrorMessage { Message = "path must not be empty!" });
136 
137  NormalizeModelPath(model, out var rawPath);
138 
139  var localPath = ioManager.ResolvePath(".");
140  NormalizeModelPath(new Api.Models.Instance
141  {
142  Path = localPath
143  }, out var normalizedLocalPath);
144 
145  if (rawPath.StartsWith(normalizedLocalPath, StringComparison.Ordinal))
146  {
147  bool sameLength = rawPath.Length == normalizedLocalPath.Length;
148  char dirSeparatorChar = rawPath.ToCharArray()[normalizedLocalPath.Length];
149  if(sameLength
150  || dirSeparatorChar == Path.DirectorySeparatorChar
151  || dirSeparatorChar == Path.AltDirectorySeparatorChar)
152  return Conflict(new ErrorMessage { Message = "Instances cannot be created in the installation directory!" });
153  }
154 
155  var dirExistsTask = ioManager.DirectoryExists(model.Path, cancellationToken);
156  bool attached = false;
157  if (await ioManager.FileExists(model.Path, cancellationToken).ConfigureAwait(false) || await dirExistsTask.ConfigureAwait(false))
158  if (!await ioManager.FileExists(ioManager.ConcatPath(model.Path, InstanceAttachFileName), cancellationToken).ConfigureAwait(false))
159  return Conflict(new ErrorMessage { Message = "Path not empty!" });
160  else
161  attached = true;
162 
163  var newInstance = new Models.Instance
164  {
165  ConfigurationType = model.ConfigurationType ?? ConfigurationType.Disallowed,
167  {
168  AllowWebClient = false,
169  AutoStart = false,
170  PrimaryPort = 1337,
171  SecondaryPort = 1338,
172  SecurityLevel = DreamDaemonSecurity.Safe,
173  SoftRestart = false,
174  SoftShutdown = false,
175  StartupTimeout = 20
176  },
178  {
179  ApiValidationPort = 1339,
180  ApiValidationSecurityLevel = DreamDaemonSecurity.Safe
181  },
182  Name = model.Name,
183  Online = false,
184  Path = model.Path,
185  AutoUpdateInterval = model.AutoUpdateInterval ?? 0,
187  {
188  CommitterEmail = "tgstation-server@users.noreply.github.com",
189  CommitterName = application.VersionPrefix,
190  PushTestMergeCommits = false,
191  ShowTestMergeCommitters = false,
192  AutoUpdatesKeepTestMerges = false,
193  AutoUpdatesSynchronize = false,
194  PostTestMergeComment = false
195  },
196  InstanceUsers = new List<Models.InstanceUser> // give this user full privileges on the instance
197  {
199  }
200  };
201 
202  DatabaseContext.Instances.Add(newInstance);
203  try
204  {
205  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
206 
207  try
208  {
209  // actually reserve it now
210  await ioManager.CreateDirectory(rawPath, cancellationToken).ConfigureAwait(false);
211  await ioManager.DeleteFile(ioManager.ConcatPath(rawPath, InstanceAttachFileName), cancellationToken).ConfigureAwait(false);
212  }
213  catch
214  {
215  // oh shit delete the model
216  DatabaseContext.Instances.Remove(newInstance);
217 
218  await DatabaseContext.Save(default).ConfigureAwait(false);
219  throw;
220  }
221  }
222  catch (IOException e)
223  {
224  return Conflict(new ErrorMessage { Message = e.Message });
225  }
226  catch (DbUpdateException e)
227  {
228  return Conflict(new ErrorMessage { Message = e.Message });
229  }
230 
231  Logger.LogInformation("{0} {1} instance {2}: {3} ({4})", AuthenticationContext.User.Name, attached ? "attached" : "created", newInstance.Name, newInstance.Id, newInstance.Path);
232 
233  var api = newInstance.ToApi();
234  return attached ? (IActionResult)Json(api) : StatusCode((int)HttpStatusCode.Created, api);
235  }
236 
245  [HttpDelete("{id}")]
246  [TgsAuthorize(InstanceManagerRights.Delete)]
247  [ProducesResponseType(200)]
248  [ProducesResponseType(410)]
249  public async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
250  {
251  var originalModel = await DatabaseContext.Instances.Where(x => x.Id == id)
252  .Include(x => x.WatchdogReattachInformation)
253  .Include(x => x.WatchdogReattachInformation.Alpha)
254  .Include(x => x.WatchdogReattachInformation.Bravo)
255  .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
256  if (originalModel == default)
257  return StatusCode((int)HttpStatusCode.Gone);
258  if (originalModel.Online.Value)
259  return Conflict(new ErrorMessage
260  {
261  Message = "Cannot detach an online instance!"
262  });
263 
264  if (originalModel.WatchdogReattachInformation != null)
265  {
266  DatabaseContext.WatchdogReattachInformations.Remove(originalModel.WatchdogReattachInformation);
267  if (originalModel.WatchdogReattachInformation.Alpha != null)
268  DatabaseContext.ReattachInformations.Remove(originalModel.WatchdogReattachInformation.Alpha);
269  if (originalModel.WatchdogReattachInformation.Bravo != null)
270  DatabaseContext.ReattachInformations.Remove(originalModel.WatchdogReattachInformation.Bravo);
271  }
272 
273  DatabaseContext.Instances.Remove(originalModel);
274 
275  var attachFileName = ioManager.ConcatPath(originalModel.Path, InstanceAttachFileName);
276  await ioManager.WriteAllBytes(attachFileName, Array.Empty<byte>(), default).ConfigureAwait(false);
277  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false); // cascades everything
278  return Ok();
279  }
280 
289  [HttpPost]
290  [TgsAuthorize(InstanceManagerRights.Relocate | InstanceManagerRights.Rename | InstanceManagerRights.SetAutoUpdate | InstanceManagerRights.SetConfiguration | InstanceManagerRights.SetOnline)]
291  [ProducesResponseType(typeof(Api.Models.Instance), 200)]
292  [ProducesResponseType(410)]
293 #pragma warning disable CA1502 // TODO: Decomplexify
294  public async Task<IActionResult> Update([FromBody] Api.Models.Instance model, CancellationToken cancellationToken)
295  {
296  if (model == null)
297  throw new ArgumentNullException(nameof(model));
298 
299  var instanceQuery = DatabaseContext.Instances.Where(x => x.Id == model.Id);
300 
301  var moveJob = await instanceQuery
302  .SelectMany(x => x.Jobs).
303 #pragma warning disable CA1307 // Specify StringComparison
304  Where(x => !x.StoppedAt.HasValue && x.Description.StartsWith(MoveInstanceJobPrefix))
305 #pragma warning restore CA1307 // Specify StringComparison
306  .Select(x => new Models.Job
307  {
308  Id = x.Id
309  }).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
310 
311  if (moveJob != default)
312  await jobManager.CancelJob(moveJob, AuthenticationContext.User, true, cancellationToken).ConfigureAwait(false); // cancel it now
313 
314  var usersInstanceUserTask = instanceQuery.SelectMany(x => x.InstanceUsers).Where(x => x.UserId == AuthenticationContext.User.Id).FirstOrDefaultAsync(cancellationToken);
315 
316  var originalModel = await instanceQuery
317  .Include(x => x.RepositorySettings)
318  .Include(x => x.ChatSettings)
319  .ThenInclude(x => x.Channels)
320  .Include(x => x.DreamDaemonSettings) // need these for onlining
321  .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
322  if (originalModel == default(Models.Instance))
323  return StatusCode((int)HttpStatusCode.Gone);
324 
325  var userRights = (InstanceManagerRights)AuthenticationContext.GetRight(RightsType.InstanceManager);
326  bool CheckModified<T>(Expression<Func<Api.Models.Instance, T>> expression, InstanceManagerRights requiredRight)
327  {
328  var memberSelectorExpression = (MemberExpression)expression.Body;
329  var property = (PropertyInfo)memberSelectorExpression.Member;
330 
331  var newVal = property.GetValue(model);
332  if (newVal == null)
333  return false;
334  if (!userRights.HasFlag(requiredRight) && property.GetValue(originalModel) != newVal)
335  return true;
336 
337  property.SetValue(originalModel, newVal);
338  return false;
339  }
340 
341  string originalModelPath = null;
342  string rawPath = null;
343  if (model.Path != null)
344  {
345  NormalizeModelPath(model, out rawPath);
346 
347  if (model.Path != originalModel.Path)
348  {
349  if (!userRights.HasFlag(InstanceManagerRights.Relocate))
350  return Forbid();
351  if (originalModel.Online.Value && model.Online != true)
352  return Conflict(new ErrorMessage { Message = "Cannot relocate an online instance!" });
353 
354  var dirExistsTask = ioManager.DirectoryExists(model.Path, cancellationToken);
355  if (await ioManager.FileExists(model.Path, cancellationToken).ConfigureAwait(false) || await dirExistsTask.ConfigureAwait(false))
356  return Conflict(new ErrorMessage { Message = "Path not empty!" });
357 
358  originalModelPath = originalModel.Path;
359  originalModel.Path = model.Path;
360  }
361  }
362 
363  var oldAutoUpdateInterval = originalModel.AutoUpdateInterval.Value;
364  var originalOnline = originalModel.Online.Value;
365  var renamed = model.Name != null && originalModel.Name != model.Name;
366 
367  if (CheckModified(x => x.AutoUpdateInterval, InstanceManagerRights.SetAutoUpdate)
368  || CheckModified(x => x.ConfigurationType, InstanceManagerRights.SetConfiguration)
369  || CheckModified(x => x.Name, InstanceManagerRights.Rename)
370  || CheckModified(x => x.Online, InstanceManagerRights.SetOnline))
371  return Forbid();
372 
373  // ensure the current user has write privilege on the instance
374  var usersInstanceUser = await usersInstanceUserTask.ConfigureAwait(false);
375  if (usersInstanceUser == default)
376  {
377  var instanceAdminUser = InstanceAdminUser();
378  instanceAdminUser.InstanceId = originalModel.Id;
379  DatabaseContext.InstanceUsers.Add(instanceAdminUser);
380  }
381  else
382  usersInstanceUser.InstanceUserRights |= InstanceUserRights.WriteUsers;
383 
384  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
385 
386  if (renamed)
387  instanceManager.GetInstance(originalModel).Rename(originalModel.Name);
388 
389  var oldAutoStart = originalModel.DreamDaemonSettings.AutoStart;
390  try
391  {
392  if (originalOnline && model.Online == false)
393  await instanceManager.OfflineInstance(originalModel, AuthenticationContext.User, cancellationToken).ConfigureAwait(false);
394  else if (!originalOnline && model.Online == true)
395  {
396  // force autostart false here because we don't want any long running jobs right now
397  // remember to document this
398  originalModel.DreamDaemonSettings.AutoStart = false;
399  await instanceManager.OnlineInstance(originalModel, cancellationToken).ConfigureAwait(false);
400  }
401  }
402  catch (Exception e)
403  {
404  if(!(e is OperationCanceledException))
405  Logger.LogError("Error changing instance online state! Exception: {0}", e);
406  originalModel.Online = originalOnline;
407  originalModel.DreamDaemonSettings.AutoStart = oldAutoStart;
408  if (originalModelPath != null)
409  originalModel.Path = originalModelPath;
410  await DatabaseContext.Save(default).ConfigureAwait(false);
411  throw;
412  }
413 
414  var api = (AuthenticationContext.GetRight(RightsType.InstanceManager) & (ulong)InstanceManagerRights.Read) != 0 ? originalModel.ToApi() : new Api.Models.Instance
415  {
416  Id = originalModel.Id
417  };
418 
419  var moving = originalModelPath != null;
420  if (moving)
421  {
422  var job = new Models.Job
423  {
424  Description = String.Format(CultureInfo.InvariantCulture, MoveInstanceJobPrefix + "{0} from {1} to {2}", originalModel.Id, originalModel.Path, rawPath),
425  Instance = originalModel,
426  CancelRightsType = RightsType.InstanceManager,
427  CancelRight = (ulong)InstanceManagerRights.Relocate,
428  StartedBy = AuthenticationContext.User
429  };
430 
431  await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressHandler, ct) => instanceManager.MoveInstance(originalModel, rawPath, ct), cancellationToken).ConfigureAwait(false);
432  api.MoveJob = job.ToApi();
433  }
434 
435  if (originalModel.Online.Value && model.AutoUpdateInterval.HasValue && oldAutoUpdateInterval != model.AutoUpdateInterval)
436  await instanceManager.GetInstance(originalModel).SetAutoUpdateInterval(model.AutoUpdateInterval.Value).ConfigureAwait(false);
437 
438  return moving ? (IActionResult)Accepted(api) : Json(api);
439  }
440 #pragma warning restore CA1502
441 
448  [HttpGet(Routes.List)]
449  [TgsAuthorize(InstanceManagerRights.List | InstanceManagerRights.Read)]
450  [ProducesResponseType(typeof(IEnumerable<Api.Models.Instance>), 200)]
451  public async Task<IActionResult> List(CancellationToken cancellationToken)
452  {
453  IQueryable<Models.Instance> query = DatabaseContext.Instances;
455  query = query.Where(x => x.InstanceUsers.Any(y => y.UserId == AuthenticationContext.User.Id)).Where(x => x.InstanceUsers.Any(y => y.AnyRights));
456 
457  var moveJobTasks = query
458  .SelectMany(x => x.Jobs)
459 #pragma warning disable CA1307 // Specify StringComparison
460  .Where(x => !x.StoppedAt.HasValue && x.Description.StartsWith(MoveInstanceJobPrefix))
461 #pragma warning restore CA1307 // Specify StringComparison
462  .Include(x => x.StartedBy).ThenInclude(x => x.CreatedBy)
463  .Include(x => x.Instance)
464  .ToListAsync(cancellationToken);
465  var instances = await query.ToListAsync(cancellationToken).ConfigureAwait(false);
466  var apis = instances.Select(x => x.ToApi());
467  var moveJobs = await moveJobTasks.ConfigureAwait(false);
468  foreach(var I in moveJobs)
469  apis.Where(x => x.Id == I.Instance.Id).First().MoveJob = I.ToApi(); // if this .First() fails i will personally murder kevinz000 because I just know he is somehow responsible
470  return Json(apis);
471  }
472 
481  [HttpGet("{id}")]
482  [TgsAuthorize(InstanceManagerRights.List | InstanceManagerRights.Read)]
483  [ProducesResponseType(typeof(Api.Models.Instance), 200)]
484  [ProducesResponseType(410)]
485  public async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
486  {
487  var query = DatabaseContext.Instances.Where(x => x.Id == id);
488  var cantList = !AuthenticationContext.User.InstanceManagerRights.Value.HasFlag(InstanceManagerRights.List);
489 
490  if (cantList)
491  query = query.Include(x => x.InstanceUsers);
492 
493  var moveJobTask = query
494  .SelectMany(x => x.Jobs)
495 #pragma warning disable CA1307 // Specify StringComparison
496  .Where(x => !x.StoppedAt.HasValue && x.Description.StartsWith(MoveInstanceJobPrefix))
497 #pragma warning restore CA1307 // Specify StringComparison
498  .Include(x => x.StartedBy).ThenInclude(x => x.CreatedBy)
499  .FirstOrDefaultAsync(cancellationToken);
500  var instance = await query.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
501 
502  if (instance == null)
503  return StatusCode((int)HttpStatusCode.Gone);
504 
505  if (cantList && !instance.InstanceUsers.Any(x => x.UserId == AuthenticationContext.User.Id && x.AnyRights))
506  return Forbid();
507 
508  var api = instance.ToApi();
509  api.MoveJob = (await moveJobTask.ConfigureAwait(false))?.ToApi();
510  return Json(api);
511  }
512  }
513 }
string Name
The name of the User
Definition: User.cs:38
+
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
-
Manages the runtime of Jobs
Definition: IJobManager.cs:12
ConfigurationRights
Rights for Models.ConfigurationFile
-
InstanceController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, IInstanceManager instanceManager, IIOManager ioManager, IApplication application, IPlatformIdentifier platformIdentifier, ILogger< InstanceController > logger)
Construct a InstanceController
+
InstanceController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, IInstanceManager instanceManager, IIOManager ioManager, IApplication application, IPlatformIdentifier platformIdentifier, ILogger< InstanceController > logger)
Construct a InstanceController
-
async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Get a specific Api.Models.Instance.
+
async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Get a specific Api.Models.Instance.
User can enable Models.Internal.DreamDaemonSettings.SoftRestart
Task MoveInstance(Models.Instance metadata, string newPath, CancellationToken cancellationToken)
Move an IInstance
- + +
ByondRights
Rights for Models.Byond
Definition: ByondRights.cs:9
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
-
DbSet< ReattachInformation > ReattachInformations
Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content
-
const string InstanceAttachFileName
File name to allow attaching instances
+
const string InstanceAttachFileName
File name to allow attaching instances
InstanceUserRights
Rights for an Models.Instance
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
-
readonly IInstanceManager instanceManager
The IInstanceManager for the InstanceController
-
readonly IApplication application
The IApplication for the InstanceController
+
readonly IInstanceManager instanceManager
The IInstanceManager for the InstanceController
+
readonly IApplication application
The IApplication for the InstanceController
IInstance GetInstance(Models.Instance metadata)
Get the IInstance associated with given metadata
string VersionPrefix
Prefix to VersionString
Definition: IApplication.cs:13
- -
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
-
async Task< IActionResult > List(CancellationToken cancellationToken)
List Api.Models.Instances.
+
Task< bool > CancelJob(Job job, User user, bool blocking, CancellationToken cancellationToken)
Cancels a give job
+
async Task< IActionResult > List(CancellationToken cancellationToken)
List Api.Models.Instances.
ConfigurationType
The type of configuration allowed on an Instance
Task CreateDirectory(string path, CancellationToken cancellationToken)
Create a directory at path
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
-
ApiController for managing Components.Instances
+
ApiController for managing Components.Instances
string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
-
Task RegisterOperation(Job job, Func< Job, IDatabaseContext, Action< int >, CancellationToken, Task > operation, CancellationToken cancellationToken)
Registers a given Job and begins running it
-
readonly IIOManager ioManager
The IIOManager for the InstanceController
-
readonly IJobManager jobManager
The IJobManager for the InstanceController
+
readonly IIOManager ioManager
The IIOManager for the InstanceController
+ +
readonly IJobManager jobManager
The IJobManager for the InstanceController
+
DbSet< WatchdogReattachInformation > WatchdogReattachInformations
-
async Task< IActionResult > Delete(long id, CancellationToken cancellationToken)
Detach an Api.Models.Instance with the given id .
+
async Task< IActionResult > Delete(long id, CancellationToken cancellationToken)
Detach an Api.Models.Instance with the given id .
+
DbSet< ReattachInformation > ReattachInformations
Routes to a server actions
Definition: Routes.cs:9
DreamDaemonRights
Rights for Models.DreamDaemon
Task< bool > FileExists(string path, CancellationToken cancellationToken)
Check that the file at path exists
+
Task OfflineInstance(Models.Instance metadata, User user, CancellationToken cancellationToken)
Offline an IInstance
+
Task OnlineInstance(Models.Instance metadata, CancellationToken cancellationToken)
Online an IInstance
InstanceManagerRights
Rights for managing Models.Instances
string Message
A human readable description of the error
Definition: ErrorMessage.cs:13
-
async Task< IActionResult > Update([FromBody] Api.Models.Instance model, CancellationToken cancellationToken)
Modify an Api.Models.Instance's settings.
+
async Task< IActionResult > Update([FromBody] Api.Models.Instance model, CancellationToken cancellationToken)
Modify an Api.Models.Instance's settings.
-
bool IsWindows
If the current platform is a Windows platform
DreamMakerRights
Rights for Models.DreamMaker
-
InstanceManagerRights? InstanceManagerRights
The Rights.InstanceManagerRights for the User
Definition: User.cs:50
-
RepositoryRights
Rights for a Models.Repository
-
Task< bool > CancelJob(Job job, User user, bool blocking, CancellationToken cancellationToken)
Cancels a give job
+
const string InstanceManager
The Models.Instance controller
Definition: Routes.cs:29
-
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for the InstanceController
+
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for the InstanceController
void Rename(string newName)
Rename the IInstance
long Id
The ID of the User
Definition: User.cs:15
ILogger Logger
The ILogger for the ApiController
Metadata about a server instance
Definition: Instance.cs:9
+
Manages the runtime of Jobs
Definition: IJobManager.cs:13
- + + -
DbSet< WatchdogReattachInformation > WatchdogReattachInformations
DreamDaemonSecurity
DreamDaemon's security level
const string List
The postfix for list operations
Definition: Routes.cs:84
Interface for using filesystems
Definition: IIOManager.cs:11
-
For identifying the current platform
-
async Task< IActionResult > Create([FromBody] Api.Models.Instance model, CancellationToken cancellationToken)
Create or attach an Api.Models.Instance.
+
Task RegisterOperation(Job job, Func< Job, IDatabaseContext, Action< int >, CancellationToken, Task > operation, CancellationToken cancellationToken)
Registers a given Job and begins running it
+
async Task< IActionResult > Create([FromBody] Api.Models.Instance model, CancellationToken cancellationToken)
Create or attach an Api.Models.Instance.
Task DeleteFile(string path, CancellationToken cancellationToken)
Deletes a file at path
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
-
void NormalizeModelPath(Api.Models.Instance model, out string absolutePath)
+
void NormalizeModelPath(Api.Models.Instance model, out string absolutePath)
+
For identifying the current platform
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
User can enable Models.Internal.DreamDaemonSettings.SoftShutdown
@@ -158,8 +159,10 @@ $(function() {
string ConcatPath(params string[] paths)
Combines an array of strings into a path
Task SetAutoUpdateInterval(uint newInterval)
Change the Api.Models.Instance.AutoUpdateInterval for the IInstance
+ +
bool IsWindows
If the current platform is a Windows platform
-Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Threading;
5 using System.Threading.Tasks;
13 using Tgstation.Server.Host.IO;
15 
17 {
20  {
25 
30 
35 
39  readonly ILoggerFactory loggerFactory;
40 
44  readonly IByondTopicSender byondTopicSender;
45 
50 
55 
60 
65 
70 
75 
80 
85 
90 
95 
100 
105 
110 
133  {
134  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
135  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
136  this.application = application ?? throw new ArgumentNullException(nameof(application));
137  this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
138  this.byondTopicSender = byondTopicSender ?? throw new ArgumentNullException(nameof(byondTopicSender));
139  this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite));
140  this.synchronousIOManager = synchronousIOManager ?? throw new ArgumentNullException(nameof(synchronousIOManager));
141  this.symlinkFactory = symlinkFactory ?? throw new ArgumentNullException(nameof(symlinkFactory));
142  this.byondInstaller = byondInstaller ?? throw new ArgumentNullException(nameof(byondInstaller));
143  this.chatFactory = chatFactory ?? throw new ArgumentNullException(nameof(chatFactory));
144  this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor));
145  this.postWriteHandler = postWriteHandler ?? throw new ArgumentNullException(nameof(postWriteHandler));
146  this.watchdogFactory = watchdogFactory ?? throw new ArgumentNullException(nameof(watchdogFactory));
147  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
148  this.credentialsProvider = credentialsProvider ?? throw new ArgumentNullException(nameof(credentialsProvider));
149  this.networkPromptReaper = networkPromptReaper ?? throw new ArgumentNullException(nameof(networkPromptReaper));
150  this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
151  this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
152  }
153 
155  #pragma warning disable CA1506 // TODO: Decomplexify
156  public IInstance CreateInstance(Models.Instance metadata)
157  {
158  // Create the ioManager for the instance
159  var instanceIoManager = new ResolvingIOManager(ioManager, metadata.Path);
160 
161  // various other ioManagers
162  var repoIoManager = new ResolvingIOManager(instanceIoManager, "Repository");
163  var byondIOManager = new ResolvingIOManager(instanceIoManager, "Byond");
164  var gameIoManager = new ResolvingIOManager(instanceIoManager, "Game");
165  var configurationIoManager = new ResolvingIOManager(instanceIoManager, "Configuration");
166 
167  var configuration = new StaticFiles.Configuration(configurationIoManager, synchronousIOManager, symlinkFactory, processExecutor, postWriteHandler, platformIdentifier, loggerFactory.CreateLogger<StaticFiles.Configuration>());
168  var eventConsumer = new EventConsumer(configuration);
169 
170  var dmbFactory = new DmbFactory(databaseContextFactory, gameIoManager, loggerFactory.CreateLogger<DmbFactory>(), metadata.CloneMetadata());
171  try
172  {
173  var repoManager = new RepositoryManager(metadata.RepositorySettings, repoIoManager, eventConsumer, credentialsProvider, loggerFactory.CreateLogger<Repository.Repository>(), loggerFactory.CreateLogger<RepositoryManager>());
174  try
175  {
176  var byond = new ByondManager(byondIOManager, byondInstaller, eventConsumer, loggerFactory.CreateLogger<ByondManager>());
177 
178  var commandFactory = new CommandFactory(application, byond, repoManager, databaseContextFactory, metadata);
179 
180  var chat = chatFactory.CreateChat(instanceIoManager, commandFactory, metadata.ChatSettings);
181  try
182  {
183  var sessionControllerFactory = new SessionControllerFactory(processExecutor, byond, byondTopicSender, cryptographySuite, application, gameIoManager, chat, networkPromptReaper, platformIdentifier, loggerFactory, metadata.CloneMetadata());
184  var reattachInfoHandler = new ReattachInfoHandler(databaseContextFactory, dmbFactory, loggerFactory.CreateLogger<ReattachInfoHandler>(), metadata.CloneMetadata());
185  var watchdog = watchdogFactory.CreateWatchdog(chat, dmbFactory, reattachInfoHandler, configuration, sessionControllerFactory, metadata.CloneMetadata(), metadata.DreamDaemonSettings);
186  eventConsumer.SetWatchdog(watchdog);
187  commandFactory.SetWatchdog(watchdog);
188  try
189  {
190  var dreamMaker = new DreamMaker(byond, gameIoManager, configuration, sessionControllerFactory, dmbFactory, application, eventConsumer, chat, processExecutor, watchdog, loggerFactory.CreateLogger<DreamMaker>());
191 
192  return new Instance(metadata.CloneMetadata(), repoManager, byond, dreamMaker, watchdog, chat, configuration, dmbFactory, databaseContextFactory, dmbFactory, jobManager, eventConsumer, gitHubClientFactory, loggerFactory.CreateLogger<Instance>());
193  }
194  catch
195  {
196  watchdog.Dispose();
197  throw;
198  }
199  }
200  catch
201  {
202  chat.Dispose();
203  throw;
204  }
205  }
206  catch
207  {
208  repoManager.Dispose();
209  throw;
210  }
211  }
212  catch
213  {
214  dmbFactory.Dispose();
215  throw;
216  }
217  }
218  #pragma warning restore CA1506
219 
221  public Task StartAsync(CancellationToken cancellationToken) => byondInstaller.CleanCache(cancellationToken);
222 
224  public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
225  }
226 }
-
readonly ISynchronousIOManager synchronousIOManager
The ISynchronousIOManager for the InstanceFactory
-
Manages the runtime of Jobs
Definition: IJobManager.cs:12
-
readonly IByondInstaller byondInstaller
The IByondInstaller for the InstanceFactory
+Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Threading;
5 using System.Threading.Tasks;
14 using Tgstation.Server.Host.IO;
18 
20 {
23  {
28 
33 
38 
42  readonly ILoggerFactory loggerFactory;
43 
47  readonly IByondTopicSender byondTopicSender;
48 
53 
58 
63 
68 
73 
78 
83 
88 
93 
98 
103 
108 
113 
139  ILoggerFactory loggerFactory,
140  IByondTopicSender byondTopicSender,
154  {
155  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
156  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
157  this.application = application ?? throw new ArgumentNullException(nameof(application));
158  this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
159  this.byondTopicSender = byondTopicSender ?? throw new ArgumentNullException(nameof(byondTopicSender));
160  this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite));
161  this.synchronousIOManager = synchronousIOManager ?? throw new ArgumentNullException(nameof(synchronousIOManager));
162  this.symlinkFactory = symlinkFactory ?? throw new ArgumentNullException(nameof(symlinkFactory));
163  this.byondInstaller = byondInstaller ?? throw new ArgumentNullException(nameof(byondInstaller));
164  this.chatFactory = chatFactory ?? throw new ArgumentNullException(nameof(chatFactory));
165  this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor));
166  this.postWriteHandler = postWriteHandler ?? throw new ArgumentNullException(nameof(postWriteHandler));
167  this.watchdogFactory = watchdogFactory ?? throw new ArgumentNullException(nameof(watchdogFactory));
168  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
169  this.credentialsProvider = credentialsProvider ?? throw new ArgumentNullException(nameof(credentialsProvider));
170  this.networkPromptReaper = networkPromptReaper ?? throw new ArgumentNullException(nameof(networkPromptReaper));
171  this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
172  this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
173  }
174 
176 #pragma warning disable CA1506 // TODO: Decomplexify
177  public IInstance CreateInstance(Models.Instance metadata)
178  {
179  // Create the ioManager for the instance
180  var instanceIoManager = new ResolvingIOManager(ioManager, metadata.Path);
181 
182  // various other ioManagers
183  var repoIoManager = new ResolvingIOManager(instanceIoManager, "Repository");
184  var byondIOManager = new ResolvingIOManager(instanceIoManager, "Byond");
185  var gameIoManager = new ResolvingIOManager(instanceIoManager, "Game");
186  var configurationIoManager = new ResolvingIOManager(instanceIoManager, "Configuration");
187 
188  var configuration = new StaticFiles.Configuration(configurationIoManager, synchronousIOManager, symlinkFactory, processExecutor, postWriteHandler, platformIdentifier, loggerFactory.CreateLogger<StaticFiles.Configuration>());
189  var eventConsumer = new EventConsumer(configuration);
190  var repoManager = new RepositoryManager(metadata.RepositorySettings, repoIoManager, eventConsumer, credentialsProvider, loggerFactory.CreateLogger<Repository.Repository>(), loggerFactory.CreateLogger<RepositoryManager>());
191  try
192  {
193  var byond = new ByondManager(byondIOManager, byondInstaller, eventConsumer, loggerFactory.CreateLogger<ByondManager>());
194 
195  var commandFactory = new CommandFactory(application, byond, repoManager, databaseContextFactory, metadata);
196 
197  var chat = chatFactory.CreateChat(instanceIoManager, commandFactory, metadata.ChatSettings);
198  try
199  {
200  var sessionControllerFactory = new SessionControllerFactory(processExecutor, byond, byondTopicSender, cryptographySuite, application, gameIoManager, chat, networkPromptReaper, platformIdentifier, loggerFactory, metadata.CloneMetadata());
201 
202  var dmbFactory = new DmbFactory(databaseContextFactory, gameIoManager, loggerFactory.CreateLogger<DmbFactory>(), metadata.CloneMetadata());
203  try
204  {
205  var reattachInfoHandler = new ReattachInfoHandler(databaseContextFactory, dmbFactory, loggerFactory.CreateLogger<ReattachInfoHandler>(), metadata.CloneMetadata());
206  var watchdog = watchdogFactory.CreateWatchdog(
207  chat,
208  dmbFactory,
209  reattachInfoHandler,
210  configuration,
211  sessionControllerFactory,
212  gameIoManager,
213  metadata.CloneMetadata(),
214  metadata.DreamDaemonSettings);
215  eventConsumer.SetWatchdog(watchdog);
216  commandFactory.SetWatchdog(watchdog);
217  try
218  {
219  var dreamMaker = new DreamMaker(byond, gameIoManager, configuration, sessionControllerFactory, eventConsumer, chat, processExecutor, watchdog, loggerFactory.CreateLogger<DreamMaker>());
220 
221  return new Instance(metadata.CloneMetadata(), repoManager, byond, dreamMaker, watchdog, chat, configuration, dmbFactory, databaseContextFactory, dmbFactory, jobManager, eventConsumer, gitHubClientFactory, loggerFactory.CreateLogger<Instance>());
222  }
223  catch
224  {
225  watchdog.Dispose();
226  throw;
227  }
228  }
229  catch
230  {
231  dmbFactory.Dispose();
232  throw;
233  }
234  }
235  catch
236  {
237  chat.Dispose();
238  throw;
239  }
240  }
241  catch
242  {
243  repoManager.Dispose();
244  throw;
245  }
246  }
247  #pragma warning restore CA1506
248 
250  public Task StartAsync(CancellationToken cancellationToken) => byondInstaller.CleanCache(cancellationToken);
251 
253  public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
254  }
255 }
readonly ISynchronousIOManager synchronousIOManager
The ISynchronousIOManager for the InstanceFactory
+
readonly IByondInstaller byondInstaller
The IByondInstaller for the InstanceFactory
IChat CreateChat(IIOManager ioManager, ICommandFactory commandFactory, IEnumerable< Models.ChatBot > initialChatBots)
Create a IChat
-
Task StartAsync(CancellationToken cancellationToken)
+
Handles changing file modes/permissions after writing
+
An IIOManager that resolve relative paths from another IIOManager to a subdirectory of that
-
IWatchdog CreateWatchdog(IChat chat, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IEventConsumer eventConsumer, ISessionControllerFactory sessionControllerFactory, Api.Models.Instance instance, DreamDaemonSettings settings)
Creates a IWatchdog
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
+
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
Task StopAsync(CancellationToken cancellationToken)
-
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the InstanceFactory
-
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
- - -
readonly IByondTopicSender byondTopicSender
The IByondTopicSender for the InstanceFactory
-
InstanceFactory(IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, IApplication application, ILoggerFactory loggerFactory, IByondTopicSender byondTopicSender, ICryptographySuite cryptographySuite, ISynchronousIOManager synchronousIOManager, ISymlinkFactory symlinkFactory, IByondInstaller byondInstaller, IChatFactory chatFactory, IProcessExecutor processExecutor, IPostWriteHandler postWriteHandler, IWatchdogFactory watchdogFactory, IJobManager jobManager, ICredentialsProvider credentialsProvider, INetworkPromptReaper networkPromptReaper, IGitHubClientFactory gitHubClientFactory, IPlatformIdentifier platformIdentifier)
Construct an InstanceFactory
+
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the InstanceFactory
+ +
readonly IByondTopicSender byondTopicSender
The IByondTopicSender for the InstanceFactory
+
InstanceFactory(IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, IApplication application, ILoggerFactory loggerFactory, IByondTopicSender byondTopicSender, ICryptographySuite cryptographySuite, ISynchronousIOManager synchronousIOManager, ISymlinkFactory symlinkFactory, IByondInstaller byondInstaller, IChatFactory chatFactory, IProcessExecutor processExecutor, IPostWriteHandler postWriteHandler, IWatchdogFactory watchdogFactory, IJobManager jobManager, ICredentialsProvider credentialsProvider, INetworkPromptReaper networkPromptReaper, IGitHubClientFactory gitHubClientFactory, IPlatformIdentifier platformIdentifier)
Construct an InstanceFactory
-
readonly ICryptographySuite cryptographySuite
The ICryptographySuite for the InstanceFactory
+
readonly ICryptographySuite cryptographySuite
The ICryptographySuite for the InstanceFactory
-
readonly IApplication application
The IApplication for the InstanceFactory
+
readonly IApplication application
The IApplication for the InstanceFactory
-
Repository(LibGit2Sharp.IRepository repository, IIOManager ioMananger, IEventConsumer eventConsumer, ICredentialsProvider credentialsProvider, ILogger< Repository > logger, Action onDispose)
Construct a Repository
Definition: Repository.cs:103
+
Repository(LibGit2Sharp.IRepository repository, IIOManager ioMananger, IEventConsumer eventConsumer, ICredentialsProvider credentialsProvider, ILogger< Repository > logger, Action onDispose)
Construct a Repository
Definition: Repository.cs:108
Contains various cryptographic functions
-
readonly IProcessExecutor processExecutor
The IProcessExecutor for the InstanceFactory
+
readonly IProcessExecutor processExecutor
The IProcessExecutor for the InstanceFactory
-
readonly INetworkPromptReaper networkPromptReaper
The INetworkPromptReaper for the InstanceFactory
-
readonly IPostWriteHandler postWriteHandler
The IPostWriteHandler for the InstanceFactory
+
readonly INetworkPromptReaper networkPromptReaper
The INetworkPromptReaper for the InstanceFactory
+
readonly IPostWriteHandler postWriteHandler
The IPostWriteHandler for the InstanceFactory
+
IWatchdog CreateWatchdog(IChat chat, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IEventConsumer eventConsumer, ISessionControllerFactory sessionControllerFactory, IIOManager ioManager, Api.Models.Instance instance, DreamDaemonSettings settings)
Creates a IWatchdog
For downloading and installing BYOND extractions for a given system
For accessing the disk in a synchronous manner
-
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the InstanceFactory
-
readonly IWatchdogFactory watchdogFactory
The IWatchdogFactory for the InstanceFactory
+
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the InstanceFactory
+
readonly IWatchdogFactory watchdogFactory
The IWatchdogFactory for the InstanceFactory
- +
Task CleanCache(CancellationToken cancellationToken)
Attempts to cleans the BYOND cache folder for the system
-
For interacting with the instance services
Definition: IInstance.cs:17
-
readonly ICredentialsProvider credentialsProvider
The ICredentialsProvider for the InstanceFactory
-
readonly IIOManager ioManager
The IIOManager for the InstanceFactory
-
readonly IGitHubClientFactory gitHubClientFactory
The IGitHubClientFactory for the InstanceFactory
-
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for the InstanceFactory
+
For interacting with the instance services
Definition: IInstance.cs:18
+
readonly ICredentialsProvider credentialsProvider
The ICredentialsProvider for the InstanceFactory
+ +
readonly IIOManager ioManager
The IIOManager for the InstanceFactory
+
readonly IGitHubClientFactory gitHubClientFactory
The IGitHubClientFactory for the InstanceFactory
+
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for the InstanceFactory
-
readonly ISymlinkFactory symlinkFactory
The ISymlinkFactory for the InstanceFactory
-
readonly IJobManager jobManager
The IJobManager for the InstanceFactory
-
readonly IChatFactory chatFactory
The IProviderFactory for the InstanceFactory
+
readonly ISymlinkFactory symlinkFactory
The ISymlinkFactory for the InstanceFactory
+
readonly IJobManager jobManager
The IJobManager for the InstanceFactory
+
readonly IChatFactory chatFactory
The IProviderFactory for the InstanceFactory
+
Manages the runtime of Jobs
Definition: IJobManager.cs:13
- + + -
IInstance CreateInstance(Models.Instance metadata)
Create an IInstance
+
IInstance CreateInstance(Models.Instance metadata)
Create an IInstance
Interface for using filesystems
Definition: IIOManager.cs:11
- +
On Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort()....
-
For identifying the current platform
- - + + +
For identifying the current platform
- + + +
diff --git a/_instance_manager_8cs_source.html b/_instance_manager_8cs_source.html index 53cb2755bb..81391619c0 100644 --- a/_instance_manager_8cs_source.html +++ b/_instance_manager_8cs_source.html @@ -71,50 +71,52 @@ $(function() {
InstanceManager.cs
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using Microsoft.Extensions.Hosting;
3 using Microsoft.Extensions.Logging;
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Threading;
8 using System.Threading.Tasks;
10 using Tgstation.Server.Host.IO;
11 
13 {
16  {
21 
26 
31 
36 
41 
46 
50  readonly ILogger<InstanceManager> logger;
51 
55  readonly Dictionary<long, IInstance> instances;
56 
61 
65  bool disposed;
66 
78  {
79  this.instanceFactory = instanceFactory ?? throw new ArgumentNullException(nameof(instanceFactory));
80  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
81  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
82  this.application = application ?? throw new ArgumentNullException(nameof(application));
83  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
84  this.serverControl = serverControl ?? throw new ArgumentNullException(nameof(serverControl));
85  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
86 
88 
89  instances = new Dictionary<long, IInstance>();
90  }
91 
93  public void Dispose()
94  {
95  lock (this)
96  {
97  if (disposed)
98  return;
99  disposed = true;
100  }
101 
102  foreach (var I in instances)
103  I.Value.Dispose();
104  }
105 
107  public IInstance GetInstance(Models.Instance metadata)
108  {
109  if (metadata == null)
110  throw new ArgumentNullException(nameof(metadata));
111  lock (this)
112  {
113  if (!instances.TryGetValue(metadata.Id, out IInstance instance))
114  throw new InvalidOperationException("Instance not online!");
115  return instance;
116  }
117  }
118 
120  public async Task MoveInstance(Models.Instance instance, string newPath, CancellationToken cancellationToken)
121  {
122  if (newPath == null)
123  throw new ArgumentNullException(nameof(newPath));
124  if (instance.Online.Value)
125  throw new InvalidOperationException("Cannot move an online instance!");
126  var oldPath = instance.Path;
127  await ioManager.CopyDirectory(oldPath, newPath, null, cancellationToken).ConfigureAwait(false);
129  {
130  var targetInstance = new Models.Instance
131  {
132  Id = instance.Id
133  };
134  db.Instances.Attach(targetInstance);
135  targetInstance.Path = newPath;
136  return db.Save(cancellationToken);
137  }).ConfigureAwait(false);
138  await ioManager.DeleteDirectory(oldPath, cancellationToken).ConfigureAwait(false);
139  }
140 
142  public async Task OfflineInstance(Models.Instance metadata, Models.User user, CancellationToken cancellationToken)
143  {
144  if (metadata == null)
145  throw new ArgumentNullException(nameof(metadata));
146  logger.LogInformation("Offlining instance ID {0}", metadata.Id);
147  IInstance instance;
148  lock (this)
149  {
150  if (!instances.TryGetValue(metadata.Id, out instance))
151  throw new InvalidOperationException("Instance not online!");
152  instances.Remove(metadata.Id);
153  }
154 
155  try
156  {
157  // we are the one responsible for cancelling his jobs
158  var tasks = new List<Task>();
159  await databaseContextFactory.UseContext(async db =>
160  {
161  var jobs = db.Jobs.Where(x => x.Instance.Id == metadata.Id).Select(x => new Models.Job
162  {
163  Id = x.Id
164  }).ToAsyncEnumerable();
165  await jobs.ForEachAsync(job =>
166  {
167  lock (tasks)
168  tasks.Add(jobManager.CancelJob(job, user, true, cancellationToken));
169  }, cancellationToken).ConfigureAwait(false);
170  }).ConfigureAwait(false);
171 
172  await Task.WhenAll(tasks).ConfigureAwait(false);
173 
174  await instance.StopAsync(cancellationToken).ConfigureAwait(false);
175  }
176  finally
177  {
178  instance.Dispose();
179  }
180  }
181 
183  public async Task OnlineInstance(Models.Instance metadata, CancellationToken cancellationToken)
184  {
185  if (metadata == null)
186  throw new ArgumentNullException(nameof(metadata));
187  logger.LogInformation("Onlining instance ID {0} ({1}) at {2}", metadata.Id, metadata.Name, metadata.Path);
188  var instance = instanceFactory.CreateInstance(metadata);
189  try
190  {
191  lock (this)
192  {
193  if (instances.ContainsKey(metadata.Id))
194  throw new InvalidOperationException("Instance already online!");
195  instances.Add(metadata.Id, instance);
196  }
197  }
198  catch
199  {
200  instance.Dispose();
201  throw;
202  }
203 
204  await instance.StartAsync(cancellationToken).ConfigureAwait(false);
205  }
206 
208  #pragma warning disable CA1506 // TODO: Decomplexify
209  public Task StartAsync(CancellationToken cancellationToken) => databaseContextFactory.UseContext(async databaseContext =>
210  {
211  try
212  {
213  var factoryStartup = instanceFactory.StartAsync(cancellationToken);
214  await databaseContext.Initialize(cancellationToken).ConfigureAwait(false);
215  await jobManager.StartAsync(cancellationToken).ConfigureAwait(false);
216  var dbInstances = databaseContext.Instances.Where(x => x.Online.Value)
217  .Include(x => x.RepositorySettings)
218  .Include(x => x.ChatSettings)
219  .ThenInclude(x => x.Channels)
220  .Include(x => x.DreamDaemonSettings)
221  .ToAsyncEnumerable();
222  var tasks = new List<Task>();
223  await factoryStartup.ConfigureAwait(false);
224  await dbInstances.ForEachAsync(metadata => tasks.Add(metadata.Online.Value ? OnlineInstance(metadata, cancellationToken) : Task.CompletedTask), cancellationToken).ConfigureAwait(false);
225  await Task.WhenAll(tasks).ConfigureAwait(false);
226  logger.LogInformation("Server ready!");
227  application.Ready(null);
228  }
229  catch (OperationCanceledException)
230  {
231  logger.LogInformation("Cancelled instance manager initialization!");
232  }
233  catch (Exception e)
234  {
235  logger.LogCritical("Instance manager startup error! Exception: {0}", e);
236  application.Ready(e);
237  try
238  {
239  await serverControl.Die(e).ConfigureAwait(false);
240  }
241  catch (Exception e2)
242  {
243  logger.LogCritical("Failed to kill server! Exception: {0}", e2);
244  }
245  }
246  });
247  #pragma warning restore CA1506 // TODO: Decomplexify
248 
250  public async Task StopAsync(CancellationToken cancellationToken)
251  {
252  await jobManager.StopAsync(cancellationToken).ConfigureAwait(false);
253  await Task.WhenAll(instances.Select(x => x.Value.StopAsync(cancellationToken))).ConfigureAwait(false);
254  await instanceFactory.StopAsync(cancellationToken).ConfigureAwait(false);
255 
256  // downgrade the db if necessary
257  if (downgradeVersion != null)
258  await databaseContextFactory.UseContext(db => db.SchemaDowngradeForServerVersion(downgradeVersion, cancellationToken)).ConfigureAwait(false);
259  }
260 
262  public Task HandleRestart(Version updateVersion, CancellationToken cancellationToken)
263  {
264  downgradeVersion = updateVersion != null && updateVersion < application.Version ? updateVersion : null;
265  return Task.CompletedTask;
266  }
267  }
268 }
Manages the runtime of Jobs
Definition: IJobManager.cs:12
-
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
-
readonly IServerControl serverControl
The IServerControl for the InstanceManager
-
IInstance GetInstance(Models.Instance metadata)
Get the IInstance associated with given metadata
+Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using Microsoft.Extensions.Hosting;
3 using Microsoft.Extensions.Logging;
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Threading;
8 using System.Threading.Tasks;
11 using Tgstation.Server.Host.IO;
13 
15 {
18  {
23 
28 
33 
38 
43 
48 
52  readonly ILogger<InstanceManager> logger;
53 
57  readonly Dictionary<long, IInstance> instances;
58 
63 
67  bool disposed;
68 
80  {
81  this.instanceFactory = instanceFactory ?? throw new ArgumentNullException(nameof(instanceFactory));
82  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
83  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
84  this.application = application ?? throw new ArgumentNullException(nameof(application));
85  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
86  this.serverControl = serverControl ?? throw new ArgumentNullException(nameof(serverControl));
87  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
88 
90 
91  instances = new Dictionary<long, IInstance>();
92  }
93 
95  public void Dispose()
96  {
97  lock (this)
98  {
99  if (disposed)
100  return;
101  disposed = true;
102  }
103 
104  foreach (var I in instances)
105  I.Value.Dispose();
106  }
107 
109  public IInstance GetInstance(Models.Instance metadata)
110  {
111  if (metadata == null)
112  throw new ArgumentNullException(nameof(metadata));
113  lock (this)
114  {
115  if (!instances.TryGetValue(metadata.Id, out IInstance instance))
116  throw new InvalidOperationException("Instance not online!");
117  return instance;
118  }
119  }
120 
122  public async Task MoveInstance(Models.Instance instance, string newPath, CancellationToken cancellationToken)
123  {
124  if (newPath == null)
125  throw new ArgumentNullException(nameof(newPath));
126  if (instance.Online.Value)
127  throw new InvalidOperationException("Cannot move an online instance!");
128  var oldPath = instance.Path;
129  await ioManager.CopyDirectory(oldPath, newPath, null, cancellationToken).ConfigureAwait(false);
131  {
132  var targetInstance = new Models.Instance
133  {
134  Id = instance.Id
135  };
136  db.Instances.Attach(targetInstance);
137  targetInstance.Path = newPath;
138  return db.Save(cancellationToken);
139  }).ConfigureAwait(false);
140  await ioManager.DeleteDirectory(oldPath, cancellationToken).ConfigureAwait(false);
141  }
142 
144  public async Task OfflineInstance(Models.Instance metadata, Models.User user, CancellationToken cancellationToken)
145  {
146  if (metadata == null)
147  throw new ArgumentNullException(nameof(metadata));
148  logger.LogInformation("Offlining instance ID {0}", metadata.Id);
149  IInstance instance;
150  lock (this)
151  {
152  if (!instances.TryGetValue(metadata.Id, out instance))
153  throw new InvalidOperationException("Instance not online!");
154  instances.Remove(metadata.Id);
155  }
156 
157  try
158  {
159  // we are the one responsible for cancelling his jobs
160  var tasks = new List<Task>();
161  await databaseContextFactory.UseContext(async db =>
162  {
163  var jobs = db.Jobs.Where(x => x.Instance.Id == metadata.Id).Select(x => new Models.Job
164  {
165  Id = x.Id
166  }).ToAsyncEnumerable();
167  await jobs.ForEachAsync(job =>
168  {
169  lock (tasks)
170  tasks.Add(jobManager.CancelJob(job, user, true, cancellationToken));
171  }, cancellationToken).ConfigureAwait(false);
172  }).ConfigureAwait(false);
173 
174  await Task.WhenAll(tasks).ConfigureAwait(false);
175 
176  await instance.StopAsync(cancellationToken).ConfigureAwait(false);
177  }
178  finally
179  {
180  instance.Dispose();
181  }
182  }
183 
185  public async Task OnlineInstance(Models.Instance metadata, CancellationToken cancellationToken)
186  {
187  if (metadata == null)
188  throw new ArgumentNullException(nameof(metadata));
189  logger.LogInformation("Onlining instance ID {0} ({1}) at {2}", metadata.Id, metadata.Name, metadata.Path);
190  var instance = instanceFactory.CreateInstance(metadata);
191  try
192  {
193  lock (this)
194  {
195  if (instances.ContainsKey(metadata.Id))
196  throw new InvalidOperationException("Instance already online!");
197  instances.Add(metadata.Id, instance);
198  }
199  }
200  catch
201  {
202  instance.Dispose();
203  throw;
204  }
205 
206  await instance.StartAsync(cancellationToken).ConfigureAwait(false);
207  }
208 
210  #pragma warning disable CA1506 // TODO: Decomplexify
211  public Task StartAsync(CancellationToken cancellationToken) => databaseContextFactory.UseContext(async databaseContext =>
212  {
213  try
214  {
215  var factoryStartup = instanceFactory.StartAsync(cancellationToken);
216  await databaseContext.Initialize(cancellationToken).ConfigureAwait(false);
217  await jobManager.StartAsync(cancellationToken).ConfigureAwait(false);
218  var dbInstances = databaseContext.Instances.Where(x => x.Online.Value)
219  .Include(x => x.RepositorySettings)
220  .Include(x => x.ChatSettings)
221  .ThenInclude(x => x.Channels)
222  .Include(x => x.DreamDaemonSettings)
223  .ToAsyncEnumerable();
224  var tasks = new List<Task>();
225  await factoryStartup.ConfigureAwait(false);
226  await dbInstances.ForEachAsync(metadata => tasks.Add(metadata.Online.Value ? OnlineInstance(metadata, cancellationToken) : Task.CompletedTask), cancellationToken).ConfigureAwait(false);
227  await Task.WhenAll(tasks).ConfigureAwait(false);
228  logger.LogInformation("Server ready!");
229  application.Ready(null);
230  }
231  catch (OperationCanceledException)
232  {
233  logger.LogInformation("Cancelled instance manager initialization!");
234  }
235  catch (Exception e)
236  {
237  logger.LogCritical("Instance manager startup error! Exception: {0}", e);
238  application.Ready(e);
239  try
240  {
241  await serverControl.Die(e).ConfigureAwait(false);
242  }
243  catch (Exception e2)
244  {
245  logger.LogCritical("Failed to kill server! Exception: {0}", e2);
246  }
247  }
248  });
249  #pragma warning restore CA1506 // TODO: Decomplexify
250 
252  public async Task StopAsync(CancellationToken cancellationToken)
253  {
254  await jobManager.StopAsync(cancellationToken).ConfigureAwait(false);
255  await Task.WhenAll(instances.Select(x => x.Value.StopAsync(cancellationToken))).ConfigureAwait(false);
256  await instanceFactory.StopAsync(cancellationToken).ConfigureAwait(false);
257 
258  // downgrade the db if necessary
259  if (downgradeVersion != null)
260  await databaseContextFactory.UseContext(db => db.SchemaDowngradeForServerVersion(downgradeVersion, cancellationToken)).ConfigureAwait(false);
261  }
262 
264  public Task HandleRestart(Version updateVersion, CancellationToken cancellationToken)
265  {
266  downgradeVersion = updateVersion != null && updateVersion < application.Version ? updateVersion : null;
267  return Task.CompletedTask;
268  }
269  }
270 }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory, removes and does not enter any symlinks encounterd.
+
readonly IServerControl serverControl
The IServerControl for the InstanceManager
+
IInstance GetInstance(Models.Instance metadata)
Get the IInstance associated with given metadata
IInstance CreateInstance(Models.Instance metadata)
Create an IInstance
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
Task CopyDirectory(string src, string dest, IEnumerable< string > ignore, CancellationToken cancellationToken)
Copies a directory from src to dest
-
async Task OnlineInstance(Models.Instance metadata, CancellationToken cancellationToken)
Online an IInstance
+
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
+
async Task OnlineInstance(Models.Instance metadata, CancellationToken cancellationToken)
Online an IInstance
Task Die(Exception exception)
Kill the server with a fatal exception
-
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
-
bool disposed
If the InstanceManager has been Disposed
-
Task HandleRestart(Version updateVersion, CancellationToken cancellationToken)
Handle a restart of the server
-
async Task OfflineInstance(Models.Instance metadata, Models.User user, CancellationToken cancellationToken)
+
bool disposed
If the InstanceManager has been Disposed
+
Task< bool > CancelJob(Job job, User user, bool blocking, CancellationToken cancellationToken)
Cancels a give job
+
Task HandleRestart(Version updateVersion, CancellationToken cancellationToken)
Handle a restart of the server
+
async Task OfflineInstance(Models.Instance metadata, Models.User user, CancellationToken cancellationToken)
Task StartAsync(CancellationToken cancellationToken)
-
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the InstanceManager
-
readonly IJobManager jobManager
The IJobManager for the InstanceManager
+
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the InstanceManager
+
readonly IJobManager jobManager
The IJobManager for the InstanceManager
-
Version downgradeVersion
Used in StopAsync(CancellationToken) to determine if database downgrades must be made
+
Version downgradeVersion
Used in StopAsync(CancellationToken) to determine if database downgrades must be made
void Ready(Exception initializationError)
Mark the IApplication as ready to run
-
For interacting with the instance services
Definition: IInstance.cs:17
- -
async Task StopAsync(CancellationToken cancellationToken)
- -
readonly ILogger< InstanceManager > logger
The ILogger for the InstanceManager
-
Task< bool > CancelJob(Job job, User user, bool blocking, CancellationToken cancellationToken)
Cancels a give job
+
For interacting with the instance services
Definition: IInstance.cs:18
+ +
async Task StopAsync(CancellationToken cancellationToken)
+ +
readonly ILogger< InstanceManager > logger
The ILogger for the InstanceManager
+
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
-
readonly IInstanceFactory instanceFactory
The IInstanceFactory for the InstanceManager
+
readonly IInstanceFactory instanceFactory
The IInstanceFactory for the InstanceManager
+
Manages the runtime of Jobs
Definition: IJobManager.cs:13
-
readonly Dictionary< long, IInstance > instances
Map of Api.Models.Instance.Ids to respective IInstances
+ +
readonly Dictionary< long, IInstance > instances
Map of Api.Models.Instance.Ids to respective IInstances
-
readonly IApplication application
The IApplication for the InstanceManager
-
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
+
readonly IApplication application
The IApplication for the InstanceManager
-
readonly IIOManager ioManager
The IIOManager for the InstanceManager
+
readonly IIOManager ioManager
The IIOManager for the InstanceManager
Interface for using filesystems
Definition: IIOManager.cs:11
-
async Task MoveInstance(Models.Instance instance, string newPath, CancellationToken cancellationToken)
Move an IInstance
+
async Task MoveInstance(Models.Instance instance, string newPath, CancellationToken cancellationToken)
Move an IInstance
IRestartRegistration RegisterForRestart(IRestartHandler handler)
Register a given handler to run before stopping the server for a restart
Version Version
The version of the Application
Definition: IApplication.cs:23
+ -
InstanceManager(IInstanceFactory instanceFactory, IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, IApplication application, IJobManager jobManager, IServerControl serverControl, ILogger< InstanceManager > logger)
Construct an InstanceManager
+
InstanceManager(IInstanceFactory instanceFactory, IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, IApplication application, IJobManager jobManager, IServerControl serverControl, ILogger< InstanceManager > logger)
Construct an InstanceManager
Represents a service that may take an updated Host assembly and run it, stopping the current assembly...
diff --git a/_instance_manager_test_8cs_source.html b/_instance_manager_test_8cs_source.html index c21f59a4d7..6011324a6b 100644 --- a/_instance_manager_test_8cs_source.html +++ b/_instance_manager_test_8cs_source.html @@ -71,7 +71,7 @@ $(function() {
InstanceManagerTest.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.IO;
4 using System.Reflection;
5 using System.Threading;
6 using System.Threading.Tasks;
11 
12 namespace Tgstation.Server.Tests
13 {
14  sealed class InstanceManagerTest
15  {
17  readonly string testRootPath;
18 
19  long counter;
20 
22  {
23  this.instanceManagerClient = instanceManagerClient ?? throw new ArgumentNullException(nameof(instanceManagerClient));
24  this.testRootPath = testRootPath ?? throw new ArgumentNullException(nameof(testRootPath));
25 
26  counter = 0;
27  }
28 
29  Task<Api.Models.Instance> CreateTestInstance(CancellationToken cancellationToken) => instanceManagerClient.CreateOrAttach(new Api.Models.Instance
30  {
31  Name = "TestInstance-" + ++counter,
32  Path = Path.Combine(testRootPath, Guid.NewGuid().ToString()),
33  Online = true
34  }, cancellationToken);
35 
36  public async Task Run(CancellationToken cancellationToken)
37  {
38  var firstTest = await CreateTestInstance(cancellationToken).ConfigureAwait(false);
39  //instances always start offline
40  Assert.AreEqual(false, firstTest.Online);
41  //check it exists
42  Assert.IsTrue(Directory.Exists(firstTest.Path));
43 
44  //cant create instances in existent directories
45  var testNonEmpty = Path.Combine(testRootPath, Guid.NewGuid().ToString());
46  Directory.CreateDirectory(testNonEmpty);
47  await Assert.ThrowsExceptionAsync<ConflictException>(() => instanceManagerClient.CreateOrAttach(new Api.Models.Instance
48  {
49  Path = testNonEmpty,
50  Name = "NonEmptyTest"
51  }, cancellationToken)).ConfigureAwait(false);
52  await Assert.ThrowsExceptionAsync<ConflictException>(() => instanceManagerClient.CreateOrAttach(firstTest, cancellationToken)).ConfigureAwait(false);
53 
54  //can't create instances in installation directory
55  await Assert.ThrowsExceptionAsync<ConflictException>(() => instanceManagerClient.CreateOrAttach(new Api.Models.Instance
56  {
57  Path = "./A/Local/Path",
58  Name = "NoInstallDirTest"
59  }, cancellationToken)).ConfigureAwait(false);
60 
61  //can't move to existent directories
62  await Assert.ThrowsExceptionAsync<ConflictException>(() => instanceManagerClient.Update(new Api.Models.Instance
63  {
64  Id = firstTest.Id,
65  Path = testNonEmpty
66  }, cancellationToken)).ConfigureAwait(false);
67 
68  //test basic move
69  Directory.Delete(testNonEmpty);
70  var initialPath = firstTest.Path;
71  firstTest = await instanceManagerClient.Update(new Api.Models.Instance
72  {
73  Id = firstTest.Id,
74  Path = testNonEmpty
75  }, cancellationToken).ConfigureAwait(false);
76 
77  Assert.IsNotNull(firstTest.MoveJob);
78 
79  do
80  {
81  firstTest = await instanceManagerClient.GetId(firstTest, cancellationToken).ConfigureAwait(false);
82  await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
83  } while (firstTest.MoveJob != null);
84 
85 
86  //online it for real for component tests
87  firstTest.Online = true;
88  firstTest.ConfigurationType = ConfigurationType.HostWrite;
89  firstTest = await instanceManagerClient.Update(firstTest, cancellationToken).ConfigureAwait(false);
90  Assert.AreEqual(true, firstTest.Online);
91  Assert.AreEqual(ConfigurationType.HostWrite, firstTest.ConfigurationType);
92 
93  //can't move online instance
94  await Assert.ThrowsExceptionAsync<ConflictException>(() => instanceManagerClient.Update(new Api.Models.Instance
95  {
96  Id = firstTest.Id,
97  Path = initialPath
98  }, cancellationToken)).ConfigureAwait(false);
99 
100  var testSuite1 = new InstanceTest(instanceManagerClient.CreateClient(firstTest));
101  await testSuite1.RunTests(cancellationToken).ConfigureAwait(false);
102 
103  //can regain permissions on instance without instance user
104  var instanceClient = instanceManagerClient.CreateClient(firstTest);
105  var ourInstanceUser = await instanceClient.Users.Read(cancellationToken).ConfigureAwait(false);
106  await instanceClient.Users.Delete(ourInstanceUser, cancellationToken).ConfigureAwait(false);
107 
108  await Assert.ThrowsExceptionAsync<InsufficientPermissionsException>(() => instanceClient.Users.Read(cancellationToken)).ConfigureAwait(false);
109 
110  await instanceManagerClient.Update(new Api.Models.Instance
111  {
112  Id = firstTest.Id
113  }, cancellationToken).ConfigureAwait(false);
114  ourInstanceUser = await instanceClient.Users.Read(cancellationToken).ConfigureAwait(false);
115 
116  //can't detach online instance
117  await Assert.ThrowsExceptionAsync<ConflictException>(() => instanceManagerClient.Detach(firstTest, cancellationToken)).ConfigureAwait(false);
118 
119  firstTest.Online = false;
120  firstTest = await instanceManagerClient.Update(firstTest, cancellationToken).ConfigureAwait(false);
121  await instanceManagerClient.Detach(firstTest, cancellationToken).ConfigureAwait(false);
122 
123  var instanceAttachFileName = (string)typeof(InstanceController).GetField("InstanceAttachFileName", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
124  var attachPath = Path.Combine(firstTest.Path, instanceAttachFileName);
125  Assert.IsTrue(File.Exists(attachPath));
126 
127  //can recreate detached instance
128  firstTest = await instanceManagerClient.CreateOrAttach(firstTest, cancellationToken).ConfigureAwait(false);
129 
130  //but only if the attach file exists
131  await instanceManagerClient.Detach(firstTest, cancellationToken).ConfigureAwait(false);
132  File.Delete(attachPath);
133  await Assert.ThrowsExceptionAsync<ConflictException>(() => instanceManagerClient.CreateOrAttach(firstTest, cancellationToken)).ConfigureAwait(false);
134  }
135  }
136 }
+Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.IO;
4 using System.Reflection;
5 using System.Threading;
6 using System.Threading.Tasks;
11 
12 namespace Tgstation.Server.Tests
13 {
14  sealed class InstanceManagerTest
15  {
17  readonly string testRootPath;
18 
19  long counter;
20 
22  {
23  this.instanceManagerClient = instanceManagerClient ?? throw new ArgumentNullException(nameof(instanceManagerClient));
24  this.testRootPath = testRootPath ?? throw new ArgumentNullException(nameof(testRootPath));
25 
26  counter = 0;
27  }
28 
29  Task<Api.Models.Instance> CreateTestInstance(CancellationToken cancellationToken) => instanceManagerClient.CreateOrAttach(new Api.Models.Instance
30  {
31  Name = "TestInstance-" + ++counter,
32  Path = Path.Combine(testRootPath, Guid.NewGuid().ToString()),
33  Online = true
34  }, cancellationToken);
35 
36  public async Task Run(CancellationToken cancellationToken)
37  {
38  var firstTest = await CreateTestInstance(cancellationToken).ConfigureAwait(false);
39  //instances always start offline
40  Assert.AreEqual(false, firstTest.Online);
41  //check it exists
42  Assert.IsTrue(Directory.Exists(firstTest.Path));
43 
44  //cant create instances in existent directories
45  var testNonEmpty = Path.Combine(testRootPath, Guid.NewGuid().ToString());
46  Directory.CreateDirectory(testNonEmpty);
47  await Assert.ThrowsExceptionAsync<ConflictException>(() => instanceManagerClient.CreateOrAttach(new Api.Models.Instance
48  {
49  Path = testNonEmpty,
50  Name = "NonEmptyTest"
51  }, cancellationToken)).ConfigureAwait(false);
52  await Assert.ThrowsExceptionAsync<ConflictException>(() => instanceManagerClient.CreateOrAttach(firstTest, cancellationToken)).ConfigureAwait(false);
53 
54  //can't create instances in installation directory
55  await Assert.ThrowsExceptionAsync<ConflictException>(() => instanceManagerClient.CreateOrAttach(new Api.Models.Instance
56  {
57  Path = "./A/Local/Path",
58  Name = "NoInstallDirTest"
59  }, cancellationToken)).ConfigureAwait(false);
60 
61  //can't move to existent directories
62  await Assert.ThrowsExceptionAsync<ConflictException>(() => instanceManagerClient.Update(new Api.Models.Instance
63  {
64  Id = firstTest.Id,
65  Path = testNonEmpty
66  }, cancellationToken)).ConfigureAwait(false);
67 
68  //test basic move
69  Directory.Delete(testNonEmpty);
70  var initialPath = firstTest.Path;
71  firstTest = await instanceManagerClient.Update(new Api.Models.Instance
72  {
73  Id = firstTest.Id,
74  Path = testNonEmpty
75  }, cancellationToken).ConfigureAwait(false);
76 
77  Assert.IsNotNull(firstTest.MoveJob);
78 
79  do
80  {
81  firstTest = await instanceManagerClient.GetId(firstTest, cancellationToken).ConfigureAwait(false);
82  await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
83  } while (firstTest.MoveJob != null);
84 
85 
86  //online it for real for component tests
87  firstTest.Online = true;
88  firstTest.ConfigurationType = ConfigurationType.HostWrite;
89  firstTest = await instanceManagerClient.Update(firstTest, cancellationToken).ConfigureAwait(false);
90  Assert.AreEqual(true, firstTest.Online);
91  Assert.AreEqual(ConfigurationType.HostWrite, firstTest.ConfigurationType);
92 
93  //can't move online instance
94  await Assert.ThrowsExceptionAsync<ConflictException>(() => instanceManagerClient.Update(new Api.Models.Instance
95  {
96  Id = firstTest.Id,
97  Path = initialPath
98  }, cancellationToken)).ConfigureAwait(false);
99 
100  var testSuite1 = new InstanceTest(instanceManagerClient.CreateClient(firstTest));
101  await testSuite1.RunTests(cancellationToken).ConfigureAwait(false);
102 
103  //can regain permissions on instance without instance user
104  var instanceClient = instanceManagerClient.CreateClient(firstTest);
105  var ourInstanceUser = await instanceClient.Users.Read(cancellationToken).ConfigureAwait(false);
106  await instanceClient.Users.Delete(ourInstanceUser, cancellationToken).ConfigureAwait(false);
107 
108  await Assert.ThrowsExceptionAsync<InsufficientPermissionsException>(() => instanceClient.Users.Read(cancellationToken)).ConfigureAwait(false);
109 
110  await instanceManagerClient.Update(new Api.Models.Instance
111  {
112  Id = firstTest.Id
113  }, cancellationToken).ConfigureAwait(false);
114  ourInstanceUser = await instanceClient.Users.Read(cancellationToken).ConfigureAwait(false);
115 
116  //can't detach online instance
117  await Assert.ThrowsExceptionAsync<ConflictException>(() => instanceManagerClient.Detach(firstTest, cancellationToken)).ConfigureAwait(false);
118 
119  firstTest.Online = false;
120  firstTest = await instanceManagerClient.Update(firstTest, cancellationToken).ConfigureAwait(false);
121  await instanceManagerClient.Detach(firstTest, cancellationToken).ConfigureAwait(false);
122 
123  var instanceAttachFileName = (string)typeof(InstanceController).GetField("InstanceAttachFileName", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);
124  var attachPath = Path.Combine(firstTest.Path, instanceAttachFileName);
125  Assert.IsTrue(File.Exists(attachPath));
126 
127  //can recreate detached instance
128  firstTest = await instanceManagerClient.CreateOrAttach(firstTest, cancellationToken).ConfigureAwait(false);
129 
130  //but only if the attach file exists
131  await instanceManagerClient.Detach(firstTest, cancellationToken).ConfigureAwait(false);
132  File.Delete(attachPath);
133  await Assert.ThrowsExceptionAsync<ConflictException>(() => instanceManagerClient.CreateOrAttach(firstTest, cancellationToken)).ConfigureAwait(false);
134  }
135  }
136 }
async Task RunTests(CancellationToken cancellationToken)
Definition: InstanceTest.cs:17
@@ -81,7 +81,7 @@ $(function() {
IInstanceClient CreateClient(Instance instance)
Create an IInstanceClient for a given Instance
ConfigurationType
The type of configuration allowed on an Instance
-
ApiController for managing Components.Instances
+
ApiController for managing Components.Instances
async Task Run(CancellationToken cancellationToken)
Task< Instance > GetId(Instance instance, CancellationToken cancellationToken)
Get a specific instance
diff --git a/_instance_user_controller_8cs_source.html b/_instance_user_controller_8cs_source.html index 440f2f8ed9..343773044b 100644 --- a/_instance_user_controller_8cs_source.html +++ b/_instance_user_controller_8cs_source.html @@ -71,50 +71,51 @@ $(function() {
InstanceUserController.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.EntityFrameworkCore;
3 using Microsoft.Extensions.Logging;
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Net;
8 using System.Threading;
9 using System.Threading.Tasks;
10 using Tgstation.Server.Api;
15 using Z.EntityFramework.Plus;
16 
18 {
22  [Route(Routes.InstanceUser)]
23  public sealed class InstanceUserController : ApiController
24  {
31  public InstanceUserController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ILogger<InstanceUserController> logger) : base(databaseContext, authenticationContextFactory, logger, true, true)
32  { }
33 
39  BadRequestObjectResult StandardModelChecks(Api.Models.InstanceUser model)
40  {
41  if (model == null)
42  throw new ArgumentNullException(nameof(model));
43 
44  if (!model.UserId.HasValue)
45  return BadRequest(new ErrorMessage { Message = "Missing UserId!" });
46 
47  return null;
48  }
49 
57  [HttpPut]
58  [TgsAuthorize(InstanceUserRights.CreateUsers)]
59  [ProducesResponseType(typeof(Api.Models.InstanceUser), 201)]
60  public async Task<IActionResult> Create([FromBody] Api.Models.InstanceUser model, CancellationToken cancellationToken)
61  {
62  var test = StandardModelChecks(model);
63  if (test != null)
64  return test;
65 
66  var dbUser = new Models.InstanceUser
67  {
68  ByondRights = model.ByondRights ?? ByondRights.None,
69  ChatBotRights = model.ChatBotRights ?? ChatBotRights.None,
70  ConfigurationRights = model.ConfigurationRights ?? ConfigurationRights.None,
71  DreamDaemonRights = model.DreamDaemonRights ?? DreamDaemonRights.None,
72  DreamMakerRights = model.DreamMakerRights ?? DreamMakerRights.None,
73  RepositoryRights = model.RepositoryRights ?? RepositoryRights.None,
74  InstanceUserRights = model.InstanceUserRights ?? InstanceUserRights.None,
75  UserId = model.UserId,
76  InstanceId = Instance.Id
77  };
78 
79  DatabaseContext.InstanceUsers.Add(dbUser);
80 
81  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
82  return StatusCode((int)HttpStatusCode.Created, dbUser.ToApi());
83  }
84 
93  [HttpPost]
94  [TgsAuthorize(InstanceUserRights.WriteUsers)]
95  [ProducesResponseType(typeof(Api.Models.InstanceUser), 200)]
96  [ProducesResponseType(410)]
97  #pragma warning disable CA1506 // TODO: Decomplexify
98  public async Task<IActionResult> Update([FromBody] Api.Models.InstanceUser model, CancellationToken cancellationToken)
99  {
100  var test = StandardModelChecks(model);
101  if (test != null)
102  return test;
103 
104  var originalUser = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).Where(x => x.UserId == model.UserId).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
105  if (originalUser == null)
106  return StatusCode((int)HttpStatusCode.Gone);
107 
108  originalUser.ByondRights = model.ByondRights ?? originalUser.ByondRights;
109  originalUser.RepositoryRights = model.RepositoryRights ?? originalUser.RepositoryRights;
110  originalUser.InstanceUserRights = model.InstanceUserRights ?? originalUser.InstanceUserRights;
111  originalUser.ChatBotRights = model.ChatBotRights ?? originalUser.ChatBotRights;
112  originalUser.ConfigurationRights = model.ConfigurationRights ?? originalUser.ConfigurationRights;
113  originalUser.DreamDaemonRights = model.DreamDaemonRights ?? originalUser.DreamDaemonRights;
114  originalUser.DreamMakerRights = model.DreamMakerRights ?? originalUser.DreamMakerRights;
115 
116  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
117  return Json(originalUser.UserId == AuthenticationContext.User.Id || (AuthenticationContext.GetRight(RightsType.InstanceUser) & (ulong)InstanceUserRights.ReadUsers) != 0 ? originalUser.ToApi() : new Api.Models.InstanceUser
118  {
119  UserId = originalUser.UserId
120  });
121  }
122 #pragma warning restore CA1506
123  [HttpGet]
129  [TgsAuthorize]
130  [ProducesResponseType(typeof(Api.Models.InstanceUser), 200)]
131  public IActionResult Read() => Json(AuthenticationContext.InstanceUser.ToApi());
132 
139  [HttpGet(Routes.List)]
140  [TgsAuthorize(InstanceUserRights.ReadUsers)]
141  [ProducesResponseType(typeof(IEnumerable<Api.Models.InstanceUser>), 200)]
142  public async Task<IActionResult> List(CancellationToken cancellationToken)
143  {
144  var users = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).ToListAsync(cancellationToken).ConfigureAwait(false);
145  return Json(users.Select(x => x.ToApi()));
146  }
147 
156  [HttpGet("{id}")]
157  [TgsAuthorize(InstanceUserRights.ReadUsers)]
158  [ProducesResponseType(typeof(Api.Models.InstanceUser), 200)]
159  [ProducesResponseType(410)]
160  public async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
161  {
162  // this functions as userId
163  var user = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).Where(x => x.UserId == id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
164  if (user == default)
165  return StatusCode((int)HttpStatusCode.Gone);
166  return Json(user.ToApi());
167  }
168 
176  [HttpDelete("{id}")]
177  [TgsAuthorize(InstanceUserRights.WriteUsers)]
178  [ProducesResponseType(200)]
179  public async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
180  {
181  await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).Where(x => x.UserId == id).DeleteAsync(cancellationToken).ConfigureAwait(false);
182  return Ok();
183  }
184  }
185 }
InstanceUserController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ILogger< InstanceUserController > logger)
Construct a UserController
- +Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.EntityFrameworkCore;
3 using Microsoft.Extensions.Logging;
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Net;
8 using System.Threading;
9 using System.Threading.Tasks;
10 using Tgstation.Server.Api;
16 using Z.EntityFramework.Plus;
17 
19 {
23  [Route(Routes.InstanceUser)]
24  public sealed class InstanceUserController : ApiController
25  {
32  public InstanceUserController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ILogger<InstanceUserController> logger) : base(databaseContext, authenticationContextFactory, logger, true, true)
33  { }
34 
40  BadRequestObjectResult StandardModelChecks(Api.Models.InstanceUser model)
41  {
42  if (model == null)
43  throw new ArgumentNullException(nameof(model));
44 
45  if (!model.UserId.HasValue)
46  return BadRequest(new ErrorMessage { Message = "Missing UserId!" });
47 
48  return null;
49  }
50 
58  [HttpPut]
59  [TgsAuthorize(InstanceUserRights.CreateUsers)]
60  [ProducesResponseType(typeof(Api.Models.InstanceUser), 201)]
61  public async Task<IActionResult> Create([FromBody] Api.Models.InstanceUser model, CancellationToken cancellationToken)
62  {
63  var test = StandardModelChecks(model);
64  if (test != null)
65  return test;
66 
67  var dbUser = new Models.InstanceUser
68  {
69  ByondRights = model.ByondRights ?? ByondRights.None,
70  ChatBotRights = model.ChatBotRights ?? ChatBotRights.None,
71  ConfigurationRights = model.ConfigurationRights ?? ConfigurationRights.None,
72  DreamDaemonRights = model.DreamDaemonRights ?? DreamDaemonRights.None,
73  DreamMakerRights = model.DreamMakerRights ?? DreamMakerRights.None,
74  RepositoryRights = model.RepositoryRights ?? RepositoryRights.None,
75  InstanceUserRights = model.InstanceUserRights ?? InstanceUserRights.None,
76  UserId = model.UserId,
77  InstanceId = Instance.Id
78  };
79 
80  DatabaseContext.InstanceUsers.Add(dbUser);
81 
82  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
83  return StatusCode((int)HttpStatusCode.Created, dbUser.ToApi());
84  }
85 
94  [HttpPost]
95  [TgsAuthorize(InstanceUserRights.WriteUsers)]
96  [ProducesResponseType(typeof(Api.Models.InstanceUser), 200)]
97  [ProducesResponseType(410)]
98  #pragma warning disable CA1506 // TODO: Decomplexify
99  public async Task<IActionResult> Update([FromBody] Api.Models.InstanceUser model, CancellationToken cancellationToken)
100  {
101  var test = StandardModelChecks(model);
102  if (test != null)
103  return test;
104 
105  var originalUser = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).Where(x => x.UserId == model.UserId).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
106  if (originalUser == null)
107  return StatusCode((int)HttpStatusCode.Gone);
108 
109  originalUser.ByondRights = model.ByondRights ?? originalUser.ByondRights;
110  originalUser.RepositoryRights = model.RepositoryRights ?? originalUser.RepositoryRights;
111  originalUser.InstanceUserRights = model.InstanceUserRights ?? originalUser.InstanceUserRights;
112  originalUser.ChatBotRights = model.ChatBotRights ?? originalUser.ChatBotRights;
113  originalUser.ConfigurationRights = model.ConfigurationRights ?? originalUser.ConfigurationRights;
114  originalUser.DreamDaemonRights = model.DreamDaemonRights ?? originalUser.DreamDaemonRights;
115  originalUser.DreamMakerRights = model.DreamMakerRights ?? originalUser.DreamMakerRights;
116 
117  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
118  return Json(originalUser.UserId == AuthenticationContext.User.Id || (AuthenticationContext.GetRight(RightsType.InstanceUser) & (ulong)InstanceUserRights.ReadUsers) != 0 ? originalUser.ToApi() : new Api.Models.InstanceUser
119  {
120  UserId = originalUser.UserId
121  });
122  }
123 #pragma warning restore CA1506
124  [HttpGet]
130  [TgsAuthorize]
131  [ProducesResponseType(typeof(Api.Models.InstanceUser), 200)]
132  public IActionResult Read() => Json(AuthenticationContext.InstanceUser.ToApi());
133 
140  [HttpGet(Routes.List)]
141  [TgsAuthorize(InstanceUserRights.ReadUsers)]
142  [ProducesResponseType(typeof(IEnumerable<Api.Models.InstanceUser>), 200)]
143  public async Task<IActionResult> List(CancellationToken cancellationToken)
144  {
145  var users = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).ToListAsync(cancellationToken).ConfigureAwait(false);
146  return Json(users.Select(x => x.ToApi()));
147  }
148 
157  [HttpGet("{id}")]
158  [TgsAuthorize(InstanceUserRights.ReadUsers)]
159  [ProducesResponseType(typeof(Api.Models.InstanceUser), 200)]
160  [ProducesResponseType(410)]
161  public async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
162  {
163  // this functions as userId
164  var user = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).Where(x => x.UserId == id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
165  if (user == default)
166  return StatusCode((int)HttpStatusCode.Gone);
167  return Json(user.ToApi());
168  }
169 
177  [HttpDelete("{id}")]
178  [TgsAuthorize(InstanceUserRights.WriteUsers)]
179  [ProducesResponseType(200)]
180  public async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
181  {
182  await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).Where(x => x.UserId == id).DeleteAsync(cancellationToken).ConfigureAwait(false);
183  return Ok();
184  }
185  }
186 }
InstanceUserController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ILogger< InstanceUserController > logger)
Construct a UserController
+
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
ConfigurationRights
Rights for Models.ConfigurationFile
- +
ByondRights
Rights for Models.Byond
Definition: ByondRights.cs:9
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
-
async Task< IActionResult > Delete(long id, CancellationToken cancellationToken)
Delete an Api.Models.InstanceUser.
+
async Task< IActionResult > Delete(long id, CancellationToken cancellationToken)
Delete an Api.Models.InstanceUser.
InstanceUserRights
Rights for an Models.Instance
IActionResult Read()
Read the active Api.Models.InstanceUser.
const string InstanceUser
The Models.InstanceUser controller
Definition: Routes.cs:64
- -
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
-
async Task< IActionResult > Create([FromBody] Api.Models.InstanceUser model, CancellationToken cancellationToken)
Create am Api.Models.InstanceUser.
+ +
async Task< IActionResult > Create([FromBody] Api.Models.InstanceUser model, CancellationToken cancellationToken)
Create am Api.Models.InstanceUser.
Routes to a server actions
Definition: Routes.cs:9
DreamDaemonRights
Rights for Models.DreamDaemon
- -
BadRequestObjectResult StandardModelChecks(Api.Models.InstanceUser model)
Checks a model for errors
+ + + +
BadRequestObjectResult StandardModelChecks(Api.Models.InstanceUser model)
Checks a model for errors
DreamMakerRights
Rights for Models.DreamMaker
- -
RepositoryRights
Rights for a Models.Repository
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
+
long Id
The ID of the User
Definition: User.cs:15
Metadata about a server instance
Definition: Instance.cs:9
const string List
The postfix for list operations
Definition: Routes.cs:84
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
-
async Task< IActionResult > List(CancellationToken cancellationToken)
Lists Api.Models.InstanceUsers for the instance.
-
async Task< IActionResult > Update([FromBody] Api.Models.InstanceUser model, CancellationToken cancellationToken)
Update the permissions for an Api.Models.InstanceUser.
+
async Task< IActionResult > List(CancellationToken cancellationToken)
Lists Api.Models.InstanceUsers for the instance.
+
async Task< IActionResult > Update([FromBody] Api.Models.InstanceUser model, CancellationToken cancellationToken)
Update the permissions for an Api.Models.InstanceUser.
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+ -
async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Gets a specific Api.Models.InstanceUser.
+
async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Gets a specific Api.Models.InstanceUser.
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.EntityFrameworkCore;
3 using Microsoft.Extensions.Logging;
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Net;
8 using System.Threading;
9 using System.Threading.Tasks;
10 using Tgstation.Server.Api;
14 
16 {
20  [Route(Routes.Jobs)]
21  public sealed class JobController : ApiController
22  {
27 
35  public JobController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, ILogger<JobController> logger) : base(databaseContext, authenticationContextFactory, logger, true, true)
36  {
37  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
38  }
39 
46  [HttpGet]
47  [TgsAuthorize]
48  [ProducesResponseType(typeof(IEnumerable<Api.Models.Job>), 200)]
49  public async Task<IActionResult> Read(CancellationToken cancellationToken)
50  {
51  var result = await DatabaseContext.Jobs.Where(x => x.Instance.Id == Instance.Id && !x.StoppedAt.HasValue).OrderByDescending(x => x.StartedAt).ToListAsync(cancellationToken).ConfigureAwait(false);
52  return Json(result.Select(x => x.ToApi()));
53  }
54 
61  [HttpGet(Routes.List)]
62  [TgsAuthorize]
63  [ProducesResponseType(typeof(List<Api.Models.EntityId>), 200)]
64  public async Task<IActionResult> List(CancellationToken cancellationToken)
65  {
66  // you KNOW this will need pagination eventually right?
67  var jobs = await DatabaseContext.Jobs.Where(x => x.Instance.Id == Instance.Id).OrderByDescending(x => x.StartedAt).Select(x => new Api.Models.EntityId
68  {
69  Id = x.Id
70  }).ToListAsync(cancellationToken).ConfigureAwait(false);
71  return Json(jobs);
72  }
73 
83  [HttpDelete("{id}")]
84  [TgsAuthorize]
85  [ProducesResponseType(202)]
86  [ProducesResponseType(404)]
87  [ProducesResponseType(410)]
88  public async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
89  {
90  // don't care if an instance post or not at this point
91  var job = await DatabaseContext.Jobs.Where(x => x.Id == id && x.Instance.Id == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
92  if (job == default(Job))
93  return NotFound();
94 
95  if (job.StoppedAt != null)
96  return StatusCode((int)HttpStatusCode.Gone);
97 
98  if (job.CancelRight.HasValue && job.CancelRightsType.HasValue && (AuthenticationContext.GetRight(job.CancelRightsType.Value) & job.CancelRight.Value) == 0)
99  return Forbid();
100 
101  var cancelled = await jobManager.CancelJob(job, AuthenticationContext.User, false, cancellationToken).ConfigureAwait(false);
102  return cancelled ? (IActionResult)Accepted() : StatusCode((int)HttpStatusCode.Gone);
103  }
104 
113  [HttpGet("{id}")]
114  [TgsAuthorize]
115  [ProducesResponseType(typeof(Api.Models.Job), 200)]
116  [ProducesResponseType(404)]
117  public async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
118  {
119  var job = await DatabaseContext.Jobs.Where(x => x.Id == id && x.Instance.Id == Instance.Id).Include(x => x.StartedBy).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
120  if (job == default(Job))
121  return NotFound();
122  var api = job.ToApi();
123  api.Progress = jobManager.JobProgress(job);
124  return Json(api);
125  }
126  }
127 }
-
Manages the runtime of Jobs
Definition: IJobManager.cs:12
- +Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.EntityFrameworkCore;
3 using Microsoft.Extensions.Logging;
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Net;
8 using System.Threading;
9 using System.Threading.Tasks;
10 using Tgstation.Server.Api;
15 
17 {
21  [Route(Routes.Jobs)]
22  public sealed class JobController : ApiController
23  {
28 
36  public JobController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, ILogger<JobController> logger) : base(databaseContext, authenticationContextFactory, logger, true, true)
37  {
38  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
39  }
40 
47  [HttpGet]
48  [TgsAuthorize]
49  [ProducesResponseType(typeof(IEnumerable<Api.Models.Job>), 200)]
50  public async Task<IActionResult> Read(CancellationToken cancellationToken)
51  {
52  var result = await DatabaseContext.Jobs.Where(x => x.Instance.Id == Instance.Id && !x.StoppedAt.HasValue).OrderByDescending(x => x.StartedAt).ToListAsync(cancellationToken).ConfigureAwait(false);
53  return Json(result.Select(x => x.ToApi()));
54  }
55 
62  [HttpGet(Routes.List)]
63  [TgsAuthorize]
64  [ProducesResponseType(typeof(List<Api.Models.EntityId>), 200)]
65  public async Task<IActionResult> List(CancellationToken cancellationToken)
66  {
67  // you KNOW this will need pagination eventually right?
68  var jobs = await DatabaseContext.Jobs.Where(x => x.Instance.Id == Instance.Id).OrderByDescending(x => x.StartedAt).Select(x => new Api.Models.EntityId
69  {
70  Id = x.Id
71  }).ToListAsync(cancellationToken).ConfigureAwait(false);
72  return Json(jobs);
73  }
74 
84  [HttpDelete("{id}")]
85  [TgsAuthorize]
86  [ProducesResponseType(202)]
87  [ProducesResponseType(404)]
88  [ProducesResponseType(410)]
89  public async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
90  {
91  // don't care if an instance post or not at this point
92  var job = await DatabaseContext.Jobs.Where(x => x.Id == id && x.Instance.Id == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
93  if (job == default(Job))
94  return NotFound();
95 
96  if (job.StoppedAt != null)
97  return StatusCode((int)HttpStatusCode.Gone);
98 
99  if (job.CancelRight.HasValue && job.CancelRightsType.HasValue && (AuthenticationContext.GetRight(job.CancelRightsType.Value) & job.CancelRight.Value) == 0)
100  return Forbid();
101 
102  var cancelled = await jobManager.CancelJob(job, AuthenticationContext.User, false, cancellationToken).ConfigureAwait(false);
103  return cancelled ? (IActionResult)Accepted() : StatusCode((int)HttpStatusCode.Gone);
104  }
105 
114  [HttpGet("{id}")]
115  [TgsAuthorize]
116  [ProducesResponseType(typeof(Api.Models.Job), 200)]
117  [ProducesResponseType(404)]
118  public async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
119  {
120  var job = await DatabaseContext.Jobs.Where(x => x.Id == id && x.Instance.Id == Instance.Id).Include(x => x.StartedBy).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
121  if (job == default(Job))
122  return NotFound();
123  var api = job.ToApi();
124  api.Progress = jobManager.JobProgress(job);
125  return Json(api);
126  }
127  }
128 }
- + -
JobController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, ILogger< JobController > logger)
Construct a HomeController
+
int? JobProgress(Job job)
Get the Api.Models.Job.Progress for a job
+
Task< bool > CancelJob(Job job, User user, bool blocking, CancellationToken cancellationToken)
Cancels a give job
+
JobController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, ILogger< JobController > logger)
Construct a HomeController
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
- + +
Routes to a server actions
Definition: Routes.cs:9
- +
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
-
async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Get a specific Api.Models.Job.
- +
async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Get a specific Api.Models.Job.
const string Jobs
The Models.Job controller
Definition: Routes.cs:79
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
-
Task< bool > CancelJob(Job job, User user, bool blocking, CancellationToken cancellationToken)
Cancels a give job
-
async Task< IActionResult > Read(CancellationToken cancellationToken)
Get active Api.Models.Jobs for the instance.
+
async Task< IActionResult > Read(CancellationToken cancellationToken)
Get active Api.Models.Jobs for the instance.
+
Manages the runtime of Jobs
Definition: IJobManager.cs:13
+ -
async Task< IActionResult > Delete(long id, CancellationToken cancellationToken)
Cancel a running Api.Models.Job.
+
async Task< IActionResult > Delete(long id, CancellationToken cancellationToken)
Cancel a running Api.Models.Job.
const string List
The postfix for list operations
Definition: Routes.cs:84
-
readonly IJobManager jobManager
The IJobManager for the JobController
-
ApiController for Api.Models.Jobs
+
readonly IJobManager jobManager
The IJobManager for the JobController
+
ApiController for Api.Models.Jobs
-
async Task< IActionResult > List(CancellationToken cancellationToken)
List all Api.Models.Job Api.Models.EntityIds for the instance in reverse creation order.
+
async Task< IActionResult > List(CancellationToken cancellationToken)
List all Api.Models.Job Api.Models.EntityIds for the instance in reverse creation order.
+ -
int? JobProgress(Job job)
Get the Api.Models.Job.Progress for a job
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

class  Tgstation.Server.Host.Core.JobException
 Operation exceptions thrown from the context of a Models.Job More...
class  Tgstation.Server.Host.Jobs.JobException
 Operation exceptions thrown from the context of a Models.Job More...
 
- +

@@ -91,7 +91,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
namespace  Tgstation.Server.Host.Jobs
 
diff --git a/_job_exception_8cs_source.html b/_job_exception_8cs_source.html index f72167aeff..701b6e3377 100644 --- a/_job_exception_8cs_source.html +++ b/_job_exception_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/JobException.cs Source File +tgstation-server: src/Tgstation.Server.Host/Jobs/JobException.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,11 +71,11 @@ $(function() {
JobException.cs
-Go to the documentation of this file.
1 using System;
2 
4 {
8  public sealed class JobException : Exception
9  {
13  public JobException()
14  {
15  }
16 
21  public JobException(string message) : base(message)
22  {
23  }
24 
30  public JobException(string message, Exception innerException) : base(message, innerException)
31  {
32  }
33  }
34 }
JobException()
Construct a JobException
Definition: JobException.cs:13
- -
JobException(string message, Exception innerException)
Construct a JobException with a message and innerException
Definition: JobException.cs:30
-
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
-
JobException(string message)
Construct a JobException with a message
Definition: JobException.cs:21
+Go to the documentation of this file.
1 using System;
2 
4 {
8  public sealed class JobException : Exception
9  {
13  public JobException()
14  {
15  }
16 
21  public JobException(string message) : base(message)
22  {
23  }
24 
30  public JobException(string message, Exception innerException) : base(message, innerException)
31  {
32  }
33  }
34 }
JobException(string message)
Construct a JobException with a message
Definition: JobException.cs:21
+
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
+
JobException()
Construct a JobException
Definition: JobException.cs:13
+
JobException(string message, Exception innerException)
Construct a JobException with a message and innerException
Definition: JobException.cs:30
+
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

class  Tgstation.Server.Host.Core.JobHandler
 Class for pairing Tasks with CancellationTokenSources More...
class  Tgstation.Server.Host.Jobs.JobHandler
 Class for pairing Tasks with CancellationTokenSources More...
 
- +

@@ -91,7 +91,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
namespace  Tgstation.Server.Host.Jobs
 
diff --git a/_job_handler_8cs_source.html b/_job_handler_8cs_source.html index ce5a4c27ff..98ad119204 100644 --- a/_job_handler_8cs_source.html +++ b/_job_handler_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/JobHandler.cs Source File +tgstation-server: src/Tgstation.Server.Host/Jobs/JobHandler.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,16 +71,16 @@ $(function() {
JobHandler.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
6 {
10  sealed class JobHandler : IDisposable
11  {
15  readonly CancellationTokenSource cancellationTokenSource;
16 
20  readonly Task task;
21 
26  public JobHandler(Func<CancellationToken, Task> job)
27  {
28  if (job == null)
29  throw new ArgumentNullException(nameof(job));
30  cancellationTokenSource = new CancellationTokenSource();
31  task = job(cancellationTokenSource.Token);
32  }
33 
35  public void Dispose() => cancellationTokenSource.Dispose();
36 
40  public int? Progress { get; set; }
41 
47  public async Task Wait(CancellationToken cancellationToken)
48  {
49  TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
50  using (cancellationToken.Register(() => tcs.SetCanceled()))
51  await Task.WhenAny(tcs.Task, task).ConfigureAwait(false);
52  cancellationToken.ThrowIfCancellationRequested();
53  }
54 
58  public void Cancel() => cancellationTokenSource.Cancel();
59  }
60 }
int? Progress
The progress of the job
Definition: JobHandler.cs:40
- - -
async Task Wait(CancellationToken cancellationToken)
Wait for task to complete
Definition: JobHandler.cs:47
- -
JobHandler(Func< CancellationToken, Task > job)
Construct a JobHandler
Definition: JobHandler.cs:26
-
readonly CancellationTokenSource cancellationTokenSource
The CancellationTokenSource for task
Definition: JobHandler.cs:15
-
readonly Task task
The Task being run
Definition: JobHandler.cs:20
+Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
6 {
10  sealed class JobHandler : IDisposable
11  {
15  readonly CancellationTokenSource cancellationTokenSource;
16 
20  readonly Task task;
21 
26  public JobHandler(Func<CancellationToken, Task> job)
27  {
28  if (job == null)
29  throw new ArgumentNullException(nameof(job));
30  cancellationTokenSource = new CancellationTokenSource();
31  task = job(cancellationTokenSource.Token);
32  }
33 
35  public void Dispose() => cancellationTokenSource.Dispose();
36 
40  public int? Progress { get; set; }
41 
47  public async Task Wait(CancellationToken cancellationToken)
48  {
49  TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
50  using (cancellationToken.Register(() => tcs.SetCanceled()))
51  await Task.WhenAny(tcs.Task, task).ConfigureAwait(false);
52  cancellationToken.ThrowIfCancellationRequested();
53  }
54 
58  public void Cancel() => cancellationTokenSource.Cancel();
59  }
60 }
readonly Task task
The Task being run
Definition: JobHandler.cs:20
+
readonly CancellationTokenSource cancellationTokenSource
The CancellationTokenSource for task
Definition: JobHandler.cs:15
+ +
Class for pairing Tasks with CancellationTokenSources
Definition: JobHandler.cs:10
+ + +
JobHandler(Func< CancellationToken, Task > job)
Construct a JobHandler
Definition: JobHandler.cs:26
-
Class for pairing Tasks with CancellationTokenSources
Definition: JobHandler.cs:10
+
int? Progress
The progress of the job
Definition: JobHandler.cs:40
+
async Task Wait(CancellationToken cancellationToken)
Wait for task to complete
Definition: JobHandler.cs:47
@@ -79,7 +79,7 @@ $(function() { - +

Classes

class  Tgstation.Server.Host.Core.JobManager
class  Tgstation.Server.Host.Jobs.JobManager
 
- +

@@ -90,7 +90,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
namespace  Tgstation.Server.Host.Jobs
 
diff --git a/_job_manager_8cs_source.html b/_job_manager_8cs_source.html index b4cced6457..01ae631028 100644 --- a/_job_manager_8cs_source.html +++ b/_job_manager_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/JobManager.cs Source File +tgstation-server: src/Tgstation.Server.Host/Jobs/JobManager.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,45 +71,46 @@ $(function() {
JobManager.cs
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 using System.Threading;
7 using System.Threading.Tasks;
9 
11 {
14  {
19 
23  readonly ILogger<JobManager> logger;
24 
28  readonly Dictionary<long, JobHandler> jobs;
29 
36  {
37  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
38  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
39  jobs = new Dictionary<long, JobHandler>();
40  }
41 
43  public void Dispose()
44  {
45  foreach (var job in jobs)
46  job.Value.Dispose();
47  }
48 
55  {
56  lock (this)
57  {
58  if (!jobs.TryGetValue(job.Id, out JobHandler jobHandler))
59  throw new InvalidOperationException("Job not running!");
60  return jobHandler;
61  }
62  }
63 
71  async Task RunJob(Job job, Func<Job, IDatabaseContext, CancellationToken, Task> operation, CancellationToken cancellationToken)
72  {
73  try
74  {
75  await databaseContextFactory.UseContext(async databaseContext =>
76  {
77  async Task HandleExceptions(Task task)
78  {
79  void LogRegularException() => logger.LogDebug("Job {0} exited with error! Exception: {1}", job.Id, job.ExceptionDetails);
80  try
81  {
82  await task.ConfigureAwait(false);
83  }
84  catch (OperationCanceledException)
85  {
86  logger.LogDebug("Job {0} cancelled!", job.Id);
87  job.Cancelled = true;
88  }
89  catch (JobException e)
90  {
91  job.ExceptionDetails = e.Message;
92  LogRegularException();
93  if (e.InnerException != null)
94  logger.LogDebug("Inner exception for job {0}: {1}", job.Id, e.InnerException);
95  }
96  catch (Exception e)
97  {
98  job.ExceptionDetails = e.ToString();
99  LogRegularException();
100  }
101  finally
102  {
103  job.StoppedAt = DateTimeOffset.Now;
104  }
105  }
106 
107  async Task RunJobInternal()
108  {
109  var oldJob = job;
110  job = new Job { Id = oldJob.Id };
111  databaseContext.Jobs.Attach(job);
112 
113  await operation(job, databaseContext, cancellationToken).ConfigureAwait(false);
114 
115  logger.LogDebug("Job {0} completed!", job.Id);
116  }
117 
118  await HandleExceptions(RunJobInternal()).ConfigureAwait(false);
119 
120  await databaseContext.Save(default).ConfigureAwait(false);
121 
122  bool JobErroredOrCancelled() => job.ExceptionDetails != null || job.Cancelled == true;
123 
124  // ok so, now it's time for the post commit step if it exists
125  if (!JobErroredOrCancelled() && job.PostComplete != null)
126  {
127  await HandleExceptions(job.PostComplete(cancellationToken)).ConfigureAwait(false);
128  if (JobErroredOrCancelled())
129  await databaseContext.Save(default).ConfigureAwait(false);
130  }
131  }).ConfigureAwait(false);
132  }
133  finally
134  {
135  lock (this)
136  {
137  var handler = jobs[job.Id];
138  jobs.Remove(job.Id);
139  handler.Dispose();
140  }
141  }
142  }
143 
145  public Task RegisterOperation(Job job, Func<Job, IDatabaseContext, Action<int>, CancellationToken, Task> operation, CancellationToken cancellationToken) => databaseContextFactory.UseContext(async databaseContext =>
146  {
147  if (job == null)
148  throw new ArgumentNullException(nameof(job));
149  if (operation == null)
150  throw new ArgumentNullException(nameof(operation));
151 
152  job.StartedAt = DateTimeOffset.Now;
153  job.Cancelled = false;
154 
155  job.Instance = new Instance
156  {
157  Id = job.Instance.Id
158  };
159  databaseContext.Instances.Attach(job.Instance);
160 
161  job.StartedBy = new User
162  {
163  Id = job.StartedBy.Id
164  };
165  databaseContext.Users.Attach(job.StartedBy);
166 
167  databaseContext.Jobs.Add(job);
168 
169  await databaseContext.Save(cancellationToken).ConfigureAwait(false);
170  logger.LogDebug("Starting job {0}: {1}...", job.Id, job.Description);
171  var jobHandler = new JobHandler(x => RunJob(job, (jobParam, serviceProvider, ct) =>
172  operation(jobParam, serviceProvider, y =>
173  {
174  lock (this)
175  if (jobs.TryGetValue(job.Id, out var handler))
176  handler.Progress = y;
177  }, ct),
178  x));
179  lock (this)
180  jobs.Add(job.Id, jobHandler);
181  });
182 
184  public async Task StartAsync(CancellationToken cancellationToken)
185  {
186  logger.LogTrace("Starting job manager...");
187  await databaseContextFactory.UseContext(async databaseContext =>
188  {
189  // mark all jobs as cancelled
190  var badJobs = await databaseContext.Jobs.Where(y => !y.StoppedAt.HasValue).Select(y => y.Id).ToListAsync(cancellationToken).ConfigureAwait(false);
191  if (badJobs.Count > 0)
192  {
193  logger.LogTrace("Cleaning {0} unfinished jobs...", badJobs.Count);
194  foreach (var I in badJobs)
195  {
196  var job = new Job { Id = I };
197  databaseContext.Jobs.Attach(job);
198  job.Cancelled = true;
199  job.StoppedAt = DateTimeOffset.Now;
200  }
201 
202  await databaseContext.Save(cancellationToken).ConfigureAwait(false);
203  }
204  }).ConfigureAwait(false);
205  logger.LogDebug("Job manager started!");
206  }
207 
209  public async Task StopAsync(CancellationToken cancellationToken)
210  {
211  var joinTasks = jobs.Select(x =>
212  {
213  x.Value.Cancel();
214  return x.Value.Wait(cancellationToken);
215  });
216  await Task.WhenAll(joinTasks).ConfigureAwait(false);
217  }
218 
220  public async Task<bool> CancelJob(Job job, User user, bool blocking, CancellationToken cancellationToken)
221  {
222  if (job == null)
223  throw new ArgumentNullException(nameof(job));
224  if (user == null)
225  throw new ArgumentNullException(nameof(user));
226  JobHandler handler;
227  try
228  {
229  handler = CheckGetJob(job);
230  }
231  catch (InvalidOperationException)
232  {
233  // this is fine
234  return false;
235  }
236 
237  handler.Cancel(); // this will ensure the db update is only done once
238  await databaseContextFactory.UseContext(async databaseContext =>
239  {
240  job = new Job { Id = job.Id };
241  databaseContext.Jobs.Attach(job);
242  user = new User { Id = user.Id };
243  databaseContext.Users.Attach(user);
244  job.CancelledBy = user;
245 
246  // let either startup or cancellation set job.cancelled
247  await databaseContext.Save(cancellationToken).ConfigureAwait(false);
248  }).ConfigureAwait(false);
249  if (blocking)
250  await handler.Wait(cancellationToken).ConfigureAwait(false);
251  return true;
252  }
253 
255  public int? JobProgress(Job job)
256  {
257  if (job == null)
258  throw new ArgumentNullException(nameof(job));
259  lock (this)
260  {
261  if (!jobs.TryGetValue(job.Id, out var handler))
262  return null;
263  return handler.Progress;
264  }
265  }
266 
268  public async Task WaitForJobCompletion(Job job, User canceller, CancellationToken jobCancellationToken, CancellationToken cancellationToken)
269  {
270  if (job == null)
271  throw new ArgumentNullException(nameof(job));
272  if (canceller == null)
273  throw new ArgumentNullException(nameof(canceller));
274  JobHandler handler;
275  lock (this)
276  {
277  if (!jobs.TryGetValue(job.Id, out handler))
278  return;
279  }
280 
281  Task cancelTask = null;
282  using (jobCancellationToken.Register(() => cancelTask = CancelJob(job, canceller, true, cancellationToken)))
283  await handler.Wait(cancellationToken).ConfigureAwait(false);
284 
285  if (cancelTask != null)
286  await cancelTask.ConfigureAwait(false);
287  }
288  }
289 }
-
Manages the runtime of Jobs
Definition: IJobManager.cs:12
- -
JobHandler CheckGetJob(Job job)
Gets the JobHandler for a given job if it exists
Definition: JobManager.cs:54
-
long Id
The ID of the entity.
Definition: EntityId.cs:11
-
async Task StartAsync(CancellationToken cancellationToken)
Definition: JobManager.cs:184
-
int? JobProgress(Job job)
Get the Api.Models.Job.Progress for a job
Definition: JobManager.cs:255
-
readonly Dictionary< long, JobHandler > jobs
Dictionary<TKey, TValue> of Job Api.Models.EntityId.Ids to running JobHandlers
Definition: JobManager.cs:28
+Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 using System.Threading;
7 using System.Threading.Tasks;
10 
12 {
15  {
20 
24  readonly ILogger<JobManager> logger;
25 
29  readonly Dictionary<long, JobHandler> jobs;
30 
37  {
38  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
39  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
40  jobs = new Dictionary<long, JobHandler>();
41  }
42 
44  public void Dispose()
45  {
46  foreach (var job in jobs)
47  job.Value.Dispose();
48  }
49 
56  {
57  lock (this)
58  {
59  if (!jobs.TryGetValue(job.Id, out JobHandler jobHandler))
60  throw new InvalidOperationException("Job not running!");
61  return jobHandler;
62  }
63  }
64 
72  async Task RunJob(Job job, Func<Job, IDatabaseContext, CancellationToken, Task> operation, CancellationToken cancellationToken)
73  {
74  try
75  {
76  await databaseContextFactory.UseContext(async databaseContext =>
77  {
78  async Task HandleExceptions(Task task)
79  {
80  void LogRegularException() => logger.LogDebug("Job {0} exited with error! Exception: {1}", job.Id, job.ExceptionDetails);
81  try
82  {
83  await task.ConfigureAwait(false);
84  }
85  catch (OperationCanceledException)
86  {
87  logger.LogDebug("Job {0} cancelled!", job.Id);
88  job.Cancelled = true;
89  }
90  catch (JobException e)
91  {
92  job.ExceptionDetails = e.Message;
93  LogRegularException();
94  if (e.InnerException != null)
95  logger.LogDebug("Inner exception for job {0}: {1}", job.Id, e.InnerException);
96  }
97  catch (Exception e)
98  {
99  job.ExceptionDetails = e.ToString();
100  LogRegularException();
101  }
102  finally
103  {
104  job.StoppedAt = DateTimeOffset.Now;
105  }
106  }
107 
108  async Task RunJobInternal()
109  {
110  var oldJob = job;
111  job = new Job { Id = oldJob.Id };
112  databaseContext.Jobs.Attach(job);
113 
114  await operation(job, databaseContext, cancellationToken).ConfigureAwait(false);
115 
116  logger.LogDebug("Job {0} completed!", job.Id);
117  }
118 
119  await HandleExceptions(RunJobInternal()).ConfigureAwait(false);
120 
121  await databaseContext.Save(default).ConfigureAwait(false);
122 
123  bool JobErroredOrCancelled() => job.ExceptionDetails != null || job.Cancelled == true;
124 
125  // ok so, now it's time for the post commit step if it exists
126  if (!JobErroredOrCancelled() && job.PostComplete != null)
127  {
128  await HandleExceptions(job.PostComplete(cancellationToken)).ConfigureAwait(false);
129  if (JobErroredOrCancelled())
130  await databaseContext.Save(default).ConfigureAwait(false);
131  }
132  }).ConfigureAwait(false);
133  }
134  finally
135  {
136  lock (this)
137  {
138  var handler = jobs[job.Id];
139  jobs.Remove(job.Id);
140  handler.Dispose();
141  }
142  }
143  }
144 
146  public Task RegisterOperation(Job job, Func<Job, IDatabaseContext, Action<int>, CancellationToken, Task> operation, CancellationToken cancellationToken) => databaseContextFactory.UseContext(async databaseContext =>
147  {
148  if (job == null)
149  throw new ArgumentNullException(nameof(job));
150  if (operation == null)
151  throw new ArgumentNullException(nameof(operation));
152 
153  job.StartedAt = DateTimeOffset.Now;
154  job.Cancelled = false;
155 
156  job.Instance = new Instance
157  {
158  Id = job.Instance.Id
159  };
160  databaseContext.Instances.Attach(job.Instance);
161 
162  job.StartedBy = new User
163  {
164  Id = job.StartedBy.Id
165  };
166  databaseContext.Users.Attach(job.StartedBy);
167 
168  databaseContext.Jobs.Add(job);
169 
170  await databaseContext.Save(cancellationToken).ConfigureAwait(false);
171  logger.LogDebug("Starting job {0}: {1}...", job.Id, job.Description);
172  var jobHandler = new JobHandler(x => RunJob(job, (jobParam, serviceProvider, ct) =>
173  operation(jobParam, serviceProvider, y =>
174  {
175  lock (this)
176  if (jobs.TryGetValue(job.Id, out var handler))
177  handler.Progress = y;
178  }, ct),
179  x));
180  lock (this)
181  jobs.Add(job.Id, jobHandler);
182  });
183 
185  public async Task StartAsync(CancellationToken cancellationToken)
186  {
187  logger.LogTrace("Starting job manager...");
188  await databaseContextFactory.UseContext(async databaseContext =>
189  {
190  // mark all jobs as cancelled
191  var badJobs = await databaseContext.Jobs.Where(y => !y.StoppedAt.HasValue).Select(y => y.Id).ToListAsync(cancellationToken).ConfigureAwait(false);
192  if (badJobs.Count > 0)
193  {
194  logger.LogTrace("Cleaning {0} unfinished jobs...", badJobs.Count);
195  foreach (var I in badJobs)
196  {
197  var job = new Job { Id = I };
198  databaseContext.Jobs.Attach(job);
199  job.Cancelled = true;
200  job.StoppedAt = DateTimeOffset.Now;
201  }
202 
203  await databaseContext.Save(cancellationToken).ConfigureAwait(false);
204  }
205  }).ConfigureAwait(false);
206  logger.LogDebug("Job manager started!");
207  }
208 
210  public async Task StopAsync(CancellationToken cancellationToken)
211  {
212  var joinTasks = jobs.Select(x =>
213  {
214  x.Value.Cancel();
215  return x.Value.Wait(cancellationToken);
216  });
217  await Task.WhenAll(joinTasks).ConfigureAwait(false);
218  }
219 
221  public async Task<bool> CancelJob(Job job, User user, bool blocking, CancellationToken cancellationToken)
222  {
223  if (job == null)
224  throw new ArgumentNullException(nameof(job));
225  if (user == null)
226  throw new ArgumentNullException(nameof(user));
227  JobHandler handler;
228  try
229  {
230  handler = CheckGetJob(job);
231  }
232  catch (InvalidOperationException)
233  {
234  // this is fine
235  return false;
236  }
237 
238  handler.Cancel(); // this will ensure the db update is only done once
239  await databaseContextFactory.UseContext(async databaseContext =>
240  {
241  job = new Job { Id = job.Id };
242  databaseContext.Jobs.Attach(job);
243  user = new User { Id = user.Id };
244  databaseContext.Users.Attach(user);
245  job.CancelledBy = user;
246 
247  // let either startup or cancellation set job.cancelled
248  await databaseContext.Save(cancellationToken).ConfigureAwait(false);
249  }).ConfigureAwait(false);
250  if (blocking)
251  await handler.Wait(cancellationToken).ConfigureAwait(false);
252  return true;
253  }
254 
256  public int? JobProgress(Job job)
257  {
258  if (job == null)
259  throw new ArgumentNullException(nameof(job));
260  lock (this)
261  {
262  if (!jobs.TryGetValue(job.Id, out var handler))
263  return null;
264  return handler.Progress;
265  }
266  }
267 
269  public async Task WaitForJobCompletion(Job job, User canceller, CancellationToken jobCancellationToken, CancellationToken cancellationToken)
270  {
271  if (job == null)
272  throw new ArgumentNullException(nameof(job));
273  if (canceller == null)
274  throw new ArgumentNullException(nameof(canceller));
275  JobHandler handler;
276  lock (this)
277  {
278  if (!jobs.TryGetValue(job.Id, out handler))
279  return;
280  }
281 
282  Task cancelTask = null;
283  using (jobCancellationToken.Register(() => cancelTask = CancelJob(job, canceller, true, cancellationToken)))
284  await handler.Wait(cancellationToken).ConfigureAwait(false);
285 
286  if (cancelTask != null)
287  await cancelTask.ConfigureAwait(false);
288  }
289  }
290 }
long Id
The ID of the entity.
Definition: EntityId.cs:11
+
readonly IDatabaseContextFactory databaseContextFactory
The IServiceProvider for the JobManager
Definition: JobManager.cs:19
+
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
-
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
-
async Task< bool > CancelJob(Job job, User user, bool blocking, CancellationToken cancellationToken)
Cancels a give job
Definition: JobManager.cs:220
-
async Task Wait(CancellationToken cancellationToken)
Wait for task to complete
Definition: JobHandler.cs:47
-
async Task WaitForJobCompletion(Job job, User canceller, CancellationToken jobCancellationToken, CancellationToken cancellationToken)
Wait for a given job to complete
Definition: JobManager.cs:268
+
async Task StartAsync(CancellationToken cancellationToken)
Definition: JobManager.cs:185
+
readonly Dictionary< long, JobHandler > jobs
Dictionary<TKey, TValue> of Job Api.Models.EntityId.Ids to running JobHandlers
Definition: JobManager.cs:29
+ +
Task RegisterOperation(Job job, Func< Job, IDatabaseContext, Action< int >, CancellationToken, Task > operation, CancellationToken cancellationToken)
Registers a given Job and begins running it
+
async Task RunJob(Job job, Func< Job, IDatabaseContext, CancellationToken, Task > operation, CancellationToken cancellationToken)
Runner for JobHandlers
Definition: JobManager.cs:72
string ExceptionDetails
Details of any exceptions caught during the Job
Definition: Job.cs:21
-
Task RegisterOperation(Job job, Func< Job, IDatabaseContext, Action< int >, CancellationToken, Task > operation, CancellationToken cancellationToken)
Registers a given Job and begins running it
+
Class for pairing Tasks with CancellationTokenSources
Definition: JobHandler.cs:10
User CancelledBy
See Api.Models.Job.CancelledBy
Definition: Job.cs:21
- -
DateTimeOffset? StoppedAt
When the Job stopped
Definition: Job.cs:32
bool? Cancelled
If the Job was cancelled
Definition: Job.cs:38
-
async Task StopAsync(CancellationToken cancellationToken)
Definition: JobManager.cs:209
-
JobManager(IDatabaseContextFactory databaseContextFactory, ILogger< JobManager > logger)
Construct a JobManager
Definition: JobManager.cs:35
+
Func< CancellationToken, Task > PostComplete
A Task to run after the job completes. This will not affect the Api.Models.Internal....
Definition: Job.cs:34
-
readonly ILogger< JobManager > logger
The ILogger for the JobManager
Definition: JobManager.cs:23
+
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
+ +
JobHandler CheckGetJob(Job job)
Gets the JobHandler for a given job if it exists
Definition: JobManager.cs:55
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
+
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
+
async Task WaitForJobCompletion(Job job, User canceller, CancellationToken jobCancellationToken, CancellationToken cancellationToken)
Wait for a given job to complete
Definition: JobManager.cs:269
long Id
The ID of the User
Definition: User.cs:15
+
JobManager(IDatabaseContextFactory databaseContextFactory, ILogger< JobManager > logger)
Construct a JobManager
Definition: JobManager.cs:36
-
readonly IDatabaseContextFactory databaseContextFactory
The IServiceProvider for the JobManager
Definition: JobManager.cs:18
+
Manages the runtime of Jobs
Definition: IJobManager.cs:13
+ +
int? JobProgress(Job job)
Get the Api.Models.Job.Progress for a job
Definition: JobManager.cs:256
-
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
-
async Task RunJob(Job job, Func< Job, IDatabaseContext, CancellationToken, Task > operation, CancellationToken cancellationToken)
Runner for JobHandlers
Definition: JobManager.cs:71
- +
async Task StopAsync(CancellationToken cancellationToken)
Definition: JobManager.cs:210
+ +
async Task Wait(CancellationToken cancellationToken)
Wait for task to complete
Definition: JobHandler.cs:47
-
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
+
async Task< bool > CancelJob(Job job, User user, bool blocking, CancellationToken cancellationToken)
Cancels a give job
Definition: JobManager.cs:221
+
readonly ILogger< JobManager > logger
The ILogger for the JobManager
Definition: JobManager.cs:24
+ -
Class for pairing Tasks with CancellationTokenSources
Definition: JobHandler.cs:10
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Newtonsoft.Json;
3 using Newtonsoft.Json.Serialization;
4 using System;
5 using System.Collections.Generic;
6 using System.Text;
7 using System.Threading;
8 using System.Threading.Tasks;
11 using Tgstation.Server.Host.IO;
12 
14 {
17  {
19  public bool Active
20  {
21  get => active;
22  set
23  {
24  active = true;
25  logger.LogDebug("Tracking {0}activated", !active ? "de" : String.Empty);
26  }
27  }
28 
31  readonly ILogger<JsonTrackingContext> logger;
32  readonly Action onDispose;
33 
34  readonly string commandsPath;
35  readonly string channelsPath;
36 
37  readonly SemaphoreSlim channelsSemaphore;
38 
39  bool active;
40 
51  {
52  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
53  this.customCommandHandler = customCommandHandler ?? throw new ArgumentNullException(nameof(customCommandHandler));
54  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
55  this.onDispose = onDispose ?? throw new ArgumentNullException(nameof(onDispose));
56  this.commandsPath = commandsPath ?? throw new ArgumentNullException(nameof(commandsPath));
57  this.channelsPath = channelsPath ?? throw new ArgumentNullException(nameof(channelsPath));
58 
59  channelsSemaphore = new SemaphoreSlim(1);
60  active = false;
61 
62  logger.LogTrace("Created tracking context for {0} and {1}", commandsPath, channelsPath);
63  }
64 
66  public void Dispose()
67  {
68  logger.LogTrace("Disposing...");
69  channelsSemaphore.Dispose();
70  onDispose();
71  }
72 
74  public async Task<IReadOnlyList<CustomCommand>> GetCustomCommands(CancellationToken cancellationToken)
75  {
76  try
77  {
78  if (Active && await ioManager.FileExists(commandsPath, cancellationToken).ConfigureAwait(false))
79  {
80  var resultBytes = await ioManager.ReadAllBytes(commandsPath, cancellationToken).ConfigureAwait(false);
81  var resultJson = Encoding.UTF8.GetString(resultBytes);
82  logger.LogTrace("Read commands JSON: {0}", resultJson);
83  var result = JsonConvert.DeserializeObject<List<CustomCommand>>(resultJson, new JsonSerializerSettings
84  {
85  ContractResolver = new DefaultContractResolver
86  {
87  NamingStrategy = new SnakeCaseNamingStrategy()
88  }
89  });
90  foreach (var I in result)
91  I.SetHandler(customCommandHandler);
92  return result;
93  }
94  }
95  catch (OperationCanceledException)
96  {
97  throw;
98  }
99  catch (Exception e)
100  {
101  logger.LogWarning("Error retrieving custom commands! Exception: {0}", e);
102  }
103 
104  return new List<CustomCommand>();
105  }
106 
108  public async Task SetChannels(IEnumerable<Channel> channels, CancellationToken cancellationToken)
109  {
110  using (await SemaphoreSlimContext.Lock(channelsSemaphore, cancellationToken).ConfigureAwait(false))
111  {
112  var json = JsonConvert.SerializeObject(channels, new JsonSerializerSettings
113  {
114  ContractResolver = new CamelCasePropertyNamesContractResolver()
115  });
116  logger.LogTrace("Writing channels JSON: {0}", json);
117  await ioManager.WriteAllBytes(channelsPath, Encoding.UTF8.GetBytes(json), cancellationToken).ConfigureAwait(false);
118  }
119  }
120  }
121 }
+Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Newtonsoft.Json;
3 using Newtonsoft.Json.Serialization;
4 using System;
5 using System.Collections.Generic;
6 using System.Text;
7 using System.Threading;
8 using System.Threading.Tasks;
11 using Tgstation.Server.Host.IO;
12 
14 {
17  {
19  public bool Active
20  {
21  get => active;
22  set
23  {
24  active = value;
25  logger.LogDebug("Tracking {0}activated", !active ? "de" : String.Empty);
26  }
27  }
28 
31  readonly ILogger<JsonTrackingContext> logger;
32  readonly Action onDispose;
33 
34  readonly string commandsPath;
35  readonly string channelsPath;
36 
37  readonly SemaphoreSlim channelsSemaphore;
38 
39  bool active;
40 
51  {
52  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
53  this.customCommandHandler = customCommandHandler ?? throw new ArgumentNullException(nameof(customCommandHandler));
54  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
55  this.onDispose = onDispose ?? throw new ArgumentNullException(nameof(onDispose));
56  this.commandsPath = commandsPath ?? throw new ArgumentNullException(nameof(commandsPath));
57  this.channelsPath = channelsPath ?? throw new ArgumentNullException(nameof(channelsPath));
58 
59  channelsSemaphore = new SemaphoreSlim(1);
60  active = false;
61 
62  logger.LogTrace("Created tracking context for {0} and {1}", commandsPath, channelsPath);
63  }
64 
66  public void Dispose()
67  {
68  logger.LogTrace("Disposing...");
69  channelsSemaphore.Dispose();
70  onDispose();
71  }
72 
74  public async Task<IReadOnlyList<CustomCommand>> GetCustomCommands(CancellationToken cancellationToken)
75  {
76  try
77  {
78  if (Active && await ioManager.FileExists(commandsPath, cancellationToken).ConfigureAwait(false))
79  {
80  var resultBytes = await ioManager.ReadAllBytes(commandsPath, cancellationToken).ConfigureAwait(false);
81  var resultJson = Encoding.UTF8.GetString(resultBytes);
82  logger.LogTrace("Read commands JSON: {0}", resultJson);
83  var result = JsonConvert.DeserializeObject<List<CustomCommand>>(resultJson, new JsonSerializerSettings
84  {
85  ContractResolver = new DefaultContractResolver
86  {
87  NamingStrategy = new SnakeCaseNamingStrategy()
88  }
89  });
90  foreach (var I in result)
91  I.SetHandler(customCommandHandler);
92  return result;
93  }
94  }
95  catch (OperationCanceledException)
96  {
97  throw;
98  }
99  catch (Exception e)
100  {
101  logger.LogWarning("Error retrieving custom commands! Exception: {0}", e);
102  }
103 
104  return new List<CustomCommand>();
105  }
106 
108  public async Task SetChannels(IEnumerable<Channel> channels, CancellationToken cancellationToken)
109  {
110  using (await SemaphoreSlimContext.Lock(channelsSemaphore, cancellationToken).ConfigureAwait(false))
111  {
112  var json = JsonConvert.SerializeObject(channels, new JsonSerializerSettings
113  {
114  ContractResolver = new CamelCasePropertyNamesContractResolver()
115  });
116  logger.LogTrace("Writing channels JSON: {0}", json);
117  await ioManager.WriteAllBytes(channelsPath, Encoding.UTF8.GetBytes(json), cancellationToken).ConfigureAwait(false);
118  }
119  }
120  }
121 }
async Task SetChannels(IEnumerable< Channel > channels, CancellationToken cancellationToken)
Writes information about connected channels to the IJsonTrackingContext
Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content
diff --git a/_launch_result_8cs_source.html b/_launch_result_8cs_source.html index f66f974b01..ff0805a4c3 100644 --- a/_launch_result_8cs_source.html +++ b/_launch_result_8cs_source.html @@ -74,8 +74,8 @@ $(function() { Go to the documentation of this file.
1 using System;
2 using System.Globalization;
3 
5 {
9  public sealed class LaunchResult
10  {
14  public TimeSpan? StartupTime { get; set; }
15 
19  public int? ExitCode { get; set; }
20 
22  public override string ToString() => String.Format(CultureInfo.InvariantCulture, "Exit Code: {0}, Time {1}ms", ExitCode, StartupTime?.TotalMilliseconds);
23  }
24 }
Represents the result of trying to start a DD process
Definition: LaunchResult.cs:9
-
int? ExitCode
The System.Diagnostics.Process.ExitCode if it exited
Definition: LaunchResult.cs:19
-
TimeSpan? StartupTime
The time it took for System.Diagnostics.Process.WaitForInputIdle() to return. If null the startup tim...
Definition: LaunchResult.cs:14
+
int? ExitCode
The global::System.Diagnostics.Process.ExitCode if it exited
Definition: LaunchResult.cs:19
+
TimeSpan? StartupTime
The time it took for global::System.Diagnostics.Process.WaitForInputIdle() to return....
Definition: LaunchResult.cs:14

Classes

class  Tgstation.Server.Host.Models.ReattachInformation
 Database representation of Components.Watchdog.ReattachInformation More...
 Database representation of Components.Watchdog.ReattachInformation More...
 
- +

diff --git a/_models_2_watchdog_reattach_information_8cs.html b/_models_2_watchdog_reattach_information_8cs.html index d08d15007a..df9000e990 100644 --- a/_models_2_watchdog_reattach_information_8cs.html +++ b/_models_2_watchdog_reattach_information_8cs.html @@ -80,7 +80,7 @@ $(function() {

Classes

class  Tgstation.Server.Host.Models.WatchdogReattachInformation
 Database representation of Components.Watchdog.WatchdogReattachInformation More...
 Database representation of Components.Watchdog.WatchdogReattachInformation More...
 

Definition at line 27 of file ApiHeaders.cs.

-

Referenced by Tgstation.Server.Api.ApiHeaders.ApiHeaders(), Tgstation.Server.Host.Controllers.TgsOpenApiFilters.Apply(), and Tgstation.Server.Api.ApiHeaders.SetRequestHeaders().

+

Referenced by Tgstation.Server.Api.ApiHeaders.ApiHeaders(), and Tgstation.Server.Api.ApiHeaders.SetRequestHeaders().

@@ -534,7 +534,7 @@ Static Private Attributes

Definition at line 22 of file ApiHeaders.cs.

-

Referenced by Tgstation.Server.Api.ApiHeaders.ApiHeaders(), Tgstation.Server.Host.Controllers.TgsOpenApiFilters.Apply(), Tgstation.Server.Client.ApiClient.RunRequest< TResult >(), Tgstation.Server.Api.ApiHeaders.SetRequestHeaders(), and Tgstation.Server.Api.Tests.TestApiHeaders.TestUserAgentsAreValid().

+

Referenced by Tgstation.Server.Host.Core.SwaggerConfiguration.AddDefaultResponses(), Tgstation.Server.Api.ApiHeaders.ApiHeaders(), Tgstation.Server.Client.ApiClient.RunRequest< TResult >(), Tgstation.Server.Api.ApiHeaders.SetRequestHeaders(), and Tgstation.Server.Api.Tests.TestApiHeaders.TestUserAgentsAreValid().

@@ -582,7 +582,7 @@ Static Private Attributes

Definition at line 42 of file ApiHeaders.cs.

-

Referenced by Tgstation.Server.Api.ApiHeaders.ApiHeaders(), and Tgstation.Server.Api.ApiHeaders.SetRequestHeaders().

+

Referenced by Tgstation.Server.Api.ApiHeaders.ApiHeaders(), Tgstation.Server.Host.Core.SwaggerConfiguration.Configure(), and Tgstation.Server.Api.ApiHeaders.SetRequestHeaders().

@@ -602,7 +602,7 @@ Static Private Attributes

Definition at line 32 of file ApiHeaders.cs.

-

Referenced by Tgstation.Server.Api.ApiHeaders.ApiHeaders(), Tgstation.Server.Host.Controllers.TgsOpenApiFilters.Apply(), and Tgstation.Server.Api.ApiHeaders.SetRequestHeaders().

+

Referenced by Tgstation.Server.Api.ApiHeaders.ApiHeaders(), Tgstation.Server.Host.Core.SwaggerConfiguration.Apply(), and Tgstation.Server.Api.ApiHeaders.SetRequestHeaders().

@@ -622,7 +622,7 @@ Static Private Attributes

Definition at line 102 of file ApiHeaders.cs.

-

Referenced by Tgstation.Server.Host.Controllers.HomeController.CreateToken(), and Tgstation.Server.Api.ApiHeaders.SetRequestHeaders().

+

Referenced by Tgstation.Server.Host.Controllers.HomeController.CreateToken(), and Tgstation.Server.Api.ApiHeaders.SetRequestHeaders().

@@ -642,7 +642,7 @@ Static Private Attributes

Definition at line 37 of file ApiHeaders.cs.

-

Referenced by Tgstation.Server.Api.ApiHeaders.ApiHeaders(), and Tgstation.Server.Api.ApiHeaders.SetRequestHeaders().

+

Referenced by Tgstation.Server.Api.ApiHeaders.ApiHeaders(), Tgstation.Server.Host.Core.SwaggerConfiguration.Configure(), and Tgstation.Server.Api.ApiHeaders.SetRequestHeaders().

@@ -831,7 +831,7 @@ Static Private Attributes

Definition at line 97 of file ApiHeaders.cs.

97 { get; }
-

Referenced by Tgstation.Server.Api.ApiHeaders.ApiHeaders(), and Tgstation.Server.Host.Controllers.HomeController.CreateToken().

+

Referenced by Tgstation.Server.Api.ApiHeaders.ApiHeaders(), and Tgstation.Server.Host.Controllers.HomeController.CreateToken().

@@ -915,7 +915,7 @@ Static Private Attributes

Definition at line 92 of file ApiHeaders.cs.

92 { get; }
-

Referenced by Tgstation.Server.Api.ApiHeaders.ApiHeaders(), and Tgstation.Server.Host.Controllers.HomeController.CreateToken().

+

Referenced by Tgstation.Server.Api.ApiHeaders.ApiHeaders(), and Tgstation.Server.Host.Controllers.HomeController.CreateToken().

diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_compile_job.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_compile_job.html index 0d9d58bce8..4b0d98f333 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_compile_job.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_compile_job.html @@ -145,7 +145,7 @@ Properties

Definition at line 21 of file CompileJob.cs.

21 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), and Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.Reattach().

+

Referenced by Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), and Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.Reattach().

@@ -199,7 +199,7 @@ Properties

Definition at line 16 of file CompileJob.cs.

16 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew().

+

Referenced by Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew().

diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_configuration_file.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_configuration_file.html index df3a4843de..200aa8ca70 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_configuration_file.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_configuration_file.html @@ -125,7 +125,7 @@ Properties

Definition at line 16 of file ConfigurationFile.cs.

16 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.StaticFiles.Configuration.Read(), and Tgstation.Server.Host.Components.StaticFiles.Configuration.Write().

+

Referenced by Tgstation.Server.Host.Components.StaticFiles.Configuration.Read(), and Tgstation.Server.Host.Components.StaticFiles.Configuration.Write().

@@ -179,7 +179,7 @@ Properties

Definition at line 21 of file ConfigurationFile.cs.

21 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.StaticFiles.Configuration.Read(), and Tgstation.Server.Host.Components.StaticFiles.Configuration.Write().

+

Referenced by Tgstation.Server.Host.Components.StaticFiles.Configuration.Read(), and Tgstation.Server.Host.Components.StaticFiles.Configuration.Write().

diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_entity_id.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_entity_id.html index b6f7fdef72..023f49dc11 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_entity_id.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_entity_id.html @@ -127,7 +127,7 @@ Properties

Definition at line 11 of file EntityId.cs.

11 { get; set; }
-

Referenced by Tgstation.Server.Host.Core.JobManager.CancelJob(), Tgstation.Server.Host.Core.JobManager.CheckGetJob(), Tgstation.Server.Host.Components.Compiler.DmbFactory.CleanJob(), Tgstation.Server.Host.Components.Compiler.DmbFactory.FromCompileJob(), Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.HandlerMonitorWakeup(), Tgstation.Server.Host.Core.JobManager.JobProgress(), Tgstation.Server.Host.Controllers.DreamMakerController.List(), Tgstation.Server.Host.Components.Compiler.DmbFactory.LockNextDmb(), Tgstation.Server.Host.Components.Watchdog.BasicWatchdog.MonitorLifetimes(), Tgstation.Server.Host.Core.JobManager.RunJob(), and Tgstation.Server.Host.Core.JobManager.WaitForJobCompletion().

+

Referenced by Tgstation.Server.Host.Jobs.JobManager.CancelJob(), Tgstation.Server.Host.Jobs.JobManager.CheckGetJob(), Tgstation.Server.Host.Components.Deployment.DmbFactory.CleanJob(), Tgstation.Server.Host.Components.Deployment.DmbFactory.FromCompileJob(), Tgstation.Server.Host.Components.Watchdog.WindowsWatchdog.HandleNewDmbAvailable(), Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.HandlerMonitorWakeup(), Tgstation.Server.Host.Jobs.JobManager.JobProgress(), Tgstation.Server.Host.Controllers.DreamMakerController.List(), Tgstation.Server.Host.Components.Deployment.DmbFactory.LockNextDmb(), Tgstation.Server.Host.Jobs.JobManager.RunJob(), and Tgstation.Server.Host.Jobs.JobManager.WaitForJobCompletion().

diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_error_message.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_error_message.html index 94a1730b93..32d4c4b199 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_error_message.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_error_message.html @@ -116,7 +116,7 @@ Properties

Definition at line 13 of file ErrorMessage.cs.

13 { get; set; }
-

Referenced by Tgstation.Server.Host.Controllers.ChatController.Create(), Tgstation.Server.Host.Controllers.InstanceController.Create(), Tgstation.Server.Host.Controllers.ConfigurationController.Create(), Tgstation.Server.Host.Controllers.ConfigurationController.File(), Tgstation.Server.Host.Controllers.ApiController.OnActionExecutionAsync(), and Tgstation.Server.Host.Controllers.ConfigurationController.Update().

+

Referenced by Tgstation.Server.Host.Controllers.ChatController.Create(), Tgstation.Server.Host.Controllers.InstanceController.Create(), Tgstation.Server.Host.Controllers.ConfigurationController.Create(), Tgstation.Server.Host.Controllers.ConfigurationController.File(), Tgstation.Server.Host.Controllers.ApiController.OnActionExecutionAsync(), and Tgstation.Server.Host.Controllers.ConfigurationController.Update().

diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance.html index 083a58e03b..ed6fe5b55f 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance.html @@ -194,7 +194,7 @@ Properties

Definition at line 38 of file Instance.cs.

38 { get; set; }
-

Referenced by Tgstation.Server.Host.Controllers.ConfigurationController.ForbidDueToModeConflicts().

+

Referenced by Tgstation.Server.Host.Controllers.ConfigurationController.ForbidDueToModeConflicts().

@@ -222,7 +222,7 @@ Properties

Definition at line 14 of file Instance.cs.

14 { get; set; }
-

Referenced by Tgstation.Server.Host.Controllers.InstanceUserController.Create(), Tgstation.Server.Host.Controllers.ChatController.Create(), Tgstation.Server.Host.Controllers.RepositoryController.Create(), Tgstation.Server.Client.InstanceManagerClient.CreateClient(), Tgstation.Server.Host.Controllers.JobController.Delete(), Tgstation.Server.Host.Controllers.InstanceUserController.Delete(), Tgstation.Server.Host.Controllers.RepositoryController.Delete(), Tgstation.Server.Host.Controllers.DreamMakerController.GetId(), Tgstation.Server.Host.Controllers.JobController.GetId(), Tgstation.Server.Host.Controllers.InstanceUserController.GetId(), Tgstation.Server.Host.Controllers.JobController.List(), Tgstation.Server.Host.Controllers.DreamMakerController.List(), Tgstation.Server.Host.Controllers.InstanceUserController.List(), Tgstation.Server.Host.Controllers.ChatController.List(), Tgstation.Server.Host.Controllers.JobController.Read(), Tgstation.Server.Client.Components.ConfigurationClient.Read(), Tgstation.Server.Host.Controllers.DreamMakerController.Read(), Tgstation.Server.Host.Controllers.RepositoryController.Read(), Tgstation.Server.Host.Controllers.DreamDaemonController.ReadImpl(), Tgstation.Server.Host.Controllers.ByondController.Update(), Tgstation.Server.Host.Controllers.InstanceUserController.Update(), Tgstation.Server.Host.Controllers.DreamMakerController.Update(), Tgstation.Server.Host.Controllers.DreamDaemonController.Update(), Tgstation.Server.Host.Controllers.ChatController.Update(), and Tgstation.Server.Host.Controllers.RepositoryController.Update().

+

Referenced by Tgstation.Server.Host.Controllers.InstanceUserController.Create(), Tgstation.Server.Host.Controllers.ChatController.Create(), Tgstation.Server.Host.Controllers.RepositoryController.Create(), Tgstation.Server.Client.InstanceManagerClient.CreateClient(), Tgstation.Server.Host.Controllers.JobController.Delete(), Tgstation.Server.Host.Controllers.InstanceUserController.Delete(), Tgstation.Server.Host.Controllers.RepositoryController.Delete(), Tgstation.Server.Host.Controllers.DreamMakerController.GetId(), Tgstation.Server.Host.Controllers.JobController.GetId(), Tgstation.Server.Host.Controllers.InstanceUserController.GetId(), Tgstation.Server.Host.Controllers.JobController.List(), Tgstation.Server.Host.Controllers.DreamMakerController.List(), Tgstation.Server.Host.Controllers.InstanceUserController.List(), Tgstation.Server.Host.Controllers.ChatController.List(), Tgstation.Server.Host.Controllers.JobController.Read(), Tgstation.Server.Client.Components.ConfigurationClient.Read(), Tgstation.Server.Host.Controllers.DreamMakerController.Read(), Tgstation.Server.Host.Controllers.RepositoryController.Read(), Tgstation.Server.Host.Controllers.DreamDaemonController.ReadImpl(), Tgstation.Server.Host.Controllers.ByondController.Update(), Tgstation.Server.Host.Controllers.InstanceUserController.Update(), Tgstation.Server.Host.Controllers.DreamMakerController.Update(), Tgstation.Server.Host.Controllers.DreamDaemonController.Update(), Tgstation.Server.Host.Controllers.ChatController.Update(), and Tgstation.Server.Host.Controllers.RepositoryController.Update().

diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance_user.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance_user.html index 6a24f881bd..ba0aecc7f9 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance_user.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance_user.html @@ -247,7 +247,7 @@ Properties

Definition at line 39 of file InstanceUser.cs.

39 { get; set; }
-

Referenced by Tgstation.Server.Host.Controllers.DreamMakerController.Update().

+

Referenced by Tgstation.Server.Host.Controllers.DreamMakerController.Update().

diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_compile_job.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_compile_job.html index ee8eab894b..567a84399a 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_compile_job.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_compile_job.html @@ -137,7 +137,7 @@ Properties

Definition at line 27 of file CompileJob.cs.

27 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.Compiler.DmbFactory.CleanJob(), and Tgstation.Server.Host.Components.Compiler.DmbFactory.CleanUnusedCompileJobs().

+

Referenced by Tgstation.Server.Host.Components.Deployment.DmbFactory.CleanJob(), and Tgstation.Server.Host.Components.Deployment.DmbFactory.CleanUnusedCompileJobs().

@@ -191,7 +191,7 @@ Properties

Definition at line 33 of file CompileJob.cs.

33 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew().

+

Referenced by Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew().

diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_dream_daemon_launch_parameters.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_dream_daemon_launch_parameters.html index ac593647d2..cd528a7600 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_dream_daemon_launch_parameters.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_dream_daemon_launch_parameters.html @@ -144,7 +144,7 @@ Properties
Returns
true if they match, false otherwise
-

Referenced by Tgstation.Server.Host.Components.Watchdog.WatchdogBase.ChangeSettings().

+

Referenced by Tgstation.Server.Host.Components.Watchdog.WatchdogBase.ChangeSettings().

@@ -173,7 +173,7 @@ Properties

Definition at line 15 of file DreamDaemonLaunchParameters.cs.

15 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), and Tgstation.Server.Host.Controllers.DreamDaemonController.ReadImpl().

+

Referenced by Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), and Tgstation.Server.Host.Controllers.DreamDaemonController.ReadImpl().

@@ -201,7 +201,7 @@ Properties

Definition at line 27 of file DreamDaemonLaunchParameters.cs.

27 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.HandlerMonitorWakeup(), Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), and Tgstation.Server.Host.Controllers.DreamDaemonController.ReadImpl().

+

Referenced by Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.HandlerMonitorWakeup(), Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), and Tgstation.Server.Host.Controllers.DreamDaemonController.ReadImpl().

@@ -229,7 +229,7 @@ Properties

Definition at line 33 of file DreamDaemonLaunchParameters.cs.

33 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.HandlerMonitorWakeup(), Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), and Tgstation.Server.Host.Controllers.DreamDaemonController.ReadImpl().

+

Referenced by Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.HandlerMonitorWakeup(), Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), and Tgstation.Server.Host.Controllers.DreamDaemonController.ReadImpl().

@@ -257,7 +257,7 @@ Properties

Definition at line 21 of file DreamDaemonLaunchParameters.cs.

21 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), and Tgstation.Server.Host.Controllers.DreamDaemonController.ReadImpl().

+

Referenced by Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), and Tgstation.Server.Host.Controllers.DreamDaemonController.ReadImpl().

@@ -285,7 +285,7 @@ Properties

Definition at line 39 of file DreamDaemonLaunchParameters.cs.

39 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.Watchdog.WatchdogBase.CheckLaunchResult(), Tgstation.Server.Host.Components.Instance.CompileProcess(), Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), and Tgstation.Server.Host.Controllers.DreamDaemonController.ReadImpl().

+

Referenced by Tgstation.Server.Host.Components.Watchdog.WatchdogBase.CheckLaunchResult(), Tgstation.Server.Host.Components.Instance.CompileProcess(), Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), and Tgstation.Server.Host.Controllers.DreamDaemonController.ReadImpl().

diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_dream_daemon_settings.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_dream_daemon_settings.html index d8b2031613..ea08b5b7d3 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_dream_daemon_settings.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_dream_daemon_settings.html @@ -153,7 +153,7 @@ Additional Inherited Members

Definition at line 14 of file DreamDaemonSettings.cs.

14 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.Watchdog.WatchdogFactory.CreateWatchdog(), and Tgstation.Server.Host.Controllers.DreamDaemonController.ReadImpl().

+

Referenced by Tgstation.Server.Host.Components.Watchdog.WatchdogFactory.CreateWatchdog(), and Tgstation.Server.Host.Controllers.DreamDaemonController.ReadImpl().

diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_job.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_job.html index 54ca78c613..3385d02c88 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_job.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_job.html @@ -146,7 +146,7 @@ Properties

Definition at line 38 of file Job.cs.

38 { get; set; }
-

Referenced by Tgstation.Server.Host.Core.JobManager.RunJob(), and Tgstation.Server.Host.Core.JobManager.StartAsync().

+

Referenced by Tgstation.Server.Host.Jobs.JobManager.RunJob(), and Tgstation.Server.Host.Jobs.JobManager.StartAsync().

@@ -252,7 +252,7 @@ Properties

Definition at line 21 of file Job.cs.

21 { get; set; }
-

Referenced by Tgstation.Server.Host.Core.JobManager.RunJob().

+

Referenced by Tgstation.Server.Host.Jobs.JobManager.RunJob().

@@ -306,7 +306,7 @@ Properties

Definition at line 32 of file Job.cs.

32 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.Instance.CompileProcess(), and Tgstation.Server.Host.Core.JobManager.RunJob().

+

Referenced by Tgstation.Server.Host.Components.Instance.CompileProcess(), and Tgstation.Server.Host.Jobs.JobManager.RunJob().

diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_repository_settings.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_repository_settings.html index 07e1171718..f95f0179ac 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_repository_settings.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_repository_settings.html @@ -147,7 +147,7 @@ Properties

Definition at line 30 of file RepositorySettings.cs.

30 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.Instance.CompileProcess().

+

Referenced by Tgstation.Server.Host.Components.Instance.CompileProcess().

diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_revision_information.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_revision_information.html index 669a6ae6d9..7a1a9ffc1b 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_revision_information.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_revision_information.html @@ -126,7 +126,7 @@ Properties

Definition at line 15 of file RevisionInformation.cs.

15 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.Instance.CompileProcess(), Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), and Tgstation.Server.Host.Components.Instance.TimerLoop().

+

Referenced by Tgstation.Server.Host.Components.Instance.CompileProcess(), Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), and Tgstation.Server.Host.Components.Instance.TimerLoop().

@@ -154,7 +154,7 @@ Properties

Definition at line 22 of file RevisionInformation.cs.

22 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.Instance.CompileProcess(), Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), and Tgstation.Server.Host.Components.Instance.TimerLoop().

+

Referenced by Tgstation.Server.Host.Components.Instance.CompileProcess(), Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), and Tgstation.Server.Host.Components.Instance.TimerLoop().

diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_user.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_user.html index 1c20854720..6f03d53ec7 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_user.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_user.html @@ -194,7 +194,7 @@ Properties

Definition at line 21 of file User.cs.

21 { get; set; }
-

Referenced by Tgstation.Server.Host.Controllers.UserController.Create().

+

Referenced by Tgstation.Server.Host.Controllers.UserController.Create().

@@ -222,7 +222,7 @@ Properties

Definition at line 15 of file User.cs.

15 { get; set; }
-

Referenced by Tgstation.Server.Host.Security.IdentityCache.CacheSystemIdentity(), Tgstation.Server.Host.Core.JobManager.CancelJob(), Tgstation.Server.Host.Controllers.HomeController.CreateToken(), Tgstation.Server.Host.Controllers.RepositoryController.Delete(), Tgstation.Server.Host.Controllers.UserController.GetId(), Tgstation.Server.Host.Controllers.InstanceController.GetId(), Tgstation.Server.Host.Controllers.InstanceController.List(), Tgstation.Server.Host.Security.IdentityCache.LoadCachedIdentity(), Tgstation.Server.Host.Controllers.ApiController.OnActionExecutionAsync(), Tgstation.Server.Host.Controllers.ByondController.Update(), Tgstation.Server.Host.Controllers.InstanceUserController.Update(), and Tgstation.Server.Host.Controllers.RepositoryController.Update().

+

Referenced by Tgstation.Server.Host.Security.IdentityCache.CacheSystemIdentity(), Tgstation.Server.Host.Jobs.JobManager.CancelJob(), Tgstation.Server.Host.Controllers.HomeController.CreateToken(), Tgstation.Server.Host.Controllers.RepositoryController.Delete(), Tgstation.Server.Host.Controllers.UserController.GetId(), Tgstation.Server.Host.Controllers.InstanceController.GetId(), Tgstation.Server.Host.Controllers.InstanceController.List(), Tgstation.Server.Host.Security.IdentityCache.LoadCachedIdentity(), Tgstation.Server.Host.Controllers.ApiController.OnActionExecutionAsync(), Tgstation.Server.Host.Controllers.ByondController.Update(), Tgstation.Server.Host.Controllers.InstanceUserController.Update(), and Tgstation.Server.Host.Controllers.RepositoryController.Update().

@@ -250,7 +250,7 @@ Properties

Definition at line 50 of file User.cs.

50 { get; set; }
-

Referenced by Tgstation.Server.Host.Controllers.InstanceController.GetId(), and Tgstation.Server.Host.Controllers.InstanceController.List().

+

Referenced by Tgstation.Server.Host.Controllers.InstanceController.GetId(), and Tgstation.Server.Host.Controllers.InstanceController.List().

@@ -278,7 +278,7 @@ Properties

Definition at line 38 of file User.cs.

38 { get; set; }
-

Referenced by Tgstation.Server.Host.Controllers.UserController.CheckValidName(), Tgstation.Server.Host.Components.Instance.CompileProcess(), Tgstation.Server.Host.Controllers.InstanceController.Create(), and Tgstation.Server.Host.Controllers.RepositoryController.Update().

+

Referenced by Tgstation.Server.Host.Controllers.UserController.CheckValidName(), Tgstation.Server.Host.Components.Instance.CompileProcess(), Tgstation.Server.Host.Controllers.InstanceController.Create(), and Tgstation.Server.Host.Controllers.RepositoryController.Update().

diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_repository.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_repository.html index 2220070d85..09430f7090 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_repository.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_repository.html @@ -226,7 +226,7 @@ Properties

Definition at line 33 of file Repository.cs.

33 { get; set; }
-

Referenced by Tgstation.Server.Host.Controllers.RepositoryController.PopulateApi().

+

Referenced by Tgstation.Server.Host.Controllers.RepositoryController.PopulateApi().

@@ -254,7 +254,7 @@ Properties

Definition at line 28 of file Repository.cs.

28 { get; set; }
-

Referenced by Tgstation.Server.Host.Controllers.RepositoryController.PopulateApi().

+

Referenced by Tgstation.Server.Host.Controllers.RepositoryController.PopulateApi().

@@ -308,7 +308,7 @@ Properties

Definition at line 13 of file Repository.cs.

13 { get; set; }
-

Referenced by Tgstation.Server.Host.Controllers.RepositoryController.PopulateApi().

+

Referenced by Tgstation.Server.Host.Controllers.RepositoryController.PopulateApi().

@@ -336,7 +336,7 @@ Properties

Definition at line 48 of file Repository.cs.

48 { get; set; }
-

Referenced by Tgstation.Server.Host.Controllers.RepositoryController.PopulateApi().

+

Referenced by Tgstation.Server.Host.Controllers.RepositoryController.PopulateApi().

@@ -364,7 +364,7 @@ Properties

Definition at line 23 of file Repository.cs.

23 { get; set; }
-

Referenced by Tgstation.Server.Host.Controllers.RepositoryController.PopulateApi().

+

Referenced by Tgstation.Server.Host.Controllers.RepositoryController.PopulateApi().

diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_revision_information.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_revision_information.html index f28d3192f2..cb0d501bf4 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_revision_information.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_revision_information.html @@ -134,7 +134,7 @@ Properties

Definition at line 16 of file RevisionInformation.cs.

16 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew().

+

Referenced by Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew().

diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_test_merge_parameters.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_test_merge_parameters.html index 32153a91ab..d4c7e6218a 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_test_merge_parameters.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_test_merge_parameters.html @@ -132,7 +132,7 @@ Properties

Definition at line 25 of file TestMergeParameters.cs.

25 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.Repository.Repository.AddTestMerge(), Tgstation.Server.Host.Components.Instance.CompileProcess(), and Tgstation.Server.Api.Models.Internal.TestMergeBase.TestMergeBase().

+

Referenced by Tgstation.Server.Host.Components.Repository.Repository.AddTestMerge(), Tgstation.Server.Host.Components.Instance.CompileProcess(), and Tgstation.Server.Api.Models.Internal.TestMergeBase.TestMergeBase().

@@ -160,7 +160,7 @@ Properties

Definition at line 14 of file TestMergeParameters.cs.

14 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.Repository.Repository.AddTestMerge(), and Tgstation.Server.Api.Models.Internal.TestMergeBase.TestMergeBase().

+

Referenced by Tgstation.Server.Host.Components.Repository.Repository.AddTestMerge(), and Tgstation.Server.Api.Models.Internal.TestMergeBase.TestMergeBase().

@@ -188,7 +188,7 @@ Properties

Definition at line 20 of file TestMergeParameters.cs.

20 { get; set; }
-

Referenced by Tgstation.Server.Host.Components.Repository.Repository.AddTestMerge(), Tgstation.Server.Host.Components.Instance.CompileProcess(), and Tgstation.Server.Api.Models.Internal.TestMergeBase.TestMergeBase().

+

Referenced by Tgstation.Server.Host.Components.Repository.Repository.AddTestMerge(), Tgstation.Server.Host.Components.Instance.CompileProcess(), and Tgstation.Server.Api.Models.Internal.TestMergeBase.TestMergeBase().

diff --git a/class_tgstation_1_1_server_1_1_api_1_1_rights_1_1_rights_helper.html b/class_tgstation_1_1_server_1_1_api_1_1_rights_1_1_rights_helper.html index 44cb7bcdd6..0e2f9b7460 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_rights_1_1_rights_helper.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_rights_1_1_rights_helper.html @@ -138,7 +138,7 @@ Static Private Attributes
Returns
true if rightsType is an instance right, false otherwise
-

Referenced by Tgstation.Server.Host.Controllers.TgsOpenApiFilters.Apply(), Tgstation.Server.Host.Security.AuthenticationContext.GetRight(), and Tgstation.Server.Host.Security.ClaimsInjector.InjectClaimsIntoContext().

+

Referenced by Tgstation.Server.Host.Core.SwaggerConfiguration.Apply(), Tgstation.Server.Host.Security.AuthenticationContext.GetRight(), and Tgstation.Server.Host.Security.ClaimsInjector.InjectClaimsIntoContext().

diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_byond_executable_lock.html b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_byond_executable_lock.html index 789279434b..46458459c8 100644 --- a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_byond_executable_lock.html +++ b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_byond_executable_lock.html @@ -110,7 +110,7 @@ Properties - + diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_byond_installer_base.html b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_byond_installer_base.html index ce5e257697..0102691ad7 100644 --- a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_byond_installer_base.html +++ b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_byond_installer_base.html @@ -413,7 +413,7 @@ Properties

Definition at line 27 of file ByondInstallerBase.cs.

27 { get; }
-

Referenced by Tgstation.Server.Host.Components.Byond.ByondInstallerBase.ByondInstallerBase(), Tgstation.Server.Host.Components.Byond.PosixByondInstaller.CleanCache(), Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.CleanCache(), Tgstation.Server.Host.Components.Byond.ByondInstallerBase.DownloadVersion(), Tgstation.Server.Host.Components.Byond.PosixByondInstaller.InstallByond(), and Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond().

+

Referenced by Tgstation.Server.Host.Components.Byond.ByondInstallerBase.ByondInstallerBase(), Tgstation.Server.Host.Components.Byond.PosixByondInstaller.CleanCache(), Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.CleanCache(), Tgstation.Server.Host.Components.Byond.ByondInstallerBase.DownloadVersion(), Tgstation.Server.Host.Components.Byond.PosixByondInstaller.InstallByond(), and Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond().

@@ -441,7 +441,7 @@ Properties

Definition at line 32 of file ByondInstallerBase.cs.

32 { get; }
-

Referenced by Tgstation.Server.Host.Components.Byond.ByondInstallerBase.ByondInstallerBase(), Tgstation.Server.Host.Components.Byond.PosixByondInstaller.CleanCache(), Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.CleanCache(), and Tgstation.Server.Host.Components.Byond.ByondInstallerBase.DownloadVersion().

+

Referenced by Tgstation.Server.Host.Components.Byond.ByondInstallerBase.ByondInstallerBase(), Tgstation.Server.Host.Components.Byond.PosixByondInstaller.CleanCache(), Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.CleanCache(), and Tgstation.Server.Host.Components.Byond.ByondInstallerBase.DownloadVersion().

diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_byond_manager.html b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_byond_manager.html index d9cf5f3636..9a62319d6c 100644 --- a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_byond_manager.html +++ b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_byond_manager.html @@ -173,7 +173,7 @@ Private Attributes

diff --git a/_monitor_state_8cs_source.html b/_monitor_state_8cs_source.html index 9ebde621df..960f173f05 100644 --- a/_monitor_state_8cs_source.html +++ b/_monitor_state_8cs_source.html @@ -72,9 +72,9 @@ $(function() {
Go to the documentation of this file.
1 using Newtonsoft.Json;
2 
4 {
8  sealed class MonitorState
9  {
13  public bool RebootingInactiveServer { get; set; }
14 
18  public bool InactiveServerCritFail { get; set; }
19 
23  public MonitorAction NextAction { get; set; }
24 
28  [JsonIgnore]
29  public ISessionController ActiveServer { get; set; }
30 
34  [JsonIgnore]
35  public ISessionController InactiveServer { get; set; }
36  }
37 }
bool InactiveServerCritFail
If the inactive server is in an unrecoverable state
Definition: MonitorState.cs:18
-
MonitorAction NextAction
The next MonitorAction to take in ExperimentalWatchdog.MonitorLifetimes(System.Threading....
Definition: MonitorState.cs:23
+
MonitorAction NextAction
The next MonitorAction to take in ExperimentalWatchdog.MonitorLifetimes(global::System....
Definition: MonitorState.cs:23
-
Handles communication with a DreamDaemon IProcess
+
Handles communication with a DreamDaemon IProcess
bool RebootingInactiveServer
If the inactive server is being rebooted
Definition: MonitorState.cs:13
ISessionController ActiveServer
The active ISessionController
Definition: MonitorState.cs:29
ISessionController InactiveServer
The inactive ISessionController
Definition: MonitorState.cs:35
diff --git a/_my_sql_database_context_8cs.html b/_my_sql_database_context_8cs.html index ce9955b129..7b7ff208f8 100644 --- a/_my_sql_database_context_8cs.html +++ b/_my_sql_database_context_8cs.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Models/MySqlDatabaseContext.cs File Reference +tgstation-server: src/Tgstation.Server.Host/Database/MySqlDatabaseContext.cs File Reference @@ -63,7 +63,7 @@ $(function() {
@@ -79,8 +79,8 @@ $(function() { - - + +

Classes

class  Tgstation.Server.Host.Models.MySqlDatabaseContext
 DatabaseContext<TParentContext> for MySQL More...
class  Tgstation.Server.Host.Database.MySqlDatabaseContext
 DatabaseContext<TParentContext> for MySQL More...
 
- +

@@ -91,7 +91,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
namespace  Tgstation.Server.Host.Database
 
diff --git a/_my_sql_database_context_8cs_source.html b/_my_sql_database_context_8cs_source.html index c9e079cf6c..e850fbb151 100644 --- a/_my_sql_database_context_8cs_source.html +++ b/_my_sql_database_context_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Models/MySqlDatabaseContext.cs Source File +tgstation-server: src/Tgstation.Server.Host/Database/MySqlDatabaseContext.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,24 +71,24 @@ $(function() {
MySqlDatabaseContext.cs
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using Microsoft.Extensions.Logging;
3 using Microsoft.Extensions.Options;
4 using MySql.Data.MySqlClient;
5 using Pomelo.EntityFrameworkCore.MySql.Infrastructure;
6 using System;
8 
10 {
14  sealed class MySqlDatabaseContext : DatabaseContext<MySqlDatabaseContext>
15  {
23  public MySqlDatabaseContext(DbContextOptions<MySqlDatabaseContext> dbContextOptions, IOptions<DatabaseConfiguration> databaseConfiguration, IDatabaseSeeder databaseSeeder, ILogger<MySqlDatabaseContext> logger) : base(dbContextOptions, databaseConfiguration, databaseSeeder, logger)
24  { }
25 
27  protected override void OnConfiguring(DbContextOptionsBuilder options)
28  {
29  base.OnConfiguring(options);
30  var stringDeconstructor = new MySqlConnectionStringBuilder
31  {
32  ConnectionString = DatabaseConfiguration.ConnectionString
33  };
34  if (stringDeconstructor.Server == "localhost")
35  Logger.LogWarning("MariaDB/MySQL server address is set to 'localhost'! If there are connection issues, try setting it to '127.0.0.1'!");
36  if (!String.IsNullOrEmpty(DatabaseConfiguration.MySqlServerVersion))
37  options.UseMySql(DatabaseConfiguration.ConnectionString, mySqlOptions => mySqlOptions.ServerVersion(Version.Parse(DatabaseConfiguration.MySqlServerVersion), DatabaseConfiguration.DatabaseType == DatabaseType.MariaDB ? ServerType.MariaDb : ServerType.MySql));
38  else
39  options.UseMySql(DatabaseConfiguration.ConnectionString);
40  }
41 
43  protected override bool UseMySQLMigrations() => true;
44  }
45 }
string ConnectionString
The connection string for the database
-
MySqlDatabaseContext(DbContextOptions< MySqlDatabaseContext > dbContextOptions, IOptions< DatabaseConfiguration > databaseConfiguration, IDatabaseSeeder databaseSeeder, ILogger< MySqlDatabaseContext > logger)
Construct a MySqlDatabaseContext
-
override void OnConfiguring(DbContextOptionsBuilder options)
- -
For initially seeding a database
+Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using Microsoft.Extensions.Logging;
3 using Microsoft.Extensions.Options;
4 using MySql.Data.MySqlClient;
5 using Pomelo.EntityFrameworkCore.MySql.Infrastructure;
6 using System;
8 
10 {
14  sealed class MySqlDatabaseContext : DatabaseContext<MySqlDatabaseContext>
15  {
23  public MySqlDatabaseContext(DbContextOptions<MySqlDatabaseContext> dbContextOptions, IOptions<DatabaseConfiguration> databaseConfiguration, IDatabaseSeeder databaseSeeder, ILogger<MySqlDatabaseContext> logger) : base(dbContextOptions, databaseConfiguration, databaseSeeder, logger)
24  { }
25 
27  protected override void OnConfiguring(DbContextOptionsBuilder options)
28  {
29  base.OnConfiguring(options);
30  var stringDeconstructor = new MySqlConnectionStringBuilder
31  {
32  ConnectionString = DatabaseConfiguration.ConnectionString
33  };
34  if (stringDeconstructor.Server == "localhost")
35  Logger.LogWarning("MariaDB/MySQL server address is set to 'localhost'! If there are connection issues, try setting it to '127.0.0.1'!");
36  if (!String.IsNullOrEmpty(DatabaseConfiguration.MySqlServerVersion))
37  options.UseMySql(DatabaseConfiguration.ConnectionString, mySqlOptions => mySqlOptions.ServerVersion(Version.Parse(DatabaseConfiguration.MySqlServerVersion), DatabaseConfiguration.DatabaseType == DatabaseType.MariaDB ? ServerType.MariaDb : ServerType.MySql));
38  else
39  options.UseMySql(DatabaseConfiguration.ConnectionString);
40  }
41 
43  protected override bool UseMySQLMigrations() => true;
44  }
45 }
string ConnectionString
The connection string for the database
+
ILogger Logger
The ILogger for the DatabaseContext<TParentContext>
+
MySqlDatabaseContext(DbContextOptions< MySqlDatabaseContext > dbContextOptions, IOptions< DatabaseConfiguration > databaseConfiguration, IDatabaseSeeder databaseSeeder, ILogger< MySqlDatabaseContext > logger)
Construct a MySqlDatabaseContext
+
override void OnConfiguring(DbContextOptionsBuilder options)
+
For initially seeding a database
+
override bool UseMySQLMigrations()
If the MY_ class of migrations should be used instead of the MS_ class
+
DatabaseType DatabaseType
The Configuration.DatabaseType to create
- -
string MySqlServerVersion
The string form of the System.Version of a target MySQL/MariaDB server
-
Configuration options for the Models.DatabaseContext<TParentContext>
+
string MySqlServerVersion
The string form of the global::System.Version of a target MySQL/MariaDB server
+
DatabaseContext<TParentContext> for MySQL
+
Configuration options for the Database.DatabaseContext<TParentContext>
DatabaseType
Type of database to user
Definition: DatabaseType.cs:6
-
readonly IDatabaseSeeder databaseSeeder
The IDatabaseSeeder for the DatabaseContext<TParentContext>
-
ILogger Logger
The ILogger for the DatabaseContext<TParentContext>
-
override bool UseMySQLMigrations()
If the MY_ class of migrations should be used instead of the MS_ class
+
readonly IDatabaseSeeder databaseSeeder
The IDatabaseSeeder for the DatabaseContext<TParentContext>
-
DatabaseContext<TParentContext> for MySQL
+
diff --git a/_my_sql_database_context_model_snapshot_8cs_source.html b/_my_sql_database_context_model_snapshot_8cs_source.html index 21a9952cbf..94f173c1f2 100644 --- a/_my_sql_database_context_model_snapshot_8cs_source.html +++ b/_my_sql_database_context_model_snapshot_8cs_source.html @@ -71,11 +71,16 @@ $(function() {
MySqlDatabaseContextModelSnapshot.cs
-Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
5 
7 {
8  [DbContext(typeof(MySqlDatabaseContext))]
10  {
11  protected override void BuildModel(ModelBuilder modelBuilder)
12  {
13 #pragma warning disable 612, 618
14  modelBuilder
15  .HasAnnotation("ProductVersion", "2.1.4-rtm-31024")
16  .HasAnnotation("Relational:MaxIdentifierLength", 64);
17 
18  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
19  {
20  b.Property<long>("Id")
21  .ValueGeneratedOnAdd();
22 
23  b.Property<string>("ConnectionString")
24  .IsRequired();
25 
26  b.Property<bool?>("Enabled");
27 
28  b.Property<long>("InstanceId");
29 
30  b.Property<string>("Name")
31  .IsRequired();
32 
33  b.Property<int?>("Provider");
34 
35  b.HasKey("Id");
36 
37  b.HasIndex("InstanceId");
38 
39  b.HasIndex("Name")
40  .IsUnique();
41 
42  b.ToTable("ChatBots");
43  });
44 
45  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
46  {
47  b.Property<long>("Id")
48  .ValueGeneratedOnAdd();
49 
50  b.Property<long>("ChatSettingsId");
51 
52  b.Property<ulong?>("DiscordChannelId");
53 
54  b.Property<string>("IrcChannel");
55 
56  b.Property<bool?>("IsAdminChannel")
57  .IsRequired();
58 
59  b.Property<bool?>("IsUpdatesChannel")
60  .IsRequired();
61 
62  b.Property<bool?>("IsWatchdogChannel")
63  .IsRequired();
64 
65  b.Property<string>("Tag");
66 
67  b.HasKey("Id");
68 
69  b.HasIndex("ChatSettingsId", "DiscordChannelId")
70  .IsUnique();
71 
72  b.HasIndex("ChatSettingsId", "IrcChannel")
73  .IsUnique();
74 
75  b.ToTable("ChatChannels");
76  });
77 
78  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
79  {
80  b.Property<long>("Id")
81  .ValueGeneratedOnAdd();
82 
83  b.Property<string>("ByondVersion")
84  .IsRequired();
85 
86  b.Property<Guid?>("DirectoryName")
87  .IsRequired();
88 
89  b.Property<string>("DmeName")
90  .IsRequired();
91 
92  b.Property<long>("JobId");
93 
94  b.Property<int>("MinimumSecurityLevel");
95 
96  b.Property<string>("Output")
97  .IsRequired();
98 
99  b.Property<long>("RevisionInformationId");
100 
101  b.HasKey("Id");
102 
103  b.HasIndex("DirectoryName");
104 
105  b.HasIndex("JobId")
106  .IsUnique();
107 
108  b.HasIndex("RevisionInformationId");
109 
110  b.ToTable("CompileJobs");
111  });
112 
113  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
114  {
115  b.Property<long>("Id")
116  .ValueGeneratedOnAdd();
117 
118  b.Property<string>("AccessToken");
119 
120  b.Property<bool?>("AllowWebClient")
121  .IsRequired();
122 
123  b.Property<bool?>("AutoStart")
124  .IsRequired();
125 
126  b.Property<long>("InstanceId");
127 
128  b.Property<ushort?>("PrimaryPort")
129  .IsRequired();
130 
131  b.Property<int?>("ProcessId");
132 
133  b.Property<ushort?>("SecondaryPort")
134  .IsRequired();
135 
136  b.Property<int>("SecurityLevel");
137 
138  b.Property<bool?>("SoftRestart")
139  .IsRequired();
140 
141  b.Property<bool?>("SoftShutdown")
142  .IsRequired();
143 
144  b.Property<uint?>("StartupTimeout")
145  .IsRequired();
146 
147  b.HasKey("Id");
148 
149  b.HasIndex("InstanceId")
150  .IsUnique();
151 
152  b.ToTable("DreamDaemonSettings");
153  });
154 
155  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
156  {
157  b.Property<long>("Id")
158  .ValueGeneratedOnAdd();
159 
160  b.Property<ushort?>("ApiValidationPort")
161  .IsRequired();
162 
163  b.Property<int>("ApiValidationSecurityLevel");
164 
165  b.Property<long>("InstanceId");
166 
167  b.Property<string>("ProjectName");
168 
169  b.HasKey("Id");
170 
171  b.HasIndex("InstanceId")
172  .IsUnique();
173 
174  b.ToTable("DreamMakerSettings");
175  });
176 
177  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
178  {
179  b.Property<long>("Id")
180  .ValueGeneratedOnAdd();
181 
182  b.Property<uint?>("AutoUpdateInterval")
183  .IsRequired();
184 
185  b.Property<int>("ConfigurationType");
186 
187  b.Property<string>("Name")
188  .IsRequired();
189 
190  b.Property<bool?>("Online")
191  .IsRequired();
192 
193  b.Property<string>("Path")
194  .IsRequired();
195 
196  b.HasKey("Id");
197 
198  b.HasIndex("Path")
199  .IsUnique();
200 
201  b.ToTable("Instances");
202  });
203 
204  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
205  {
206  b.Property<long>("Id")
207  .ValueGeneratedOnAdd();
208 
209  b.Property<ulong>("ByondRights");
210 
211  b.Property<ulong>("ChatBotRights");
212 
213  b.Property<ulong>("ConfigurationRights");
214 
215  b.Property<ulong>("DreamDaemonRights");
216 
217  b.Property<ulong>("DreamMakerRights");
218 
219  b.Property<long>("InstanceId");
220 
221  b.Property<ulong>("InstanceUserRights");
222 
223  b.Property<ulong>("RepositoryRights");
224 
225  b.Property<long?>("UserId")
226  .IsRequired();
227 
228  b.HasKey("Id");
229 
230  b.HasIndex("InstanceId");
231 
232  b.HasIndex("UserId", "InstanceId")
233  .IsUnique();
234 
235  b.ToTable("InstanceUsers");
236  });
237 
238  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
239  {
240  b.Property<long>("Id")
241  .ValueGeneratedOnAdd();
242 
243  b.Property<ulong?>("CancelRight");
244 
245  b.Property<ulong?>("CancelRightsType");
246 
247  b.Property<bool?>("Cancelled")
248  .IsRequired();
249 
250  b.Property<long?>("CancelledById");
251 
252  b.Property<string>("Description")
253  .IsRequired();
254 
255  b.Property<string>("ExceptionDetails");
256 
257  b.Property<long>("InstanceId");
258 
259  b.Property<DateTimeOffset?>("StartedAt")
260  .IsRequired();
261 
262  b.Property<long>("StartedById");
263 
264  b.Property<DateTimeOffset?>("StoppedAt");
265 
266  b.HasKey("Id");
267 
268  b.HasIndex("CancelledById");
269 
270  b.HasIndex("InstanceId");
271 
272  b.HasIndex("StartedById");
273 
274  b.ToTable("Jobs");
275  });
276 
277  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
278  {
279  b.Property<long>("Id")
280  .ValueGeneratedOnAdd();
281 
282  b.Property<string>("AccessIdentifier")
283  .IsRequired();
284 
285  b.Property<string>("ChatChannelsJson")
286  .IsRequired();
287 
288  b.Property<string>("ChatCommandsJson")
289  .IsRequired();
290 
291  b.Property<long>("CompileJobId");
292 
293  b.Property<bool>("IsPrimary");
294 
295  b.Property<ushort>("Port");
296 
297  b.Property<int>("ProcessId");
298 
299  b.Property<int>("RebootState");
300 
301  b.Property<string>("ServerCommandsJson")
302  .IsRequired();
303 
304  b.HasKey("Id");
305 
306  b.HasIndex("CompileJobId");
307 
308  b.ToTable("ReattachInformations");
309  });
310 
311  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
312  {
313  b.Property<long>("Id")
314  .ValueGeneratedOnAdd();
315 
316  b.Property<string>("AccessToken");
317 
318  b.Property<string>("AccessUser");
319 
320  b.Property<bool?>("AutoUpdatesKeepTestMerges")
321  .IsRequired();
322 
323  b.Property<bool?>("AutoUpdatesSynchronize")
324  .IsRequired();
325 
326  b.Property<string>("CommitterEmail")
327  .IsRequired();
328 
329  b.Property<string>("CommitterName")
330  .IsRequired();
331 
332  b.Property<long>("InstanceId");
333 
334  b.Property<bool?>("PostTestMergeComment")
335  .IsRequired();
336 
337  b.Property<bool?>("PushTestMergeCommits")
338  .IsRequired();
339 
340  b.Property<bool?>("ShowTestMergeCommitters")
341  .IsRequired();
342 
343  b.HasKey("Id");
344 
345  b.HasIndex("InstanceId")
346  .IsUnique();
347 
348  b.ToTable("RepositorySettings");
349  });
350 
351  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
352  {
353  b.Property<long>("Id")
354  .ValueGeneratedOnAdd();
355 
356  b.Property<long>("RevisionInformationId");
357 
358  b.Property<long>("TestMergeId");
359 
360  b.HasKey("Id");
361 
362  b.HasIndex("RevisionInformationId");
363 
364  b.HasIndex("TestMergeId");
365 
366  b.ToTable("RevInfoTestMerges");
367  });
368 
369  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
370  {
371  b.Property<long>("Id")
372  .ValueGeneratedOnAdd();
373 
374  b.Property<string>("CommitSha")
375  .IsRequired()
376  .HasMaxLength(40);
377 
378  b.Property<long>("InstanceId");
379 
380  b.Property<string>("OriginCommitSha")
381  .IsRequired()
382  .HasMaxLength(40);
383 
384  b.HasKey("Id");
385 
386  b.HasIndex("InstanceId", "CommitSha")
387  .IsUnique();
388 
389  b.ToTable("RevisionInformations");
390  });
391 
392  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
393  {
394  b.Property<long>("Id")
395  .ValueGeneratedOnAdd();
396 
397  b.Property<string>("Author")
398  .IsRequired();
399 
400  b.Property<string>("BodyAtMerge")
401  .IsRequired();
402 
403  b.Property<string>("Comment");
404 
405  b.Property<DateTimeOffset>("MergedAt");
406 
407  b.Property<long>("MergedById");
408 
409  b.Property<int?>("Number")
410  .IsRequired();
411 
412  b.Property<long?>("PrimaryRevisionInformationId")
413  .IsRequired();
414 
415  b.Property<string>("PullRequestRevision")
416  .IsRequired();
417 
418  b.Property<string>("TitleAtMerge")
419  .IsRequired();
420 
421  b.Property<string>("Url")
422  .IsRequired();
423 
424  b.HasKey("Id");
425 
426  b.HasIndex("MergedById");
427 
428  b.HasIndex("PrimaryRevisionInformationId")
429  .IsUnique();
430 
431  b.ToTable("TestMerges");
432  });
433 
434  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
435  {
436  b.Property<long>("Id")
437  .ValueGeneratedOnAdd();
438 
439  b.Property<ulong>("AdministrationRights");
440 
441  b.Property<string>("CanonicalName")
442  .IsRequired();
443 
444  b.Property<DateTimeOffset?>("CreatedAt")
445  .IsRequired();
446 
447  b.Property<long?>("CreatedById");
448 
449  b.Property<bool?>("Enabled")
450  .IsRequired();
451 
452  b.Property<ulong>("InstanceManagerRights");
453 
454  b.Property<DateTimeOffset?>("LastPasswordUpdate");
455 
456  b.Property<string>("Name")
457  .IsRequired();
458 
459  b.Property<string>("PasswordHash");
460 
461  b.Property<string>("SystemIdentifier");
462 
463  b.HasKey("Id");
464 
465  b.HasIndex("CanonicalName")
466  .IsUnique();
467 
468  b.HasIndex("CreatedById");
469 
470  b.ToTable("Users");
471  });
472 
473  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
474  {
475  b.Property<long>("Id")
476  .ValueGeneratedOnAdd();
477 
478  b.Property<long?>("AlphaId");
479 
480  b.Property<bool>("AlphaIsActive");
481 
482  b.Property<long?>("BravoId");
483 
484  b.Property<long>("InstanceId");
485 
486  b.HasKey("Id");
487 
488  b.HasIndex("AlphaId");
489 
490  b.HasIndex("BravoId");
491 
492  b.HasIndex("InstanceId")
493  .IsUnique();
494 
495  b.ToTable("WatchdogReattachInformations");
496  });
497 
498  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
499  {
500  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
501  .WithMany("ChatSettings")
502  .HasForeignKey("InstanceId")
503  .OnDelete(DeleteBehavior.Cascade);
504  });
505 
506  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
507  {
508  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
509  .WithMany("Channels")
510  .HasForeignKey("ChatSettingsId")
511  .OnDelete(DeleteBehavior.Cascade);
512  });
513 
514  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
515  {
516  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
517  .WithOne()
518  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
519  .OnDelete(DeleteBehavior.Restrict);
520 
521  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
522  .WithMany("CompileJobs")
523  .HasForeignKey("RevisionInformationId")
524  .OnDelete(DeleteBehavior.Cascade);
525  });
526 
527  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
528  {
529  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
530  .WithOne("DreamDaemonSettings")
531  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
532  .OnDelete(DeleteBehavior.Cascade);
533  });
534 
535  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
536  {
537  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
538  .WithOne("DreamMakerSettings")
539  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
540  .OnDelete(DeleteBehavior.Cascade);
541  });
542 
543  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
544  {
545  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
546  .WithMany("InstanceUsers")
547  .HasForeignKey("InstanceId")
548  .OnDelete(DeleteBehavior.Cascade);
549 
550  b.HasOne("Tgstation.Server.Host.Models.User")
551  .WithMany("InstanceUsers")
552  .HasForeignKey("UserId")
553  .OnDelete(DeleteBehavior.Cascade);
554  });
555 
556  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
557  {
558  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
559  .WithMany()
560  .HasForeignKey("CancelledById");
561 
562  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
563  .WithMany("Jobs")
564  .HasForeignKey("InstanceId")
565  .OnDelete(DeleteBehavior.Cascade);
566 
567  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
568  .WithMany()
569  .HasForeignKey("StartedById")
570  .OnDelete(DeleteBehavior.Cascade);
571  });
572 
573  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
574  {
575  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
576  .WithMany()
577  .HasForeignKey("CompileJobId")
578  .OnDelete(DeleteBehavior.Cascade);
579  });
580 
581  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
582  {
583  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
584  .WithOne("RepositorySettings")
585  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
586  .OnDelete(DeleteBehavior.Cascade);
587  });
588 
589  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
590  {
591  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
592  .WithMany("ActiveTestMerges")
593  .HasForeignKey("RevisionInformationId")
594  .OnDelete(DeleteBehavior.Cascade);
595 
596  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
597  .WithMany("RevisonInformations")
598  .HasForeignKey("TestMergeId")
599  .OnDelete(DeleteBehavior.Cascade);
600  });
601 
602  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
603  {
604  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
605  .WithMany("RevisionInformations")
606  .HasForeignKey("InstanceId")
607  .OnDelete(DeleteBehavior.Cascade);
608  });
609 
610  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
611  {
612  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
613  .WithMany("TestMerges")
614  .HasForeignKey("MergedById")
615  .OnDelete(DeleteBehavior.Restrict);
616 
617  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
618  .WithOne("PrimaryTestMerge")
619  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
620  .OnDelete(DeleteBehavior.Restrict);
621  });
622 
623  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
624  {
625  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
626  .WithMany("CreatedUsers")
627  .HasForeignKey("CreatedById");
628  });
629 
630  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
631  {
632  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
633  .WithMany()
634  .HasForeignKey("AlphaId");
635 
636  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
637  .WithMany()
638  .HasForeignKey("BravoId");
639 
640  b.HasOne("Tgstation.Server.Host.Models.Instance")
641  .WithOne("WatchdogReattachInformation")
642  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
643  .OnDelete(DeleteBehavior.Cascade);
644  });
645 #pragma warning restore 612, 618
646  }
647  }
648 }
+Go to the documentation of this file.
1 // <auto-generated />
2 using System;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.EntityFrameworkCore.Infrastructure;
6 
8 {
11  {
12  protected override void BuildModel(ModelBuilder modelBuilder)
13  {
14 #pragma warning disable 612, 618
15  modelBuilder
16  .HasAnnotation("ProductVersion", "2.1.4-rtm-31024")
17  .HasAnnotation("Relational:MaxIdentifierLength", 64);
18 
19  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
20  {
21  b.Property<long>("Id")
22  .ValueGeneratedOnAdd();
23 
24  b.Property<string>("ConnectionString")
25  .IsRequired();
26 
27  b.Property<bool?>("Enabled");
28 
29  b.Property<long>("InstanceId");
30 
31  b.Property<string>("Name")
32  .IsRequired();
33 
34  b.Property<int?>("Provider");
35 
36  b.HasKey("Id");
37 
38  b.HasIndex("InstanceId");
39 
40  b.HasIndex("Name")
41  .IsUnique();
42 
43  b.ToTable("ChatBots");
44  });
45 
46  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
47  {
48  b.Property<long>("Id")
49  .ValueGeneratedOnAdd();
50 
51  b.Property<long>("ChatSettingsId");
52 
53  b.Property<ulong?>("DiscordChannelId");
54 
55  b.Property<string>("IrcChannel");
56 
57  b.Property<bool?>("IsAdminChannel")
58  .IsRequired();
59 
60  b.Property<bool?>("IsUpdatesChannel")
61  .IsRequired();
62 
63  b.Property<bool?>("IsWatchdogChannel")
64  .IsRequired();
65 
66  b.Property<string>("Tag");
67 
68  b.HasKey("Id");
69 
70  b.HasIndex("ChatSettingsId", "DiscordChannelId")
71  .IsUnique();
72 
73  b.HasIndex("ChatSettingsId", "IrcChannel")
74  .IsUnique();
75 
76  b.ToTable("ChatChannels");
77  });
78 
79  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
80  {
81  b.Property<long>("Id")
82  .ValueGeneratedOnAdd();
83 
84  b.Property<string>("ByondVersion")
85  .IsRequired();
86 
87  b.Property<Guid?>("DirectoryName")
88  .IsRequired();
89 
90  b.Property<string>("DmeName")
91  .IsRequired();
92 
93  b.Property<long>("JobId");
94 
95  b.Property<int>("MinimumSecurityLevel");
96 
97  b.Property<string>("Output")
98  .IsRequired();
99 
100  b.Property<long>("RevisionInformationId");
101 
102  b.HasKey("Id");
103 
104  b.HasIndex("DirectoryName");
105 
106  b.HasIndex("JobId")
107  .IsUnique();
108 
109  b.HasIndex("RevisionInformationId");
110 
111  b.ToTable("CompileJobs");
112  });
113 
114  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
115  {
116  b.Property<long>("Id")
117  .ValueGeneratedOnAdd();
118 
119  b.Property<string>("AccessToken");
120 
121  b.Property<bool?>("AllowWebClient")
122  .IsRequired();
123 
124  b.Property<bool?>("AutoStart")
125  .IsRequired();
126 
127  b.Property<long>("InstanceId");
128 
129  b.Property<ushort?>("PrimaryPort")
130  .IsRequired();
131 
132  b.Property<int?>("ProcessId");
133 
134  b.Property<ushort?>("SecondaryPort")
135  .IsRequired();
136 
137  b.Property<int>("SecurityLevel");
138 
139  b.Property<bool?>("SoftRestart")
140  .IsRequired();
141 
142  b.Property<bool?>("SoftShutdown")
143  .IsRequired();
144 
145  b.Property<uint?>("StartupTimeout")
146  .IsRequired();
147 
148  b.HasKey("Id");
149 
150  b.HasIndex("InstanceId")
151  .IsUnique();
152 
153  b.ToTable("DreamDaemonSettings");
154  });
155 
156  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
157  {
158  b.Property<long>("Id")
159  .ValueGeneratedOnAdd();
160 
161  b.Property<ushort?>("ApiValidationPort")
162  .IsRequired();
163 
164  b.Property<int>("ApiValidationSecurityLevel");
165 
166  b.Property<long>("InstanceId");
167 
168  b.Property<string>("ProjectName");
169 
170  b.HasKey("Id");
171 
172  b.HasIndex("InstanceId")
173  .IsUnique();
174 
175  b.ToTable("DreamMakerSettings");
176  });
177 
178  modelBuilder.Entity("Tgstation.Server.Host.Models.Instance", b =>
179  {
180  b.Property<long>("Id")
181  .ValueGeneratedOnAdd();
182 
183  b.Property<uint?>("AutoUpdateInterval")
184  .IsRequired();
185 
186  b.Property<int>("ConfigurationType");
187 
188  b.Property<string>("Name")
189  .IsRequired();
190 
191  b.Property<bool?>("Online")
192  .IsRequired();
193 
194  b.Property<string>("Path")
195  .IsRequired();
196 
197  b.HasKey("Id");
198 
199  b.HasIndex("Path")
200  .IsUnique();
201 
202  b.ToTable("Instances");
203  });
204 
205  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
206  {
207  b.Property<long>("Id")
208  .ValueGeneratedOnAdd();
209 
210  b.Property<ulong>("ByondRights");
211 
212  b.Property<ulong>("ChatBotRights");
213 
214  b.Property<ulong>("ConfigurationRights");
215 
216  b.Property<ulong>("DreamDaemonRights");
217 
218  b.Property<ulong>("DreamMakerRights");
219 
220  b.Property<long>("InstanceId");
221 
222  b.Property<ulong>("InstanceUserRights");
223 
224  b.Property<ulong>("RepositoryRights");
225 
226  b.Property<long?>("UserId")
227  .IsRequired();
228 
229  b.HasKey("Id");
230 
231  b.HasIndex("InstanceId");
232 
233  b.HasIndex("UserId", "InstanceId")
234  .IsUnique();
235 
236  b.ToTable("InstanceUsers");
237  });
238 
239  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
240  {
241  b.Property<long>("Id")
242  .ValueGeneratedOnAdd();
243 
244  b.Property<ulong?>("CancelRight");
245 
246  b.Property<ulong?>("CancelRightsType");
247 
248  b.Property<bool?>("Cancelled")
249  .IsRequired();
250 
251  b.Property<long?>("CancelledById");
252 
253  b.Property<string>("Description")
254  .IsRequired();
255 
256  b.Property<string>("ExceptionDetails");
257 
258  b.Property<long>("InstanceId");
259 
260  b.Property<DateTimeOffset?>("StartedAt")
261  .IsRequired();
262 
263  b.Property<long>("StartedById");
264 
265  b.Property<DateTimeOffset?>("StoppedAt");
266 
267  b.HasKey("Id");
268 
269  b.HasIndex("CancelledById");
270 
271  b.HasIndex("InstanceId");
272 
273  b.HasIndex("StartedById");
274 
275  b.ToTable("Jobs");
276  });
277 
278  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
279  {
280  b.Property<long>("Id")
281  .ValueGeneratedOnAdd();
282 
283  b.Property<string>("AccessIdentifier")
284  .IsRequired();
285 
286  b.Property<string>("ChatChannelsJson")
287  .IsRequired();
288 
289  b.Property<string>("ChatCommandsJson")
290  .IsRequired();
291 
292  b.Property<long>("CompileJobId");
293 
294  b.Property<bool>("IsPrimary");
295 
296  b.Property<ushort>("Port");
297 
298  b.Property<int>("ProcessId");
299 
300  b.Property<int>("RebootState");
301 
302  b.Property<string>("ServerCommandsJson")
303  .IsRequired();
304 
305  b.HasKey("Id");
306 
307  b.HasIndex("CompileJobId");
308 
309  b.ToTable("ReattachInformations");
310  });
311 
312  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
313  {
314  b.Property<long>("Id")
315  .ValueGeneratedOnAdd();
316 
317  b.Property<string>("AccessToken");
318 
319  b.Property<string>("AccessUser");
320 
321  b.Property<bool?>("AutoUpdatesKeepTestMerges")
322  .IsRequired();
323 
324  b.Property<bool?>("AutoUpdatesSynchronize")
325  .IsRequired();
326 
327  b.Property<string>("CommitterEmail")
328  .IsRequired();
329 
330  b.Property<string>("CommitterName")
331  .IsRequired();
332 
333  b.Property<long>("InstanceId");
334 
335  b.Property<bool?>("PostTestMergeComment")
336  .IsRequired();
337 
338  b.Property<bool?>("PushTestMergeCommits")
339  .IsRequired();
340 
341  b.Property<bool?>("ShowTestMergeCommitters")
342  .IsRequired();
343 
344  b.HasKey("Id");
345 
346  b.HasIndex("InstanceId")
347  .IsUnique();
348 
349  b.ToTable("RepositorySettings");
350  });
351 
352  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
353  {
354  b.Property<long>("Id")
355  .ValueGeneratedOnAdd();
356 
357  b.Property<long>("RevisionInformationId");
358 
359  b.Property<long>("TestMergeId");
360 
361  b.HasKey("Id");
362 
363  b.HasIndex("RevisionInformationId");
364 
365  b.HasIndex("TestMergeId");
366 
367  b.ToTable("RevInfoTestMerges");
368  });
369 
370  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
371  {
372  b.Property<long>("Id")
373  .ValueGeneratedOnAdd();
374 
375  b.Property<string>("CommitSha")
376  .IsRequired()
377  .HasMaxLength(40);
378 
379  b.Property<long>("InstanceId");
380 
381  b.Property<string>("OriginCommitSha")
382  .IsRequired()
383  .HasMaxLength(40);
384 
385  b.HasKey("Id");
386 
387  b.HasIndex("InstanceId", "CommitSha")
388  .IsUnique();
389 
390  b.ToTable("RevisionInformations");
391  });
392 
393  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
394  {
395  b.Property<long>("Id")
396  .ValueGeneratedOnAdd();
397 
398  b.Property<string>("Author")
399  .IsRequired();
400 
401  b.Property<string>("BodyAtMerge")
402  .IsRequired();
403 
404  b.Property<string>("Comment");
405 
406  b.Property<DateTimeOffset>("MergedAt");
407 
408  b.Property<long>("MergedById");
409 
410  b.Property<int?>("Number")
411  .IsRequired();
412 
413  b.Property<long?>("PrimaryRevisionInformationId")
414  .IsRequired();
415 
416  b.Property<string>("PullRequestRevision")
417  .IsRequired();
418 
419  b.Property<string>("TitleAtMerge")
420  .IsRequired();
421 
422  b.Property<string>("Url")
423  .IsRequired();
424 
425  b.HasKey("Id");
426 
427  b.HasIndex("MergedById");
428 
429  b.HasIndex("PrimaryRevisionInformationId")
430  .IsUnique();
431 
432  b.ToTable("TestMerges");
433  });
434 
435  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
436  {
437  b.Property<long>("Id")
438  .ValueGeneratedOnAdd();
439 
440  b.Property<ulong>("AdministrationRights");
441 
442  b.Property<string>("CanonicalName")
443  .IsRequired();
444 
445  b.Property<DateTimeOffset?>("CreatedAt")
446  .IsRequired();
447 
448  b.Property<long?>("CreatedById");
449 
450  b.Property<bool?>("Enabled")
451  .IsRequired();
452 
453  b.Property<ulong>("InstanceManagerRights");
454 
455  b.Property<DateTimeOffset?>("LastPasswordUpdate");
456 
457  b.Property<string>("Name")
458  .IsRequired();
459 
460  b.Property<string>("PasswordHash");
461 
462  b.Property<string>("SystemIdentifier");
463 
464  b.HasKey("Id");
465 
466  b.HasIndex("CanonicalName")
467  .IsUnique();
468 
469  b.HasIndex("CreatedById");
470 
471  b.ToTable("Users");
472  });
473 
474  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
475  {
476  b.Property<long>("Id")
477  .ValueGeneratedOnAdd();
478 
479  b.Property<long?>("AlphaId");
480 
481  b.Property<bool>("AlphaIsActive");
482 
483  b.Property<long?>("BravoId");
484 
485  b.Property<long>("InstanceId");
486 
487  b.HasKey("Id");
488 
489  b.HasIndex("AlphaId");
490 
491  b.HasIndex("BravoId");
492 
493  b.HasIndex("InstanceId")
494  .IsUnique();
495 
496  b.ToTable("WatchdogReattachInformations");
497  });
498 
499  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
500  {
501  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
502  .WithMany("ChatSettings")
503  .HasForeignKey("InstanceId")
504  .OnDelete(DeleteBehavior.Cascade);
505  });
506 
507  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
508  {
509  b.HasOne("Tgstation.Server.Host.Models.ChatBot", "ChatSettings")
510  .WithMany("Channels")
511  .HasForeignKey("ChatSettingsId")
512  .OnDelete(DeleteBehavior.Cascade);
513  });
514 
515  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
516  {
517  b.HasOne("Tgstation.Server.Host.Models.Job", "Job")
518  .WithOne()
519  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
520  .OnDelete(DeleteBehavior.Restrict);
521 
522  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
523  .WithMany("CompileJobs")
524  .HasForeignKey("RevisionInformationId")
525  .OnDelete(DeleteBehavior.Cascade);
526  });
527 
528  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamDaemonSettings", b =>
529  {
530  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
531  .WithOne("DreamDaemonSettings")
532  .HasForeignKey("Tgstation.Server.Host.Models.DreamDaemonSettings", "InstanceId")
533  .OnDelete(DeleteBehavior.Cascade);
534  });
535 
536  modelBuilder.Entity("Tgstation.Server.Host.Models.DreamMakerSettings", b =>
537  {
538  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
539  .WithOne("DreamMakerSettings")
540  .HasForeignKey("Tgstation.Server.Host.Models.DreamMakerSettings", "InstanceId")
541  .OnDelete(DeleteBehavior.Cascade);
542  });
543 
544  modelBuilder.Entity("Tgstation.Server.Host.Models.InstanceUser", b =>
545  {
546  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
547  .WithMany("InstanceUsers")
548  .HasForeignKey("InstanceId")
549  .OnDelete(DeleteBehavior.Cascade);
550 
551  b.HasOne("Tgstation.Server.Host.Models.User")
552  .WithMany("InstanceUsers")
553  .HasForeignKey("UserId")
554  .OnDelete(DeleteBehavior.Cascade);
555  });
556 
557  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
558  {
559  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
560  .WithMany()
561  .HasForeignKey("CancelledById");
562 
563  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
564  .WithMany("Jobs")
565  .HasForeignKey("InstanceId")
566  .OnDelete(DeleteBehavior.Cascade);
567 
568  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
569  .WithMany()
570  .HasForeignKey("StartedById")
571  .OnDelete(DeleteBehavior.Cascade);
572  });
573 
574  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
575  {
576  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
577  .WithMany()
578  .HasForeignKey("CompileJobId")
579  .OnDelete(DeleteBehavior.Cascade);
580  });
581 
582  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
583  {
584  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
585  .WithOne("RepositorySettings")
586  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
587  .OnDelete(DeleteBehavior.Cascade);
588  });
589 
590  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
591  {
592  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
593  .WithMany("ActiveTestMerges")
594  .HasForeignKey("RevisionInformationId")
595  .OnDelete(DeleteBehavior.Cascade);
596 
597  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
598  .WithMany("RevisonInformations")
599  .HasForeignKey("TestMergeId")
600  .OnDelete(DeleteBehavior.Cascade);
601  });
602 
603  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
604  {
605  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
606  .WithMany("RevisionInformations")
607  .HasForeignKey("InstanceId")
608  .OnDelete(DeleteBehavior.Cascade);
609  });
610 
611  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
612  {
613  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
614  .WithMany("TestMerges")
615  .HasForeignKey("MergedById")
616  .OnDelete(DeleteBehavior.Restrict);
617 
618  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
619  .WithOne("PrimaryTestMerge")
620  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
621  .OnDelete(DeleteBehavior.Restrict);
622  });
623 
624  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
625  {
626  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
627  .WithMany("CreatedUsers")
628  .HasForeignKey("CreatedById");
629  });
630 
631  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
632  {
633  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
634  .WithMany()
635  .HasForeignKey("AlphaId");
636 
637  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
638  .WithMany()
639  .HasForeignKey("BravoId");
640 
641  b.HasOne("Tgstation.Server.Host.Models.Instance")
642  .WithOne("WatchdogReattachInformation")
643  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
644  .OnDelete(DeleteBehavior.Cascade);
645  });
646 #pragma warning restore 612, 618
647  }
648  }
649 }
- + +
DatabaseContext<TParentContext> for MySQL
+ + + +
diff --git a/_my_sql_design_time_db_context_factory_8cs_source.html b/_my_sql_design_time_db_context_factory_8cs_source.html index 5ba9ac2a7c..f09f1b78b8 100644 --- a/_my_sql_design_time_db_context_factory_8cs_source.html +++ b/_my_sql_design_time_db_context_factory_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Models/Migrations/MySqlDesignTimeDbContextFactory.cs Source File +tgstation-server: src/Tgstation.Server.Host/Database/Design/MySqlDesignTimeDbContextFactory.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,17 +71,18 @@ $(function() {
MySqlDesignTimeDbContextFactory.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Identity;
2 using Microsoft.EntityFrameworkCore;
3 using Microsoft.EntityFrameworkCore.Design;
4 using Microsoft.Extensions.Logging;
6 
8 {
10  sealed class MySqlDesignTimeDbContextFactory : IDesignTimeDbContextFactory<MySqlDatabaseContext>
11  {
13  public MySqlDatabaseContext CreateDbContext(string[] args)
14  {
15  using (var loggerFactory = new LoggerFactory())
16  {
17  return new MySqlDatabaseContext(new DbContextOptions<MySqlDatabaseContext>(), DesignTimeDbContextFactoryHelpers.GetDbContextOptions(), new DatabaseSeeder(new CryptographySuite(new PasswordHasher<User>())), loggerFactory.CreateLogger<MySqlDatabaseContext>());
18  }
19  }
20  }
21 }
-
static IOptions< DatabaseConfiguration > GetDbContextOptions()
Get the IOptions<TOptions> for the DatabaseConfiguration
- -
Contains helpers for creating design time DatabaseContext<TParentContext>s
+Go to the documentation of this file.
1 using Microsoft.AspNetCore.Identity;
2 using Microsoft.EntityFrameworkCore;
3 using Microsoft.EntityFrameworkCore.Design;
4 using Microsoft.Extensions.Logging;
7 
9 {
11  sealed class MySqlDesignTimeDbContextFactory : IDesignTimeDbContextFactory<MySqlDatabaseContext>
12  {
14  public MySqlDatabaseContext CreateDbContext(string[] args)
15  {
16  using (var loggerFactory = new LoggerFactory())
17  {
18  return new MySqlDatabaseContext(new DbContextOptions<MySqlDatabaseContext>(), DesignTimeDbContextFactoryHelpers.GetDbContextOptions(), new DatabaseSeeder(new CryptographySuite(new PasswordHasher<User>())), loggerFactory.CreateLogger<MySqlDatabaseContext>());
19  }
20  }
21  }
22 }
+ - + +
DatabaseContext<TParentContext> for MySQL
+ +
Contains helpers for creating design time DatabaseContext<TParentContext>s
- +
static IOptions< DatabaseConfiguration > GetDbContextOptions()
Get the IOptions<TOptions> for the DatabaseConfiguration
+ -
DatabaseContext<TParentContext> for MySQL
diff --git a/_native_methods_8cs_source.html b/_native_methods_8cs_source.html index 4b5fa6c0bd..1bd9872075 100644 --- a/_native_methods_8cs_source.html +++ b/_native_methods_8cs_source.html @@ -71,15 +71,20 @@ $(function() {
NativeMethods.cs
-Go to the documentation of this file.
1 using System;
2 using System.Runtime.InteropServices;
3 using System.Text;
4 
5 namespace Tgstation.Server.Host
6 {
10  #pragma warning disable SA1600
11  #pragma warning disable SA1602
12  #pragma warning disable SA1611
13  #pragma warning disable SA1615
14  static class NativeMethods
15  {
19  [Flags]
20  public enum CreateSymbolicLinkFlags : int
21  {
22  None = 0,
23  Directory = 1,
24  AllowUnprivilegedCreate = 2
25  }
26 
30  [DllImport("user32.dll")]
31  public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
32 
36  [DllImport("user32.dll", CharSet = CharSet.Unicode)]
37  public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
38 
42  [DllImport("user32.dll")]
43  public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
44 
48  public delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam);
49 
53  [DllImport("user32.dll")]
54  public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam);
55 
59  [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
60  public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
61 
65  [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
66  public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);
67 
71  [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
72  public static extern bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, CreateSymbolicLinkFlags dwFlags);
73  }
74 }
static int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount)
See https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getwindowtextw
+Go to the documentation of this file.
1 using System;
2 using System.Runtime.InteropServices;
3 using System.Text;
4 
5 namespace Tgstation.Server.Host
6 {
10  #pragma warning disable SA1600
11  #pragma warning disable SA1602
12  #pragma warning disable SA1611
13  #pragma warning disable SA1615
14  static class NativeMethods
15  {
19  [Flags]
20  public enum CreateSymbolicLinkFlags : int
21  {
22  None = 0,
23  Directory = 1,
24  AllowUnprivilegedCreate = 2
25  }
26 
30  public enum ThreadAccess : int
31  {
32  SuspendResume = 0x0002,
33  }
34 
38  [DllImport("user32.dll")]
39  public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
40 
44  [DllImport("user32.dll", CharSet = CharSet.Unicode)]
45  public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
46 
50  [DllImport("user32.dll")]
51  public static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
52 
56  public delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam);
57 
61  [DllImport("user32.dll")]
62  public static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam);
63 
67  [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
68  public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
69 
73  [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
74  public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);
75 
79  [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
80  public static extern bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, CreateSymbolicLinkFlags dwFlags);
81 
85  [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
86  public static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
87 
91  [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
92  public static extern bool CloseHandle(IntPtr hObject);
93 
97  [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
98  public static extern uint SuspendThread(IntPtr hThread);
99 
103  [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
104  public static extern uint ResumeThread(IntPtr hThread);
105  }
106 }
static uint ResumeThread(IntPtr hThread)
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms685086(v=vs.85).aspx
+
static int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount)
See https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getwindowtextw
CreateSymbolicLinkFlags
See https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createsymboliclinka#param...
static IntPtr FindWindow(string lpClassName, string lpWindowName)
See https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-findwindoww
static bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken)
See https://msdn.microsoft.com/en-us/library/windows/desktop/aa378184(v=vs.85).aspx
static bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, CreateSymbolicLinkFlags dwFlags)
See https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createsymboliclinkw
static int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam)
See https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-sendmessage
delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam)
See https://msdn.microsoft.com/en-us/library/ms633493(v=VS.85).aspx
+
static bool CloseHandle(IntPtr hObject)
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx
Native methods used by the code
+
ThreadAccess
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686769(v=vs.85).aspx
static int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId)
See https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getwindowthreadprocessid
+
static uint SuspendThread(IntPtr hThread)
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686345(v=vs.85).aspx
+
static IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId)
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms684335(v=vs.85).aspx
static bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam)
See https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-enumchildwindows
diff --git a/_i_d_b_connection_factory_8cs.html b/_open_api_enum_var_names_extension_8cs.html similarity index 87% rename from _i_d_b_connection_factory_8cs.html rename to _open_api_enum_var_names_extension_8cs.html index 154d781989..fcf8823d69 100644 --- a/_i_d_b_connection_factory_8cs.html +++ b/_open_api_enum_var_names_extension_8cs.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/IDBConnectionFactory.cs File Reference +tgstation-server: src/Tgstation.Server.Host/Core/OpenApiEnumVarNamesExtension.cs File Reference @@ -71,16 +71,16 @@ $(function() { Classes | Namespaces
-
IDBConnectionFactory.cs File Reference
+
OpenApiEnumVarNamesExtension.cs File Reference
-

Go to the source code of this file.

+

Go to the source code of this file.

- - + +

Classes

interface  Tgstation.Server.Host.Core.IDBConnectionFactory
 For creating DbConnection More...
class  Tgstation.Server.Host.Core.OpenApiEnumVarNamesExtension
 Implements the "x-enum-varnames" OpenAPI 3.0 extension. More...
 

The documentation for this class was generated from the following files: diff --git a/class_db_context.html b/class_db_context.html index 7fe2ce8d1a..e75eea3b68 100644 --- a/class_db_context.html +++ b/class_db_context.html @@ -73,11 +73,11 @@ Inheritance diagram for DbContext:
-Tgstation.Server.Host.Models.DatabaseContext< TParentContext > +Tgstation.Server.Host.Database.DatabaseContext< TParentContext >

The documentation for this class was generated from the following file: diff --git a/class_db_context.png b/class_db_context.png index 72dcd863e0fb75c3d22109771a4f10269cad994b..8040b515e309f2c5e4450b2689ec01e8325dc73c 100644 GIT binary patch literal 1019 zcmeAS@N?(olHy`uVBq!ia0y~yV4MJC2XHV0Nrr!y{{cyf0G|-o|Ns93nJ?aaE$u%9 zQUS&X4jf?Zydw|fa+C!51v3B@fxy*MAw~=g%w3)?jv*C{Z|7zfy;cxlo87N<|Nn{e zW==fado-r**_a)aWhunNoHcF#k|{wGg1qb$7+DzPI20NBkns;4#h2g0cjew=DCx7G3|K1xrL#|Qjz6=ATAuPsJT>R$&^Xl4Evh69T*-o3ot!s zKdsusutTwh;m5;Q$~_DfK-LbW5(W#U7TV%R*)31zd^RsQY582gLC3RErBb2AW0JB{ zhl-^VjIoHz^Qr%&owpu;-M?^+n2+P6EsH{=we!y>f708mB3o!waPw{RzMDSRR~#*$ zl(N41Whc*Lu1b;mE6tOlC(Zj5aU$T`t_i`7uk-Bx#^}D;`1Z4;m{VTyf zPkQ_5yV&-h1*^k;C&ztt%5u!D)yvs#JCidjQJuNhH2A7Xfx*#g#j=`Y>vZEYPVWSR zjHXYzm8um|Ulw#_(YMW~Z)^Mc%87m38yK{^PUOb2i%CbkvZlZMuaRQWdMTcJ_9?c`*PQG04=;G)(DC-- zsl4sKr4bBJtA`V?MpJdH|ENH zU7nq3#qxbd*^e*WH=nHjpSxGr|JlO(+V{C-cIAq`i@vobQFq&#+L&N#b>kAJwp@ov zOrF1j-4q`ODg)#6ui#~_mEBPwvFNbqX)3IfzQ}VZPI}TIpyUb6Jy6CDE?^>1cs?ig a1OKFa|BaWMSJnY@Dubu1pUXO@geCyt5xv>~ literal 1045 zcmeAS@N?(olHy`uVBq!ia0y~yU~B=h12~w0q~7jNIY3Gxz$e7@|Ns9$=8HF9OZyK^ z0J6aNz<~p-op8-g`W$6?lc2)((4kc9vmdQd4O`e<#2bZukB&<_f zc;~+^=WHPc_xPfT{kwhUy-#ri9E-C>3rt@?mNRUAuM8seW;TQB_2_~BrTms9kE+fv_y z-V|;LTh7vOf03-w_m=Ci7rC|-FTZ>K?B#o651My&u{79wdoggRp}8%H$-zLAQDMgH zmLM-rFHKdRhVIX-6Bv$66kg7q>gI$n2>9SJW(uX!XXGaY zWUsycZ1uG$ecsSXLY`epsvbcGnvRoz!8u99$7{lpgjp?{{!C7p_xJhR_3PG!^2}Aq zJa%bK{+@q%NB7-2`rR=1prf(pyP3;_RgJL-gZUv;M3dRUTyD9SN?e=bc_8v6WLjQPBS`-gwp2UO#dFmBA%>t@JW(> zOJUX71lOSUzc2IVR(5o@6wXs;pIw~%XeY;J%~!0m_$BpZs@2cff36m^;$;`gaWh{0 zE+zWgZMj5i_m~THe|JrhJGxmR?9La9TUx#Mx4pdmGHv_2l&+Z9FZZVS$4WmA<+N+s z`@>&#j+}emr$2I=Pv44{Zf;2w^;bP3{{LcOiPXcCxxX5Z%{92sTDK$LrDC7(y!)KR zobN8HAHVo>u0gDWdU@0PkAM7L1i$?~>uGU;x`&qX-#L3E9)9uLaee08JMaFk-QrQS zrakrd`CgNltmyfFjU>~v*1vOlw|dFk3(-Yy*I&zc`6lRf(AHbq9%otfs2#ufP4}>c zea{1x67l&es*}EyRdN2ks_5CNvUg&l`j)fWAlCewg(^V$uX<3E3hQJc70nq_6g+{M m%9HDv+QMs5lcTbEAIl5;^GzzW3eN`SVFpiEKbLh*2~7Y?X3RDK diff --git a/class_i_design_time_db_context_factory.html b/class_i_design_time_db_context_factory.html index 7e7b85a494..3b740dd2df 100644 --- a/class_i_design_time_db_context_factory.html +++ b/class_i_design_time_db_context_factory.html @@ -73,12 +73,12 @@ Inheritance diagram for IDesignTimeDbContextFactory:
-Tgstation.Server.Host.Models.Migrations.MySqlDesignTimeDbContextFactory -Tgstation.Server.Host.Models.Migrations.SqlServerDesignTimeDbContextFactory +Tgstation.Server.Host.Database.Design.MySqlDesignTimeDbContextFactory +Tgstation.Server.Host.Database.Design.SqlServerDesignTimeDbContextFactory

The documentation for this class was generated from the following file: diff --git a/class_i_design_time_db_context_factory.png b/class_i_design_time_db_context_factory.png index 3191e8cb11a01033a002b942d5af0b293f82ad8c..18788f830d1c1c6cb5a37e80779981640c6ae10d 100644 GIT binary patch literal 1769 zcmcgrdo+}382_eOC8dxgEox(OuMp7%#pWBP^qE1qr)*-5JsJ0Ca%qclo7_fd^BMOK zVaPDVN+r?fGHFb5*_ceaOx7i`pSJyH_nh5x_K$tedEejfIp=xa=XrkTeXiOaJt8fo zBn1F~G-z!J0RSGxxSb>(yG`P(BQQ|3vn5+CEiGYmLNpzi*ph^?FQ>V=S>o!TD&|Vk zpriHx7PM@AkI4D}urdU+v>=Dz-ekW?DbSW^^e80t4K%{ z8WuGHO|d>qf&r;V9;+|2X3ZKIyzgomjQk@ey^o0~KRdsGBa4PEgg1T)WGCUr*x|Cg zTjqfWM#Z%tZiPMze2a(*kFBc+nm8iLl)rV4Ah8Qr!jCd(Mgx$HV{2!uID%iVv$OxF z!9c1;V|~rVNbXWst&3j=nst%Q-%nAN^N{p|==5t;v`u=0ACGtjEuSpL-Tk>Z(Kmc^ z^3~VHrfHp%yFD2z6zNMb1sT<$2&COK^BEx|^z;$_8Cnvh1 zlg+=QZI5B550iy`5$r)7H(+Hmph&O8=2=U}DJJqd^f0kkdhGSX>UjY7N8cRh$S+4c z{TdllKo{IJ^W{}L zm=JMzE0~fDx7#zxDc95vsAQ2-ZhJ6@5GDl}7e&$nhbusJO(~-ywb)idDy;DgPLWUO zhkF)w6xFfYXD)Ksr*5jb8U*u$-Ew9ajs`ZUY&Jzz`lP$U^}d%~D*jf^0ezY3s~%8i zzC$e3DZH{lBf_G@DI-+ivJfpl<$zXYCLHSPNQDnS2^4U~*@&4_^PMPHk?w%mm7vVT z*OqnUSI>-6XjbJZmp6&m=Z7b?>>#*4N$e_En2zA;7WCD6eeUiUJss(0+FyRom3Mhh z7{5;N;dI+A>NAVpz*R$!{alS1dJ%DbT^$X|REqbO8YIY9BegWxUbI`ajYJ3zErhg- z>JmswPLH{?^!STOE$xKGb;+y|6n>*+N_PLu?m=;rCB#dFF;A~XCDL<5e5r#{9@uHl zVc&K4K}*hBA?#!d{akpqfaYCjIwiJaIY6PxOv8$d>ons{OIu@)kxr)H$U!)GOSBg{ zh!lVaolWgU<0Xs}jb^->(1S)kHS^I=1!wstd=@K$3wbNl7Hd#f{5IF{16uf}R$N1$ z%3(@;o(pBogEQeX#f%(k9FceE(+6#*oHPr5P<(WmsN2{lXhiR>GQ-W%SAEbS+`i?> z+PP0=$raNR`QY}r0qfv^_v@kA=kSp|oW*xpP>zj5=3D~85s$sxdhS)JS??1LqekIO zH95~6?7AJ;HP9M8KXFqq&Mt~1$@01FxfzD63}qqmbtq-FS$EAN3;TxkFuzSW5!R3} zdTH`_KTYr~^P`~FZeIVSV~bWZ671Mwl{9i;uV}V_a9zjSu|B@d%zD_1q37&&?xRb! z8J<_mfaB)+P>96}qc{`|+WAdy@ZK_=?Z4EGp;K6OHp~ zKD_Ay7jy(a4P^9kTD)V2PWyMid59wHp|c}6;*c^HuNLQ&z2s4Ta4O+O6{Uw zOmhIoh#!q7u}m5jV|~LNSVhjqN09OO0J89Fu`giYaPWwFi618}IXC69lEyK>YirQ^ z&Mtbs?eYp@7+KgS9S9SR5524<=$Qz^4;D9wD{0PMgy@mURp!n-%2=TuYv8A?sOxD0kFxC=0<`t zmfhs-R?uKnyB6F|Y8cSoj*{EdVT~hz&r4^vtCVqP3flThUY)zi>R$c=5dRTdYFX)O z@|Neg(c(}VZ!@S64t~3&38Cxbq4`IPPz4t-7?{{vEL5&Ao-}Qq=y}BjGFJNy(8fZ^ zzvztnn)P4a|D75D+hS)5z#;$>VJipnf~?o%mV048^g|P&>dVEiVmS{m5CVPc7#2ck z(%;oa>nc|P|D<|46aQ0sQS|10QvRbi@3WSY^$gDi=^Ijp^s~4KF`uXAM) z3I#9`q|GgUz-*(9Sy~fCyPG=wh?-g4G0<0BkLuPOO9?`MBNg%RL@)zgMtbr4gv8$_Y-12{GR4EmCCs$C z5s!Os$

ksJuUNvNC8p9aX70w46N{MS#gIP0Q2LW4o-q{flThhqY$aYpGg0cn?fl zF*7tRv#G)}QI8X{L)Hx?%k8xDqY66*j8$b?RYvs88HyEMTt;Yf@7>)_L7OnAD+$Wm zti~ul42?Tt9iAtR-VrOeLd`YYuza`oj#R9PnM+)0d*`%uYAAg;jvsSM9gsQ2!yQ1- z7kl9{nS;*TNbz5MLtyus-;FuJjH3%v*b{{)MZGP@;Z(HsndL#5TIQ7G(W_#gJKJvO ziuZZUgvhR)5Y3d+idF=>UH5#IqNyNkpvXOwbe(=C$}3z>-;DG3nteSgf7a+6?%N~L zP~VNF7L#0BeRy$l&~#8To0>#M6t!uq84Aw)x`i$-2d(n_*sODEJ1L=h-n}2(J#II1 zAR%F-sA8mRz;*JP032ZxO3I8n803WDCAeU{#0owp`e4q7!D9n)SS`Ff(dv`m19vY3 z!!hrABT>*BzC7;*vNG~$*N*2SA&&G$ncSb&VjOB!$7@9WsbN33M&xg;sXQ9ngBHUR zYLt|FUi12OvlL>`Q~N3tCNvtFl%tTs;8CeVALjV zDwuWdwQU%#BDDGUx&@E6>c*T>=P6nC>CQz(_HfyF-44+58?07c?jA_)qu z2+Kb2d03Q>w$q-CT#Z?CIZEn9y~@nsKwzwa=*jGW=!wzM zV*$}qeh{Ju57Coz9-`-9a$#a2tJ6p7&{4KU<$%3bz#`<_PoGrZbIz Tgstation.Server.Host.Components.Chat.IChat Tgstation.Server.Host.Components.Chat.IJsonTrackingContext Tgstation.Server.Host.Components.Chat.Providers.IProvider -Tgstation.Server.Host.Components.Compiler.ICompileJobConsumer -Tgstation.Server.Host.Components.IDmbProvider +Tgstation.Server.Host.Components.Deployment.ICompileJobConsumer +Tgstation.Server.Host.Components.Deployment.IDmbProvider Tgstation.Server.Host.Components.IInstance Tgstation.Server.Host.Components.InstanceManager Tgstation.Server.Host.Components.Interop.ICommContext @@ -92,17 +92,17 @@ Inheritance diagram for IDisposable: Tgstation.Server.Host.Components.StaticFiles.IConfiguration Tgstation.Server.Host.Components.Watchdog.IWatchdog Tgstation.Server.Host.Components.Watchdog.WindowsNetworkPromptReaper -Tgstation.Server.Host.Core.IProcessBase -Tgstation.Server.Host.Core.IRestartRegistration -Tgstation.Server.Host.Core.JobHandler -Tgstation.Server.Host.Core.JobManager -Tgstation.Server.Host.Core.SemaphoreSlimContext -Tgstation.Server.Host.IO.Console -Tgstation.Server.Host.Security.AuthenticationContextFactory -Tgstation.Server.Host.Security.IAuthenticationContext -Tgstation.Server.Host.Security.IdentityCache -Tgstation.Server.Host.Security.IdentityCacheObject -Tgstation.Server.Host.Security.ISystemIdentity +Tgstation.Server.Host.Core.IRestartRegistration +Tgstation.Server.Host.Core.SemaphoreSlimContext +Tgstation.Server.Host.IO.Console +Tgstation.Server.Host.Jobs.JobHandler +Tgstation.Server.Host.Jobs.JobManager +Tgstation.Server.Host.Security.AuthenticationContextFactory +Tgstation.Server.Host.Security.IAuthenticationContext +Tgstation.Server.Host.Security.IdentityCache +Tgstation.Server.Host.Security.IdentityCacheObject +Tgstation.Server.Host.Security.ISystemIdentity +Tgstation.Server.Host.System.IProcessBase


The documentation for this class was generated from the following file:
    diff --git a/class_i_disposable.png b/class_i_disposable.png index ab15d53c942712894b8ce9753bb89772e24a55bc..2f8dd8a8798afb8f1e08eb42de44db5701eedfc0 100644 GIT binary patch literal 25645 zcmeIb3sjS5);8SMu^y@ti$WEJiA1O^LKOvpK&GHWQx$5dpmOqrcmN_Ggg{8DB8f%8 zMg=t-R7R;qf{L6&q7p!ifD|EMLLvbYBtS?4B!L{h`w3um+B!4;x4!rN*P3Q6S0#o# z&wW4l-uv3uzV`0vZ@fI`&s{qAz4zXmkN#@ox9`0-gZ$omAO19Z26$&|d}cWK&nMq( z`EHY5uLpna8yJmAdvp%`&G6^Jg9kHD^DMxRvyXl2ScIf0534*#Z*uC+{yan`rva zyLOK1%?I4|evgX!^{(xwbcIQwt@?yJA8CWoX|hf=jeyW zrMWr1$OG1&m%$&|4!~JW_|)XtGf_{1+%t(AhR%{&N;y^Xk->4HrtMH)OJR5N?8-Yu zu%^0R>sg$A+BTjgG9P-22@`80M#I;a!QCIG-7SKpx$v!6E#-PLu@RZj$&pY>(;K$HLFqU(aS0eLuf|G%L`mf`Bwai(S&-53E zZ;um=Vy{i_&ZDlQ8=iwd$d#Xds=6C=_3G7^6YDpA`spX#y*F06fB6tLf8pG@wJK(H z`s|rAE!RQ+a&rlI|F6*dA08rq^UW7uc_f`U@#WGLix$oM1$OP~?sH(rW}Y;B^dIp5 z#~)R@!o6D7wXWOR;&Z}vViVj7y|UgI+MW4p(AnD!dxMrwZq62pVRx49r5K*k7jCTT zSHYB;$V9c?o2oS7tgQFUtm9K9c;QI+=#Z>t!q2My)AX@Y$QunvSwp=Q;XzLbp`7^z zJXFGWWKM5l!#@Asz1pUUwl;aM8Jy-&G>j(yo0q!FdY zMMKwI4z2uD*^Bp43xz*-4c;1Urd zs1e%NE3Z*%;}MW`rOw83S7Y%HMDyq+!+h}ZZ=jDagh%|ah4Lez)(26a08Z?qra7{E zb5_=WGk+l=DftpYFmO}_pSf(-yL~)sdZadzZ(bCaEJJvDNZhod? zEoYDT>=E2y*JJ9jLo}R!U{W0aT9b18aSeJcF#AB&D!936Y}AfrPCfB9A3p7D+coP{*^@niHO_Z8{XjyPu`@79Wpu$RT8nR-%Rp7i z`Tf9aR1R0W2lT`+f9MtFD9Rhx1gm_>8K(vOg;G+SRESuzUk_){>2%Fp)M^$NHk7;} zxajA>WkRb5F4PyXvvhG}CA6LjOJE3BVSX+zt=$9G(_M?r6YM$Nunc9w1o)1BKxT3Q z7VM{sOl%5XP-mP`L_&O?=Of0Z!)aa(`_gBw7VoMdI;|Is&j7c+!EozIWvkYrYbVf6 z6ohj9#`aS=9}DTthXhozKvOJGa0^*0B&cFK~Vn50cUH z3p(kYsrUX~xZDAJ1^6}ZzINy=U%Gkd=R;R+=KUpMEWsUkQj44aubt+9a5mrZQB5{1 z@6eUQS8l#q^)Op|9d`a7l%6@z?trB={XDf=U$B4I;8yj9h&An#KUpm78nLSvmN7K? zyoQ7n38lxfai6py#w`**anhcF@~7YnA%i~ZNe^V?1GBG{X=ZV>$T9x#5wb;=Y(~+_ zdL`uLt35PCs?*@+I@eHHFWrCnte~;mYzhjqudupt;<@~Je4l)rEJ*=rHQ$$W)h{+PQ;;;vl2^CIyUwWF&sbbujb`{k=lgwlP=b zXu?R=3toP}X80voN0$1^_Hc2S!~6V>>JpdX-aKWf=5ZKWUS&AH-~ZG3)xrcORfx@St35xutMnhxz7-*06V{M+bK6`_35dj0Wy(-n>Yk{lJ^z1Hghl zSuUg(B0!J~T?d|2my59L*@E*uX@(yR!Bf0->WM{P0e-{7V+$p3gh-lt&pv)|`WU;{ zEieOqW!+Yvtu5`4H%ALzN8G8MF940c5LYJ-!b5Y61yNy@wT%OM!!vBCs>DGuOv&J7hOJH6^ zu=kB_u1Hu>FH}9vgCbTA@Wp(H(W7)neqf1c;#+Rccr7*i&vw#m*dZ!S?aU6u~A_bCel2C!5MF4`-x}q zlFA5VNetE~J}-ldNcowta%3zmp?U@5K#nNNA_pz$l+FKE(+ z)HwUz&-&P_8&~ow6%F|=^|zUUB-eSep=X-}rIwgRfx2Kdszo!{ov;_Oi<7Xz%?FDQ zVvPO&5%<--yLcSmC`j*0uZeADRE=Ra@8I<|3I%SeLuLusKF!m7ZycACyH>hD69W=~oCet+!lUgrg=oMzWiI?EavzXd}zY&V_=3NSRm^FKC!a72`JC zf$xn3zMrmHKwK&epPkmGIQ-DoBVcBnHEZyutbDmlHss2bHNyl;E8QnJX{}PU12UADa-1sst{@WX22uH?n~}a;TdPg8}0gso}%Ro zA;(_?;LXkMA1=QIZ*Irt_1{@;5lrYJ(ytc$2uGpx(aC$C5lNn`235wAfiM#tWIt#a56#Ne8a91vu#ojG&-$F5~Q&{-l zz>rj@q2GuhOB;%2%Vu~q-O#-fkP+%T5M)^l*D*yw#JIrty7}Gm-eY5`(TXoJ-Zs-1 zxngzWz9!`^0Z!eo`JM{n7)4eMd66;m1C!&V3u#PRYv@*r_YvS6f?-0OY<1eQC|8pi z=?OJ4YwYaGGk2YuvQFAc9#1W5J#d{$+HnT|iLmpUBIhD0?augPVrevVtP1DIDsKCw zj5$ohEb;1|Q9-r;Z4Ww;?J4jz>z5xNB2;P~;)s1KSPeQHR>*v1IA($56uKzR{8U`g zPvX`}WK5_hoi9|t`HK=eelX$ksvk#SS*7vx2ojr03l2veq2OQWJn%RiPQ94%1%PAb z1>)B9`|~0fzs!PVm=Xw{czQw;2EUF~nr!Qi$6$gI&mh#dhoB`I3lGoIY$WGDD9HmE zju$TUxD*?v?OZ4Q?iC3c52q^9hq^5C+KOk_MAzy+gb3zgWdE8CKFCI~rMXV0a#@^)+jWBl?$aJeM z68*z}V$Z6W7{uq+3~6iW9Bb`^r)j88D;7dchHfJiZY#gijawwdS(MR!!6n*xcXli+ zECpZdxXI43!X;lPbq_$ka13wE#G~bZ+E8w))2OvQ0I>GfRh4Xh_ z!Sd;DPiMu_jFRFyoGp^d+7CGz8bckm*}BO$N-TPxN( z{Dv}^@Tx93X;+AH+eT@62c-q(B9_g3VnP4dPHjTCM9 z3C7_$dMj4K3`$SVLEw-DCc>CNTDmlRZ^|Mgv_raGlS`9?Nh;kziqog3F;-_Euy1x| zj;6*bk5M!;pzHX11oW)0Q+&!&h>k6DXj&6oHaD`!G6*A6!!SQ&mv(X+X&&H|FFl9Q zvtGwI$7#x;|0SRt&Qf8H{;k#qYigiklFQ7&hc{wD1jc+6Sv-TVg0+1&WIRE6bo=Jf zxV$=}Eyt)s-S4C2-cYV3og<6swcv;}y+@IeP6=P#i*k-3gciH3_AYRsu~!1LkZWqZ zdi=!{u*Af;jI65{d6j}S2Ok1!)+1S4e?+h4d&j3E)IO7Ym#I9BP|pEz?l?%mgZri^ z31g7Be2bQ!{4=flT`J;rS{M56w2n)1+j`$Efl#bV-;d*I7t==v(z3_9Lbp(ipyxrn zW63DKZeDPsTb;K0eyN9swGr)Gm(>%Yi@+mTO1A@)Fdnf#c{b)SNFyJBXeA?YP$PBB zu?)yg8btTz+c@5DktiOF-ijeB%oGEX9N56-Z?)BV}IL1oPo!CMx{s}l}U5BU*2y)1A}yVbKo zX<-x3IkPJ8cN7Jbo?Hks0>3fM74DDJu&p6X51vd&G!(T$lU0Sp&5*gKVOiB(o&{Qq z3QJwL;9Dr(bwdo={>(pd<-2iZF3c#8h&HJk?bV~g`ThYJ2&v0_?g9o~r-E#5?3%Z6 zK~r{cr}_+cAv&r_f_d3g=tW60SZReNpLTsa86DLfr`yMt4#H4tK+KD@E~hfh*x&H! zY${x*Zbi%2K#xf3uF+$3kseNi@1;yx>6(ATN@J)JO-4a9qeJe~xNj&))s=s~=R9;W zf=|T-C9tPCM~R%yh|$LGe3Eh8(T6s1856mS!y(}$tyQN>nwSe@BB!Q0(L=us!gxPO zo1ha5f{CBt@O-{i$yc&-`}e8k^z~J`gt(L#vJ#{2;|dQs7_T;SMpgG4)y1YaoGi4` zjew=>gqHF-pw$fluXU;GKZQHS0Ll>_MB*nZ$IG}KO*tWJWMZ&i-mgJqMiK-fVd5jc z%LCd(hh>7KvKK$QRav_6t1x^`7+Erl+2M#9WIUxv;})&UUlhUGe6 z1boso7e5^U-2v14R(*7M!@GfE#Xw_T8J3GE7bAyMgM-!;>a({AJBbsQDLsD&?kp}E zaQF7uHeX6_S!O}rp&D?)09y5L+6Zc@n&Sq@PDjn8|B{kvGwENt%h{YXTo54vDatqYZEs)mR-gf z3%jj%;UCXZ@*2+pI9gR#rrU(3oQ2Hr8mutoU@5ACtl;zAU zdXbf$=WE94rKnBB%_*l%J~|dXKIY`*jZ=Rfl`UQ?ay~}bS0oTT9ld6~E3iuEfKm+3 z;{*??9V-&gfO4+#z@)`86VqKd`rZrO1Q*CxX<=d%7cDo&CzADl9Ym-;VIYNH;`JQY=87D2lzFEWXwyp}wLJ)65F10x| zu9Dyj_?5E|tfl|ff_2X=aK8Xl3ptTzQ>b>lj;VoAZCzm<7US?vP#YB-co!KtH1IJu zmIg4~k14lA9LMvv1Y*8X4#J`hWRyDOTeS*P(P)9BbhBmtO2(C_#Us5Yd5aShFO>#` zTgQKKAW?@uNxcmC3fzTRIiq-Ca+heVBW^D?JMy9z36f`Q9DNg0X98U*K zriqLJWXjnvd(lI0rOuhYTqxSsG~@=#xn>6HrCLCWBR2DsK!v*h<-O1R&UPl1?NsOR z7FtO8Mzy>nqK5&1=oM94*OLt8iTtT@-(-2>=aYjQQ|3zs&80Jo>7xy?1UnYVMR-7p zUnZ2RP0hlbVNCn(t`)kD$pR73`jgQG6Uhl zY+q6a%>Ym#kg-H7Fv6V;A`>5wTU zc+hPnqe8-+6HN(QqaHs2wxpl3C8P^B-B=il9p|O0 z_(R&4KD^3MipHaJAy|PUt960uG|Vrbn9%RQl3c)AO%?TYKFk;#MPndF%slXc>bk|w zM5krm0gdLA+nHWjf}Mk2Y@htIlBjxoilVP(V@i@k9ww)I|GF9{H1KnN+>Jn`kjjj@zK! zd~XBIPOm?t;0r4dIKiRz*x}yMI_t0RIs0a~W}?s$4H$h_0T3oYK)$eZA;z?OO1pG- zyJo5spvs3edAGv4Qb4I(O=n-hYrA3&nJa&qER{}p0ydB}IGHTN^0=#~;iNDYw2C{V{w?$c4wXw2M7uznhOdM?N zfL!HPK=oJc;9*T zoNkYcw?CLT%9e-;8{u{t+b%r=FM~2 zN~eE{W*FpwFJO+Ftm@-XFL&x%fp)b06cHw*!+~(>3)N0tZ=pf5n6g}URE1u?K%YBo zL|hIzncyTyj-lTLtnCl8lh@QfP)=RBc_{wtJE2T#AWl{7`QOo@{-=!oW8he>+`M)3 z(3R|u2RiKLLb|bRNF({LSIh+3)A5Y`kpaOveT%57CI-armOFzl*^)GGz{=mY^>>Y; zAY+#e>%yg}ajG?x9wTV$nSzCaT@h&}FAlA-uCL@TkQqaA6{4|lqO=MHXnt!TSW{n$ zUPWq|o7g$S4@4F3eC0jQe`Y)gBLAm1o}RR*az?$3k_4eNNN!drQBsofEyuErd6~&= z0J5Mbrhw~s{+jFP9a_sQ-chSqS~c&VgG+vkqj$0Scx`wSikBKULPb+hhI*_mOY&$} zK|7aavdWwiW)s}Vtqn0Q2NYyHbBcm=)xNxCo^)whMCu^f<)Y)pxXr*Dr%lD1ZDjFT z;fAp6eT<`vg;p0@=j!%@f>{%H=;p;5OORP8dgd?W%jDqYf{!GZ!g=!}83(p=omkty z$GQgusnpA54V?)-%_xvZh1H|wI77U#oid-};gI=opHw+Q1&PvdQ;9h6R9uTp%cY_E zP9|jQd!7owu0y`dZmulmhIvN&yNUi??UOVkKSC%bF_DkdS9+g0Moh%94$GZbOdCkG zqe-01mI?{!IU^k)jchPIwL#zNP06_mf207hN4|tqowh4~{=)2Fun}KVEW#k~0;Tya zAlzGkgb8^=|5`EId}LbFW$YXapsp!6iPKWPY#`!(N%~Ju^#76yoN3K^!v%cGLfk^& z+<_PQjp*<FNe%=8CEC&jz)yL$9?V=YQ3PSX>bg!t_x;Ak>B$ z(`I)K(LN4@B<~Fo^Zvbj2&68RFGqx2n+@ouc9 z7wA{CBo$;$pW{P*--tpYv$}Qg78h3N!@t}Y zPjBgty*`LkqH0JUn)A>{AqQ4CTNcx~+?4ZfQ!<&Dj7d>G%^{D+Wxg3aH<`fuM+EUE zWJDoTlmk9JEl5{eW_M`?ns4woD_FQZG$rR{0+7zNn{N3LAvI_{?pc~IK;5ba<+_G# z!C!2m&>=brk2WB^Do7^)#UUq9TN{JUo6k5C(xF4|EvYhC6=ZeS_Ccn$=T~npoda4Y z2$%i`yCnWEY+0V*p82alIRzAfzouA2`2(~xsMqCnB>rdFZ`X`}M}XBT8!mc^(bX(c zbf7e!PEmnjfICD^>3-{cJGpSeUPv>tTu2h(Tv*IY!hqo%-BvWk41x>xK!BAD39!Dd zJKHrSzX-LoGu}dhD-#T)gH?Romq7Z?g>2Q@=jkR!j5&4|K&W6UjM-UeBL1}~ z?f>YFqI7}7^WGVqgvwh7wU_b|htl$PB$YL)MQP7OrJ#HUo%SY@A#vJ9c1*zron`xA zV_A~bZWh9=%^3wD>UN`8apmIGG(B~d$i$CX&h_I$SH3?D3{kUX4oQ{pM$YZS)Y4Ni z`yAo6b{b8pDo#oGV!z^+FZGv@k17MkNj^3JA=(8e4j^#<Rz>0VC5IY8@)LC0MWxyqM{((^wETU`8 z7~B+>O*oYwyx$`XM6k!CbWaNYB=cA61e)0a&&ekeshg3FKs{6@soL(?T@p$ORfdN@ zMGR)c1j|Ne`e-@}OQD+r`k7k@HT+KteYb_CxxZ7(EMYe)kZ~hwA2$`UE?Sw>qmRb8 z391F(Q1GDFEKt<~V&U=v-)PVnRlq~wIMa3-(~4|5=^0FqTO`z4_T_ogl-) zv-NU|(z6D3|J$mtCI2MSa#pKNqD>SpJqsI+$_Q8M(ikt8Cf-q4C6Cu5mz3jK-6@Vl z4*+za2VeNMR^;>Y+nmu`+sUAoc7nkZ(tD(xKquJ=q*ZLkXu!j8iVXoh zphXZ7auv$pzQzY$G$^pP$NxrwH5!$JS!24!h%f?_$ROE4>E-=N;eb?8{nq;Z``XxslljPAzUYvBh(&{S$+f& zgsonY)bf7TvKT{Or%=+~HJ*bM())*3Q5o~^uTkZcqytr>AN6M4F8 zQlJ$X81_eRG3SpRqV0F#-GD9n$)aOi}9??;H!Q z2<)LvX&Z`;MC+hF8`X(P>O&y6A>z(Y34fMw=EFf7nYc-wVWB!g2!=L{9SejY)-kI2 z#6>#!3}U_1fG~F&5N6_^@$233YtdVMWC}A!)0OqEd3(4IGdLDGP*Y9d*!bR9u?Me8 z)L1N0TDY~3*}E={GglsOQpHP~G@n5ZEX0$p&Cx$xJa%`xVwzesom3d}kYg@z!b|%` z;$Pgx^PyCX3eyMs*VV+0x6oBl&I!AI%3!v?4r5iH7?}4XI7ZE~8lBd*GlZ&tM|68E&V%GWZTNeS7LXRLJV)1(BUUJiOPHNH?ol`~86vHxUqj?Gw7 zO?*I5lvD9s*?}k9pJn)GruU5Q;l~%_uZ}iYoB^iSc|>}a;gxVYMseBK(u7H2dsS*z zcM_hl^`z0#hFLDCXmA$Gpq_xji(&Zz;d{^vN`XL<_{7_#_T+R^0L?p^|9wPD1@4ZE zg(!ZItK8+L)iV94O~j6;qQQXzBWELjWJeYXBle5{TY#M|UsG%B3wwLt?A^IpGA~ly z7rb03mp1jE=Fg2(z@s1cw+C&|19fq%!oPD`nXH9bXm1H_cS1dI8O8L&16HhXOF&#& z4DeH4VH}=UtpheUcbYkeTyeTrBx=3@u zhzILx1N^oTDd%~Y<2t#A+fk1sel|r)lL&Vi~IVhap3xoX^n=gX34i&HX}u?T8NY)zRAv zyPi%r55!*IO6Ia1{dh}aze=wY!KK9MJM?#_kKO(G<*%JP1w&;at`#*_tkKrI&Lg;d zD%);-=RAKaX8d(Wlph6O0Aa20NuGwj+mWr;LohUi7@Ci_XDQ}!0eYw9498mXeVOAa zvLBl+B7$F+*aW7+!KGD|yMe5$IBT+vuJ@D?mendMu4olq^L6Qs7xu=+xm3U(W%Q+9 zLJ$YxLA%Q7ncSz0)I!*$j9tqpZzN%ZPEE z)~VE*UTE}%fBC?Q*8y>|`NmmYvz^mzt|n0|U~GtHND56ZXX6TC^Mk<;^*FfX-NA5N|B{ zhC-Kg!Z^{1yG6;f1<>|koj_anc3H(N8Y8nY`-k#@?VJd&ydYA;w$)w*9+`qmp}~V? z5{#oVlNk{~L3BfGpoOt;O={1b4Tie(rOLpeg9?8RCgY%AO~Fmz>_=Ut$md4wpFjZ8 zd#-F(&CitAl`})X8KzTM04p^G$~i0WkQwZ?uWQabrfbfQh8FDEkr%Z>26}DdG+RLk zAeRnyzF8jQ^(gPcFczPoKa`|`({z4{GHiV^_B{8Di6Vej;ixz%ZjWe0%eBzy1G7ce zS9kYkztz48&4{T$V6#FZQ*h7JXGilJTua4`8Hjo?Kp?iu+90C;Y?7NNY#}SW&V!1u z1r!_zjllcguSTeWgs^fr+Q3JrK_Yvo()G@K`@e5I%y8%LGYs^&stSL~?M`|k@lh%0 z`eS?vvV>2-p|$PA{&J~_7}fv*Sl}A;k8yh}Qc?7w=(>iXNorj+_$A-|;H)4Z3X@&M+SqN!+mqgG`ftnXyjY|W+4l`>qtRei!iV?@0Y%EV4iry)lc zaVBL&C(8N4ZHFWU17GIlhl2C~2LZcjt^f?a2v3-lO2jUhYElML`p)x$*|O$JuJu`G;-rpwcT4K~0BtDGc=Yzt}_3T!enG zF%Z`u{fYd4*OVFSf4^jFTIh$}Oev<8ij6JkL<&9^@(rD!gZKo&`m9=0_qA#q)@1Ln zQ56fkgzgl(f&frH&cd;BN-HE}Zam8WB$$+ye0$mjKP_fF{P`}mGy@({NVQ`smZ9bI zp$B;mmKKR1)l4=i9`>)eaF0I4jd3OlF~dV#v1%y5F_<8BqV$+St{Xh;8D&=Y1G`e( z8xyuoYUZf%TCCp0@odCrbp6;$*60M*lPEPPPX9ismxF+acp8W}WVBW)xgGr8*v(nN zw#LEC7j96QWV+-!Z@#RgYP#0*bBIB}5LdZ4LfPZ!fgjN|`OSk|X=>y<=#}>gC zXrWl@Z#oWsQ%T(N>tr`qXeN?T%m4Ivx&Lp4Q_xHN20YqkSaH(7wPFqW z_fy-ZLP3_8Z+zPe8PA$!%3qS8Trz|lt_p6=6?jwdUJ&6}ysco=&J_kAmuD{!A$2OCy+ zWbn$fs#f}zKB&zpioeCypFL(m#hDC7e4F6HN?3wfyLmy%KEQ4W#sO;f^6z*S`FK`x#nU3z6m}B-)iaS`{ zBH)z=P^=8_3I?50^uXJ1g^AJx!B_||+gIFNbp)ltRA^=)9$YSqc#at)r&w>Lq#009 z2Ao!M2DHr24NK_Xwm~W0IrMjnIkNG`N^AAwa>wkhctLlm3!G*ZMjrkK$a5Ss{l;)8 z>Te;DjR1o6yvyRX`rDGELTZ`FxKQG5|XsNSKeOwedm1Y$Bq< z2?w)X;O4&8g4t`(zUD@BP8dbf4D0d$(h2-86RIeG;tMHE(h zdHCkF!5cA8iv(0LKDR^0RKp`YGIRRZg*iPOY+=eyn-Jq51H>PcdQprFI+f+Z$cB~E zQHeKLoFp-%2X-?sH|bg8#zpzoJ36CcI%4|FELMUx--hk^b#a;_Us0GGDDVD~%qfly zlq=KaYp)q9p*ZXEfzP@AVWM)u3z9qCPrenE)*V2KixxE0UPcfNy3Jge>CUGzB&ZZ& zmysHxpPJI#K?6l;%D8irKipRA&)-*66MiK)oRQ|%YzA+1JWL+mGuayflG@lC{I^ny zp+s&*J^b@LOp3b1hmVM{V>!Ata}8Ou=7u3_22)`OGAL^f_jdhRq(ia``cA@wa>jK? z3nyjmz5q;OB7l2_4x)UZ_@e?N(iBWQ<^j^0NJG10AuUdl&0%TcQ5Xt@&FcEqCJ4@mXPZ;^PtoCqZH<=eLp^%Y%h}F zAb3Z`rBnI+16#>hW~WhPWb>epRXr0LV#07@Z8CwnijY#f*V(r^02Ao~S&pbOEQ0z# z8h(|Xc5j|ca{(=vzK%|n9&gNSootLCzF=%wu+u5A5;RGq`Jb)YKXwp|x!7mWtFC!d zuUhs(;GnQc2F(=lpFaf=+I-^ZP(oz_1z!b$8Xl1$Ung8`Lh{nohH0Ob?g3#4w7eS`Vz3o1sB%KKk^y-u zfr(*)(!V#ap&rZF>{%&&xOh=J*UBAOk^aHJs)x$eG{^GC6h_!Y>H*Qs}^1fN8~yqXB7! zl}`-QiVK2bFR|tH0c%6|(BDL$dq~<4&1fD_2{bT{zW{f;<)@nVn&9)JJg!Sabzy1H z8P#wtAZ-m~{Z?|_dN31snzUtC?I%da2R|MRdD(EGRKdHvcl0lu%ju3t1a;qH;enxq zlO;twsufxn1cBC2FkZ7WzFshL_bUU~lhg0gb(O@F1|)kcCT7fvRVf%Em6i2H$gu}H z&UjPo3_S56a*B;%R2kp%bx%?H_^3&#g1%U|m%$d5%+c^atk8VQhLu{I7V)58yf-b4 zBbxm)5r7$^QnwSaX;o7uv}okuNCTf~%YZ-1i}Bn-K}DVJ0{y$dFYu>DIHmbo(E>3E z_c?3S_Y$Z*7CcLVubI$TV6WEZb+n8^3$Nc_5qS{8hXNrQ)AVJe442BhqKS$KMK(Pk2an$^s zfgQG0j8Ho$_#2RSEX1<7Gs^*Bj#vh=tCdVcb~Q&fv_0n|S#?^@BqG9l zll7Q2c~zn^fej-Qd$s!k+wIs+mblkV7W zE;|5j0=nF4xH;#I5+eT}M+^458AJeF+|ZW0@h6V_Ld`E}!u>FS=iyHzfSy4^-Hh=$ z>xe~umAE8rle=NWvUuyzs6Y!~+|H7c`Qd6&RsPUF2#P+VCtE2*gUbjdr_6LS3_>!A zo}SZkzJAJ(;u)L33&dSi@r5HK2YEu_mv}_1vdfE}0ghT(}#)Px4)-w865i$ow&o6L6<3r5DJy44N}`jWvzMwzADhV{w=%rkrj zXfMP-w6DA5Vxo3Wu?L^K#UvzCe9120RM}}sd`d4;u_&Y9X!OMPV}LZkR9*>H?`*U- zjj^gn6-@`6g}A9X1QQ>e1(2l0 zjI)+iS4wnYx%lyt%dR+~b%vsU7MyV)E+F@9_Xf1~`&W(pDNQO5fi+91Ba=IBi+gt{IX_MrV?Gi6~c$I#H-23qnClBPO?AKw*ch5!Hn literal 25481 zcmeHw2~?BU)^_jpItzqarHa6fL}{x+6%~{r7PK@~p{*5UcE$mS0T~m>Re_{M#fECo zFxXn979|Q|0%ULqAVxq%2nZw+h6n*-5&{Wi_|FO8(7}Gg`tSd*b<0|=N}9ZR-*e91 z``OQa_V$}EyuD0j%%AbjJMWlaK3o6QJMT;)zw^$NpQlX%uMCY$jsX98|BFpuZ!j1P z;IGg7R52NMPJzD}|J=HDYw|a(HsIH3hrjaP@(y?t{AsxV^@?}i+4VkV{U=|?|E<4G z>MQ>2ozzD))d3uXZQZngP~HhCi`XdcsrH?Yxp=6zSig3GDGC0`|HtIILc@}Ff0ed7K|wWnvz?BMh0F!S^vO ztQxsm>J{$`Um_xFN85T^dd2X=m9-wO1MxJ3k3?@s6q-1+bj$zYdNplY`85WD5!ik# zy5PjSxm!F_f}1vy3vSg0ibh&B6+`21At6Ey!8=`5G49KWw9o|x+DupO%(`FT-6@D& zbpJf?bw42Q6dxd8n`vU6yA@pKx#9D8UmbU9`9s6$7gt7zX0boKWi3c|+rI#RUVMN4 z{IjaWBS()Ol?f0(oZo(&Np%G5{SJd^;KKLbJN^*%XpFx!Gs>P@hF= z7V0$0=V!1wD|x5{xD`Jj7gvuh&T@=#b@q`liYxOM_T5n<%<_qtxmBtz13E$&*h)p& z;5b9VZIapf*n+qW2O-xH^XY!DtmvIytl-B5h|JE)4>M5-B0@i#Peocs7OHRMU{-t% zR$ToFQqNT_aLNC#f~N9yoF4 zi1$2;Ag7NGkm6;vsCjz~NDhm|(#}9T@LGlj(ws%bzw|E&c(@C7)8$3e7gc{@ zVxF9mmW2}a9a1AFuUxM-pTCpxHATA}+6COQ>`Q6WMjwJb_)sU>G5*@|5SMUx?7_}H zynYv4{^M6iVK@bxJoKi2_j&xE8HC0S>0Q6FVddufEl1r(Hy{^d7FEwSTJ*0Dt%v6( zN>~F}cd$CH1@MX2^6vJ8QYvss8iNmQc<%6`YOicM+o@5*>$+NR#^(#UYcRkz!71Jj zPH~;_6w9?!J+tWSI88Y+`B^t=-cP_@v{?v)DDI?7o%F}hq%}Ei{hw2VUp&5*u#3R% zW8s$hTy+TMB+Wl4^tC|d#ywXSyGKP+fQ^F_@Hx3EHD|$GFVj-%^qJj}61;=XKCv|9 zdc=OW#=BNHou1}oR}FkbZ2Qzy=KUSP6>G0=_?CpSeyi~qfHjZ-ttLd9*D;uNb0ZImf;!XF6*ad?gmb&{KXazLa?SvmB!WkCvWq2m=!{wa~mnGg0aU| zewv9wf8v?a4mN{OaJSv-sxEEX-Bmo)Wt8SNIIiXJxUSi3Vm<_&(3TM{JfiTmdFvDcle7MB`_2E^IsLVdSKvLeFYW(j|G7)~|G*EW zdu*b7PO*FP+VO->>%VG!Qz|fRW6+v#%R9a%lj^ys^o|jQA#b&8*}z6hhI1$$dqw$8 zM~lq@x$Y6A6AwRl#6{e%2nK%L>7)eB9FQE81t*)xFW4q;zk$+(z_p7f8?cV~Nj*%- zQciYUK}RapO-uK(rye|!bULp4SbR$JpVnBq3goGrg=DjP9z{h!J z%lsQ+YxmB6mg5#)J}ERgk;uz9eg-8fa4~)_u4Gd3Lf+Q9EnB1qv6W>u;=tFQ`!Jb4 z&zh>#b{%rXt-*g*6ty-cIqYmr?-N4Jima|}0yTQA7=K|=HRB+#{z;zD@1924z_a@) z$yv4p^A$!h53Zm3WW4i@yC{wA*kZ!h6aMnL5J*ixh2MDH7mt2}9b_)SH`!{%NXMi_ z{#FGo1B7qE;nsFbr;gmZIGnr$bEc}7dU$v}r9ytzry1;l`*mAk;iRgS z^ztt#4cATOY}{PnlpmWt03gQZ02xz+v+p{jZI7{Z9+*sZ$S8==Q>9y^ z2#HhoBSCsxGEehVS={Io!ddHcXtp@X@fJ zlnyq!y%?Emp;FvK3U=XcxAtG8uPN*w5%!UtJPVI}V07F7`mDP$jh zG~9pMNg~rWp2^#I;074-5Jd`V=mYLv6b~7dgXT&A8 znhu5pE0YJ0Ae`_|RYkOo_Li!g&?jx*Wp>&^`w#OZ1aGdIh}uJYe3P89v}7E%$iCRHmz5y>Tt^C+RkcT{!wF zX(NO#dDC!Pc2kZIOQJQr9CXhlyHe}1%}MT-#Za^diLO+)!ys1JxU+4oP0Q{r0-#FX59bQoz>y#xQ>qZ?qeJ6K95V>{~(z2|D=^%9WE1 z5pnJt0DMYTswO2pd#ur+vq6B^1~GlPl|1(PRS?rGtCTi@7qKMuH}DfNWZ8-0Y4SN?=t~o}r1Mb)o4=u5Vt$$HAc+#@6i{H~Hm&WX{cY4!KtLtElOKu#g=KD#eM|uSL zfK!r#5S1OCCuV;bL<}ydJBP|^1m1!3Po7d7XuYO0ajE^bfjNQ-7ON}jz#MVSsel$|s`+L6e`*O`hPX$kY zH`I1qS&U<2w>})DM%t9^8zS6RSkxohe*jPqSx zid9`^SpB_wX6Uw#(CrjgXb0{bTcQ2;4QoFiGr}FO8)3BNP7qC~o2V?HUv2#c~%bk;3=bt-YNBU>NLemT zxW1N3$4&x~Qc+naBWJ|PG$$CIEKa=k`!x;HUGSFk%Qce=-6JWiix7TFJcIiG1p-vb zKN$Iuo~+`PGFC#)gQ>BFW-0N_Yi&}PP5YfD5q5XtZJyOSTtlt~vFBOP{e+yFP}8c} z)M659N&Xf|oNsx(;>m%Ivep%7F+sKSe8uCoY)($q{xekWLJ7_{lPP5M%7$e36uayT zv(P_R8i8mSgj7OrcYXY^JGfrRCPyb-;YMO)odj{ zq{dk3<-dr$KteSH;0?^7eI9}{G?6O*CN{jxMgHTmuXa&dyt8g&k#nJg!LVN`6mtNr z)l<}8K^558d{EunjyH~6ZQAKDRFEovE7u< zi`EXj7o&{ZWiF;oypi)E&k&d15tS7DO923^`4?BCrKR$@v{T~s zp!tCXIx!~qSxw3rs=c*xXfj6O19w+8UC#QMIzcB;18cO6s+No2ZJkko6zCpgIF}G} z9t6?{Om5^DHj{_#Kcf(h2PKd!h$#)=yoNitV?;w$Uk`v@V@%cJSzAJZO41EOxh#K zO1A>jT4dy7=5$=~)}$ye0t+uU&rbq=Ap$wZKFkQm_patiPsL3svz862 zj~t1tPa=Fm(awgb0dFKBO4hs`Stdnzi)uSo@}(Cd9o$Tc5+3)1TcX3IB3g?t-9ycj z+0`t<=)Z;$EEge3T8K$Lnl{bnJlHCWwF{D;JjIe<`~z6QUvwH|3f~^Dn%^F;S}=K2 z0`lCr0mO|(t^@iR!gHe+{L$Lu7zGmUr&%nI;rrx5$zfN+_0*wQa^CyEn3$QZHKG$4 zDQaQWCd!G?;z;s~O8|qIWp7-w02CZNi2&wnAZZ+K-*PL;(}nFG%5*O=#U<~uPRh}O z?4m>xb~TSh7&nzjYe(WOn%PPsTNu?GBI#H$ytOZG@k*}2E-(q6fOm8Z;K7;~)m8^C7r-3`;Bk1$(^?|14YR|Vz#AF_m202wW$(#y`T@i`O6P27 zAfYMo!7dq%{d;F_jAE7$*2rd2lf<>QjT=XdAo9Up$A=5`E_OF<_Oaa@2FkVHm1$zb zvin1SNSn3~2 z2S2hG45TpakQ1-#@4+mN$qR3C+|6Hn`e4+W8sVBaqC+r-*{d?D0taKc-jocZ#aWD7 zT!6S`OPrq};x+@xsqdINrOXmOr4!Gy$aU^)y!KkXPda)dMuCGH<^xi@?NwV>zTE(q z5XVzHn;3l0{!^tH74=Sc3-u?n-4%+XT{hXJMg3Rkv&#tAlou$S7vR!?==k9ZOywvh z8dKz~?|J}V%L7qs0gPH_k$S1E!&_Eg>8`KP#%ITdUuACP(LH^c*7j0k! zyJ&dHbw4@?IYY=P&R%OI5&?C1;M}F24{zt{azR4(jPz@s?%z|3`ERFrTst114$ocM zpZNK;FzyHN$rC)rAMJN*HZSu%{Rh9Hy+^&N5e^)dUcCsAtc0K_6I|NF!*Shkv>7}#9B=GG%a8rqM#0mW` z5oHKfqPi+&@W0{ME^TXwFd9XVr?Be^zm_qx>{M|s1oJdO*-y#PX~4dirI zcf55fGvI<`dAFq>GBTDYwRN`!fs_KFT?lneB%1Uz4+zTl_TVOunzBpzDmrTvA{$Y1zor zG1w^ZY70r6znk{hHKRgw0WA_5;pjBqSBOd(rPt`x38U6J5Ux?@Ax-XI{(|& z^{Og+Pc|L*3gbG=SdRG!lluj5Kz~SZzQoGIp03&YMg9u}RDRA{Cybtwyvca$!ZO<22ZC7<29=fsHfvBd^Zoh#Ux4NNs*6!k{9~CJ7fmJeH z9%_5{M&^~{RG31)a4#mIRzr=N7vpjal>qBmAaPLs7&6A7WR(X;ey9u-V5y(_ZcJX) z`O$N}t#^N@owBjO$K)^(UPOoSb&PjqH~dVShpL85c>5M)h(*JJ>b6&gHkkztO|_6? zxaTFBTbw{VkB=VhJCSjzc-{`(8nbFelh!)3lLM`^2Vs#=BX^x4*HZOkp>OYXQS(QJ zr99e?4wn3>__CZ9Nu+i?xq$n%S=cF5#!G;yL~=@O!Y2hRy|af*TM0O#aS}y$`$U8z z!>3K%cx6C)Zs2&7l4OgqHU_@SO%a`1wA z)IG5?ioa{stK|`NMFss+NxduQb@d^u@Ao{>#F-Qge_#{=A%f0xp9b z@F^XDPg%)Jo8}__W-Lit4SvDPzcJche%4?1H@*UIlyzU)AMssr`=CR$n90!^@@w$v zqm<61eEv;~&=4ZwJgQ(`McR5|UTbNif|M|#ymt(G3T^goiKT7jCG_+6> zGvI-sB8k?tu)>paqKmJz9~zOh+cqMF#Lf%Y^yVw+q7-~{zx8ok*i($+G(2o^DdV|Y z!K!5IT^!sT@!knOB&nGzoP|@KDlXsUv|c^i0sL_9GE(Bp(_~{>hoYN)C)!e&EVqLt`l_RSTiQops$Jo(Ffg1Dl#ov z!aY+!Mx5D+1qdE%{&ov`BOP#LIB*I?qos4(?9sc%FR@WuunN$Ts?2T* zig*>qt9oF}UX)pli1xF9pU~h*cQXP;fv^Vyw(N6?P558HaAF01H<9BY-wq6WZ@SFZ z-QAJdxzR{9G@D~B`aa^JN^u}#JFOqj*!Gb>{sJsFJ$kJ4hF?4I<$ujW3O!gM4DEZg z76&sQ3K7bX2)oFV4Q$t_d#Y_gAIIT)4u)t1C-%FS%#iQBxAh^_EBh(eyZfqN!I1%0 zv|$MQbQvhv+!;;-Y@xJ5w|#Qn@VU-Yr-4c6m2a3txI+`++s#^F%3r}7EuMw@POzY^ z<7y{Uu)u*h%g|af`hi8zvc3CLH;|T@Dl$3bOJ8cLF-nS&jGiY+W z9j||2u+&Pi>_*J?@K|{`tvz(Vu{~0CkJn~LmBQUiB zD^UFE2lm|j7moq_)SvShsYq*Y17+z+Dc?YR%3?4bFv7U9aJ;-rRW%imcD@X^1!zoU z4c5?pA+s~XSmtO0wg4!wFuvfPkP2+ ziAxxSicZK7s%j@r>3XNFmQ#-T3ofs{+i*hY#se3!vlwpZEc)$~2r6qnT8zgg;& zgCc^;sJ*s)0+F#IURp?SFFy`F52im?dxh$_kZ za9q5_su11!ahne=QSZ+J-9uo6TBV`0l_g8JM3iu$wpW%ryWQea5k zXnT{BjRS_W4nE6NB&V>vgF@pjIB91eW`^eFE6s2Epi%y%rF|=3C@!HiA3@tYXw-Ie=>AozE%?w#3nIiUB&yoy<9K_6LSQ6s zD}cyD`;#fj@THo>1(MeC7Y;_Xjxp#=5aEBUm0Y=b%jWu(Zi||VMYDmpQ~U9&F1c3yTdiE0>B~L_qo)X3B{rTY^vMN(jRg{@*INl0!Yr>5f5cB6mvKDN z$E?7z159qLO>!(yUBtQ$Y47&W$w+p@DDokU5~RilZ!4ICe+j)3TA1Mr556o52#*Sfn}|8hnhANO=$t2=gEyD*%8j^e;d* zMne7xQ@8j}0a@O{>fU&@f47q%ij2}sf-cP=j@NRr1P~RG3+jmBn>pjPrbcA)zHE@r z@R5{pQNVP$q2`&2ByekIE)U{l*IIL}MeOD`tG;$rl;~5gjB@x#k6=0%qN^j$6;o5{qr>nYkJ z(3@_6QRx8gHCpb1ku4afxcOs+j_3lvNk>vEz|RuGp4Y{%uWK!I&nPwd0TH|M=Q&_?>2R5heB6%{ z6hTA(cqr?z{oJ|uqUcI&q%P&8>>n=NEDA+M9hJiX`fNzj1XfQPPm`aX$PuQqO!i1FFQ1k z2`q+F)ZJS{KVDB^8R<%lQRc(`OGpcK-Y*G(Ukhp5C;b`HYty_3lK;DPE4Ug9&j(?K z7Z*^~Mt0^p5ID)NObDD}UTG_A=1ck!hMnZ-+r$y4MVLs4De6+xhWUxQ_LvW?oYMHz z`sNOS)FUu*U%o&xQ;^??ti?XKK+nvBEfm@-s!S@qc6Mu8yezFgT@WqsatLEhmz$++ zOH)4|a^ccY3C7%LAy2t8U|i%B@i%Ho`RgJl=Vi@C%3$8}b`#Jc5e~25la`fEkiK>W zd!x>&_BEYT%5QW|$>o>#xz*IW4_A3E^$3y>lwSLkftx7C8Zgi}bgrsWe!!zuxX>%R zF1xshRpxnSpghHIEXp1_)~1QvkUnbIOD?Twzzz&G48>)l%=#ya!Db#4#o(vi5j)zN zHk0|5Xs)fhkZluGr1`pFb5BufaHQ@oaxRj?pwiuADXx!Ugo~c2RQ=Mj1@QSKmg7T} z`r$87%aJ&cG4cq3cHyy2qVS_N^d%S}%!k~~#nQEF?7!3S+vCMiL#K9k9q!fE9*6_2 zB@sc?z;2-V51DmiTOX~Sp>(c^+VZH2q8jvNwAQNWq$cmE?<75b%#jU%dCNj&5cVaY zs-4vQQo`VnQ{m`QBuEqLl7E6;>>I$>Jp+6l!3QWPhbDV!+vp7F8TWd*E=c~0B$_Rz z`6b;(5Qn7^APdQx4vFMsGQ`&qLV5!+R1&0=zt_v4+7Q0>Dcwk%Lt_1T6J*n~Ug^d0 z9-vvs=Fhdk4lo=qE zt`Mch>-ogi)xM$LVLlsGMSFgySd~?r<&Zqs>v~(2V(pVuLR_{tDsH&dwNoK2CGa}Z zors=e((rb=hpR(x*LR+URpO(iEnU7*{&eY<0t7ZKXfojR5~@XbMNL8Z>@pYCR$Rf7 zn~<>UwT*Ni(22gF5Ii8B0>OrlD{;ln4!oirBlo6^F&TV=v535Eq^mJ*ws!xFVJXW- zY$=K?=Zu0UH-nn>P;>D@`kLG-ejjsk&|I~Ys;R8m$u8ci_a{4TsB0PcCBOd(mVY*% z>8`6rpkKg`JtdNjaPtlo5Pn4i_Qfz~lOX*5CY&x0`KOJ@+(sre%TLD64D?a>cn~B` z-=p##L6gLK2I-OvfRDd*6NsIH7}v%EWZPq5?#QtvzQiP}Fp4wLA4+uL zZ?9MR4viCkv-Gu3s6T)uKHE{V$(Oj_o|}8{Mh0AB3`9CU5R-?dsx658 z%uc@U8p5EX=L191w!!S}=MqDGERU#{8e^;l)N{;QK5+u~16Iro(gKeS69!lJykw%` zWV)5Hc>J1%)(3R!y}0}TM-Shh8X)jHuM*JE_u!Me0+GQV2gR2*NVNP@`aHck#|$@| zTSL;;w*aXrTu_H5bF81BZ9`UPB7~p*6Yz8XLTxx$WB2Dl_uFs08|v593xvM=Plv3g zccsN9CUFiW9k3E>D_uttOY1VS(#MU=1z9NJvha>4lr^9c1P>T9c<(Q^z9GOrprc2Y zX1~IkOSB;830Y=$!=!gWCEdStvD|`TR}C5hfLXjRj`63*e)}ru#a)L%4`-J~gG#5* z+Hcs2_9i%9Z!vSkRuJPSzOZ6U+RIX(EWaZ!N;s~m+)AdsRNTk-1$=)ad&DM1-3*uE zWsEC;f~WSU!I2oy)CbH6SAGx8uyt=@Tig|eXW2}bJ4E_`Bn;Zn%yGfsSmIW&fn#L^ znKkP&J`V^bDtp-o^r4BH*^1=Y7j(@36Xt_6&U~=ll5$6C+GzWiG8)k=H;g_A`j(?( zxteGNl}i9DgcInz(j1qjokDf!l%?9PsrqvwqpG)PtnQS2*Cv&#y%nk$HLl`Zc#H^n ze+4htOZ;CgsUh z&3T%w5Ipiv#*d;6$CmW%D(D`UTgUNRRwXt6`Ugh{?ITYTmm7hmK%phC`Bo$L0x**`yFO9RFL$bU7O{lpvS2n# zyrQO|*w=3I=9{py+6X(dAC9z} z6^8nB46ug_Ii~n;Vw7jWC6gCXb7DsW%XH_d1~Vy^W)_f7}7rsL~GbpL41{*Wc-8<|_7|c&Dj)nAoaHHav>of%81R>Ika1HN}#%=ysWP*#4 z9V?)Z_ILI5PNy#M1;P6P(%+ij%vmMvs_F+CM$kw!#f!rCxFw&_QP_Z?>r@p`l5oJ9TjqZAw?(|vlcziDZD28&Iv&SCYK8fo@nksVwr!9so;3`3D3_6eRqq${b9;tge?g2b)(Vdf= z)-zQHjpR-KU-IDJZO&{T_4p&z2V-htlD^7j6)_hz&zQqWL9IFRWvyAw@Fawt*O=WV zwT!ejU=%8dX#NE{i@idK@onBG@%P8-2J$xAghj9AX-*^z#wgOu3u#YR@VWw9uvEIB zK!8mOqd|Z)>gif2@4V(bQ9?86907XZMNh{`POImOd9<)_ub`kLtRADVf?s$FK~K8! z5p#3+cVc99CD7VCB|@z|4Izlj8@iQH+gKp;{Jn4H4yJd_9waj+*4 zVNa((`X>1@Pu%-t(NEG3(m|HTnfH7|3G~G8OR?!V3v7;|EU0iJ1#7ICt%6c{&>3Z< zc85Wa=VADp#JB~(0QQkEipgX90i{n^(3or#5k{W_FM0xl$R8w52n!t(`zJCuk1D8# zy7LNv{ijp_xHIL4MyR`SL7{p>eK)%z38=^F_q3!t&_&kIRhr>KX3mQ?{@e_p@U%`Y zL}?Dd)0zi57MF@h1u7sd+^FeCi017x?cPy^4IOGU!6@9|@;d=0B~~$VS6Ud=8ek97 zw2aUUnK1lUOiE~LOk2yD)CeqBxZEc?x>?gLHKAU&fnO8_zeq%i56XEpIbx_tA*o0< z37e=aGbTlNvvgE~a`yvbikC!XD4B6^aNuYT>~l87&3TrCpgOs?n)}fNy3;oe$Cq-Mrf7czwhfUc|pffC%R(~^9dMaZ|06HwXBKE6c57*E`pPljYOd&#u zAL>Gl64rJ9X7t1v+T*She9#aknsr#0@MTkfe|~jNsIateq?2E@w5*X8hL_I9nt%VnTlKmooSF1sH4oi0@A( zo^J@Z&QK2#GCM7e>I)G_vj%D&`%q3postF+`?uDCIUr=pd`L0Nx7@S=gwKxh#66_G>W8YB!T<5r#mRx9QX^+0DuV=mgC{!?d6^SJn1>d@vR5^jGepl5tQar z=wN7|ilrhH4`%M}0^tD3vJ!)C1QWUIZqF2~0H|7Qm`kMsn-ITYTt*oIv@9mG3w6I@ z5?-EhK0@GF?%rOzo-$@U=16NQF>2d_u@+%4t>ud|j3Do;u*+l4VE?*wM&s-(8dq7l zN9{5jGX@Z*q{jDm1XRZ!q2IiQA_elPlHgvI=&o0|M{6rP0+hl=bme|TSu$uJx0~{^ zcOyqK(Yq0`j2|Z>#ap-I$m#uun$;r>u?sN@lOY>1Y}ufHyyE3Np$OsS#xadu`$@pg zea!Qci5@J&aJ=GxseLjbkLX*S5A{SgCN~mlqcU1TMn8T+D+Ti^U=nBxI-|;}wz|Bj zCj#SHVlV@1?~8#Z96KdI%Ss$}&Z8wPjTP4ysIFKpB*5lg!(%6U6G{_SnREu8=7qcj z9}FeTX{Z?5InqVkehui=pNByf&C{rX;7;_=zqQcvpEskWz2FbU-*Hn$9!3k9VuGPY z!gLw9i&iq(t@zqwSdyn@g-T=2To_>SZfpA^Vd1U zUcYj#ZDjY*khN~RSCEMK*_kR!7xB;r3gLuNmijTT;fxZ>Qro(3nBdrzGLu2|8Yjmx z7jEiQq;OuGs#^@aJmD-j?=R@Ua_Xx#IRA;|B;(Eb`x7O%SDS4+dA(Gw-$e}$4U3)c zis2XsnoUJUehWrT$-^BZ;kJInO9=gpB6);pp9;Gu{7gv_DM%1}#=0o%Ag=sVP1=9p za4y&14;AiQ_vF9~mHwU$;Sfa|2t$QkADJOdoU@bC>OA>-P~>sqskYg?Uy8gF2McP! zwHFt7Z)FV}F*elhw8uA;(CRM>_}xFxohZG=wyGGku-Z^3GYka>;cLcp`TJh4EF*XT zR6Ril#6G`@t7!yBp2|_SsdsAlapRY##$VmJwK`&F`naO5yh+MsSj&CMEucS!kO`cs zXwN)jF$NrWrzIU_`(^jBl zGMzI|OsXtp$0c;1Kmhn7Pn8X+)IMKP2u8JxA5w3~*8|xOS6zi3ozPYb3S_JetdQ8U z-7({J6gIBb?3|T>W_Nu$F86WIxvnETu5y^Y77jJacFF`|fF$1D><#6#Cqh$sNG0t7_?9LDo=e~Iqw-VE zSh-v}b-UvI`l?Psz$- zk%g_BhHCSEL}{{LCd?bijC9qTgp#a3i!a?8js%0-HNux7F11Ze;z-fB|Pc1wY()^ne z<}6%HZxMlhVW~APEStZGkC63Ulq~m_*)J|BJE(d{vI%n}Rd{CDb(hUOk~4)y=W1_^ zOe{Tm793=xU58GL!W4r1JP>|KblYJ{r=&T_IFW%K%e(u7)#7T=NXJ>&OUE^~p&3UL z{uMf2Hnzf6UkF1%dGPlI+}e>gT;$$EVJxp=R-9g65|=OESBp`^L6>g<$fv8fybj7h zwlPy#gFvsW%|VzIWMTnzu_VKRB?zZTK?wJRQtrp4-`77)ZhQY^`P~UhR&~x*hN4q* z?EQ1bWT?s5Y~``NRfcX%YnpRi@8RaCf3-Ao<=@OD#;<1NaS8iCQ>&S=m}Vu$)qt^} z6H0-D(*=w|k^Q3(d)7QfY_^N%mA%&zJ9}?RFJcMbgRFdY+|^5Rwcr$rNQdR^V+i`e z{<2QlvaUTI#=($E@2FQa z!oJc5;L3+1LKl;+WOJ5PwwNYlK4Bw7>h)L|xy1sbpc+Sq9YgqyR*X$6QvG~xv|}mb zN3*o}9F-2|9yM@ce~?X54w&iy^XC^0ptkwEnOjyWJ>0GsY`czjmV)jph>k45 zP=~qF3w!XOMQD|7FBz!g?jj3)L^kEfJAM!iZ>U|Oh9mmS)3w(m+TZe88>0kY&dp#t)^<_$ke%>7?EN{l%L;=}B2G3UOvdkXCXI#RofPLS!Ti}EQ8&1SH1iTClDZ&T=Ehd=U-{mnU9Pxi%*7Bm{ z?V%?*CR)&Qr>m!YmuOQb;gRKCko!Y2C6r^!DcNST>~7c7%@ijV1b~`DWNH0y6=&E< zqTvdpPmsCByT@~#<)Y-ww8v-IB5Th?X@4KXkhc{4eCs68p}#jizt{E z34!o+&TuYuu>6l(Atf^hi#0sYE)j@Jj#4#DZcc zq)-=&=2dKt%j7!V?;b&E7DAT*DhKy=j?LrhoM6XlzT*C_1r2rX{GKMw>`Z@YMPT^S zujpW!u6u8TsBM=lh1u5OD+rm9cvw{<v6XyPJ9=-=m)36%IF9kJev3t27q^JZh*^UV;sY7 zfCGvCe8Rwg-b@A1Ed9GZ-F0-4m1OS}I(?umCM-*N8BcZBZXa)W<_bY~Ugt!2-f68d z3@zrB$0gbG%zV(}m?#%i+IM>6Yj9kDFs^4^)l7%chkMNP7?%WmZ|W8AtA4sSBT?~& zkUVDgU{7`W@XfquE1&HJyr~5=3(zkel=oV7adGOwMPv07;mPPQa>J}b40hmYt@6EQ z4O8=v;k3;ZP>=)lYd^BU-4|aMVUwO>YV6IUwMx080LT@GM_4{p)ZpXVFuJ|HX7|Ad zF2WClk<%x;LjksOZZs==td)ClrqnjFDq#sv6<<)SBn!TbbgHfq9i@S;-O#29fhXgo z5yfN!iP~QL=-SeLK4_M$XT2U+a{nOh_~f!-3~?9 zk+f1}igLI6eDPgOD5=bfi}biXHEAQ6&Q~#4{1NXUu63qvJcAVWT~r1ON<;0y)bpw~ zpF?XI@2|$_zk`v5Zd7xkAL^=gs_!iqzQ>XTdT7tIAu;-g#bbeJf{Q4DZ+9~WA}TDv g|M!QG82%PEe0x4RLyZ9cZpJ&94c_YuJ+>eHKgJi*{{R30 diff --git a/class_i_document_filter.html b/class_i_document_filter.html index 3d3dd611db..1ed4ef7957 100644 --- a/class_i_document_filter.html +++ b/class_i_document_filter.html @@ -73,11 +73,11 @@ Inheritance diagram for IDocumentFilter:
    -Tgstation.Server.Host.Controllers.TgsOpenApiFilters +Tgstation.Server.Host.Core.SwaggerConfiguration

    The documentation for this class was generated from the following file: diff --git a/class_i_document_filter.png b/class_i_document_filter.png index d723fd62d4d1dd2051b7f9782c566c8848fbc362..beebc61fd17dc5e9d2da495baee702c2335af993 100644 GIT binary patch literal 946 zcmeAS@N?(olHy`uVBq!ia0y~yVAKGz12~w0D7Y|Ma0D{&If*nhOS|s1 zj_T)c;MaIt_wFgvj_I>qbITdb!_L;LWc|FGcCG4m#IdBV>5*UlX(q>LPrVe~{@;61 znd!4_GYrq4O)_R(o!?;nqc-qs&nBr=k8<;0yE5K6WbFDj`g@6+>@$YE2OEu7>AstO z&zzn4K>43bE6pQfCahXrX?=GwL*B!*z}sD!etVPo_4&>u-k4MMJMzc+E~X#VoKUx+ zITgr#psTfXO4F1eE7k{vdl;A+ik(Cbn63|>!L&ogg)!#yH<4uw>wrGfa}sW7#?+1M zZ%Sm{yG~g?U;YtDv^!2);xOqPN8qF<3ND_Lngvun`JASxSZXY~^h(B1~ zv?yD}Q~6p}?$f_Nl_u<;->vq3(`ARvKC30K?l)hgvNBooduoB+E2RtUf9II*>@i$@ zq4QSH|C*ks-EZu(Uw+!X=dIe2UwcBgxQ2yP1}?hoAGFnK*^#pQ&et8cJv58mCV1U( z{mnPLeHGJZZd){MSI{awRoU>+g%zffGt{al3SMnBIrQ5h)Lw0)(7`)CkF6d}oSJJc z@y+0J?#Fy2!SvsdUB>Z0glr!Zqd67QlTEb~bmp6H#yYpSHF27gjr!%|0R_w;p zM84HlLFNzMU9sMFI&i_O|9?yW=AA7rdG%HBxAL-mvV!e1qXNt3d0)EkxVuXAwx}N-LMSDChY0h7M^Q=bo1&>RMH*$wfs;Rk?u;q)2=7f-VMXyOREgGIh0*h2m pI(AG_Vb2e=d@l23&S%YfhOLjSkJYa`9s|r^44$rjF6*2UngFvdo`(Pc literal 963 zcmeAS@N?(olHy`uVBq!ia0y~yU^E4?12~w0q<_CqHjt7C@CkAK|NlRb`Qpvj(*8pe zfGjXRaNq!I=N)+ z7h^iIGhmPV?e1%<{dTjwvItiH=k2A*s=4$@1B(DdjM^H;3eIeXxIJg^c>46( zyUS~1ISw5Bw)gn+Z%h^3`5VLR81<5E|AuCtu3owG>*5V5DQ(k#?b@F^a~*%~;`fn9 zq}RTkcjow_lQHJimw48EVvIYnJYseBS*w+8rz>wnGgqk2&&jp_y?kp~21|vkd|dY1 zg8k0*mm(Sdb#MQ6;h@3^gsL4C>{X3waN?MlgR6KF6>J zD4-9N^#*c>XVae$hQ_oLA*Hlh=M@&}HPxPI%C+FIw zU+OEXWT$`sKdbt7?>p~FCP}qxYAg23vAy~{)7R|G|H`Uo&y;IAH|qMqn{|2P=47 zzsij#rfoHwlauzgq}^=w*3ECPxjo?a`(OJ+51wZ&q>oasCmX6nx#^?Gy1gUbA{(~)_>+tcee`^ TZk2fg%yA5!u6{1-oD!M Tgstation.Server.Host.Components.Byond.IByondManager Tgstation.Server.Host.Components.Chat.IChat -Tgstation.Server.Host.Components.Compiler.ICompileJobConsumer +Tgstation.Server.Host.Components.Deployment.ICompileJobConsumer Tgstation.Server.Host.Components.IInstance Tgstation.Server.Host.Components.IInstanceFactory Tgstation.Server.Host.Components.InstanceManager Tgstation.Server.Host.Components.StaticFiles.IConfiguration Tgstation.Server.Host.Components.Watchdog.IWatchdog Tgstation.Server.Host.Components.Watchdog.WindowsNetworkPromptReaper -Tgstation.Server.Host.Core.IJobManager +Tgstation.Server.Host.Jobs.IJobManager
    The documentation for this class was generated from the following file: diff --git a/class_i_hosted_service.png b/class_i_hosted_service.png index 552b2d0ac42b470804a40f1905e81f2891eecc6f..8f6ebed2687ac30ebda5e8cb65b64833d1285b39 100644 GIT binary patch literal 9082 zcmeHN2~<wcfpNt^3YeS%kwG_SyUY z{%<&(-|p$YVBV5>GiJlrg&w4Cto6#7xng!^T|%YgxyYKT@3FmF_4b7AQs`sy$wJ46TNNMJN$#HdyTj2)`O`JKwd(wnz+M(mZ zgMu=?Abm^+mWQacbPS6D(TzZzfi=iF+x)HRYv^scd<$Cd+Lb5m}UoL-*$Z_}hpesT?b+7KHz zKBlWaoIQKC3mt*p_;`_*mxbQEd5Om;+qbWMsx^MFY30gA*Py?w<-zC8`zQ$7zu7h6 z?AeV=mMvWP@pJgKANF5LoHKj&H`dUhH=#p6TL3Qczj^4-;<>o1dAIU{u9|$(+hjWL z3(RVa$#&NS|6>%4;-@9cdeN?1sqPJ6x|bZJI^Is4Q(gzZ+_7W*rkCfu5~6M6%`z$q zGqu`#vEfkxRAyiF%aPaI!BML#hvoaSqS{wcYXfMgT+?o2a*kMAea)<<96D1_KxwXd zFy{-5O~4>KJe6f4(XoWiNE~jAJc?ko*X_Ke9a;PxQq~CW%UZ_KN?VjL!A{wc#|)xF zf1El#J6$=uj}d2oqAYl^M14`&kXDl$jXGjs^0!DG z(0+GF^cI407^8rJ6|OW)7m;?q{S??v2lTLf1q>bwJ;%2P2DLw7Ccrx%*)3cS5MnzOs|c@%PY{n2t=j4H~312N|;qDnx>-<5D)jmyo9=?W;gJSYbp_ zjv;aHj*N~OdfbgJ(1~N#MaY7BI@viPw1+7bdI_v z0CnLNF{~C%RGmhu4WMh2(HheI=!`YG(!XG#q3v3|rm-9_eyDMw~v6c$iL2@;~OzEFDWma&fNWR+)It(TS-YW^r z+|5;5B==!;l&=~K<`-16=gJ$WPfIx$ot>8SrhHpSssvH<3sHGb;Yez&s9MKqE@cjh zL#*@XTPS@CDJcAk8q_gR04_@;Yv?B(htQ4|o>t^+I?frVCpqrM6iM0s-r2tZRkhytSOxs!lx2tEh!^Y8ct3#POBgz=U4mF z@CNzyMB%}v~FJAK!OD7>(hDvz(< zOYOiysK}iwXL=%Q!t3B|Gr?-B(c~xetD_6_Og4a4>_NqbKvV~nemy7@Q>ZQ9)cy*G zXD1;zTth6cnHBq{2-M5gdg})3ZS}5aokkrXMzN~@xA4qA4Uch8O1<^A_1o$PF6|eL zZ>M0s#wbqzDIZNEqy;8Fq48Kp@JDI2K`K!%6B*MiFH${D>l?zZtdZQe?R&bjFr-N{2?W*O|{FKsZQfmn(uV>`79FpaMl6*HZAqivBX=rIEF zaH?VwZLBp&VfmeuGG%>%7a5ii9s4sZfic|i%C9?oipH2O9HFyTIFq-$)sf@21cmnF zX<&tvA#a&OwI5B}mC-01d3hoFB#&UmDW9*D7=DK|hxkmSFF80{vw@Oy{((sK%Ti|K zwI&aFY)UCLT^w7IC7ve_kc5BRJ$^P$HqY+xpgmG4l$3st42Bw6A3T><%}uZ+IWT(} zy-r9U+kX3slD*ko&zd1Lv7NCT2-CWC|?zSvH*Ya7;aF(R;HJF zGscg5v7f2df)W(xPeRt&A=OAqQc&CD9VYK3Fl`1DM~tJ0FGW!`rzeU-Uw&eEn{j-c zO>X?d#5v;Yh~*fw8Y>$J=up81fr*7dV1BMOwwc=3UG`*3XU(iQ^%C@Lpw5n8&3l7* zoHLdU(EB>=|Auz_OH7kiZ~(Ji%?pa%Tog!J3GsT&hN<>+W4ep&p5pZ1iOu-WI8Wr} zHNBCo8ZE7XP@<%EgjPRk)WJRwldd6?gpzwkv&O2q%WKjmdT`0Iuob;PH#9{zX;~TL zQ;5w+RBixM%i`a<@`MW$aO=5CBGpkXql&T4R^HjD7H4Bd%l(h#ny2cw+zvshtuf)D zP{CIMgc<^mkm*wOc7V&f++hT*mFdTF>swO#(ug>ot}UMMrpHl9pI;yIUN?ql?bC%1 z3=AL2`F-`IWA`C_;$kF;+-J37D0?w+Uoh3x0ANlfRrmB;q#{JD&I;|(8$PB*u@`o0 z7U((O0xesZL7vcvV?TBrDTuM_C00ZVA_hBQfNh77ERFEwZEXVxl?p@y|M?#rR{~ib~mVk%KgjVkeR9V9{m5gLn(lIhzF2n1FTv2w`IF zw)$Ow6<~7*du0j0DY3WyyZzH&Vqn6+sT~lW?|ImDq6f_SQvgi6t#>~nOp>vfqx7CG ztxJI@Gdm3#?qKr3dHC+w_CJ*4ttfy%3ZRG$22v(x&#(VADf+6@#hu#qZD6B!HIj#8v24en>7{XUHT zoTGX>P^>R6Xc*=143XKHid*4c6C;DfAAU;w9UP>;H&LiqKWz8lPh#6RW65!!P|CX< zpo+(0hOGb<9{r*?)XsD(&`Y`OF)ay!fhMIQ3#-!6#^Mp!|RHXXew0|NVn)XjSnqxA2Y#z+T zRcwe0aU({mSjsugMtn3exX=INFEP&f5Rirvrd-tN-_TB>hryYO^3G0%EP$Yl#wcb( zgF=BELKcwM@)tRT+oV`4^O=cCDPoO+xT345{hV}#S&erP=to#1$?cz!i)Du2c9tjB zLH!WHQJ%eoWIujgOq9}ZKy9b`LbRIPjXTrvE%krP=xC z_~{Iy^|UM=QLmCY3b?H1&($PxetY?-kp~q9QH1v4vM}khgElK_p5nTe*JK93P|aFXC$^hgKE$HqXMOi0MXZV8r*QEXpVf(XELmwj4r~HMF2kVms;z()5`=xK|0n(pmg#T){QiWB8CI z>Xsi3qQl1cdPynQg#D3YbVQ{Ni0NW@{{Uy%lz5kyw%aC0M9EQ!&ahA$Dt8g;b06Y! zzj!C%F_|`z+VKs9TXrI2^*YSc(QSv+-ytBe>;>GhK!H?8u-9;8S{0-NLF79TW3WTr zG=o?#h{OFL$gSf{r(JnK2|7cnZ?hH;nI1?1U6(@9DTGL!f#*>8m;OF1!=piTj?Md* zq~!mY%KH;nrpboW-kZ2<@XI%;9W$pr;BR9+D7pEaH5v~2bLdqC35)_!CXz0@e6mJZ zf4RdHx~$b+z0#7NF67pTxQbqq_#V-T1M>snM+3ZVLWXy*DTT~fHS%yZ&*Lg= z%oMHZhR&GwNADUCVXh1ZymZTR5IdX(v4fWa*dzQNSyLx!eis3);XsE!Tn32Y03}KP z-7JLV2fngbiH!7)p85XR@Bv0yT?I9@I{blXp4|A?XV8}@@5N>u`U|Ht9sCunA9Ebw zHRT_uO=~1Mf*JIOX7DWB+iiJGw9C3wFA)&L`Jm{DoXCxvsd84_nq1;*x;k!RIejOC zau{(XQE`UdF*FgBubBwS?fyR~|GS#+*Pwinq;2^7!-EgQ#(`KcW zr(T{69Lk7*!!As67*nr4LZdA4eqx)=^wSGBc5;!dtF5XqaIYnqDJzp5!koI*h80U+ z4?eSEHvmd10%1f|*JK!xUNE;rZR_$|;Ca?e0WU`BP;EuVDO-Hqu~vlhk*cjppC4sY zxgO=?7NMpC3jE&j(%7QVDxSaz>c4U%mO-H=RwpxwPx83*Q-mnZ;1G?(G6#H6oz?)#pGYX@R)RP)aDpJO=2m#FqpN^X=cD6mR( zjo=m_OsGAcC=&>ZCKE)4^g*s!kZCNEPVKdD4c89G-PiL!I0)@gjf>iQDO%;McdZ(;{`c z{Qm>rjOqNro3RiAt`u1!465#;D3kHJ2u!>u)PtM!aSoYS%psOGZZUBSg_dNqX*dYV z4Mj)3cG13bEX5j>b4%MrX)<93Y1Qj{Yn@G_91j;yy?G84?i1~g%jD@P;X+yt{luY_ z7{wUWF;2s=lFhm$lP|&6G~V2@T)ES-+yD_~8B?KEd?YNTYYS3rtMKhFl=@*Gn_*a3 zFqlQ3O4gsQ(um)`UA~dS4ig`&?_T#jlp@tyA}q!1n1Pf+=q=AdKS~LcFK?MIzt{gO z9ro-okco5yWBPf!=-f7@qO&m;8qqWvu3gIsB}{~cE4!GU7Rz2G+PdJ%7mD^?#x9VH zMl+w8)ugw_6vsisiS^bzoDIBZw% z-}p6q8*yaN+t}}$EV@RM4ReffZ{9xD%m1#nQPSQR(E{=?=dQqsq=T@wH)wLE1m+%8 zN7gkj=&E1c0ZK8)fb-qtZxaDWuJyE5`ls^pF&&O!YDI-gZ#MWxnHd;2&rOBs{b&CR DG7lAE literal 9021 zcmeHNd010ty2r5{K?OolgRBikur9<6*#fCV)S!aZ3L+$kXca*qN+4`WRhCo~+Mwbn zgi>v}Es~%jAcRCAkU=b<2tk%a5->mrAs~B}`yG%jcV_Ipf84qEd1mrFc?gGdPR{wx z`+I-O%UAoocIhuRU96*{qmSFYB~S#ruuUo!VBDzR0N$OO;1g;K94=;Drk(1%a#41)A}r#?u8!CtF08 zVeZsx!*{1UF7E4NeZ)9KjW5zuAF6sV5Mj8j`xELltzjHysQ!6I2g|=g%YEIx!iI=V z+Sf*=MYxo>;LWVVszy`Eherrpu9_@#vnX*Mkc;{k=LhFT?R41DmXvR(%x>u?sX}tw zAGHNDWm|l-PclPjMS9+5VofNmKRRH>@}60apgu+S!{)FP9_X=c<4#fWoe#}qu9bR? z-y^DQ!fbdQ1)T^sDbv9{DgPxb$hhPq@ia-*Z_PuzN&{cy`R|XlG7O<$M$LQ#S6x~}*u*@Dmd+_K|ZXg?f0_(5xpjD`S=`Aw$l-3)rC~Vk6 z&yX8dpeKvfQ%hE_BvgkuFs$naNaWG6^KQgGr5a;?gr0B&tovlea%J3oeS}TjwNiEN zt?w17laG_>OIe$E8O#TZmBy)-p6X_<5pEN8{zMDF4GJ3&<~NFp;@tM62Lg$)JzjudpkgKNQbGROvNh8=<>`B*w(jPw+?b)n zu}R#>BJiZE;7OCtEa49?l^sK8_#q0rx}#j#a6^%EVT}F~LH||B27_HJyW#=av57Iq z@!M$ia;JckCcG(j-nSWsmF)hXUR5uU8UBE%!s~CsSq}R)e}dyQ5{N&W*>U}0+DBoQhvmhL9pTAbz{1o5pr zWUSX7Y|@!iG~CElfT4HWcCswC%~hgzUtu*U&Z7182S6En>y->nBmo>@_Wu7s*B`-q z$`xT(fB)tE_4NlYY?$#t*x**z8AA&OmXdJ@Kn1$-yMGUk!d~XZj&f37y)rPFESo<)r z#cNr?=m~f9dasC73lVAu(+)-nHd?fRSwwMm)7KpvBC#>e~VX(59g7ZTq%02%P`$ z^%Fmy@VlP>f&X~CJD?n^AO4B#@<;Xm9(q$TU|A>pPWxT&{p87Y^>?t$JMLB*ByW<_ z{e6Su2YKDNhFt-K?zh=|!``TtdLv|=D|E_Hgr&{c^fi0~t7QQ{T(IY8P~C8R-*t=~z>8c!vC*G2eFO&PXb``Vea8*T@M752@~G@1KI6;%!SjiCH~W zaic{auqj=YHI83Jh(?6eg69bddH%uiZ+Y?6kIJehvn!6P%O}k&vFLF269O$yxPVao6h6NG`1WGa=n-Jkz zw)B*}o&Z6(LtHMN=J9=bGX)d2@RGE9u2JIn+vUnlU1d*OtkRK>Zm$C!28%FQ_j)11 zz*uos;Bs!HHQ8q!f5uhwB$=5~F+G)OOR#I2V1AAFVd3vn^jGbs$3tyNicQF|i!kna zKh*ZMrF97;Z5bm81u>|ou-CP1md-?U6ql5kJi04(@&n)HOiU5-5eslh!dhOMb>?vn z%B;%OM<*o36AxEj*S6wEl1MB@%+UK zeLpML>dl8d&dInfrato zZTL$73ToKlRrKTcb2nc{S?z+*#8^%&oxxdXuEMw!6X=k5_q}vadc?zjqv*Ht?Qc=E z@sChcA@HV$@=LYDt+)|BRGI=NO^`_hbj@VTwVmrJ7~Uc~V2ad-XsMss@0dIWT9swY z%}f@C?e%l1{lMEZ+zI(ite6Qe{+)d5$tZO+k1rFDrDLr@U&_9p5l@#kxDElwAT9E5 zq$8s~;qW%0feS%G7Q@87p9gYhj?#QRaJRqE^F@0YIrFh(+dM};ZvV68g=XmE& zWt}7o@f6*`E{c-)6CF|HU5ZYh8G6XFMBzBIT#*6`ly-Gob$LJcEPuy6zUyAMtO^h& zW*v_twP~tkp#2rhwm*EIa^Y(v=1I@J1Sx;k#RhwH$|(m@o3(2a zBy(FXGHRER9r=uvP+#r?^ytKDQ{n% zEOzU&H^@i#b06VG@+PneuibGeg2+~-b4&`Sy$mjvf0N)?jQSD8Gd?OjEtRW^sIMJ9 z!;Qfl^4?P$x4k36%D_D43c^z4NJ!kPA*The;9pdnvG}v2L7%26bu84Leyc!Qv(L+_ zvEN9vO$dFp5%kq8kkt*m%j(j*m|67Z1dAAb1OY$mhN`b}Nz#JCTMNsb-sY8c)9QgR zJ4@!J@hjDOtLqj*eL$2#W~5iYWqXC$kH+Ba?m8GQc_tHd`Co3E$1M4vcHhd-L&|XuKdp@P(0Y&IFZG4;p#B+p4_C#C$?9S z8GVqvD@7PkMS!n#2hR#fwBRLhxHH$SPx(cN!cg5{RGphQF+|b;$8r&*v25x7r$MfN zfU_+#bBq;$S6$3wVg0Z4Y^^Q$W+^oUtg%!347gbIe}LYl3ZcP0Z0Zs)A?vlrch4=k zDvjHV8|kGSrirvl2$NiYqZlZGptfI{lv{a2R8|4m@#FtCLVu9amA*ft)6cIAH}4|T zZb<{sJ-G}9k_tVOgeRBCt`*^4RY<9zL({mg{vF_a=X7_St%c_+`AM6lp#S^GOnv{9RS z(5oT^#*z9RVwgm3G_ zQ!6r3LB0@s=*YEV%W12m$-aKvNNS0dxE{P%!z~CxYGlk1GwTj%&K+g^Pty!;`}7)~clP`eAEL3E2hOBh zaOJ}2?C~M`((wud#nOW2I6+Zlj+YadCA=MQFW}fk2WA9gp8AJQ6Z?Em1}+V*EY@^` z>ytvg1)fCy>^S||gm>*omIKgyOrZHP98tQs&7#tbUX;~js2dAfuoLUV;S-t8szuag znvwI|o>55b1g%WM?)HX}7W< zeAy24qsD)suuSD-t#UvT;3gEC)F@xagISZ17GkcQ9!v`|_pmaUMDri9g{0tL^7IX-WiSC&I{*_z)^tXR3w z+;Uueuxmclki!(}AGtRw_~%mEz0Sp+8eGe(-w8yf;;yiuK5)Ygs}#rVcxm5gTztDr zXLl42CYE;$(#Jww+b4EbQaYKS>U|LeO-Q4iRN#Uzm_zibp4ztMgWaJH9P|y5y@N$6o$z?_HOvF$OV*wSOshl$3p)9uer) z*Bvg=F)SDyThs*$TIGdcaJ-Cda5gix!BcvMs^=y{Y!RsFT391h3KGQ#t9tL)*D1OJ ziu_Vphx(3zcKa$!&v`TJfSHH0*~!6E@1XtODD7Wxu4Rb*N8#ZFDvBIx(iF$H<$sOT zf(hTg$%aA#H zY05WFg`p1mapPTh)yswY#E0h0Emoy=d^%DTK5yWRvFvcg7c>Z3>Gdz$+78iV#tJ5_ zpcSL56wdfo@1awJMiEttjkfbsU|F^uG`$ig*UkjovA^8cwV#!eh15c>?FLLNV<+Ca z&yT1mwaBlmKweZct6jj58K2+N;Oo}~c(5h80b`giS0sk6DX1ZH?G4xn_a|78jzYrG z=2=`eXqp=#lSW6HZ5$;+%y=0D9UU((I4b9Un;qStHh|^_jcU#v0lQ$qv&nx;g-8wB qwk1wJKiYMVm< + + + + + + +tgstation-server: IOpenApiExtension Class Reference + + + + + + + + + +
    +
    +

diff --git a/_open_api_enum_var_names_extension_8cs_source.html b/_open_api_enum_var_names_extension_8cs_source.html new file mode 100644 index 0000000000..b5283dd3c9 --- /dev/null +++ b/_open_api_enum_var_names_extension_8cs_source.html @@ -0,0 +1,89 @@ + + + + + + + +tgstation-server: src/Tgstation.Server.Host/Core/OpenApiEnumVarNamesExtension.cs Source File + + + + + + + + + +
+
+ + + + + + + +
+
tgstation-server +
+
The /tg/station 13 server suite
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
OpenApiEnumVarNamesExtension.cs
+
+
+Go to the documentation of this file.
1 using Microsoft.OpenApi;
2 using Microsoft.OpenApi.Interfaces;
3 using Microsoft.OpenApi.Models;
4 using Microsoft.OpenApi.Writers;
5 using System;
6 
8 {
13  {
17  readonly Type enumType;
18 
24  {
25  this.enumType = enumType ?? throw new ArgumentNullException(nameof(enumType));
26  }
27 
33  public static void Apply(OpenApiSchema openApiSchema, Type enumType)
34  {
35  if (openApiSchema == null)
36  throw new ArgumentNullException(nameof(openApiSchema));
37 
38  openApiSchema.Extensions.Add("x-enum-varnames", new OpenApiEnumVarNamesExtension(enumType));
39  }
40 
42  public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion)
43  {
44  if (writer == null)
45  throw new ArgumentNullException(nameof(writer));
46 
47  if (specVersion != OpenApiSpecVersion.OpenApi3_0)
48  throw new InvalidOperationException("This extension only applies to OpenAPI 3.0!");
49 
50  writer.WriteStartArray();
51  foreach (var enumValue in Enum.GetValues(enumType))
52  writer.WriteValue(enumValue.ToString());
53 
54  writer.WriteEndArray();
55  }
56  }
57 }
+ +
void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion)
+
readonly Type enumType
The Type of the Enum being described.
+
OpenApiEnumVarNamesExtension(Type enumType)
Initializes a new instance of the OpenApiEnumVarNamesExtension class.
+
static void Apply(OpenApiSchema openApiSchema, Type enumType)
Applies the extension to a give openApiSchema .
+
Implements the "x-enum-varnames" OpenAPI 3.0 extension.
+
+ + + + diff --git a/_platform_identifier_8cs.html b/_platform_identifier_8cs.html index 11e3137a67..dab47da977 100644 --- a/_platform_identifier_8cs.html +++ b/_platform_identifier_8cs.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/PlatformIdentifier.cs File Reference +tgstation-server: src/Tgstation.Server.Host/System/PlatformIdentifier.cs File Reference @@ -63,7 +63,7 @@ $(function() {
@@ -79,7 +79,7 @@ $(function() { - +

Classes

class  Tgstation.Server.Host.Core.PlatformIdentifier
class  Tgstation.Server.Host.System.PlatformIdentifier
 
- +

@@ -90,7 +90,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
namespace  Tgstation.Server.Host.System
 
diff --git a/_platform_identifier_8cs_source.html b/_platform_identifier_8cs_source.html index 2af23637bd..1050e33fcf 100644 --- a/_platform_identifier_8cs_source.html +++ b/_platform_identifier_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/PlatformIdentifier.cs Source File +tgstation-server: src/Tgstation.Server.Host/System/PlatformIdentifier.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,12 +71,12 @@ $(function() {
PlatformIdentifier.cs
-Go to the documentation of this file.
1 using System.Runtime.InteropServices;
2 
4 {
7  {
9  public bool IsWindows { get; }
10 
12  public string ScriptFileExtension { get; }
13 
18  {
19  IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
20  ScriptFileExtension = IsWindows ? "bat" : "sh";
21  }
22  }
23 }
PlatformIdentifier()
Construct a PlatformIdentifier
- - - - -
For identifying the current platform
+Go to the documentation of this file.
1 using System.Runtime.InteropServices;
2 
4 {
7  {
9  public bool IsWindows { get; }
10 
12  public string ScriptFileExtension { get; }
13 
18  {
19  IsWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
20  ScriptFileExtension = IsWindows ? "bat" : "sh";
21  }
22  }
23 }
+ +
PlatformIdentifier()
Construct a PlatformIdentifier
+ +
For identifying the current platform
+
Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using System;
3 using System.Globalization;
4 using System.Text;
5 using System.Threading;
6 using System.Threading.Tasks;
7 using Tgstation.Server.Host.IO;
8 
10 {
15  {
19  const string ByondCachePath = "~/.byond/cache";
20 
21  const string DreamDaemonExecutableName = "DreamDaemon";
22  const string DreamMakerExecutableName = "DreamMaker";
23  const string ShellScriptExtension = ".sh";
24 
27 
30 
32  protected override string ByondRevisionsURLTemplate => "https://secure.byond.com/download/build/{0}/{0}.{1}_byond_linux.zip";
33 
38 
45  public PosixByondInstaller(IPostWriteHandler postWriteHandler, IIOManager ioManager, ILogger<PosixByondInstaller> logger)
46  : base(ioManager, logger)
47  {
48  this.postWriteHandler = postWriteHandler ?? throw new ArgumentNullException(nameof(postWriteHandler));
49  }
50 
52  public override async Task CleanCache(CancellationToken cancellationToken)
53  {
54  try
55  {
56  await IOManager.DeleteDirectory(ByondCachePath, cancellationToken).ConfigureAwait(false);
57  }
58  catch (OperationCanceledException)
59  {
60  throw;
61  }
62  catch (Exception e)
63  {
64  Logger.LogWarning("Error deleting BYOND cache! Exception: {0}", e);
65  }
66  }
67 
69  public override Task InstallByond(string path, Version version, CancellationToken cancellationToken)
70  {
71  if (path == null)
72  throw new ArgumentNullException(nameof(path));
73  if (version == null)
74  throw new ArgumentNullException(nameof(version));
75 
76  // write the scripts for running the ting
77  // need to add $ORIGIN to LD_LIBRARY_PATH
78  const string StandardScript = "#!/bin/sh\nexport LD_LIBRARY_PATH=\"\\$ORIGIN:$LD_LIBRARY_PATH\"\nBASEDIR=$(dirname \"$0\")\nexec \"$BASEDIR/{0}\" \"$@\"\n";
79 
80  var dreamDaemonScript = String.Format(CultureInfo.InvariantCulture, StandardScript, DreamDaemonExecutableName);
81  var dreamMakerScript = String.Format(CultureInfo.InvariantCulture, StandardScript, DreamMakerExecutableName);
82 
83  async Task WriteAndMakeExecutable(string fullPath, string script)
84  {
85  await IOManager.WriteAllBytes(fullPath, Encoding.ASCII.GetBytes(script), cancellationToken).ConfigureAwait(false);
86  postWriteHandler.HandleWrite(fullPath);
87  }
88 
89  var basePath = IOManager.ConcatPath(path, ByondManager.BinPath);
90 
91  var task = Task.WhenAll(WriteAndMakeExecutable(IOManager.ConcatPath(basePath, DreamDaemonName), dreamDaemonScript), WriteAndMakeExecutable(IOManager.ConcatPath(basePath, DreamMakerName), dreamMakerScript));
92 
95 
96  return task;
97  }
98  }
99 }
IIOManager IOManager
Gets the IIOManager for the ByondInstallerBase.
-
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
+
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory, removes and does not enter any symlinks encounterd.
Handles changing file modes/permissions after writing
Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content
@@ -88,10 +88,10 @@ $(function() {
readonly IPostWriteHandler postWriteHandler
The IPostWriteHandler for the PosixByondInstaller
- +
Interface for using filesystems
Definition: IIOManager.cs:11
-
const string BinPath
The path to the BYOND bin folder
Definition: ByondManager.cs:21
+
const string BinPath
The path to the BYOND bin folder
Definition: ByondManager.cs:22
override Task InstallByond(string path, Version version, CancellationToken cancellationToken)
Does actions necessary to get an extracted BYOND installation working
diff --git a/_posix_network_prompt_reaper_8cs_source.html b/_posix_network_prompt_reaper_8cs_source.html index 5fa148c2fc..689a270c2d 100644 --- a/_posix_network_prompt_reaper_8cs_source.html +++ b/_posix_network_prompt_reaper_8cs_source.html @@ -71,11 +71,11 @@ $(function() {
PosixNetworkPromptReaper.cs
-Go to the documentation of this file.
2 
4 {
7  {
9  public void RegisterProcess(IProcess process)
10  {
11  // POSIX BYOND doesn't prompt you when you change the port
12  }
13  }
14 }
+Go to the documentation of this file.
2 
4 {
7  {
9  public void RegisterProcess(IProcess process)
10  {
11  // POSIX BYOND doesn't prompt you when you change the port
12  }
13  }
14 }
+
void RegisterProcess(IProcess process)
Register a given process for network prompt reaping
- -
Abstraction over a System.Diagnostics.Process
Definition: IProcess.cs:9
+
Abstraction over a global::System.Diagnostics.Process
Definition: IProcess.cs:8
On Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort()....
diff --git a/_process_8cs.html b/_process_8cs.html index 3e0e93a08f..b854ec2f7d 100644 --- a/_process_8cs.html +++ b/_process_8cs.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/Process.cs File Reference +tgstation-server: src/Tgstation.Server.Host/System/Process.cs File Reference @@ -63,7 +63,7 @@ $(function() {
@@ -79,7 +79,7 @@ $(function() { - +

Classes

class  Tgstation.Server.Host.Core.Process
class  Tgstation.Server.Host.System.Process
 
- +

@@ -90,7 +90,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
namespace  Tgstation.Server.Host.System
 
diff --git a/_process_8cs_source.html b/_process_8cs_source.html index 876a7c7f45..4fb58f60ba 100644 --- a/_process_8cs_source.html +++ b/_process_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/Process.cs Source File +tgstation-server: src/Tgstation.Server.Host/System/Process.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,24 +71,33 @@ $(function() {
Process.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using System;
3 using System.Text;
4 using System.Threading.Tasks;
5 
7 {
9  sealed class Process : IProcess
10  {
12  public int Id { get; }
13 
15  public Task Startup { get; }
16 
18  public Task<int> Lifetime { get; }
19 
20  readonly System.Diagnostics.Process handle;
21 
22  readonly StringBuilder outputStringBuilder;
23  readonly StringBuilder errorStringBuilder;
24  readonly StringBuilder combinedStringBuilder;
25 
29  readonly ILogger<Process> logger;
30 
41  public Process(System.Diagnostics.Process handle, Task<int> lifetime, StringBuilder outputStringBuilder, StringBuilder errorStringBuilder, StringBuilder combinedStringBuilder, ILogger<Process> logger, bool preExisting)
42  {
43  this.handle = handle ?? throw new ArgumentNullException(nameof(handle));
44  Lifetime = lifetime ?? throw new ArgumentNullException(nameof(lifetime));
45 
46  this.outputStringBuilder = outputStringBuilder;
47  this.errorStringBuilder = errorStringBuilder;
48  this.combinedStringBuilder = combinedStringBuilder;
49 
50  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
51 
52  Id = handle.Id;
53 
54  if (preExisting)
55  {
56  Startup = Task.CompletedTask;
57  return;
58  }
59 
60  Startup = Task.Factory.StartNew(() =>
61  {
62  try
63  {
64  handle.WaitForInputIdle();
65  }
66  catch (InvalidOperationException) { }
67  }, default, TaskCreationOptions.LongRunning, TaskScheduler.Current);
68 
69  logger.LogTrace("Created process ID: {0}", Id);
70  }
71 
73  public void Dispose() => handle.Dispose();
74 
76  public string GetCombinedOutput()
77  {
78  if (combinedStringBuilder == null)
79  throw new InvalidOperationException("Output/Error reading was not enabled!");
80  return combinedStringBuilder.ToString().TrimStart(Environment.NewLine.ToCharArray());
81  }
82 
84  public string GetErrorOutput()
85  {
86  if (errorStringBuilder == null)
87  throw new InvalidOperationException("Error reading was not enabled!");
88  return errorStringBuilder.ToString().TrimStart(Environment.NewLine.ToCharArray());
89  }
90 
92  public string GetStandardOutput()
93  {
94  if (outputStringBuilder == null)
95  throw new InvalidOperationException("Output reading was not enabled!");
96  return errorStringBuilder.ToString().TrimStart(Environment.NewLine.ToCharArray());
97  }
98 
100  public void Terminate()
101  {
102  if (handle.HasExited)
103  return;
104  try
105  {
106  logger.LogTrace("Terminating process...");
107  handle.Kill();
108  handle.WaitForExit();
109  }
110  catch (Exception e)
111  {
112  logger.LogDebug("Process termination exception: {0}", e);
113  }
114  }
115 
117  public void SetHighPriority()
118  {
119  try
120  {
121  handle.PriorityClass = System.Diagnostics.ProcessPriorityClass.AboveNormal;
122  logger.LogTrace("Set to above normal priority", handle.Id);
123  }
124  catch (Exception e)
125  {
126  logger.LogWarning("Unable to raise process priority! Exception: {0}", e);
127  }
128  }
129  }
130 }
readonly StringBuilder errorStringBuilder
Definition: Process.cs:23
- -
string GetErrorOutput()
Get the stderr output of the IProcess
Definition: Process.cs:84
- - -
Process(System.Diagnostics.Process handle, Task< int > lifetime, StringBuilder outputStringBuilder, StringBuilder errorStringBuilder, StringBuilder combinedStringBuilder, ILogger< Process > logger, bool preExisting)
Construct a Process
Definition: Process.cs:41
- -
readonly StringBuilder combinedStringBuilder
Definition: Process.cs:24
- -
string GetStandardOutput()
Get the stdout output of the IProcess
Definition: Process.cs:92
-
string GetCombinedOutput()
Get the stderr and stdout output of the IProcess
Definition: Process.cs:76
-
Abstraction over a System.Diagnostics.Process
Definition: IProcess.cs:9
- -
void SetHighPriority()
Set's the owned System.Diagnostics.Process.PriorityClass to System.Diagnostics.ProcessPriorityClass....
Definition: Process.cs:117
-
readonly ILogger< Process > logger
The ILogger for the Process
Definition: Process.cs:29
-
readonly System.Diagnostics.Process handle
Definition: Process.cs:20
-
readonly StringBuilder outputStringBuilder
Definition: Process.cs:22
-
void Terminate()
Terminates the process
Definition: Process.cs:100
+Go to the documentation of this file.
1 using BetterWin32Errors;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Diagnostics;
5 using System.Text;
6 using System.Threading.Tasks;
7 
9 {
11  sealed class Process : IProcess
12  {
14  public int Id { get; }
15 
17  public Task Startup { get; }
18 
20  public Task<int> Lifetime { get; }
21 
22  readonly global::System.Diagnostics.Process handle;
23 
24  readonly StringBuilder outputStringBuilder;
25  readonly StringBuilder errorStringBuilder;
26  readonly StringBuilder combinedStringBuilder;
27 
31  readonly ILogger<Process> logger;
32 
43  public Process(
44  global::System.Diagnostics.Process handle,
45  Task<int> lifetime,
46  StringBuilder outputStringBuilder,
47  StringBuilder errorStringBuilder,
48  StringBuilder combinedStringBuilder,
49  ILogger<Process> logger,
50  bool preExisting)
51  {
52  this.handle = handle ?? throw new ArgumentNullException(nameof(handle));
53 
54  this.outputStringBuilder = outputStringBuilder;
55  this.errorStringBuilder = errorStringBuilder;
56  this.combinedStringBuilder = combinedStringBuilder;
57 
58  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
59 
60  Lifetime = WrapLifetimeTask(lifetime ?? throw new ArgumentNullException(nameof(lifetime)));
61 
62  Id = handle.Id;
63 
64  if (preExisting)
65  {
66  Startup = Task.CompletedTask;
67  return;
68  }
69 
70  Startup = Task.Factory.StartNew(() =>
71  {
72  try
73  {
74  handle.WaitForInputIdle();
75  }
76  catch (InvalidOperationException) { }
77  }, default, TaskCreationOptions.LongRunning, TaskScheduler.Current);
78 
79  logger.LogTrace("Created process ID: {0}", Id);
80  }
81 
83  public void Dispose() => handle.Dispose();
84 
85  async Task<int> WrapLifetimeTask(Task<int> lifetimeTask)
86  {
87  var result = await lifetimeTask.ConfigureAwait(false);
88  logger.LogTrace("Process {0} ended with code {1}", Id, result);
89  return result;
90  }
91 
93  public string GetCombinedOutput()
94  {
95  if (combinedStringBuilder == null)
96  throw new InvalidOperationException("Output/Error reading was not enabled!");
97  return combinedStringBuilder.ToString().TrimStart(Environment.NewLine.ToCharArray());
98  }
99 
101  public string GetErrorOutput()
102  {
103  if (errorStringBuilder == null)
104  throw new InvalidOperationException("Error reading was not enabled!");
105  return errorStringBuilder.ToString().TrimStart(Environment.NewLine.ToCharArray());
106  }
107 
109  public string GetStandardOutput()
110  {
111  if (outputStringBuilder == null)
112  throw new InvalidOperationException("Output reading was not enabled!");
113  return errorStringBuilder.ToString().TrimStart(Environment.NewLine.ToCharArray());
114  }
115 
117  public void Terminate()
118  {
119  if (handle.HasExited)
120  return;
121  try
122  {
123  logger.LogTrace("Terminating process...");
124  handle.Kill();
125  handle.WaitForExit();
126  }
127  catch (Exception e)
128  {
129  logger.LogDebug("Process termination exception: {0}", e);
130  }
131  }
132 
134  public void SetHighPriority()
135  {
136  try
137  {
138  handle.PriorityClass = ProcessPriorityClass.AboveNormal;
139  logger.LogTrace("Set PID {0} to above normal priority", Id);
140  }
141  catch (Exception e)
142  {
143  logger.LogWarning("Unable to raise process priority! Exception: {0}", e);
144  }
145  }
146 
148  public void Suspend()
149  {
150  try
151  {
152  foreach (ProcessThread thread in handle.Threads)
153  {
154  var pOpenThread = NativeMethods.OpenThread(NativeMethods.ThreadAccess.SuspendResume, false, (uint)thread.Id);
155  if (pOpenThread == IntPtr.Zero)
156  continue;
157 
158  if (NativeMethods.SuspendThread(pOpenThread) == UInt32.MaxValue)
159  throw new Win32Exception();
160 
161  NativeMethods.CloseHandle(pOpenThread);
162  }
163 
164  logger.LogTrace("Suspended PID {0}", Id);
165  }
166  catch (Exception e)
167  {
168  logger.LogError(e, "Failed to suspend PID {0}!", Id);
169  throw;
170  }
171  }
172 
174  public void Resume()
175  {
176  try
177  {
178  foreach (ProcessThread thread in handle.Threads)
179  {
180  var pOpenThread = NativeMethods.OpenThread(NativeMethods.ThreadAccess.SuspendResume, false, (uint)thread.Id);
181  if (pOpenThread == IntPtr.Zero)
182  continue;
183 
184  if (NativeMethods.ResumeThread(pOpenThread) == UInt32.MaxValue)
185  throw new Win32Exception();
186 
187  NativeMethods.CloseHandle(pOpenThread);
188  }
189 
190  logger.LogTrace("Resumed PID {0}", Id);
191  }
192  catch (Exception e)
193  {
194  logger.LogError(e, "Failed to resume PID {0}!", Id);
195  throw;
196  }
197  }
198  }
199 }
void Suspend()
Suspends the process.
Definition: Process.cs:148
+
static uint ResumeThread(IntPtr hThread)
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms685086(v=vs.85).aspx
+ +
string GetCombinedOutput()
Get the stderr and stdout output of the IProcess
Definition: Process.cs:93
+ +
void SetHighPriority()
Set's the owned global::System.Diagnostics.Process.PriorityClass to global::System....
Definition: Process.cs:134
+ + +
string GetStandardOutput()
Get the stdout output of the IProcess
Definition: Process.cs:109
+
void Resume()
Resumes the process.
Definition: Process.cs:174
+
string GetErrorOutput()
Get the stderr output of the IProcess
Definition: Process.cs:101
+
readonly StringBuilder errorStringBuilder
Definition: Process.cs:25
+
void Terminate()
Terminates the process
Definition: Process.cs:117
+ + +
static bool CloseHandle(IntPtr hObject)
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx
+
Native methods used by the code
+
Abstraction over a global::System.Diagnostics.Process
Definition: IProcess.cs:8
+
ThreadAccess
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686769(v=vs.85).aspx
+
readonly global::System.Diagnostics.Process handle
Definition: Process.cs:22
+
static uint SuspendThread(IntPtr hThread)
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms686345(v=vs.85).aspx
+
readonly ILogger< Process > logger
The ILogger for the Process
Definition: Process.cs:31
+
Process(global::System.Diagnostics.Process handle, Task< int > lifetime, StringBuilder outputStringBuilder, StringBuilder errorStringBuilder, StringBuilder combinedStringBuilder, ILogger< Process > logger, bool preExisting)
Construct a Process
Definition: Process.cs:43
+
static IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, uint dwThreadId)
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms684335(v=vs.85).aspx
+
readonly StringBuilder outputStringBuilder
Definition: Process.cs:24
+
readonly StringBuilder combinedStringBuilder
Definition: Process.cs:26
+
async Task< int > WrapLifetimeTask(Task< int > lifetimeTask)
Definition: Process.cs:85
@@ -79,7 +79,7 @@ $(function() { - +

Classes

class  Tgstation.Server.Host.Core.ProcessExecutor
class  Tgstation.Server.Host.System.ProcessExecutor
 
- +

@@ -90,7 +90,7 @@ Namespaces

 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
namespace  Tgstation.Server.Host.System
 
diff --git a/_process_executor_8cs_source.html b/_process_executor_8cs_source.html index a6a8be060a..0b8cce93bf 100644 --- a/_process_executor_8cs_source.html +++ b/_process_executor_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: src/Tgstation.Server.Host/Core/ProcessExecutor.cs Source File +tgstation-server: src/Tgstation.Server.Host/System/ProcessExecutor.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,17 +71,17 @@ $(function() {
ProcessExecutor.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using System;
3 using System.Text;
4 using System.Threading.Tasks;
5 
7 {
10  {
14  readonly ILogger<ProcessExecutor> logger;
15 
19  readonly ILoggerFactory loggerFactory;
20 
26  static Task<int> AttachExitHandler(System.Diagnostics.Process handle)
27  {
28  handle.EnableRaisingEvents = true;
29  var tcs = new TaskCompletionSource<int>();
30  handle.Exited += (a, b) =>
31  {
32  int exitCode;
33  try
34  {
35  exitCode = handle.ExitCode;
36  }
37  catch (InvalidOperationException)
38  {
39  return;
40  }
41 
42  tcs.SetResult(exitCode);
43  };
44  return tcs.Task;
45  }
46 
52  public ProcessExecutor(ILogger<ProcessExecutor> logger, ILoggerFactory loggerFactory)
53  {
54  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
55  this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
56  }
57 
59  public IProcess GetProcess(int id)
60  {
61  logger.LogDebug("Attaching to process {0}...", id);
62  System.Diagnostics.Process handle;
63  try
64  {
65  handle = System.Diagnostics.Process.GetProcessById(id);
66  }
67  catch(Exception e)
68  {
69  logger.LogDebug("Unable to get process {0}! Exception: {1}", id, e);
70  return null;
71  }
72 
73  try
74  {
75  return new Process(handle, AttachExitHandler(handle), null, null, null, loggerFactory.CreateLogger<Process>(), true);
76  }
77  catch
78  {
79  handle.Dispose();
80  throw;
81  }
82  }
83 
85  public IProcess LaunchProcess(string fileName, string workingDirectory, string arguments, bool readOutput, bool readError, bool noShellExecute)
86  {
87  logger.LogDebug("Launching process in {0}: {1} {2}", workingDirectory, fileName, arguments);
88  var handle = new System.Diagnostics.Process();
89  try
90  {
91  handle.StartInfo.FileName = fileName;
92  handle.StartInfo.Arguments = arguments;
93  handle.StartInfo.WorkingDirectory = workingDirectory;
94 
95  handle.StartInfo.UseShellExecute = !(noShellExecute || readOutput || readError);
96 
97  StringBuilder outputStringBuilder = null, errorStringBuilder = null, combinedStringBuilder = null;
98  if (readOutput || readError)
99  {
100  combinedStringBuilder = new StringBuilder();
101  if (readOutput)
102  {
103  outputStringBuilder = new StringBuilder();
104  handle.StartInfo.RedirectStandardOutput = true;
105  handle.OutputDataReceived += (sender, e) =>
106  {
107  combinedStringBuilder.Append(Environment.NewLine);
108  combinedStringBuilder.Append(e.Data);
109  outputStringBuilder.Append(Environment.NewLine);
110  outputStringBuilder.Append(e.Data);
111  };
112  }
113 
114  if (readError)
115  {
116  errorStringBuilder = new StringBuilder();
117  handle.StartInfo.RedirectStandardError = true;
118  handle.ErrorDataReceived += (sender, e) =>
119  {
120  combinedStringBuilder.Append(Environment.NewLine);
121  combinedStringBuilder.Append(e.Data);
122  errorStringBuilder.Append(Environment.NewLine);
123  errorStringBuilder.Append(e.Data);
124  };
125  }
126  }
127 
128  var lifetimeTask = AttachExitHandler(handle);
129 
130  handle.Start();
131  try
132  {
133  if (readOutput)
134  handle.BeginOutputReadLine();
135  }
136  catch (InvalidOperationException) { }
137  try
138  {
139  if (readError)
140  handle.BeginErrorReadLine();
141  }
142  catch (InvalidOperationException) { }
143 
144  return new Process(handle, lifetimeTask, outputStringBuilder, errorStringBuilder, combinedStringBuilder, loggerFactory.CreateLogger<Process>(), false);
145  }
146  catch
147  {
148  handle.Dispose();
149  throw;
150  }
151  }
152  }
153 }
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the ProcessExecutor
- -
IProcess LaunchProcess(string fileName, string workingDirectory, string arguments, bool readOutput, bool readError, bool noShellExecute)
Launch a IProcess
- -
IProcess GetProcess(int id)
Get a IProcess by id
- -
static Task< int > AttachExitHandler(System.Diagnostics.Process handle)
Create a Task<TResult> resulting in the exit code of a given handle
- -
Abstraction over a System.Diagnostics.Process
Definition: IProcess.cs:9
-
ProcessExecutor(ILogger< ProcessExecutor > logger, ILoggerFactory loggerFactory)
Construct a ProcessExecutor
-
readonly ILogger< ProcessExecutor > logger
The ILogger for the ProcessExecutor
+Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using System;
3 using System.Text;
4 using System.Threading.Tasks;
5 
7 {
10  {
14  readonly ILogger<ProcessExecutor> logger;
15 
19  readonly ILoggerFactory loggerFactory;
20 
26  static Task<int> AttachExitHandler(global::System.Diagnostics.Process handle)
27  {
28  handle.EnableRaisingEvents = true;
29  var tcs = new TaskCompletionSource<int>();
30  handle.Exited += (a, b) =>
31  {
32  int exitCode;
33  try
34  {
35  exitCode = handle.ExitCode;
36  }
37  catch (InvalidOperationException)
38  {
39  return;
40  }
41 
42  tcs.SetResult(exitCode);
43  };
44  return tcs.Task;
45  }
46 
52  public ProcessExecutor(ILogger<ProcessExecutor> logger, ILoggerFactory loggerFactory)
53  {
54  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
55  this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
56  }
57 
59  public IProcess GetProcess(int id)
60  {
61  logger.LogDebug("Attaching to process {0}...", id);
62  global::System.Diagnostics.Process handle;
63  try
64  {
65  handle = global::System.Diagnostics.Process.GetProcessById(id);
66  }
67  catch(Exception e)
68  {
69  logger.LogDebug("Unable to get process {0}! Exception: {1}", id, e);
70  return null;
71  }
72 
73  try
74  {
75  return new Process(handle, AttachExitHandler(handle), null, null, null, loggerFactory.CreateLogger<Process>(), true);
76  }
77  catch
78  {
79  handle.Dispose();
80  throw;
81  }
82  }
83 
85  public IProcess LaunchProcess(string fileName, string workingDirectory, string arguments, bool readOutput, bool readError, bool noShellExecute)
86  {
87  logger.LogDebug("Launching process in {0}: {1} {2}", workingDirectory, fileName, arguments);
88  var handle = new global::System.Diagnostics.Process();
89  try
90  {
91  handle.StartInfo.FileName = fileName;
92  handle.StartInfo.Arguments = arguments;
93  handle.StartInfo.WorkingDirectory = workingDirectory;
94 
95  handle.StartInfo.UseShellExecute = !(noShellExecute || readOutput || readError);
96 
97  StringBuilder outputStringBuilder = null, errorStringBuilder = null, combinedStringBuilder = null;
98  if (readOutput || readError)
99  {
100  combinedStringBuilder = new StringBuilder();
101  if (readOutput)
102  {
103  outputStringBuilder = new StringBuilder();
104  handle.StartInfo.RedirectStandardOutput = true;
105  handle.OutputDataReceived += (sender, e) =>
106  {
107  combinedStringBuilder.Append(Environment.NewLine);
108  combinedStringBuilder.Append(e.Data);
109  outputStringBuilder.Append(Environment.NewLine);
110  outputStringBuilder.Append(e.Data);
111  };
112  }
113 
114  if (readError)
115  {
116  errorStringBuilder = new StringBuilder();
117  handle.StartInfo.RedirectStandardError = true;
118  handle.ErrorDataReceived += (sender, e) =>
119  {
120  combinedStringBuilder.Append(Environment.NewLine);
121  combinedStringBuilder.Append(e.Data);
122  errorStringBuilder.Append(Environment.NewLine);
123  errorStringBuilder.Append(e.Data);
124  };
125  }
126  }
127 
128  var lifetimeTask = AttachExitHandler(handle);
129 
130  handle.Start();
131  try
132  {
133  if (readOutput)
134  handle.BeginOutputReadLine();
135  }
136  catch (InvalidOperationException) { }
137  try
138  {
139  if (readError)
140  handle.BeginErrorReadLine();
141  }
142  catch (InvalidOperationException) { }
143 
144  return new Process(handle, lifetimeTask, outputStringBuilder, errorStringBuilder, combinedStringBuilder, loggerFactory.CreateLogger<Process>(), false);
145  }
146  catch
147  {
148  handle.Dispose();
149  throw;
150  }
151  }
152  }
153 }
+ +
ProcessExecutor(ILogger< ProcessExecutor > logger, ILoggerFactory loggerFactory)
Construct a ProcessExecutor
+
static Task< int > AttachExitHandler(global::System.Diagnostics.Process handle)
Create a Task<TResult> resulting in the exit code of a given handle
+
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the ProcessExecutor
+
readonly ILogger< ProcessExecutor > logger
The ILogger for the ProcessExecutor
+
IProcess LaunchProcess(string fileName, string workingDirectory, string arguments, bool readOutput, bool readError, bool noShellExecute)
Launch a IProcess
+
Abstraction over a global::System.Diagnostics.Process
Definition: IProcess.cs:8
+ +
IProcess GetProcess(int id)
Get a IProcess by id
+
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using System;
3 using System.Collections.Generic;
4 using System.Globalization;
5 using System.Linq;
6 using System.Threading;
7 using System.Threading.Tasks;
11 
13 {
18  {
20  public string Name => "prs";
21 
23  public string HelpText => "Display live test merge pull request numbers. Add --repo to view repository test merges";
24 
26  public bool AdminOnly => false;
27 
31  readonly IWatchdog watchdog;
32 
37 
42 
46  readonly Models.Instance instance;
47 
56  {
57  this.watchdog = watchdog ?? throw new ArgumentNullException(nameof(watchdog));
58  this.repositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager));
59  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
60  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
61  }
62 
64  // TODO: Decomplexify
65  #pragma warning disable CA1506
66  public async Task<string> Invoke(string arguments, User user, CancellationToken cancellationToken)
67  {
68  IEnumerable<Models.TestMerge> results = null;
69  if (arguments.Split(' ').Any(x => x.ToUpperInvariant() == "--REPO"))
70  {
71  string head;
72  using (var repo = await repositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false))
73  {
74  if (repo == null)
75  return "Repository unavailable!";
76  head = repo.Head;
77  }
78 
79  await databaseContextFactory.UseContext(async db => results = await db.RevisionInformations.Where(x => x.Instance.Id == instance.Id && x.CommitSha == head)
80  .SelectMany(x => x.ActiveTestMerges)
81  .Select(x => x.TestMerge)
82  .Select(x => new Models.TestMerge
83  {
84  Number = x.Number,
85  PullRequestRevision = x.PullRequestRevision
86  }).ToListAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false);
87  }
88  else
89  {
90  if (!watchdog.Running)
91  return "Server offline!";
92  results = watchdog.ActiveCompileJob?.RevisionInformation.ActiveTestMerges.Select(x => x.TestMerge).ToList() ?? new List<Models.TestMerge>();
93  }
94 
95  return !results.Any() ? "None!" : String.Join(", ", results.Select(x => String.Format(CultureInfo.InvariantCulture, "#{0} at {1}", x.Number, x.PullRequestRevision.Substring(0, 7))));
96  }
97  #pragma warning restore CA1506
98  }
99 }
+Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using System;
3 using System.Collections.Generic;
4 using System.Globalization;
5 using System.Linq;
6 using System.Threading;
7 using System.Threading.Tasks;
11 
13 {
18  {
20  public string Name => "prs";
21 
23  public string HelpText => "Display live test merge pull request numbers. Add --repo to view repository test merges";
24 
26  public bool AdminOnly => false;
27 
31  readonly IWatchdog watchdog;
32 
37 
42 
46  readonly Models.Instance instance;
47 
56  {
57  this.watchdog = watchdog ?? throw new ArgumentNullException(nameof(watchdog));
58  this.repositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager));
59  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
60  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
61  }
62 
64  // TODO: Decomplexify
65  #pragma warning disable CA1506
66  public async Task<string> Invoke(string arguments, User user, CancellationToken cancellationToken)
67  {
68  IEnumerable<Models.TestMerge> results = null;
69  if (arguments.Split(' ').Any(x => x.ToUpperInvariant() == "--REPO"))
70  {
71  string head;
72  using (var repo = await repositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false))
73  {
74  if (repo == null)
75  return "Repository unavailable!";
76  head = repo.Head;
77  }
78 
79  await databaseContextFactory.UseContext(async db => results = await db.RevisionInformations.Where(x => x.Instance.Id == instance.Id && x.CommitSha == head)
80  .SelectMany(x => x.ActiveTestMerges)
81  .Select(x => x.TestMerge)
82  .Select(x => new Models.TestMerge
83  {
84  Number = x.Number,
85  PullRequestRevision = x.PullRequestRevision
86  }).ToListAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false);
87  }
88  else
89  {
90  if (!watchdog.Running)
91  return "Server offline!";
92  results = watchdog.ActiveCompileJob?.RevisionInformation.ActiveTestMerges.Select(x => x.TestMerge).ToList() ?? new List<Models.TestMerge>();
93  }
94 
95  return !results.Any() ? "None!" : String.Join(", ", results.Select(x => String.Format(CultureInfo.InvariantCulture, "#{0} at {1}", x.Number, x.PullRequestRevision.Substring(0, 7))));
96  }
97  #pragma warning restore CA1506
98  }
99 }
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the PullRequestsCommand
+
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
readonly IRepositoryManager repositoryManager
The IRepositoryManager for the PullRequestsCommand
-
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
Models.CompileJob ActiveCompileJob
The CompileJob currently running on the server
Definition: IWatchdog.cs:27
-
readonly Models.Instance instance
The Models.Instance for the PullRequestsCommand
Command for reading the active Api.Models.TestMerges
Task< IRepository > LoadRepository(CancellationToken cancellationToken)
Attempt to load the IRepository from the default location
readonly IWatchdog watchdog
The IWatchdog for the PullRequestsCommand
+
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
Represents a tgs_chat_user datum
Definition: User.cs:10
bool Running
If the watchdog is running
Definition: IWatchdog.cs:17
-
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
PullRequestsCommand(IWatchdog watchdog, IRepositoryManager repositoryManager, IDatabaseContextFactory databaseContextFactory, Models.Instance instance)
Construct a PullRequestsCommand
Represents a command that can be invoked by talking to chat bots
Definition: ICommand.cs:9
async Task< string > Invoke(string arguments, User user, CancellationToken cancellationToken)
Invoke the ICommand
+
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
diff --git a/_reattach_info_handler_8cs_source.html b/_reattach_info_handler_8cs_source.html index 17fd7ced67..7a247f0701 100644 --- a/_reattach_info_handler_8cs_source.html +++ b/_reattach_info_handler_8cs_source.html @@ -71,37 +71,37 @@ $(function() {
ReattachInfoHandler.cs
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Linq;
5 using System.Threading;
6 using System.Threading.Tasks;
10 using Z.EntityFramework.Plus;
11 
13 {
16  {
21 
26 
30  readonly ILogger<ReattachInfoHandler> logger;
31 
35  readonly Api.Models.Instance metadata;
36 
44  public ReattachInfoHandler(IDatabaseContextFactory databaseContextFactory, IDmbFactory dmbFactory, ILogger<ReattachInfoHandler> logger, Api.Models.Instance metadata)
45  {
46  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
47  this.dmbFactory = dmbFactory ?? throw new ArgumentNullException(nameof(dmbFactory));
48  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
49  this.metadata = metadata ?? throw new ArgumentNullException(nameof(metadata));
50  }
51 
53  public Task Save(WatchdogReattachInformation reattachInformation, CancellationToken cancellationToken) => databaseContextFactory.UseContext(async (db) =>
54  {
55  if (reattachInformation == null)
56  throw new ArgumentNullException(nameof(reattachInformation));
57 
58  logger.LogDebug("Saving reattach information: {0}...", reattachInformation);
59 
60  var deleteTask = db.WatchdogReattachInformations.Where(x => x.InstanceId == metadata.Id).DeleteAsync(cancellationToken);
61 
62  var instance = new Models.Instance { Id = metadata.Id };
63  db.Instances.Attach(instance);
64 
65  Models.ReattachInformation ConvertReattachInfo(ReattachInformation wdInfo)
66  {
67  if (wdInfo == null)
68  return null;
69  db.CompileJobs.Attach(wdInfo.Dmb.CompileJob);
70  return new Models.ReattachInformation
71  {
72  AccessIdentifier = wdInfo.AccessIdentifier,
73  ChatChannelsJson = wdInfo.ChatChannelsJson,
74  ChatCommandsJson = wdInfo.ChatCommandsJson,
75  ServerCommandsJson = wdInfo.ServerCommandsJson,
76  CompileJob = wdInfo.Dmb.CompileJob,
77  IsPrimary = wdInfo.IsPrimary,
78  Port = wdInfo.Port,
79  ProcessId = wdInfo.ProcessId,
80  RebootState = wdInfo.RebootState
81  };
82  }
83 
84  instance.WatchdogReattachInformation = new Models.WatchdogReattachInformation
85  {
86  Alpha = ConvertReattachInfo(reattachInformation.Alpha),
87  Bravo = ConvertReattachInfo(reattachInformation.Bravo),
88  AlphaIsActive = reattachInformation.AlphaIsActive,
89  };
90  await deleteTask.ConfigureAwait(false);
91  await db.Save(cancellationToken).ConfigureAwait(false);
92  });
93 
95  public async Task<WatchdogReattachInformation> Load(CancellationToken cancellationToken)
96  {
97  Models.WatchdogReattachInformation result = null;
98  await databaseContextFactory.UseContext(async (db) =>
99  {
100  var instance = await db.Instances.Where(x => x.Id == metadata.Id)
101  .Include(x => x.WatchdogReattachInformation).ThenInclude(x => x.Alpha).ThenInclude(x => x.CompileJob)
102  .Include(x => x.WatchdogReattachInformation).ThenInclude(x => x.Bravo).ThenInclude(x => x.CompileJob)
103  .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
104  result = instance.WatchdogReattachInformation;
105  if (result == default)
106  return;
107  instance.WatchdogReattachInformation = null;
108  db.WatchdogReattachInformations.Remove(result);
109  await db.Save(cancellationToken).ConfigureAwait(false);
110  }).ConfigureAwait(false);
111 
112  if (result == default)
113  {
114  logger.LogDebug("Reattach information not found!");
115  return null;
116  }
117 
118  var bravoDmbTask = dmbFactory.FromCompileJob(result.Bravo.CompileJob, cancellationToken);
119  var info = new WatchdogReattachInformation(result, await dmbFactory.FromCompileJob(result.Alpha.CompileJob, cancellationToken).ConfigureAwait(false), await bravoDmbTask.ConfigureAwait(false));
120  logger.LogDebug("Reattach information loaded: {0}", info);
121  return info;
122  }
123  }
124 }
string ServerCommandsJson
Path to the server commands json file
+Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Linq;
5 using System.Threading;
6 using System.Threading.Tasks;
10 using Z.EntityFramework.Plus;
11 
13 {
16  {
21 
26 
30  readonly ILogger<ReattachInfoHandler> logger;
31 
35  readonly Api.Models.Instance metadata;
36 
44  public ReattachInfoHandler(IDatabaseContextFactory databaseContextFactory, IDmbFactory dmbFactory, ILogger<ReattachInfoHandler> logger, Api.Models.Instance metadata)
45  {
46  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
47  this.dmbFactory = dmbFactory ?? throw new ArgumentNullException(nameof(dmbFactory));
48  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
49  this.metadata = metadata ?? throw new ArgumentNullException(nameof(metadata));
50  }
51 
53  public Task Save(WatchdogReattachInformation reattachInformation, CancellationToken cancellationToken) => databaseContextFactory.UseContext(async (db) =>
54  {
55  if (reattachInformation == null)
56  throw new ArgumentNullException(nameof(reattachInformation));
57 
58  logger.LogDebug("Saving reattach information: {0}...", reattachInformation);
59 
60  var deleteTask = db.WatchdogReattachInformations.Where(x => x.InstanceId == metadata.Id).DeleteAsync(cancellationToken);
61 
62  var instance = new Models.Instance { Id = metadata.Id };
63  db.Instances.Attach(instance);
64 
65  Models.ReattachInformation ConvertReattachInfo(ReattachInformation wdInfo)
66  {
67  if (wdInfo == null)
68  return null;
69  db.CompileJobs.Attach(wdInfo.Dmb.CompileJob);
70  return new Models.ReattachInformation
71  {
72  AccessIdentifier = wdInfo.AccessIdentifier,
73  ChatChannelsJson = wdInfo.ChatChannelsJson,
74  ChatCommandsJson = wdInfo.ChatCommandsJson,
75  ServerCommandsJson = wdInfo.ServerCommandsJson,
76  CompileJob = wdInfo.Dmb.CompileJob,
77  IsPrimary = wdInfo.IsPrimary,
78  Port = wdInfo.Port,
79  ProcessId = wdInfo.ProcessId,
80  RebootState = wdInfo.RebootState
81  };
82  }
83 
84  instance.WatchdogReattachInformation = new Models.WatchdogReattachInformation
85  {
86  Alpha = ConvertReattachInfo(reattachInformation.Alpha),
87  Bravo = ConvertReattachInfo(reattachInformation.Bravo),
88  AlphaIsActive = reattachInformation.AlphaIsActive,
89  };
90  await deleteTask.ConfigureAwait(false);
91  await db.Save(cancellationToken).ConfigureAwait(false);
92  });
93 
95  public async Task<WatchdogReattachInformation> Load(CancellationToken cancellationToken)
96  {
97  Models.WatchdogReattachInformation result = null;
98  await databaseContextFactory.UseContext(async (db) =>
99  {
100  var instance = await db.Instances.Where(x => x.Id == metadata.Id)
101  .Include(x => x.WatchdogReattachInformation).ThenInclude(x => x.Alpha).ThenInclude(x => x.CompileJob)
102  .Include(x => x.WatchdogReattachInformation).ThenInclude(x => x.Bravo).ThenInclude(x => x.CompileJob)
103  .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
104  result = instance.WatchdogReattachInformation;
105  if (result == default)
106  return;
107  instance.WatchdogReattachInformation = null;
108  db.WatchdogReattachInformations.Remove(result);
109  await db.Save(cancellationToken).ConfigureAwait(false);
110  }).ConfigureAwait(false);
111 
112  if (result == default)
113  {
114  logger.LogDebug("Reattach information not found!");
115  return null;
116  }
117 
118  var bravoDmbTask = dmbFactory.FromCompileJob(result.Bravo.CompileJob, cancellationToken);
119  var info = new WatchdogReattachInformation(result, await dmbFactory.FromCompileJob(result.Alpha.CompileJob, cancellationToken).ConfigureAwait(false), await bravoDmbTask.ConfigureAwait(false));
120  logger.LogDebug("Reattach information loaded: {0}", info);
121  return info;
122  }
123  }
124 }
string ServerCommandsJson
Path to the server commands json file
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the ReattachInfoHandler
-
CompileJob CompileJob
The CompileJob of the .dmb
Definition: IDmbProvider.cs:29
- +
CompileJob CompileJob
The CompileJob of the .dmb
Definition: IDmbProvider.cs:29
+ +
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
string ChatCommandsJson
Path to the chat commands json file
-
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
- -
readonly ILogger< ReattachInfoHandler > logger
The ILogger for the ReattachInfoHandler
Task Save(WatchdogReattachInformation reattachInformation, CancellationToken cancellationToken)
Save some reattachInformation
async Task< WatchdogReattachInformation > Load(CancellationToken cancellationToken)
Load a saved WatchdogReattachInformation
ushort Port
The port DreamDaemon was last listening on
-
IDmbProvider Dmb
The IDmbProvider used by DreamDaemon
+
IDmbProvider Dmb
The IDmbProvider used by DreamDaemon
readonly Api.Models.Instance metadata
The Api.Models.Instance for the ReattachInfoHandler
readonly IDmbFactory dmbFactory
The IDmbFactory for the ReattachInfoHandler
ReattachInfoHandler(IDatabaseContextFactory databaseContextFactory, IDmbFactory dmbFactory, ILogger< ReattachInfoHandler > logger, Api.Models.Instance metadata)
Construct a ReattachInfoHandler
- -
bool IsPrimary
If the Components.IDmbProvider.PrimaryDirectory of the associated dmb is being used
+ +
bool IsPrimary
If the Components.Deployment.IDmbProvider.PrimaryDirectory of the associated dmb is being used
+
string ChatChannelsJson
Path to the chat channels json file
+
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
-
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
-
Task< IDmbProvider > FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken)
Gets a IDmbProvider for a given CompileJob
+
Task< IDmbProvider > FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken)
Gets a IDmbProvider for a given CompileJob
RebootState RebootState
The current DreamDaemon reboot state
Handles saving and loading WatchdogReattachInformation
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
-
Parameters necessary for duplicating a ISessionController session
+
Parameters necessary for duplicating a ISessionController session
+
string AccessIdentifier
Used to identify and authenticate the DreamDaemon instance
diff --git a/_reattach_information_base_8cs_source.html b/_reattach_information_base_8cs_source.html index 599147f058..619c49e256 100644 --- a/_reattach_information_base_8cs_source.html +++ b/_reattach_information_base_8cs_source.html @@ -79,7 +79,7 @@ $(function() {
Information used in for reattaching and interop
ushort Port
The port DreamDaemon was last listening on
-
bool IsPrimary
If the Components.IDmbProvider.PrimaryDirectory of the associated dmb is being used
+
bool IsPrimary
If the Components.Deployment.IDmbProvider.PrimaryDirectory of the associated dmb is being used
diff --git a/_release_notes_8_assembly_info_8cs.html b/_release_notes_8_assembly_info_8cs.html index edd49068bf..90ae4f85dc 100644 --- a/_release_notes_8_assembly_info_8cs.html +++ b/_release_notes_8_assembly_info_8cs.html @@ -5,7 +5,7 @@ -tgstation-server: tools/ReleaseNotes/obj/Release/netcoreapp2.1/ReleaseNotes.AssemblyInfo.cs File Reference +tgstation-server: tools/ReleaseNotes/obj/Debug/netcoreapp2.1/ReleaseNotes.AssemblyInfo.cs File Reference @@ -63,7 +63,7 @@ $(function() {
diff --git a/_release_notes_8_assembly_info_8cs_source.html b/_release_notes_8_assembly_info_8cs_source.html index b45eb2b693..4cfe3e21d0 100644 --- a/_release_notes_8_assembly_info_8cs_source.html +++ b/_release_notes_8_assembly_info_8cs_source.html @@ -5,7 +5,7 @@ -tgstation-server: tools/ReleaseNotes/obj/Release/netcoreapp2.1/ReleaseNotes.AssemblyInfo.cs Source File +tgstation-server: tools/ReleaseNotes/obj/Debug/netcoreapp2.1/ReleaseNotes.AssemblyInfo.cs Source File @@ -63,7 +63,7 @@ $(function() {
@@ -71,7 +71,7 @@ $(function() {
ReleaseNotes.AssemblyInfo.cs
-Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // <auto-generated>
3 // This code was generated by a tool.
4 // Runtime Version:4.0.30319.42000
5 //
6 // Changes to this file may cause incorrect behavior and will be lost if
7 // the code is regenerated.
8 // </auto-generated>
9 //------------------------------------------------------------------------------
10 
11 using System;
12 using System.Reflection;
13 
14 [assembly: System.Reflection.AssemblyCompanyAttribute("ReleaseNotes")]
15 [assembly: System.Reflection.AssemblyConfigurationAttribute("Release")]
16 [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
17 [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
18 [assembly: System.Reflection.AssemblyProductAttribute("ReleaseNotes")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("ReleaseNotes")]
20 [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
21 
22 // Generated by the MSBuild WriteCodeFragment class.
23 
+Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // <auto-generated>
3 // This code was generated by a tool.
4 // Runtime Version:4.0.30319.42000
5 //
6 // Changes to this file may cause incorrect behavior and will be lost if
7 // the code is regenerated.
8 // </auto-generated>
9 //------------------------------------------------------------------------------
10 
11 using System;
12 using System.Reflection;
13 
14 [assembly: System.Reflection.AssemblyCompanyAttribute("ReleaseNotes")]
15 [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
16 [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
17 [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
18 [assembly: System.Reflection.AssemblyProductAttribute("ReleaseNotes")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("ReleaseNotes")]
20 [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
21 
22 // Generated by the MSBuild WriteCodeFragment class.
23 

Headers

-

TGS4 expects this set of headers. Failure to provide them may result in 400 error responses

+

TGS4 expects this set of headers. Failure to provide them will result in 400 error responses

  • User-Agent: The user agent product header value of the calling program
  • -
  • Accept: application/json
  • Api: Another product header value representing the version of the API to use. Currently this must be: Tgstation.Server.Api/4.0.0.0

For POST, PATCH, and PUT requests you must also include the content type. Currently only json is supported

@@ -168,13 +167,12 @@ Authentication

POST "/" => Tgstation.Server.Api.Models.Token

Headers:

    -
  • Username: <your username>
  • -
  • Authorization:Password <your password>
  • +
  • Authorization:basic <Base64 encoded credentials in the form username:password>

If the provided credentials are valid and your user account is enabled you will recieve a Tgstation.Server.Api.Models.Token object

{
"bearer": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiZXhwIjoiMTUzMzIzNjk0MSIsIm5iZiI6IjE1MzMyMzYwNDEiLCJpc3MiOiJUZ3N0YXRpb24uU2VydmVyLkhvc3QiLCJhdWQiOiJUZ3N0YXRpb24uU2VydmVyLkFwaSJ9.QWFSWNi9mgol582zaK4MQ5XDK2gZF-Nx3z9_ToHjKW4"
}

If your account is disabled, you will recieve a 403 response.

You may recognize the bearer value as a Json Web Token. This is a secure representation of your identity to the server. It expires after a set period of time or until your password changes. It must be present for requests made to all other APIs. To do so add the following header to your other requests

    -
  • Authorization:Bearer <your bearer token>
  • +
  • Authorization:bearer <your bearer token>

Continue to use this token until you begin to recieve 401 responses from the API. Then repeat the process to get a new one if your credentials are still valid

diff --git a/architecture.html b/architecture.html index 66ec57fd98..de1ac21624 100644 --- a/architecture.html +++ b/architecture.html @@ -119,7 +119,7 @@ Main Server

Server Initialization

The server's entrypoint is in the Tgstation.Server.Host.Program class. This class mainly determines if the Host watchdog is present and creates and runs the Tgstation.Server.Host.Server class. That class then builds an ASP.NET Core web host using the Tgstation.Server.Host.Core.Application class.

-

The Tgstation.Server.Host.Core.Application class has two methods called by the framework. First the Tgstation.Server.Host.Core.Application.ConfigureServices method sets up dependency injection of interfaces for Controllers, the Tgstation.Server.Host.Models.DatabaseContext, and the component factories of the server. The framework handles constructing these things once the application starts. Configuration is loaded from the appropriate appSettings.json into the Tgstation.Server.Host.Configuration classes for injection as well. Then Tgstation.Server.Host.Core.Application.Configure method is run which sets up the web request pipeline which currently has the following stack of handlers:

+

The Tgstation.Server.Host.Core.Application class has two methods called by the framework. First the Tgstation.Server.Host.Core.Application.ConfigureServices method sets up dependency injection of interfaces for Controllers, the Tgstation.Server.Host.Database.DatabaseContext, and the component factories of the server. The framework handles constructing these things once the application starts. Configuration is loaded from the appropriate appSettings.json into the Tgstation.Server.Host.Configuration classes for injection as well. Then Tgstation.Server.Host.Core.Application.Configure method is run which sets up the web request pipeline which currently has the following stack of handlers:

+ + + + + + +
+
tgstation-server +
+
The /tg/station 13 server suite
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
IOpenApiExtension Class Reference
+
+
+
+Inheritance diagram for IOpenApiExtension:
+
+
+ + +Tgstation.Server.Host.Core.OpenApiEnumVarNamesExtension + +
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/class_i_open_api_extension.png b/class_i_open_api_extension.png new file mode 100644 index 0000000000000000000000000000000000000000..3feb213e1a006707faebd6b1cf477be0807f986e GIT binary patch literal 1086 zcmeAS@N?(olHy`uVBq!ia0y~yV9Wus12~w0Bv;@5mq1D)z$e7@|Ns9$=8HF9OZyK^ z0J6aNz<~p-opbm}zY4~KmWLJij^Z(>aP@yqKrgCbCmgxtEzW)3XCK(hQmecRkQZ~J_;E*0M&o9eg7-2QhsgJHfA4+$-TL3{tn2^3 zuV_26Ci~v58Ctvd+zLqFK7Xt9RiTXkyYn_!-D=siKUKe6dgIkMi+A&1_ub;2m;AnJ z`-I&Quj)2$-15D5o7>IT0V_-TyKY@BeKBbv_a^zG5XqaDr#xGHR+x9w-GH`4=Z0nV zXJ=3RrMc%`+zG9${^z;do}S1P{`NEFer8Z$(9D_w!@ReAKJ&Y@SqNzpi5Iv4K7N|KB>Lm@lmdKI;Vst0Q%1s<^TWy literal 0 HcmV?d00001 diff --git a/class_i_operation_filter.html b/class_i_operation_filter.html index 0e2d034c74..11b7d2ebf1 100644 --- a/class_i_operation_filter.html +++ b/class_i_operation_filter.html @@ -73,11 +73,11 @@ Inheritance diagram for IOperationFilter:
-Tgstation.Server.Host.Controllers.TgsOpenApiFilters +Tgstation.Server.Host.Core.SwaggerConfiguration

The documentation for this class was generated from the following file:
diff --git a/class_i_operation_filter.png b/class_i_operation_filter.png index 58b89542c652fe43a4c477c9ff71ede629c2fd46..742be138ce9ca2f4e55821f0ddd617d239f2dcfd 100644 GIT binary patch literal 964 zcmeAS@N?(olHy`uVBq!ia0y~yVAKGz12~w0FuS-s=2g;ms5dZhms4U1xFwQpOZ*KvjFRZ2fd4~ z^|=k9%@JpbF-MP`ujgDbb+U;qAfaK6ea zyRQuQ4obT+KKJkCId?>h4ii5!qsUQK?XP;> zw`xbe?Frwqe$9%-4?6PfJ+H3v>HPbhCzkzY`|XmOZg<%BrWTuNe9SY>bzNJ!G$htb zD?Ie!hb$ul-*e$^A>x-f-ZO{(opGd(XrLuZogeGo}F1DpM3qBX^zDjBk9LBmpfNz{Z-yMb49Y^9NoV6vHPXYthjVEBxJMf z?ZPdWW(V5nzp}bKbH(YU*Ht3cAMv`9v3uLu_0#74l~_8z_W#UhxsxlLuJ|s~e;b$_ z=ysqW>iqW=i3=R<7jI#UKBtiMJ$P%iYe?;@xzCU6`guLQF;?!`hE>X?%S?6X$G`n>AP@(b(YJU@MiX$}k79q4^Y+}JWs<>jR3 zm*1pKvCU9Qep32F{hXh7=x4k aGk6}eJ~7?r9}6(cF?hQAxvX z*JCNj6Is7y>D7;`HZNk4Nq=>u-cxg_!qO=+6Bw8pPPdpc=qK_X@Qz^qAaspk&z`%t zjP71)V_0U>zFXbvw^nlbzgycQqR%q=NcPUE{=aam(c_}6*J3pHs?OXxXWoCY{ihu& zb53vBv%|Lfv{K&IvYc&KFV@BK&N$vDaJHHu|M9!1)#3IRH=VxiwSFtx2S2;Rw-zS9 z7IDs=8}eK3!0sP2qBhTcv}x<)Ym6V#@7#92UHn%3+P~RRx62+bXrK1_>AtrMm9w|C zGwqqUJ({`i{M=&ZKhrj_Jy2c4Sh4fE)B$sli;+C=Y0I=AFGnxUSoR0bl?*Hle21hO zCLdSc!uW$Do5641B`4{IZlHGcIgAyY*$i<&+38TzsL1`9l5P3?&rF-5b3ct0y@M1y zr*mdcdZN0NX@$Q=_xI0S^ykg*;#5Vm4Vp{!{_DPyT5={*cfpge zebW9-1>4^DRKM7l`R0yVz3|qT3v<`9Xvt zEd`#x{MdfZ*FU-U!L_LBOWv2v4Nv~>Uz;nc=^200;{X0_YMzZMa|N!cob-;EtfHUj pI|-P!JU;;wRq;8;bC&VX + + + + + + +tgstation-server: ISchemaFilter Class Reference + + + + + + + + + +
+
+ + + + + + + +
+
tgstation-server +
+
The /tg/station 13 server suite
+
+
+ + + + + + + + +
+
+ + +
+ +
+ +
+
+
+
ISchemaFilter Class Reference
+
+
+
+Inheritance diagram for ISchemaFilter:
+
+
+ + +Tgstation.Server.Host.Core.SwaggerConfiguration + +
+
The documentation for this class was generated from the following file: +
+ + + + diff --git a/class_i_schema_filter.png b/class_i_schema_filter.png new file mode 100644 index 0000000000000000000000000000000000000000..5b0d7c0f4e37f419f9ed40f9b02ecbdc8db60e53 GIT binary patch literal 960 zcmeAS@N?(olHy`uVBq!ia0y~yVAKGz12~w0!Gh7jN#_yYZUi!iC;;|0V@_IeKZ%b!OsVIL8slz~>~=&@90EK*5F4Vn_6q z-P@n?82U3j%TYhK`&t#F%|Yfx)A+L2i!VC1jN$v|DJycftx=A+IyES8=hWF{ukYMi zb>HrT`n0&eJExghX1}bxx=Ao*{&WR~?H^iJ=$>Bt_?X9j@wK0qhrDxPymP{Mk(G4s z#A9xn<;JUKG4JSQH~(Dd=9_k|GeNiZ{h zJ?H{@Q^|zU0!bUl*Hq;G@Cvki{wMd(lR2NKJ5F2TFbNpKlb$HJcur~-Q1#?Y!Ht(;**7>>rEzjIm``Eam+oyi3`&m~>#><(td)$4QeSghdYI?IsO|U)s z@;mcIw}SKS)u)}^Z_EAWlR&4H7KyF+xp#lw{k4_n{Pr3?syMP`yHw$< zm7=N7cdGp5{dHB_Q_e2?Lia24EYDv_e0}1cR!={hv`eP)OL_jvdebyjMPA-~hOVtA zm&(@gj!7!)ie8gsS~NV11Qw~BJm?*A&XV2odCjT%KeMe@ZF!zk2+VE_p00i_>zopr E0AI(fBme*a literal 0 HcmV?d00001 diff --git a/class_tgstation_1_1_server_1_1_api_1_1_api_headers.html b/class_tgstation_1_1_server_1_1_api_1_1_api_headers.html index 1abf4c7036..13d7f6a65e 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_api_headers.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_api_headers.html @@ -514,7 +514,7 @@ Static Private Attributes

 
- Properties inherited from Tgstation.Server.Host.Components.Byond.IByondExecutableLock
Version Version [get]
 The System.Version of the locked executables More...
 The global::System.Version of the locked executables More...
 
string DreamDaemonPath [get]
 The path to the DreamDaemon executable More...

Detailed Description

-

Definition at line 16 of file ByondManager.cs.

+

Definition at line 17 of file ByondManager.cs.

Constructor & Destructor Documentation

◆ ByondManager()

@@ -224,15 +224,15 @@ Private Attributes -

Definition at line 90 of file ByondManager.cs.

-
91  {
92  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
93  this.byondInstaller = byondInstaller ?? throw new ArgumentNullException(nameof(byondInstaller));
94  this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
95  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
96 
97  installedVersions = new Dictionary<string, Task>();
98  semaphore = new SemaphoreSlim(1);
99  }
readonly IIOManager ioManager
The IIOManager for the ByondManager
Definition: ByondManager.cs:49
-
readonly Dictionary< string, Task > installedVersions
Map of byond Versions to Tasks that complete when they are installed
Definition: ByondManager.cs:69
-
readonly ILogger< ByondManager > logger
The ILogger for the ByondManager
Definition: ByondManager.cs:64
-
readonly IByondInstaller byondInstaller
The IByondInstaller for the ByondManager
Definition: ByondManager.cs:54
-
readonly SemaphoreSlim semaphore
The SemaphoreSlim for the ByondManager
Definition: ByondManager.cs:74
-
readonly IEventConsumer eventConsumer
The IEventConsumer for the ByondManager
Definition: ByondManager.cs:59
+

Definition at line 91 of file ByondManager.cs.

+
92  {
93  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
94  this.byondInstaller = byondInstaller ?? throw new ArgumentNullException(nameof(byondInstaller));
95  this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
96  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
97 
98  installedVersions = new Dictionary<string, Task>();
99  semaphore = new SemaphoreSlim(1);
100  }
readonly IIOManager ioManager
The IIOManager for the ByondManager
Definition: ByondManager.cs:50
+
readonly Dictionary< string, Task > installedVersions
Map of byond Versions to Tasks that complete when they are installed
Definition: ByondManager.cs:70
+
readonly ILogger< ByondManager > logger
The ILogger for the ByondManager
Definition: ByondManager.cs:65
+
readonly IByondInstaller byondInstaller
The IByondInstaller for the ByondManager
Definition: ByondManager.cs:55
+
readonly SemaphoreSlim semaphore
The SemaphoreSlim for the ByondManager
Definition: ByondManager.cs:75
+
readonly IEventConsumer eventConsumer
The IEventConsumer for the ByondManager
Definition: ByondManager.cs:60
-

References Tgstation.Server.Host.Components.Byond.ByondManager.byondInstaller, Tgstation.Server.Host.Components.Byond.ByondManager.eventConsumer, Tgstation.Server.Host.Components.Byond.ByondManager.installedVersions, Tgstation.Server.Host.Components.Byond.ByondManager.ioManager, Tgstation.Server.Host.Components.Byond.ByondManager.logger, and Tgstation.Server.Host.Components.Byond.ByondManager.semaphore.

+

References Tgstation.Server.Host.Components.Byond.ByondManager.byondInstaller, Tgstation.Server.Host.Components.Byond.ByondManager.eventConsumer, Tgstation.Server.Host.Components.Byond.ByondManager.installedVersions, Tgstation.Server.Host.Components.Byond.ByondManager.ioManager, Tgstation.Server.Host.Components.Byond.ByondManager.logger, and Tgstation.Server.Host.Components.Byond.ByondManager.semaphore.

@@ -267,21 +267,21 @@ Private Attributes

Implements Tgstation.Server.Host.Components.Byond.IByondManager.

-

Definition at line 179 of file ByondManager.cs.

-
180  {
181  if (version == null)
182  throw new ArgumentNullException(nameof(version));
183  var versionKey = VersionKey(version);
184  await InstallVersion(version, cancellationToken).ConfigureAwait(false);
185  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
186  {
187  await ioManager.WriteAllBytes(ActiveVersionFileName, Encoding.UTF8.GetBytes(versionKey), cancellationToken).ConfigureAwait(false);
188  await eventConsumer.HandleEvent(EventType.ByondActiveVersionChange, new List<string> { ActiveVersion != null ? VersionKey(ActiveVersion) : null, versionKey }, cancellationToken).ConfigureAwait(false);
189  ActiveVersion = version;
190  }
191  }
readonly IIOManager ioManager
The IIOManager for the ByondManager
Definition: ByondManager.cs:49
+

Definition at line 180 of file ByondManager.cs.

+
181  {
182  if (version == null)
183  throw new ArgumentNullException(nameof(version));
184  var versionKey = VersionKey(version);
185  await InstallVersion(version, cancellationToken).ConfigureAwait(false);
186  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
187  {
188  await ioManager.WriteAllBytes(ActiveVersionFileName, Encoding.UTF8.GetBytes(versionKey), cancellationToken).ConfigureAwait(false);
189  await eventConsumer.HandleEvent(EventType.ByondActiveVersionChange, new List<string> { ActiveVersion != null ? VersionKey(ActiveVersion) : null, versionKey }, cancellationToken).ConfigureAwait(false);
190  ActiveVersion = version;
191  }
192  }
readonly IIOManager ioManager
The IIOManager for the ByondManager
Definition: ByondManager.cs:50
Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content
- -
const string ActiveVersionFileName
The file in which we store the VersionKey(Version) for the active installation
Definition: ByondManager.cs:31
+ +
const string ActiveVersionFileName
The file in which we store the VersionKey(Version) for the active installation
Definition: ByondManager.cs:32
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
-
async Task InstallVersion(Version version, CancellationToken cancellationToken)
Installs a BYOND version if it isn't already
+
async Task InstallVersion(Version version, CancellationToken cancellationToken)
Installs a BYOND version if it isn't already
Task< bool > HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
Handle a given eventType
static string VersionKey(Version version)
Converts a BYOND version to a string
-
readonly SemaphoreSlim semaphore
The SemaphoreSlim for the ByondManager
Definition: ByondManager.cs:74
+
readonly SemaphoreSlim semaphore
The SemaphoreSlim for the ByondManager
Definition: ByondManager.cs:75
static async Task< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore
-
readonly IEventConsumer eventConsumer
The IEventConsumer for the ByondManager
Definition: ByondManager.cs:59
+
readonly IEventConsumer eventConsumer
The IEventConsumer for the ByondManager
Definition: ByondManager.cs:60
-

References Tgstation.Server.Host.Components.Byond.ByondManager.ActiveVersion, Tgstation.Server.Host.Components.Byond.ByondManager.ActiveVersionFileName, Tgstation.Server.Host.Components.Byond.ByondManager.eventConsumer, Tgstation.Server.Host.Components.IEventConsumer.HandleEvent(), Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), Tgstation.Server.Host.Components.Byond.ByondManager.ioManager, Tgstation.Server.Host.Core.SemaphoreSlimContext.Lock(), Tgstation.Server.Host.Components.Byond.ByondManager.semaphore, Tgstation.Server.Host.Components.Byond.ByondManager.VersionKey(), and Tgstation.Server.Host.IO.IIOManager.WriteAllBytes().

+

References Tgstation.Server.Host.Components.Byond.ByondManager.ActiveVersion, Tgstation.Server.Host.Components.Byond.ByondManager.ActiveVersionFileName, Tgstation.Server.Host.Components.Byond.ByondManager.eventConsumer, Tgstation.Server.Host.Components.IEventConsumer.HandleEvent(), Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), Tgstation.Server.Host.Components.Byond.ByondManager.ioManager, Tgstation.Server.Host.Core.SemaphoreSlimContext.Lock(), Tgstation.Server.Host.Components.Byond.ByondManager.semaphore, Tgstation.Server.Host.Components.Byond.ByondManager.VersionKey(), and Tgstation.Server.Host.IO.IIOManager.WriteAllBytes().

@@ -348,9 +348,9 @@ Private Attributes
Returns
A Task representing the running operation
-

Definition at line 110 of file ByondManager.cs.

-
111  {
112  var ourTcs = new TaskCompletionSource<object>();
113  Task inProgressTask;
114 
115  var versionKey = VersionKey(version);
116  bool installed;
117  lock (installedVersions)
118  {
119  installed = installedVersions.TryGetValue(versionKey, out inProgressTask);
120  if (!installed)
121  installedVersions.Add(versionKey, ourTcs.Task);
122  }
123 
124  if (installed)
125  using (cancellationToken.Register(() => ourTcs.SetCanceled()))
126  {
127  await Task.WhenAny(ourTcs.Task, inProgressTask).ConfigureAwait(false);
128  cancellationToken.ThrowIfCancellationRequested();
129  return;
130  }
131 
132  // okay up to us to install it then
133  try
134  {
135  await eventConsumer.HandleEvent(EventType.ByondInstallStart, new List<string> { versionKey }, cancellationToken).ConfigureAwait(false);
136  var downloadTask = byondInstaller.DownloadVersion(version, cancellationToken);
137 
138  await ioManager.DeleteDirectory(versionKey, cancellationToken).ConfigureAwait(false);
139  await ioManager.CreateDirectory(versionKey, cancellationToken).ConfigureAwait(false);
140 
141  try
142  {
143  var download = await downloadTask.ConfigureAwait(false);
144  await ioManager.ZipToDirectory(versionKey, download, cancellationToken).ConfigureAwait(false);
145  await byondInstaller.InstallByond(ioManager.ResolvePath(versionKey), version, cancellationToken).ConfigureAwait(false);
146 
147  // make sure to do this last because this is what tells us we have a valid version in the future
148  await ioManager.WriteAllBytes(ioManager.ConcatPath(versionKey, VersionFileName), Encoding.UTF8.GetBytes(version.ToString()), cancellationToken).ConfigureAwait(false);
149  }
150  catch (WebException e)
151  {
152  // since the user can easily provide non-exitent version numbers, we'll turn this into a JobException
153  throw new JobException(String.Format(CultureInfo.InvariantCulture, "Error downloading BYOND version: {0}", e.Message));
154  }
155  catch (OperationCanceledException)
156  {
157  throw;
158  }
159  catch
160  {
161  await ioManager.DeleteDirectory(versionKey, cancellationToken).ConfigureAwait(false);
162  throw;
163  }
164 
165  ourTcs.SetResult(null);
166  }
167  catch (Exception e)
168  {
169  if (!(e is OperationCanceledException))
170  await eventConsumer.HandleEvent(EventType.ByondInstallFail, new List<string> { e.Message }, cancellationToken).ConfigureAwait(false);
171  lock (installedVersions)
172  installedVersions.Remove(versionKey);
173  ourTcs.SetException(e);
174  throw;
175  }
176  }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
-
readonly IIOManager ioManager
The IIOManager for the ByondManager
Definition: ByondManager.cs:49
+

Definition at line 111 of file ByondManager.cs.

+
112  {
113  var ourTcs = new TaskCompletionSource<object>();
114  Task inProgressTask;
115 
116  var versionKey = VersionKey(version);
117  bool installed;
118  lock (installedVersions)
119  {
120  installed = installedVersions.TryGetValue(versionKey, out inProgressTask);
121  if (!installed)
122  installedVersions.Add(versionKey, ourTcs.Task);
123  }
124 
125  if (installed)
126  using (cancellationToken.Register(() => ourTcs.SetCanceled()))
127  {
128  await Task.WhenAny(ourTcs.Task, inProgressTask).ConfigureAwait(false);
129  cancellationToken.ThrowIfCancellationRequested();
130  return;
131  }
132 
133  // okay up to us to install it then
134  try
135  {
136  await eventConsumer.HandleEvent(EventType.ByondInstallStart, new List<string> { versionKey }, cancellationToken).ConfigureAwait(false);
137  var downloadTask = byondInstaller.DownloadVersion(version, cancellationToken);
138 
139  await ioManager.DeleteDirectory(versionKey, cancellationToken).ConfigureAwait(false);
140  await ioManager.CreateDirectory(versionKey, cancellationToken).ConfigureAwait(false);
141 
142  try
143  {
144  var download = await downloadTask.ConfigureAwait(false);
145  await ioManager.ZipToDirectory(versionKey, download, cancellationToken).ConfigureAwait(false);
146  await byondInstaller.InstallByond(ioManager.ResolvePath(versionKey), version, cancellationToken).ConfigureAwait(false);
147 
148  // make sure to do this last because this is what tells us we have a valid version in the future
149  await ioManager.WriteAllBytes(ioManager.ConcatPath(versionKey, VersionFileName), Encoding.UTF8.GetBytes(version.ToString()), cancellationToken).ConfigureAwait(false);
150  }
151  catch (WebException e)
152  {
153  // since the user can easily provide non-exitent version numbers, we'll turn this into a JobException
154  throw new JobException(String.Format(CultureInfo.InvariantCulture, "Error downloading BYOND version: {0}", e.Message));
155  }
156  catch (OperationCanceledException)
157  {
158  throw;
159  }
160  catch
161  {
162  await ioManager.DeleteDirectory(versionKey, cancellationToken).ConfigureAwait(false);
163  throw;
164  }
165 
166  ourTcs.SetResult(null);
167  }
168  catch (Exception e)
169  {
170  if (!(e is OperationCanceledException))
171  await eventConsumer.HandleEvent(EventType.ByondInstallFail, new List<string> { e.Message }, cancellationToken).ConfigureAwait(false);
172  lock (installedVersions)
173  installedVersions.Remove(versionKey);
174  ourTcs.SetException(e);
175  throw;
176  }
177  }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory, removes and does not enter any symlinks encounterd.
+
readonly IIOManager ioManager
The IIOManager for the ByondManager
Definition: ByondManager.cs:50
Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content
Task ZipToDirectory(string path, byte[] zipFileBytes, CancellationToken cancellationToken)
Extract a set of zipFileBytes to a given path
Task< byte[]> DownloadVersion(Version version, CancellationToken cancellationToken)
Download a given BYOND version
@@ -358,18 +358,18 @@ Private Attributes
Task InstallByond(string path, Version version, CancellationToken cancellationToken)
Does actions necessary to get an extracted BYOND installation working
Task CreateDirectory(string path, CancellationToken cancellationToken)
Create a directory at path
string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
-
readonly Dictionary< string, Task > installedVersions
Map of byond Versions to Tasks that complete when they are installed
Definition: ByondManager.cs:69
-
const string VersionFileName
The file in which we store the VersionKey(Version) for installations
Definition: ByondManager.cs:26
-
readonly IByondInstaller byondInstaller
The IByondInstaller for the ByondManager
Definition: ByondManager.cs:54
+
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
+
readonly Dictionary< string, Task > installedVersions
Map of byond Versions to Tasks that complete when they are installed
Definition: ByondManager.cs:70
+
const string VersionFileName
The file in which we store the VersionKey(Version) for installations
Definition: ByondManager.cs:27
+
readonly IByondInstaller byondInstaller
The IByondInstaller for the ByondManager
Definition: ByondManager.cs:55
Task< bool > HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
Handle a given eventType
static string VersionKey(Version version)
Converts a BYOND version to a string
string ConcatPath(params string[] paths)
Combines an array of strings into a path
-
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
-
readonly IEventConsumer eventConsumer
The IEventConsumer for the ByondManager
Definition: ByondManager.cs:59
+
readonly IEventConsumer eventConsumer
The IEventConsumer for the ByondManager
Definition: ByondManager.cs:60
-

References Tgstation.Server.Host.Components.Byond.ByondManager.byondInstaller, Tgstation.Server.Host.IO.IIOManager.ConcatPath(), Tgstation.Server.Host.IO.IIOManager.CreateDirectory(), Tgstation.Server.Host.IO.IIOManager.DeleteDirectory(), Tgstation.Server.Host.Components.Byond.IByondInstaller.DownloadVersion(), Tgstation.Server.Host.Components.Byond.ByondManager.eventConsumer, Tgstation.Server.Host.Components.IEventConsumer.HandleEvent(), Tgstation.Server.Host.Components.Byond.IByondInstaller.InstallByond(), Tgstation.Server.Host.Components.Byond.ByondManager.installedVersions, Tgstation.Server.Host.Components.Byond.ByondManager.ioManager, Tgstation.Server.Host.IO.IIOManager.ResolvePath(), Tgstation.Server.Host.Components.Byond.ByondManager.VersionFileName, Tgstation.Server.Host.Components.Byond.ByondManager.VersionKey(), Tgstation.Server.Host.IO.IIOManager.WriteAllBytes(), and Tgstation.Server.Host.IO.IIOManager.ZipToDirectory().

+

References Tgstation.Server.Host.Components.Byond.ByondManager.byondInstaller, Tgstation.Server.Host.IO.IIOManager.ConcatPath(), Tgstation.Server.Host.IO.IIOManager.CreateDirectory(), Tgstation.Server.Host.IO.IIOManager.DeleteDirectory(), Tgstation.Server.Host.Components.Byond.IByondInstaller.DownloadVersion(), Tgstation.Server.Host.Components.Byond.ByondManager.eventConsumer, Tgstation.Server.Host.Components.IEventConsumer.HandleEvent(), Tgstation.Server.Host.Components.Byond.IByondInstaller.InstallByond(), Tgstation.Server.Host.Components.Byond.ByondManager.installedVersions, Tgstation.Server.Host.Components.Byond.ByondManager.ioManager, Tgstation.Server.Host.IO.IIOManager.ResolvePath(), Tgstation.Server.Host.Components.Byond.ByondManager.VersionFileName, Tgstation.Server.Host.Components.Byond.ByondManager.VersionKey(), Tgstation.Server.Host.IO.IIOManager.WriteAllBytes(), and Tgstation.Server.Host.IO.IIOManager.ZipToDirectory().

-

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ChangeVersion(), and Tgstation.Server.Host.Components.Byond.ByondManager.UseExecutables().

+

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ChangeVersion(), and Tgstation.Server.Host.Components.Byond.ByondManager.UseExecutables().

@@ -391,26 +391,26 @@ Private Attributes

-

Definition at line 207 of file ByondManager.cs.

-
208  {
209  async Task<byte[]> GetActiveVersion()
210  {
211  var activeVersionFileExists = await ioManager.FileExists(ActiveVersionFileName, cancellationToken).ConfigureAwait(false);
212  return !activeVersionFileExists ? null : await ioManager.ReadAllBytes(ActiveVersionFileName, cancellationToken).ConfigureAwait(false);
213  }
214 
215  var activeVersionBytesTask = GetActiveVersion();
216 
217  await ioManager.CreateDirectory(".", cancellationToken).ConfigureAwait(false);
218  var directories = await ioManager.GetDirectories(".", cancellationToken).ConfigureAwait(false);
219 
220  async Task ReadVersion(string path)
221  {
222  var versionFile = ioManager.ConcatPath(path, VersionFileName);
223  if (!await ioManager.FileExists(versionFile, cancellationToken).ConfigureAwait(false))
224  {
225  logger.LogInformation("Cleaning unparsable version path: {0}", ioManager.ResolvePath(path));
226  await ioManager.DeleteDirectory(path, cancellationToken).ConfigureAwait(false); // cleanup
227  return;
228  }
229 
230  var bytes = await ioManager.ReadAllBytes(versionFile, cancellationToken).ConfigureAwait(false);
231  var text = Encoding.UTF8.GetString(bytes);
232  if (Version.TryParse(text, out var version))
233  {
234  var key = VersionKey(version);
235  lock (installedVersions)
236  if (!installedVersions.ContainsKey(key))
237  {
238  installedVersions.Add(key, Task.CompletedTask);
239  return;
240  }
241  }
242 
243  await ioManager.DeleteDirectory(path, cancellationToken).ConfigureAwait(false);
244  }
245 
246  await Task.WhenAll(directories.Select(x => ReadVersion(x))).ConfigureAwait(false);
247 
248  var activeVersionBytes = await activeVersionBytesTask.ConfigureAwait(false);
249  if (activeVersionBytes != null)
250  {
251  var activeVersionString = Encoding.UTF8.GetString(activeVersionBytes);
252  if (Version.TryParse(activeVersionString, out var activeVersion))
253  ActiveVersion = activeVersion;
254  else
255  await ioManager.DeleteFile(ActiveVersionFileName, cancellationToken).ConfigureAwait(false);
256  }
257  }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
-
readonly IIOManager ioManager
The IIOManager for the ByondManager
Definition: ByondManager.cs:49
- -
const string ActiveVersionFileName
The file in which we store the VersionKey(Version) for the active installation
Definition: ByondManager.cs:31
+

Definition at line 208 of file ByondManager.cs.

+
209  {
210  async Task<byte[]> GetActiveVersion()
211  {
212  var activeVersionFileExists = await ioManager.FileExists(ActiveVersionFileName, cancellationToken).ConfigureAwait(false);
213  return !activeVersionFileExists ? null : await ioManager.ReadAllBytes(ActiveVersionFileName, cancellationToken).ConfigureAwait(false);
214  }
215 
216  var activeVersionBytesTask = GetActiveVersion();
217 
218  await ioManager.CreateDirectory(".", cancellationToken).ConfigureAwait(false);
219  var directories = await ioManager.GetDirectories(".", cancellationToken).ConfigureAwait(false);
220 
221  async Task ReadVersion(string path)
222  {
223  var versionFile = ioManager.ConcatPath(path, VersionFileName);
224  if (!await ioManager.FileExists(versionFile, cancellationToken).ConfigureAwait(false))
225  {
226  logger.LogInformation("Cleaning unparsable version path: {0}", ioManager.ResolvePath(path));
227  await ioManager.DeleteDirectory(path, cancellationToken).ConfigureAwait(false); // cleanup
228  return;
229  }
230 
231  var bytes = await ioManager.ReadAllBytes(versionFile, cancellationToken).ConfigureAwait(false);
232  var text = Encoding.UTF8.GetString(bytes);
233  if (Version.TryParse(text, out var version))
234  {
235  var key = VersionKey(version);
236  lock (installedVersions)
237  if (!installedVersions.ContainsKey(key))
238  {
239  installedVersions.Add(key, Task.CompletedTask);
240  return;
241  }
242  }
243 
244  await ioManager.DeleteDirectory(path, cancellationToken).ConfigureAwait(false);
245  }
246 
247  await Task.WhenAll(directories.Select(x => ReadVersion(x))).ConfigureAwait(false);
248 
249  var activeVersionBytes = await activeVersionBytesTask.ConfigureAwait(false);
250  if (activeVersionBytes != null)
251  {
252  var activeVersionString = Encoding.UTF8.GetString(activeVersionBytes);
253  if (Version.TryParse(activeVersionString, out var activeVersion))
254  ActiveVersion = activeVersion;
255  else
256  await ioManager.DeleteFile(ActiveVersionFileName, cancellationToken).ConfigureAwait(false);
257  }
258  }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory, removes and does not enter any symlinks encounterd.
+
readonly IIOManager ioManager
The IIOManager for the ByondManager
Definition: ByondManager.cs:50
+ +
const string ActiveVersionFileName
The file in which we store the VersionKey(Version) for the active installation
Definition: ByondManager.cs:32
Task< IReadOnlyList< string > > GetDirectories(string path, CancellationToken cancellationToken)
Returns directory names in a given path
Task CreateDirectory(string path, CancellationToken cancellationToken)
Create a directory at path
string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
Task< bool > FileExists(string path, CancellationToken cancellationToken)
Check that the file at path exists
-
readonly Dictionary< string, Task > installedVersions
Map of byond Versions to Tasks that complete when they are installed
Definition: ByondManager.cs:69
-
readonly ILogger< ByondManager > logger
The ILogger for the ByondManager
Definition: ByondManager.cs:64
-
const string VersionFileName
The file in which we store the VersionKey(Version) for installations
Definition: ByondManager.cs:26
+
readonly Dictionary< string, Task > installedVersions
Map of byond Versions to Tasks that complete when they are installed
Definition: ByondManager.cs:70
+
readonly ILogger< ByondManager > logger
The ILogger for the ByondManager
Definition: ByondManager.cs:65
+
const string VersionFileName
The file in which we store the VersionKey(Version) for installations
Definition: ByondManager.cs:27
static string VersionKey(Version version)
Converts a BYOND version to a string
Task< byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
Returns all the contents of a file at path as a byte array
Task DeleteFile(string path, CancellationToken cancellationToken)
Deletes a file at path
string ConcatPath(params string[] paths)
Combines an array of strings into a path
-

References Tgstation.Server.Host.Components.Byond.ByondManager.ActiveVersion, Tgstation.Server.Host.Components.Byond.ByondManager.ActiveVersionFileName, Tgstation.Server.Host.IO.IIOManager.ConcatPath(), Tgstation.Server.Host.IO.IIOManager.CreateDirectory(), Tgstation.Server.Host.IO.IIOManager.DeleteDirectory(), Tgstation.Server.Host.IO.IIOManager.DeleteFile(), Tgstation.Server.Host.IO.IIOManager.FileExists(), Tgstation.Server.Host.IO.IIOManager.GetDirectories(), Tgstation.Server.Host.Components.Byond.ByondManager.installedVersions, Tgstation.Server.Host.Components.Byond.ByondManager.ioManager, Tgstation.Server.Host.Components.Byond.ByondManager.logger, Tgstation.Server.Host.IO.IIOManager.ReadAllBytes(), Tgstation.Server.Host.IO.IIOManager.ResolvePath(), Tgstation.Server.Host.Components.Byond.ByondManager.VersionFileName, and Tgstation.Server.Host.Components.Byond.ByondManager.VersionKey().

+

References Tgstation.Server.Host.Components.Byond.ByondManager.ActiveVersion, Tgstation.Server.Host.Components.Byond.ByondManager.ActiveVersionFileName, Tgstation.Server.Host.IO.IIOManager.ConcatPath(), Tgstation.Server.Host.IO.IIOManager.CreateDirectory(), Tgstation.Server.Host.IO.IIOManager.DeleteDirectory(), Tgstation.Server.Host.IO.IIOManager.DeleteFile(), Tgstation.Server.Host.IO.IIOManager.FileExists(), Tgstation.Server.Host.IO.IIOManager.GetDirectories(), Tgstation.Server.Host.Components.Byond.ByondManager.installedVersions, Tgstation.Server.Host.Components.Byond.ByondManager.ioManager, Tgstation.Server.Host.Components.Byond.ByondManager.logger, Tgstation.Server.Host.IO.IIOManager.ReadAllBytes(), Tgstation.Server.Host.IO.IIOManager.ResolvePath(), Tgstation.Server.Host.Components.Byond.ByondManager.VersionFileName, and Tgstation.Server.Host.Components.Byond.ByondManager.VersionKey().

-

Referenced by Tgstation.Server.Host.Components.Instance.StartAsync().

+

Referenced by Tgstation.Server.Host.Components.Instance.StartAsync().

@@ -464,20 +464,20 @@ Private Attributes

Implements Tgstation.Server.Host.Components.Byond.IByondManager.

-

Definition at line 194 of file ByondManager.cs.

-
195  {
196  var versionToUse = requiredVersion ?? ActiveVersion;
197  if (versionToUse == null)
198  throw new JobException("No BYOND versions installed!");
199  await InstallVersion(versionToUse, cancellationToken).ConfigureAwait(false);
200 
201  var versionKey = VersionKey(versionToUse);
202 
204  }
readonly IIOManager ioManager
The IIOManager for the ByondManager
Definition: ByondManager.cs:49
- +

Definition at line 195 of file ByondManager.cs.

+
196  {
197  var versionToUse = requiredVersion ?? ActiveVersion;
198  if (versionToUse == null)
199  throw new JobException("No BYOND versions installed!");
200  await InstallVersion(versionToUse, cancellationToken).ConfigureAwait(false);
201 
202  var versionKey = VersionKey(versionToUse);
203 
205  }
readonly IIOManager ioManager
The IIOManager for the ByondManager
Definition: ByondManager.cs:50
+
string DreamMakerName
Get the file name of the DreamMaker executable
string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
-
async Task InstallVersion(Version version, CancellationToken cancellationToken)
Installs a BYOND version if it isn't already
+
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
+
async Task InstallVersion(Version version, CancellationToken cancellationToken)
Installs a BYOND version if it isn't already
string DreamDaemonName
Get the file name of the DreamDaemon executable
-
readonly IByondInstaller byondInstaller
The IByondInstaller for the ByondManager
Definition: ByondManager.cs:54
+
readonly IByondInstaller byondInstaller
The IByondInstaller for the ByondManager
Definition: ByondManager.cs:55
static string VersionKey(Version version)
Converts a BYOND version to a string
-
const string BinPath
The path to the BYOND bin folder
Definition: ByondManager.cs:21
+
const string BinPath
The path to the BYOND bin folder
Definition: ByondManager.cs:22
string ConcatPath(params string[] paths)
Combines an array of strings into a path
-
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
-

References Tgstation.Server.Host.Components.Byond.ByondManager.ActiveVersion, Tgstation.Server.Host.Components.Byond.ByondManager.BinPath, Tgstation.Server.Host.Components.Byond.ByondManager.byondInstaller, Tgstation.Server.Host.IO.IIOManager.ConcatPath(), Tgstation.Server.Host.Components.Byond.IByondInstaller.DreamDaemonName, Tgstation.Server.Host.Components.Byond.IByondInstaller.DreamMakerName, Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), Tgstation.Server.Host.Components.Byond.ByondManager.ioManager, Tgstation.Server.Host.IO.IIOManager.ResolvePath(), and Tgstation.Server.Host.Components.Byond.ByondManager.VersionKey().

+

References Tgstation.Server.Host.Components.Byond.ByondManager.ActiveVersion, Tgstation.Server.Host.Components.Byond.ByondManager.BinPath, Tgstation.Server.Host.Components.Byond.ByondManager.byondInstaller, Tgstation.Server.Host.IO.IIOManager.ConcatPath(), Tgstation.Server.Host.Components.Byond.IByondInstaller.DreamDaemonName, Tgstation.Server.Host.Components.Byond.IByondInstaller.DreamMakerName, Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), Tgstation.Server.Host.Components.Byond.ByondManager.ioManager, Tgstation.Server.Host.IO.IIOManager.ResolvePath(), and Tgstation.Server.Host.Components.Byond.ByondManager.VersionKey().

@@ -514,7 +514,7 @@ Private Attributes
Returns
The string representation of version
-

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ChangeVersion(), Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync(), and Tgstation.Server.Host.Components.Byond.ByondManager.UseExecutables().

+

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ChangeVersion(), Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync(), and Tgstation.Server.Host.Components.Byond.ByondManager.UseExecutables().

@@ -541,9 +541,9 @@ Private Attributes

The file in which we store the VersionKey(Version) for the active installation

-

Definition at line 31 of file ByondManager.cs.

+

Definition at line 32 of file ByondManager.cs.

-

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ChangeVersion(), and Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync().

+

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ChangeVersion(), and Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync().

@@ -561,9 +561,9 @@ Private Attributes

The path to the BYOND bin folder

-

Definition at line 21 of file ByondManager.cs.

+

Definition at line 22 of file ByondManager.cs.

-

Referenced by Tgstation.Server.Host.Components.Byond.PosixByondInstaller.InstallByond(), and Tgstation.Server.Host.Components.Byond.ByondManager.UseExecutables().

+

Referenced by Tgstation.Server.Host.Components.Byond.PosixByondInstaller.InstallByond(), and Tgstation.Server.Host.Components.Byond.ByondManager.UseExecutables().

@@ -589,9 +589,9 @@ Private Attributes

The IByondInstaller for the ByondManager

-

Definition at line 54 of file ByondManager.cs.

+

Definition at line 55 of file ByondManager.cs.

-

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ByondManager(), Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), and Tgstation.Server.Host.Components.Byond.ByondManager.UseExecutables().

+

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ByondManager(), Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), and Tgstation.Server.Host.Components.Byond.ByondManager.UseExecutables().

@@ -617,9 +617,9 @@ Private Attributes

The IEventConsumer for the ByondManager

-

Definition at line 59 of file ByondManager.cs.

+

Definition at line 60 of file ByondManager.cs.

-

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ByondManager(), Tgstation.Server.Host.Components.Byond.ByondManager.ChangeVersion(), and Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion().

+

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ByondManager(), Tgstation.Server.Host.Components.Byond.ByondManager.ChangeVersion(), and Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion().

@@ -645,9 +645,9 @@ Private Attributes

Map of byond Versions to Tasks that complete when they are installed

-

Definition at line 69 of file ByondManager.cs.

+

Definition at line 70 of file ByondManager.cs.

-

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ByondManager(), Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), and Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync().

+

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ByondManager(), Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), and Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync().

@@ -673,9 +673,9 @@ Private Attributes

The IIOManager for the ByondManager

-

Definition at line 49 of file ByondManager.cs.

+

Definition at line 50 of file ByondManager.cs.

-

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ByondManager(), Tgstation.Server.Host.Components.Byond.ByondManager.ChangeVersion(), Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync(), and Tgstation.Server.Host.Components.Byond.ByondManager.UseExecutables().

+

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ByondManager(), Tgstation.Server.Host.Components.Byond.ByondManager.ChangeVersion(), Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync(), and Tgstation.Server.Host.Components.Byond.ByondManager.UseExecutables().

@@ -701,9 +701,9 @@ Private Attributes

The ILogger for the ByondManager

-

Definition at line 64 of file ByondManager.cs.

+

Definition at line 65 of file ByondManager.cs.

-

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ByondManager(), and Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync().

+

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ByondManager(), and Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync().

@@ -729,9 +729,9 @@ Private Attributes

The SemaphoreSlim for the ByondManager

-

Definition at line 74 of file ByondManager.cs.

+

Definition at line 75 of file ByondManager.cs.

-

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ByondManager(), and Tgstation.Server.Host.Components.Byond.ByondManager.ChangeVersion().

+

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ByondManager(), and Tgstation.Server.Host.Components.Byond.ByondManager.ChangeVersion().

@@ -757,9 +757,9 @@ Private Attributes

The file in which we store the VersionKey(Version) for installations

-

Definition at line 26 of file ByondManager.cs.

+

Definition at line 27 of file ByondManager.cs.

-

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), and Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync().

+

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), and Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync().

@@ -786,9 +786,9 @@ Private Attributes

-

Definition at line 34 of file ByondManager.cs.

-
34 { get; private set; }
-

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ChangeVersion(), Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync(), and Tgstation.Server.Host.Components.Byond.ByondManager.UseExecutables().

+

Definition at line 35 of file ByondManager.cs.

+
35 { get; private set; }
+

Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ChangeVersion(), Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync(), and Tgstation.Server.Host.Components.Byond.ByondManager.UseExecutables().

@@ -814,8 +814,8 @@ Private Attributes

-

Definition at line 38 of file ByondManager.cs.

-
38  {
39  get
40  {
41  lock (installedVersions)
42  return installedVersions.Select(x => Version.Parse(x.Key)).ToList();
43  }
44  }
readonly Dictionary< string, Task > installedVersions
Map of byond Versions to Tasks that complete when they are installed
Definition: ByondManager.cs:69
+

Definition at line 39 of file ByondManager.cs.

+
39  {
40  get
41  {
42  lock (installedVersions)
43  return installedVersions.Select(x => Version.Parse(x.Key)).ToList();
44  }
45  }
readonly Dictionary< string, Task > installedVersions
Map of byond Versions to Tasks that complete when they are installed
Definition: ByondManager.cs:70
diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_posix_byond_installer.html b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_posix_byond_installer.html index 48234f7763..da1f69825a 100644 --- a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_posix_byond_installer.html +++ b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_posix_byond_installer.html @@ -247,7 +247,7 @@ Additional Inherited Members

Definition at line 52 of file PosixByondInstaller.cs.

53  {
54  try
55  {
56  await IOManager.DeleteDirectory(ByondCachePath, cancellationToken).ConfigureAwait(false);
57  }
58  catch (OperationCanceledException)
59  {
60  throw;
61  }
62  catch (Exception e)
63  {
64  Logger.LogWarning("Error deleting BYOND cache! Exception: {0}", e);
65  }
66  }
IIOManager IOManager
Gets the IIOManager for the ByondInstallerBase.
-
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
+
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory, removes and does not enter any symlinks encounterd.
ILogger< ByondInstallerBase > Logger
Gets the ILogger for the ByondInstallerBase.
@@ -310,7 +310,7 @@ Additional Inherited Members
string ConcatPath(params string[] paths)
Combines an array of strings into a path
-

References Tgstation.Server.Host.Components.Byond.ByondManager.BinPath, Tgstation.Server.Host.IO.IIOManager.ConcatPath(), Tgstation.Server.Host.Components.Byond.PosixByondInstaller.DreamDaemonExecutableName, Tgstation.Server.Host.Components.Byond.PosixByondInstaller.DreamDaemonName, Tgstation.Server.Host.Components.Byond.PosixByondInstaller.DreamMakerExecutableName, Tgstation.Server.Host.Components.Byond.PosixByondInstaller.DreamMakerName, Tgstation.Server.Host.IO.IPostWriteHandler.HandleWrite(), Tgstation.Server.Host.Components.Byond.ByondInstallerBase.IOManager, Tgstation.Server.Host.Components.Byond.PosixByondInstaller.postWriteHandler, and Tgstation.Server.Host.IO.IIOManager.WriteAllBytes().

+

References Tgstation.Server.Host.Components.Byond.ByondManager.BinPath, Tgstation.Server.Host.IO.IIOManager.ConcatPath(), Tgstation.Server.Host.Components.Byond.PosixByondInstaller.DreamDaemonExecutableName, Tgstation.Server.Host.Components.Byond.PosixByondInstaller.DreamDaemonName, Tgstation.Server.Host.Components.Byond.PosixByondInstaller.DreamMakerExecutableName, Tgstation.Server.Host.Components.Byond.PosixByondInstaller.DreamMakerName, Tgstation.Server.Host.IO.IPostWriteHandler.HandleWrite(), Tgstation.Server.Host.Components.Byond.ByondInstallerBase.IOManager, Tgstation.Server.Host.Components.Byond.PosixByondInstaller.postWriteHandler, and Tgstation.Server.Host.IO.IIOManager.WriteAllBytes().

diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_windows_byond_installer.html b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_windows_byond_installer.html index 30856947bf..38e79d493b 100644 --- a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_windows_byond_installer.html +++ b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_windows_byond_installer.html @@ -94,7 +94,7 @@ Inheritance diagram for Tgstation.Server.Host.Components.Byond.WindowsByondInsta - + @@ -136,7 +136,7 @@ Private Attributes - + @@ -177,7 +177,7 @@ Additional Inherited Members

Detailed Description

IByondInstaller for windows systems

-

Definition at line 15 of file WindowsByondInstaller.cs.

+

Definition at line 17 of file WindowsByondInstaller.cs.

Constructor & Destructor Documentation

◆ WindowsByondInstaller()

@@ -188,7 +188,7 @@ Additional Inherited Members - + @@ -221,12 +221,12 @@ Additional Inherited Members -

Definition at line 67 of file WindowsByondInstaller.cs.

-
68  : base(ioManager, logger)
69  {
70  this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor));
71 
72  semaphore = new SemaphoreSlim(1);
73  installedDirectX = false;
74  }
readonly SemaphoreSlim semaphore
The SemaphoreSlim for the WindowsByondInstaller
-
readonly IProcessExecutor processExecutor
The IProcessExecutor for the WindowsByondInstaller
- +

Definition at line 69 of file WindowsByondInstaller.cs.

+
70  : base(ioManager, logger)
71  {
72  this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor));
73 
74  semaphore = new SemaphoreSlim(1);
75  installedDirectX = false;
76  }
readonly SemaphoreSlim semaphore
The SemaphoreSlim for the WindowsByondInstaller
+
readonly IProcessExecutor processExecutor
The IProcessExecutor for the WindowsByondInstaller
+
-

References Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.installedDirectX, Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.processExecutor, and Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.semaphore.

+

References Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.installedDirectX, Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.processExecutor, and Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.semaphore.

@@ -259,9 +259,9 @@ Additional Inherited Members

Implements Tgstation.Server.Host.Components.Byond.ByondInstallerBase.

-

Definition at line 80 of file WindowsByondInstaller.cs.

-
81  {
82  try
83  {
84  await IOManager.DeleteDirectory(IOManager.ConcatPath(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "byond/cache"), cancellationToken).ConfigureAwait(false);
85  }
86  catch(OperationCanceledException)
87  {
88  throw;
89  }
90  catch (Exception e)
91  {
92  Logger.LogWarning("Error deleting BYOND cache! Exception: {0}", e);
93  }
94  }
IIOManager IOManager
Gets the IIOManager for the ByondInstallerBase.
-
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
+

Definition at line 82 of file WindowsByondInstaller.cs.

+
83  {
84  try
85  {
86  await IOManager.DeleteDirectory(IOManager.ConcatPath(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "byond/cache"), cancellationToken).ConfigureAwait(false);
87  }
88  catch(OperationCanceledException)
89  {
90  throw;
91  }
92  catch (Exception e)
93  {
94  Logger.LogWarning("Error deleting BYOND cache! Exception: {0}", e);
95  }
96  }
IIOManager IOManager
Gets the IIOManager for the ByondInstallerBase.
+
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory, removes and does not enter any symlinks encounterd.
ILogger< ByondInstallerBase > Logger
Gets the ILogger for the ByondInstallerBase.
string ConcatPath(params string[] paths)
Combines an array of strings into a path
@@ -332,27 +332,27 @@ Additional Inherited Members

Implements Tgstation.Server.Host.Components.Byond.ByondInstallerBase.

-

Definition at line 97 of file WindowsByondInstaller.cs.

-
98  {
99  async Task SetNoPromptTrusted()
100  {
101  var configPath = IOManager.ConcatPath(path, ByondConfigDir);
102  await IOManager.CreateDirectory(configPath, cancellationToken).ConfigureAwait(false);
103  await IOManager.WriteAllBytes(IOManager.ConcatPath(configPath, ByondDDConfig), Encoding.UTF8.GetBytes(ByondNoPromptTrustedMode), cancellationToken).ConfigureAwait(false);
104  }
105 
106  var setNoPromptTrustedModeTask = SetNoPromptTrusted();
107 
108  // after this version lummox made DD depend of directx lol
109  // but then he became amazing and not only fixed it but also gave us 30s compiles \[T]/
110  // then he readded it again so -_-
111  if (!installedDirectX)
112  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
113  if (!installedDirectX)
114  {
115  // ^check again because race conditions
116  // always install it, it's pretty fast and will do better redundancy checking than us
117  var rbdx = IOManager.ConcatPath(path, ByondDXDir);
118 
119  // noShellExecute because we aren't doing runas shennanigans
120  IProcess directXInstaller;
121  try
122  {
123  directXInstaller = processExecutor.LaunchProcess(IOManager.ConcatPath(rbdx, "DXSETUP.exe"), rbdx, "/silent", noShellExecute: true);
124  }
125  catch (Exception e)
126  {
127  throw new JobException("Unable to start DirectX installer process! Is the server running with admin privileges?", e);
128  }
129 
130  using (directXInstaller)
131  {
132  int exitCode;
133  using (cancellationToken.Register(() => directXInstaller.Terminate()))
134  exitCode = await directXInstaller.Lifetime.ConfigureAwait(false);
135  cancellationToken.ThrowIfCancellationRequested();
136 
137  if (exitCode != 0)
138  throw new JobException(String.Format(CultureInfo.InvariantCulture, "Failed to install included DirectX! Exit code: {0}", exitCode));
139  installedDirectX = true;
140  }
141  }
142 
143  await setNoPromptTrustedModeTask.ConfigureAwait(false);
144  }
readonly SemaphoreSlim semaphore
The SemaphoreSlim for the WindowsByondInstaller
+

Definition at line 99 of file WindowsByondInstaller.cs.

+
100  {
101  async Task SetNoPromptTrusted()
102  {
103  var configPath = IOManager.ConcatPath(path, ByondConfigDir);
104  await IOManager.CreateDirectory(configPath, cancellationToken).ConfigureAwait(false);
105  await IOManager.WriteAllBytes(IOManager.ConcatPath(configPath, ByondDDConfig), Encoding.UTF8.GetBytes(ByondNoPromptTrustedMode), cancellationToken).ConfigureAwait(false);
106  }
107 
108  var setNoPromptTrustedModeTask = SetNoPromptTrusted();
109 
110  // after this version lummox made DD depend of directx lol
111  // but then he became amazing and not only fixed it but also gave us 30s compiles \[T]/
112  // then he readded it again so -_-
113  if (!installedDirectX)
114  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
115  if (!installedDirectX)
116  {
117  // ^check again because race conditions
118  // always install it, it's pretty fast and will do better redundancy checking than us
119  var rbdx = IOManager.ConcatPath(path, ByondDXDir);
120 
121  // noShellExecute because we aren't doing runas shennanigans
122  IProcess directXInstaller;
123  try
124  {
125  directXInstaller = processExecutor.LaunchProcess(IOManager.ConcatPath(rbdx, "DXSETUP.exe"), rbdx, "/silent", noShellExecute: true);
126  }
127  catch (Exception e)
128  {
129  throw new JobException("Unable to start DirectX installer process! Is the server running with admin privileges?", e);
130  }
131 
132  using (directXInstaller)
133  {
134  int exitCode;
135  using (cancellationToken.Register(() => directXInstaller.Terminate()))
136  exitCode = await directXInstaller.Lifetime.ConfigureAwait(false);
137  cancellationToken.ThrowIfCancellationRequested();
138 
139  if (exitCode != 0)
140  throw new JobException(String.Format(CultureInfo.InvariantCulture, "Failed to install included DirectX! Exit code: {0}", exitCode));
141  installedDirectX = true;
142  }
143  }
144 
145  await setNoPromptTrustedModeTask.ConfigureAwait(false);
146  }
readonly SemaphoreSlim semaphore
The SemaphoreSlim for the WindowsByondInstaller
IIOManager IOManager
Gets the IIOManager for the ByondInstallerBase.
-
Task< int > Lifetime
The Task<TResult> resulting in the exit code of the process
Definition: IProcessBase.cs:14
-
readonly IProcessExecutor processExecutor
The IProcessExecutor for the WindowsByondInstaller
+
Task< int > Lifetime
The Task<TResult> resulting in the exit code of the process
Definition: IProcessBase.cs:14
+
readonly IProcessExecutor processExecutor
The IProcessExecutor for the WindowsByondInstaller
Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content
Task CreateDirectory(string path, CancellationToken cancellationToken)
Create a directory at path
- -
const string ByondNoPromptTrustedMode
Setting to add to ByondDDConfig to suppress an invisible user prompt for running a trusted mode ....
-
IProcess LaunchProcess(string fileName, string workingDirectory, string arguments=null, bool readOutput=false, bool readError=false, bool noShellExecute=false)
Launch a IProcess
-
const string ByondDDConfig
BYOND's DreamDaemon config file
-
void Terminate()
Terminates the process
-
Abstraction over a System.Diagnostics.Process
Definition: IProcess.cs:9
-
const string ByondConfigDir
Directory to byond installation configuration
-
const string ByondDXDir
The directory that contains the BYOND directx redistributable
+ +
const string ByondNoPromptTrustedMode
Setting to add to ByondDDConfig to suppress an invisible user prompt for running a trusted mode ....
+
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
+
const string ByondDDConfig
BYOND's DreamDaemon config file
+
const string ByondConfigDir
Directory to byond installation configuration
+
Abstraction over a global::System.Diagnostics.Process
Definition: IProcess.cs:8
+
IProcess LaunchProcess(string fileName, string workingDirectory, string arguments=null, bool readOutput=false, bool readError=false, bool noShellExecute=false)
Launch a IProcess
+
const string ByondDXDir
The directory that contains the BYOND directx redistributable
static async Task< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore
string ConcatPath(params string[] paths)
Combines an array of strings into a path
-
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
+
void Terminate()
Terminates the process
-

References Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.ByondConfigDir, Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.ByondDDConfig, Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.ByondDXDir, Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.ByondNoPromptTrustedMode, Tgstation.Server.Host.IO.IIOManager.ConcatPath(), Tgstation.Server.Host.IO.IIOManager.CreateDirectory(), Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.installedDirectX, Tgstation.Server.Host.Components.Byond.ByondInstallerBase.IOManager, Tgstation.Server.Host.Core.IProcessExecutor.LaunchProcess(), Tgstation.Server.Host.Core.IProcessBase.Lifetime, Tgstation.Server.Host.Core.SemaphoreSlimContext.Lock(), Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.processExecutor, Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.semaphore, Tgstation.Server.Host.Core.IProcess.Terminate(), and Tgstation.Server.Host.IO.IIOManager.WriteAllBytes().

+

References Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.ByondConfigDir, Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.ByondDDConfig, Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.ByondDXDir, Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.ByondNoPromptTrustedMode, Tgstation.Server.Host.IO.IIOManager.ConcatPath(), Tgstation.Server.Host.IO.IIOManager.CreateDirectory(), Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.installedDirectX, Tgstation.Server.Host.Components.Byond.ByondInstallerBase.IOManager, Tgstation.Server.Host.System.IProcessExecutor.LaunchProcess(), Tgstation.Server.Host.System.IProcessBase.Lifetime, Tgstation.Server.Host.Core.SemaphoreSlimContext.Lock(), Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.processExecutor, Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.semaphore, Tgstation.Server.Host.System.IProcess.Terminate(), and Tgstation.Server.Host.IO.IIOManager.WriteAllBytes().

@@ -379,9 +379,9 @@ Additional Inherited Members

Directory to byond installation configuration

-

Definition at line 20 of file WindowsByondInstaller.cs.

+

Definition at line 22 of file WindowsByondInstaller.cs.

-

Referenced by Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond().

+

Referenced by Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond().

@@ -407,9 +407,9 @@ Additional Inherited Members

BYOND's DreamDaemon config file

-

Definition at line 25 of file WindowsByondInstaller.cs.

+

Definition at line 27 of file WindowsByondInstaller.cs.

-

Referenced by Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond().

+

Referenced by Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond().

@@ -435,9 +435,9 @@ Additional Inherited Members

The directory that contains the BYOND directx redistributable

-

Definition at line 35 of file WindowsByondInstaller.cs.

+

Definition at line 37 of file WindowsByondInstaller.cs.

-

Referenced by Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond().

+

Referenced by Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond().

@@ -463,9 +463,9 @@ Additional Inherited Members

Setting to add to ByondDDConfig to suppress an invisible user prompt for running a trusted mode .dmb

-

Definition at line 30 of file WindowsByondInstaller.cs.

+

Definition at line 32 of file WindowsByondInstaller.cs.

-

Referenced by Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond().

+

Referenced by Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond().

@@ -491,7 +491,7 @@ Additional Inherited Members

-

Definition at line 44 of file WindowsByondInstaller.cs.

+

Definition at line 46 of file WindowsByondInstaller.cs.

@@ -509,7 +509,7 @@ Additional Inherited Members

-

Definition at line 38 of file WindowsByondInstaller.cs.

+

Definition at line 40 of file WindowsByondInstaller.cs.

@@ -527,7 +527,7 @@ Additional Inherited Members

-

Definition at line 41 of file WindowsByondInstaller.cs.

+

Definition at line 43 of file WindowsByondInstaller.cs.

@@ -553,9 +553,9 @@ Additional Inherited Members

If DirectX was installed

-

Definition at line 59 of file WindowsByondInstaller.cs.

+

Definition at line 61 of file WindowsByondInstaller.cs.

-

Referenced by Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond(), and Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.WindowsByondInstaller().

+

Referenced by Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond(), and Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.WindowsByondInstaller().

@@ -569,7 +569,7 @@ Additional Inherited Members @@ -581,9 +581,9 @@ Additional Inherited Members

The IProcessExecutor for the WindowsByondInstaller

-

Definition at line 49 of file WindowsByondInstaller.cs.

+

Definition at line 51 of file WindowsByondInstaller.cs.

-

Referenced by Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond(), and Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.WindowsByondInstaller().

+

Referenced by Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond(), and Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.WindowsByondInstaller().

@@ -609,9 +609,9 @@ Additional Inherited Members

The SemaphoreSlim for the WindowsByondInstaller

-

Definition at line 54 of file WindowsByondInstaller.cs.

+

Definition at line 56 of file WindowsByondInstaller.cs.

-

Referenced by Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond(), and Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.WindowsByondInstaller().

+

Referenced by Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond(), and Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.WindowsByondInstaller().

diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_chat.html b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_chat.html index 8a76c95e5e..dbe3c2f7b9 100644 --- a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_chat.html +++ b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_chat.html @@ -495,7 +495,7 @@ Private Attributes

References Tgstation.Server.Host.Components.Chat.Chat.handlerCts, Tgstation.Server.Host.Components.Chat.Chat.providers, and Tgstation.Server.Host.Components.Chat.Chat.restartRegistration.

-

Referenced by Tgstation.Server.Host.Components.Instance.Dispose().

+

Referenced by Tgstation.Server.Host.Components.Instance.Dispose().

@@ -790,7 +790,7 @@ Private Attributes

Definition at line 492 of file Chat.cs.

493  {
494  if (message == null)
495  throw new ArgumentNullException(nameof(message));
496  if (channelIds == null)
497  throw new ArgumentNullException(nameof(channelIds));
498 
499  return Task.WhenAll(channelIds.Select(x =>
500  {
501  ChannelMapping channelMapping;
502  lock (mappedChannels)
503  if (!mappedChannels.TryGetValue(x, out channelMapping))
504  return Task.CompletedTask;
505  IProvider provider;
506  lock (providers)
507  if (!providers.TryGetValue(channelMapping.ProviderId, out provider))
508  return Task.CompletedTask;
509  return provider.SendMessage(channelMapping.ProviderChannelId, message, cancellationToken);
510  }));
511  }
-

Referenced by Tgstation.Server.Host.Components.Watchdog.WatchdogBase.HandleEvent(), Tgstation.Server.Host.Components.Chat.Chat.HandleRestart(), Tgstation.Server.Host.Components.Chat.Chat.ProcessMessage(), Tgstation.Server.Host.Components.Chat.Chat.SendUpdateMessage(), and Tgstation.Server.Host.Components.Chat.Chat.SendWatchdogMessage().

+

Referenced by Tgstation.Server.Host.Components.Watchdog.WatchdogBase.HandleEvent(), Tgstation.Server.Host.Components.Chat.Chat.HandleRestart(), Tgstation.Server.Host.Components.Chat.Chat.ProcessMessage(), Tgstation.Server.Host.Components.Chat.Chat.SendUpdateMessage(), and Tgstation.Server.Host.Components.Chat.Chat.SendWatchdogMessage().

@@ -868,7 +868,7 @@ Private Attributes

References Tgstation.Server.Host.Components.Chat.Chat.mappedChannels, and Tgstation.Server.Host.Components.Chat.Chat.SendMessage().

-

Referenced by Tgstation.Server.Host.Components.Watchdog.BasicWatchdog.HandleMonitorWakeup(), Tgstation.Server.Host.Components.Watchdog.WatchdogBase.HandleRestart(), Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.HandlerMonitorWakeup(), Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.InitControllers(), Tgstation.Server.Host.Components.Watchdog.WatchdogBase.LaunchImplNoLock(), Tgstation.Server.Host.Components.Watchdog.BasicWatchdog.MonitorLifetimes(), Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.MonitorLifetimes(), Tgstation.Server.Host.Components.Watchdog.WatchdogBase.NotifyOfFailedReattach(), Tgstation.Server.Host.Components.Watchdog.WatchdogBase.Restart(), and Tgstation.Server.Host.Components.Watchdog.WatchdogBase.TerminateNoLock().

+

Referenced by Tgstation.Server.Host.Components.Watchdog.BasicWatchdog.HandleMonitorWakeup(), Tgstation.Server.Host.Components.Watchdog.WatchdogBase.HandleRestart(), Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.HandlerMonitorWakeup(), Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.InitControllers(), Tgstation.Server.Host.Components.Watchdog.WatchdogBase.LaunchImplNoLock(), Tgstation.Server.Host.Components.Watchdog.BasicWatchdog.MonitorLifetimes(), Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.MonitorLifetimes(), Tgstation.Server.Host.Components.Watchdog.WatchdogBase.NotifyOfFailedReattach(), Tgstation.Server.Host.Components.Watchdog.WatchdogBase.Restart(), and Tgstation.Server.Host.Components.Watchdog.WatchdogBase.TerminateNoLock().

@@ -905,7 +905,7 @@ Private Attributes

References Tgstation.Server.Host.Components.Chat.Chat.builtinCommands, Tgstation.Server.Host.Components.Chat.Chat.ChangeChannels(), Tgstation.Server.Host.Components.Chat.Chat.ChangeSettings(), Tgstation.Server.Host.Components.Chat.Chat.chatHandler, Tgstation.Server.Host.Components.Chat.Chat.commandFactory, Tgstation.Server.Host.Components.Chat.Commands.ICommandFactory.GenerateCommands(), Tgstation.Server.Host.Components.Chat.Chat.handlerCts, Tgstation.Server.Host.Components.Chat.Chat.initialChatBots, Tgstation.Server.Host.Components.Chat.Chat.MonitorMessages(), Tgstation.Server.Host.Components.Chat.Chat.providers, and Tgstation.Server.Host.Components.Chat.Chat.started.

-

Referenced by Tgstation.Server.Host.Components.Instance.StartAsync().

+

Referenced by Tgstation.Server.Host.Components.Instance.StartAsync().

diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_commands_1_1_command_factory.html b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_commands_1_1_command_factory.html index 464c74f32c..fe1544525c 100644 --- a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_commands_1_1_command_factory.html +++ b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_commands_1_1_command_factory.html @@ -90,7 +90,7 @@ Inheritance diagram for Tgstation.Server.Host.Components.Chat.Commands.CommandFa

Public Member Functions

 WindowsByondInstaller (IProcessExecutor processExecutor, IIOManager ioManager, ILogger< WindowsByondInstaller > logger)
 WindowsByondInstaller (IProcessExecutor processExecutor, IIOManager ioManager, ILogger< WindowsByondInstaller > logger)
 Construct a WindowsByondInstaller More...
 
void Dispose ()
const string ByondDXDir = "byond/directx"
 The directory that contains the BYOND directx redistributable More...
 
readonly IProcessExecutor processExecutor
readonly IProcessExecutor processExecutor
 The IProcessExecutor for the WindowsByondInstaller More...
 
readonly SemaphoreSlim semaphore
Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.WindowsByondInstaller (IProcessExecutor IProcessExecutor  processExecutor,
- +
readonly IProcessExecutor Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.processExecutorreadonly IProcessExecutor Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.processExecutor
- + @@ -111,7 +111,7 @@ Private Attributes - + @@ -123,7 +123,7 @@ Private Attributes

Public Member Functions

 CommandFactory (IApplication application, IByondManager byondManager, IRepositoryManager repositoryManager, IDatabaseContextFactory databaseContextFactory, Models.Instance instance)
 CommandFactory (IApplication application, IByondManager byondManager, IRepositoryManager repositoryManager, IDatabaseContextFactory databaseContextFactory, Models.Instance instance)
 Construct a CommandFactory More...
 
void SetWatchdog (IWatchdog watchdog)
readonly IRepositoryManager repositoryManager
 The IRepositoryManager for the CommandFactory More...
 
readonly IDatabaseContextFactory databaseContextFactory
readonly IDatabaseContextFactory databaseContextFactory
 The IDatabaseContextFactory for the CommandFactory More...
 
readonly Models.Instance instance

Detailed Description

-

Definition at line 11 of file CommandFactory.cs.

+

Definition at line 12 of file CommandFactory.cs.

Constructor & Destructor Documentation

◆ CommandFactory()

@@ -152,7 +152,7 @@ Private Attributes - IDatabaseContextFactory  + IDatabaseContextFactory  databaseContextFactory, @@ -181,14 +181,14 @@ Private Attributes -

Definition at line 51 of file CommandFactory.cs.

-
52  {
53  this.application = application ?? throw new ArgumentNullException(nameof(application));
54  this.byondManager = byondManager ?? throw new ArgumentNullException(nameof(byondManager));
55  this.repositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager));
56  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
57  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
58  }
readonly IByondManager byondManager
The IByondManager for the CommandFactory
-
readonly Models.Instance instance
The Models.Instance for the CommandFactory
-
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the CommandFactory
-
readonly IApplication application
The IApplication for the CommandFactory
-
readonly IRepositoryManager repositoryManager
The IRepositoryManager for the CommandFactory
+

Definition at line 52 of file CommandFactory.cs.

+
53  {
54  this.application = application ?? throw new ArgumentNullException(nameof(application));
55  this.byondManager = byondManager ?? throw new ArgumentNullException(nameof(byondManager));
56  this.repositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager));
57  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
58  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
59  }
readonly IByondManager byondManager
The IByondManager for the CommandFactory
+
readonly Models.Instance instance
The Models.Instance for the CommandFactory
+
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the CommandFactory
+
readonly IApplication application
The IApplication for the CommandFactory
+
readonly IRepositoryManager repositoryManager
The IRepositoryManager for the CommandFactory
-

References Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.application, Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.byondManager, Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.databaseContextFactory, Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.instance, and Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.repositoryManager.

+

References Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.application, Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.byondManager, Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.databaseContextFactory, Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.instance, and Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.repositoryManager.

@@ -212,15 +212,15 @@ Private Attributes

Implements Tgstation.Server.Host.Components.Chat.Commands.ICommandFactory.

-

Definition at line 72 of file CommandFactory.cs.

-
73  {
74  if (watchdog == null)
75  throw new InvalidOperationException("SetWatchdog has not been called!");
76  return new List<ICommand>
77  {
78  new VersionCommand(application),
79  new ByondCommand(byondManager, watchdog),
80  new RevisionCommand(watchdog, repositoryManager, instance),
81  new PullRequestsCommand(watchdog, repositoryManager, databaseContextFactory, instance),
82  new KekCommand()
83  };
84  }
readonly IByondManager byondManager
The IByondManager for the CommandFactory
-
readonly Models.Instance instance
The Models.Instance for the CommandFactory
-
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the CommandFactory
-
IWatchdog watchdog
The IWatchdog for the CommandFactory
-
readonly IApplication application
The IApplication for the CommandFactory
-
readonly IRepositoryManager repositoryManager
The IRepositoryManager for the CommandFactory
+

Definition at line 73 of file CommandFactory.cs.

+
74  {
75  if (watchdog == null)
76  throw new InvalidOperationException("SetWatchdog has not been called!");
77  return new List<ICommand>
78  {
79  new VersionCommand(application),
80  new ByondCommand(byondManager, watchdog),
81  new RevisionCommand(watchdog, repositoryManager, instance),
82  new PullRequestsCommand(watchdog, repositoryManager, databaseContextFactory, instance),
83  new KekCommand()
84  };
85  }
readonly IByondManager byondManager
The IByondManager for the CommandFactory
+
readonly Models.Instance instance
The Models.Instance for the CommandFactory
+
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the CommandFactory
+
IWatchdog watchdog
The IWatchdog for the CommandFactory
+
readonly IApplication application
The IApplication for the CommandFactory
+
readonly IRepositoryManager repositoryManager
The IRepositoryManager for the CommandFactory
-

References Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.application, Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.byondManager, Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.databaseContextFactory, Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.instance, Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.repositoryManager, and Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.watchdog.

+

References Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.application, Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.byondManager, Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.databaseContextFactory, Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.instance, Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.repositoryManager, and Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.watchdog.

@@ -248,10 +248,10 @@ Private Attributes -

Definition at line 64 of file CommandFactory.cs.

-
65  {
66  if (this.watchdog != null)
67  throw new InvalidOperationException("SetWatchdog has already been called!");
68  this.watchdog = watchdog ?? throw new ArgumentNullException(nameof(watchdog));
69  }
IWatchdog watchdog
The IWatchdog for the CommandFactory
+

Definition at line 65 of file CommandFactory.cs.

+
66  {
67  if (this.watchdog != null)
68  throw new InvalidOperationException("SetWatchdog has already been called!");
69  this.watchdog = watchdog ?? throw new ArgumentNullException(nameof(watchdog));
70  }
IWatchdog watchdog
The IWatchdog for the CommandFactory
-

References Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.watchdog.

+

References Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.watchdog.

@@ -278,9 +278,9 @@ Private Attributes

The IApplication for the CommandFactory

-

Definition at line 16 of file CommandFactory.cs.

+

Definition at line 17 of file CommandFactory.cs.

-

Referenced by Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.CommandFactory(), and Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.GenerateCommands().

+

Referenced by Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.CommandFactory(), and Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.GenerateCommands().

@@ -306,9 +306,9 @@ Private Attributes

The IByondManager for the CommandFactory

-

Definition at line 21 of file CommandFactory.cs.

+

Definition at line 22 of file CommandFactory.cs.

-

Referenced by Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.CommandFactory(), and Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.GenerateCommands().

+

Referenced by Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.CommandFactory(), and Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.GenerateCommands().

@@ -322,7 +322,7 @@ Private Attributes - +
readonly IDatabaseContextFactory Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.databaseContextFactoryreadonly IDatabaseContextFactory Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.databaseContextFactory
@@ -334,9 +334,9 @@ Private Attributes

The IDatabaseContextFactory for the CommandFactory

-

Definition at line 31 of file CommandFactory.cs.

+

Definition at line 32 of file CommandFactory.cs.

-

Referenced by Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.CommandFactory(), and Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.GenerateCommands().

+

Referenced by Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.CommandFactory(), and Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.GenerateCommands().

@@ -362,9 +362,9 @@ Private Attributes

The Models.Instance for the CommandFactory

-

Definition at line 36 of file CommandFactory.cs.

+

Definition at line 37 of file CommandFactory.cs.

-

Referenced by Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.CommandFactory(), and Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.GenerateCommands().

+

Referenced by Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.CommandFactory(), and Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.GenerateCommands().

@@ -390,9 +390,9 @@ Private Attributes

The IRepositoryManager for the CommandFactory

-

Definition at line 26 of file CommandFactory.cs.

+

Definition at line 27 of file CommandFactory.cs.

-

Referenced by Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.CommandFactory(), and Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.GenerateCommands().

+

Referenced by Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.CommandFactory(), and Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.GenerateCommands().

@@ -418,9 +418,9 @@ Private Attributes

The IWatchdog for the CommandFactory

-

Definition at line 41 of file CommandFactory.cs.

+

Definition at line 42 of file CommandFactory.cs.

-

Referenced by Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.GenerateCommands(), and Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.SetWatchdog().

+

Referenced by Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.GenerateCommands(), and Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.SetWatchdog().

diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_commands_1_1_pull_requests_command.html b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_commands_1_1_pull_requests_command.html index 39b1aca991..2742f640d5 100644 --- a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_commands_1_1_pull_requests_command.html +++ b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_commands_1_1_pull_requests_command.html @@ -91,7 +91,7 @@ Inheritance diagram for Tgstation.Server.Host.Components.Chat.Commands.PullReque - + @@ -115,7 +115,7 @@ Private Attributes - + @@ -161,7 +161,7 @@ Additional Inherited Members - + @@ -237,17 +237,17 @@ Additional Inherited Members

Implements Tgstation.Server.Host.Components.Chat.Commands.ICommand.

Definition at line 66 of file PullRequestsCommand.cs.

-
67  {
68  IEnumerable<Models.TestMerge> results = null;
69  if (arguments.Split(' ').Any(x => x.ToUpperInvariant() == "--REPO"))
70  {
71  string head;
72  using (var repo = await repositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false))
73  {
74  if (repo == null)
75  return "Repository unavailable!";
76  head = repo.Head;
77  }
78 
79  await databaseContextFactory.UseContext(async db => results = await db.RevisionInformations.Where(x => x.Instance.Id == instance.Id && x.CommitSha == head)
80  .SelectMany(x => x.ActiveTestMerges)
81  .Select(x => x.TestMerge)
82  .Select(x => new Models.TestMerge
83  {
84  Number = x.Number,
85  PullRequestRevision = x.PullRequestRevision
86  }).ToListAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false);
87  }
88  else
89  {
90  if (!watchdog.Running)
91  return "Server offline!";
92  results = watchdog.ActiveCompileJob?.RevisionInformation.ActiveTestMerges.Select(x => x.TestMerge).ToList() ?? new List<Models.TestMerge>();
93  }
94 
95  return !results.Any() ? "None!" : String.Join(", ", results.Select(x => String.Format(CultureInfo.InvariantCulture, "#{0} at {1}", x.Number, x.PullRequestRevision.Substring(0, 7))));
96  }
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the PullRequestsCommand
+
67  {
68  IEnumerable<Models.TestMerge> results = null;
69  if (arguments.Split(' ').Any(x => x.ToUpperInvariant() == "--REPO"))
70  {
71  string head;
72  using (var repo = await repositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false))
73  {
74  if (repo == null)
75  return "Repository unavailable!";
76  head = repo.Head;
77  }
78 
79  await databaseContextFactory.UseContext(async db => results = await db.RevisionInformations.Where(x => x.Instance.Id == instance.Id && x.CommitSha == head)
80  .SelectMany(x => x.ActiveTestMerges)
81  .Select(x => x.TestMerge)
82  .Select(x => new Models.TestMerge
83  {
84  Number = x.Number,
85  PullRequestRevision = x.PullRequestRevision
86  }).ToListAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false);
87  }
88  else
89  {
90  if (!watchdog.Running)
91  return "Server offline!";
92  results = watchdog.ActiveCompileJob?.RevisionInformation.ActiveTestMerges.Select(x => x.TestMerge).ToList() ?? new List<Models.TestMerge>();
93  }
94 
95  return !results.Any() ? "None!" : String.Join(", ", results.Select(x => String.Format(CultureInfo.InvariantCulture, "#{0} at {1}", x.Number, x.PullRequestRevision.Substring(0, 7))));
96  }
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the PullRequestsCommand
readonly IRepositoryManager repositoryManager
The IRepositoryManager for the PullRequestsCommand
Models.CompileJob ActiveCompileJob
The CompileJob currently running on the server
Definition: IWatchdog.cs:27
readonly Models.Instance instance
The Models.Instance for the PullRequestsCommand
Task< IRepository > LoadRepository(CancellationToken cancellationToken)
Attempt to load the IRepository from the default location
readonly IWatchdog watchdog
The IWatchdog for the PullRequestsCommand
+
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
bool Running
If the watchdog is running
Definition: IWatchdog.cs:17
-
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
-

References Tgstation.Server.Host.Components.Watchdog.IWatchdog.ActiveCompileJob, Tgstation.Server.Host.Components.Chat.Commands.PullRequestsCommand.databaseContextFactory, Tgstation.Server.Host.Components.Chat.Commands.PullRequestsCommand.instance, Tgstation.Server.Host.Components.Repository.IRepositoryManager.LoadRepository(), Tgstation.Server.Host.Components.Chat.Commands.PullRequestsCommand.repositoryManager, Tgstation.Server.Host.Components.Watchdog.IWatchdog.Running, Tgstation.Server.Host.Core.IDatabaseContextFactory.UseContext(), and Tgstation.Server.Host.Components.Chat.Commands.PullRequestsCommand.watchdog.

+

References Tgstation.Server.Host.Components.Watchdog.IWatchdog.ActiveCompileJob, Tgstation.Server.Host.Components.Chat.Commands.PullRequestsCommand.databaseContextFactory, Tgstation.Server.Host.Components.Chat.Commands.PullRequestsCommand.instance, Tgstation.Server.Host.Components.Repository.IRepositoryManager.LoadRepository(), Tgstation.Server.Host.Components.Chat.Commands.PullRequestsCommand.repositoryManager, Tgstation.Server.Host.Components.Watchdog.IWatchdog.Running, Tgstation.Server.Host.Database.IDatabaseContextFactory.UseContext(), and Tgstation.Server.Host.Components.Chat.Commands.PullRequestsCommand.watchdog.

@@ -280,7 +280,7 @@ Additional Inherited Members diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_json_tracking_context.html b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_json_tracking_context.html index 37e88fe15f..018edc2d3e 100644 --- a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_json_tracking_context.html +++ b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_json_tracking_context.html @@ -551,7 +551,7 @@ Private Attributes

Definition at line 20 of file JsonTrackingContext.cs.

-
20  {
21  get => active;
22  set
23  {
24  active = true;
25  logger.LogDebug("Tracking {0}activated", !active ? "de" : String.Empty);
26  }
27  }
+
20  {
21  get => active;
22  set
23  {
24  active = value;
25  logger.LogDebug("Tracking {0}activated", !active ? "de" : String.Empty);
26  }
27  }

Referenced by Tgstation.Server.Host.Components.Chat.JsonTrackingContext.GetCustomCommands().

diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_factory-members.html b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_factory-members.html deleted file mode 100644 index 83ded4ab50..0000000000 --- a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_factory-members.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - - - - -tgstation-server: Member List - - - - - - - - - -
-
-

Public Member Functions

 PullRequestsCommand (IWatchdog watchdog, IRepositoryManager repositoryManager, IDatabaseContextFactory databaseContextFactory, Models.Instance instance)
 PullRequestsCommand (IWatchdog watchdog, IRepositoryManager repositoryManager, IDatabaseContextFactory databaseContextFactory, Models.Instance instance)
 Construct a PullRequestsCommand More...
 
async Task< string > Invoke (string arguments, User user, CancellationToken cancellationToken)
readonly IRepositoryManager repositoryManager
 The IRepositoryManager for the PullRequestsCommand More...
 
readonly IDatabaseContextFactory databaseContextFactory
readonly IDatabaseContextFactory databaseContextFactory
 The IDatabaseContextFactory for the PullRequestsCommand More...
 
readonly Models.Instance instance
IDatabaseContextFactory IDatabaseContextFactory  databaseContextFactory,
- +
readonly IDatabaseContextFactory Tgstation.Server.Host.Components.Chat.Commands.PullRequestsCommand.databaseContextFactoryreadonly IDatabaseContextFactory Tgstation.Server.Host.Components.Chat.Commands.PullRequestsCommand.databaseContextFactory
- - - - - - -
-
tgstation-server -
-
The /tg/station 13 server suite
-
- - - - - - - - - -
-
- - -
- -
- - - -
-
-
Tgstation.Server.Host.Components.Compiler.DmbFactory Member List
-
-
- -

This is the complete list of members for Tgstation.Server.Host.Components.Compiler.DmbFactory, including all inherited members.

- - - - - - - - - - - - - - - - - - - - - -
CleanJob(CompileJob job)Tgstation.Server.Host.Components.Compiler.DmbFactoryprivate
CleanUnusedCompileJobs(CompileJob exceptThisOne, CancellationToken cancellationToken)Tgstation.Server.Host.Components.Compiler.DmbFactory
cleanupCtsTgstation.Server.Host.Components.Compiler.DmbFactoryprivate
cleanupTaskTgstation.Server.Host.Components.Compiler.DmbFactoryprivate
databaseContextFactoryTgstation.Server.Host.Components.Compiler.DmbFactoryprivate
Dispose()Tgstation.Server.Host.Components.Compiler.DmbFactory
DmbAvailableTgstation.Server.Host.Components.Compiler.DmbFactory
DmbFactory(IDatabaseContextFactory databaseContextFactory, IIOManager ioManager, ILogger< DmbFactory > logger, Api.Models.Instance instance)Tgstation.Server.Host.Components.Compiler.DmbFactory
FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken)Tgstation.Server.Host.Components.Compiler.DmbFactory
instanceTgstation.Server.Host.Components.Compiler.DmbFactoryprivate
ioManagerTgstation.Server.Host.Components.Compiler.DmbFactoryprivate
jobLockCountsTgstation.Server.Host.Components.Compiler.DmbFactoryprivate
LoadCompileJob(CompileJob job, CancellationToken cancellationToken)Tgstation.Server.Host.Components.Compiler.DmbFactory
LockNextDmb(int lockCount)Tgstation.Server.Host.Components.Compiler.DmbFactory
loggerTgstation.Server.Host.Components.Compiler.DmbFactoryprivate
newerDmbTcsTgstation.Server.Host.Components.Compiler.DmbFactoryprivate
nextDmbProviderTgstation.Server.Host.Components.Compiler.DmbFactoryprivate
OnNewerDmbTgstation.Server.Host.Components.Compiler.DmbFactory
StartAsync(CancellationToken cancellationToken)Tgstation.Server.Host.Components.Compiler.DmbFactory
StopAsync(CancellationToken cancellationToken)Tgstation.Server.Host.Components.Compiler.DmbFactory
- - - - diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_factory.html b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_factory.html deleted file mode 100644 index 4f11950dfc..0000000000 --- a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_factory.html +++ /dev/null @@ -1,836 +0,0 @@ - - - - - - - -tgstation-server: Tgstation.Server.Host.Components.Compiler.DmbFactory Class Reference - - - - - - - - - -
-
- - - - - - - -
-
tgstation-server -
-
The /tg/station 13 server suite
-
-
- - - - - - - - -
-
- - -
- -
- - -
-
- -
-
Tgstation.Server.Host.Components.Compiler.DmbFactory Class Reference
-
-
- -

Standard IDmbFactory - More...

-
-Inheritance diagram for Tgstation.Server.Host.Components.Compiler.DmbFactory:
-
-
- - -Tgstation.Server.Host.Components.Compiler.IDmbFactory -Tgstation.Server.Host.Components.Compiler.ICompileJobConsumer -IHostedService -IDisposable - -
- - - - - - - - - - - - - - - - - - - - - - - -

-Public Member Functions

 DmbFactory (IDatabaseContextFactory databaseContextFactory, IIOManager ioManager, ILogger< DmbFactory > logger, Api.Models.Instance instance)
 Construct a DmbFactory More...
 
void Dispose ()
 
async Task LoadCompileJob (CompileJob job, CancellationToken cancellationToken)
 Load a new job into the ICompileJobConsumer More...
 
IDmbProvider LockNextDmb (int lockCount)
 Gets the next IDmbProvider More...
 
Task StartAsync (CancellationToken cancellationToken)
 
async Task StopAsync (CancellationToken cancellationToken)
 
async Task< IDmbProviderFromCompileJob (CompileJob compileJob, CancellationToken cancellationToken)
 Gets a IDmbProvider for a given CompileJob More...
 
async Task CleanUnusedCompileJobs (CompileJob exceptThisOne, CancellationToken cancellationToken)
 Deletes all compile jobs that are inactive in the Game folder exceptThisOne More...
 
- - - -

-Public Attributes

bool DmbAvailable => nextDmbProvider != null
 
- - - - - - - - - - -

-Properties

Task OnNewerDmb [get]
 
- Properties inherited from Tgstation.Server.Host.Components.Compiler.IDmbFactory
Task OnNewerDmb [get]
 Get a Task that completes when the result of a call to LockNextDmb will be different than the previous call if any More...
 
bool DmbAvailable [get]
 If LockNextDmb will succeed More...
 
- - - - -

-Private Member Functions

void CleanJob (CompileJob job)
 Delete the Api.Models.Internal.CompileJob.DirectoryName of job More...
 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Private Attributes

readonly IDatabaseContextFactory databaseContextFactory
 The IDatabaseContextFactory for the DmbFactory More...
 
readonly IIOManager ioManager
 The IIOManager for the DmbFactory More...
 
readonly ILogger< DmbFactorylogger
 The ILogger for the DmbFactory More...
 
readonly Api.Models.Instance instance
 The Api.Models.Instance for the DmbFactory More...
 
readonly CancellationTokenSource cleanupCts
 The CancellationTokenSource for cleanupTask More...
 
readonly IDictionary< long, int > jobLockCounts
 Map of CompileJob.JobIds to locks on them. More...
 
Task cleanupTask
 Task representing calls to CleanJob(CompileJob) More...
 
TaskCompletionSource< object > newerDmbTcs
 TaskCompletionSource<TResult> resulting in the latest DmbProvider yet to exist More...
 
IDmbProvider nextDmbProvider
 The latest DmbProvider More...
 
-

Detailed Description

-

Standard IDmbFactory

- -

Definition at line 17 of file DmbFactory.cs.

-

Constructor & Destructor Documentation

- -

◆ DmbFactory()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Tgstation.Server.Host.Components.Compiler.DmbFactory.DmbFactory (IDatabaseContextFactory databaseContextFactory,
IIOManager ioManager,
ILogger< DmbFactorylogger,
Api.Models.Instance instance 
)
-
- -

Construct a DmbFactory

-
Parameters
- - - - - -
databaseContextFactoryThe value of databaseContextFactory
ioManagerThe value of ioManager
loggerThe value of logger
instanceThe value of instance
-
-
- -

Definition at line 84 of file DmbFactory.cs.

-
85  {
86  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
87  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
88  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
89  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
90 
91  cleanupTask = Task.CompletedTask;
92  newerDmbTcs = new TaskCompletionSource<object>();
93  cleanupCts = new CancellationTokenSource();
94  jobLockCounts = new Dictionary<long, int>();
95  }
Task cleanupTask
Task representing calls to CleanJob(CompileJob)
Definition: DmbFactory.cs:65
-
readonly IIOManager ioManager
The IIOManager for the DmbFactory
Definition: DmbFactory.cs:40
-
readonly CancellationTokenSource cleanupCts
The CancellationTokenSource for cleanupTask
Definition: DmbFactory.cs:55
-
readonly ILogger< DmbFactory > logger
The ILogger for the DmbFactory
Definition: DmbFactory.cs:45
-
readonly IDictionary< long, int > jobLockCounts
Map of CompileJob.JobIds to locks on them.
Definition: DmbFactory.cs:60
-
readonly Api.Models.Instance instance
The Api.Models.Instance for the DmbFactory
Definition: DmbFactory.cs:50
-
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the DmbFactory
Definition: DmbFactory.cs:35
-
TaskCompletionSource< object > newerDmbTcs
TaskCompletionSource<TResult> resulting in the latest DmbProvider yet to exist
Definition: DmbFactory.cs:70
-
-

References Tgstation.Server.Host.Components.Compiler.DmbFactory.cleanupCts, Tgstation.Server.Host.Components.Compiler.DmbFactory.cleanupTask, Tgstation.Server.Host.Components.Compiler.DmbFactory.databaseContextFactory, Tgstation.Server.Host.Components.Compiler.DmbFactory.instance, Tgstation.Server.Host.Components.Compiler.DmbFactory.ioManager, Tgstation.Server.Host.Components.Compiler.DmbFactory.jobLockCounts, Tgstation.Server.Host.Components.Compiler.DmbFactory.logger, and Tgstation.Server.Host.Components.Compiler.DmbFactory.newerDmbTcs.

- -
-
-

Member Function Documentation

- -

◆ CleanJob()

- -
-
- - - - - -
- - - - - - - - -
void Tgstation.Server.Host.Components.Compiler.DmbFactory.CleanJob (CompileJob job)
-
-private
-
- -

Delete the Api.Models.Internal.CompileJob.DirectoryName of job

-
Parameters
- - -
jobThe CompileJob to clean
-
-
- -

Definition at line 104 of file DmbFactory.cs.

-
105  {
106  async Task HandleCleanup()
107  {
108  var deleteJob = ioManager.DeleteDirectory(job.DirectoryName.ToString(), cleanupCts.Token);
109  Task otherTask;
110 
111  // lock (this) //already locked below
112  otherTask = cleanupTask;
113  await Task.WhenAll(otherTask, deleteJob).ConfigureAwait(false);
114  }
115 
116  lock (this)
117  if (!jobLockCounts.TryGetValue(job.Id, out var currentVal) || currentVal == 1)
118  {
119  jobLockCounts.Remove(job.Id);
120  logger.LogDebug("Cleaning compile job {0} => {1}", job.Id, job.DirectoryName);
121  cleanupTask = HandleCleanup();
122  }
123  else
124  {
125  var decremented = --jobLockCounts[job.Id];
126  logger.LogTrace("Compile job {0} lock count now: {1}", job.Id, decremented);
127  }
128  }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
-
Task cleanupTask
Task representing calls to CleanJob(CompileJob)
Definition: DmbFactory.cs:65
-
long Id
The ID of the entity.
Definition: EntityId.cs:11
-
readonly IIOManager ioManager
The IIOManager for the DmbFactory
Definition: DmbFactory.cs:40
-
Guid? DirectoryName
The Game folder the results were compiled into
Definition: CompileJob.cs:27
-
readonly CancellationTokenSource cleanupCts
The CancellationTokenSource for cleanupTask
Definition: DmbFactory.cs:55
-
readonly ILogger< DmbFactory > logger
The ILogger for the DmbFactory
Definition: DmbFactory.cs:45
-
readonly IDictionary< long, int > jobLockCounts
Map of CompileJob.JobIds to locks on them.
Definition: DmbFactory.cs:60
-
-

References Tgstation.Server.Host.Components.Compiler.DmbFactory.cleanupCts, Tgstation.Server.Host.Components.Compiler.DmbFactory.cleanupTask, Tgstation.Server.Host.IO.IIOManager.DeleteDirectory(), Tgstation.Server.Api.Models.Internal.CompileJob.DirectoryName, Tgstation.Server.Api.Models.EntityId.Id, Tgstation.Server.Host.Components.Compiler.DmbFactory.ioManager, Tgstation.Server.Host.Components.Compiler.DmbFactory.jobLockCounts, and Tgstation.Server.Host.Components.Compiler.DmbFactory.logger.

- -

Referenced by Tgstation.Server.Host.Components.Compiler.DmbFactory.FromCompileJob().

- -
-
- -

◆ CleanUnusedCompileJobs()

- -
-
- - - - - - - - - - - - - - - - - - -
async Task Tgstation.Server.Host.Components.Compiler.DmbFactory.CleanUnusedCompileJobs (CompileJob exceptThisOne,
CancellationToken cancellationToken 
)
-
- -

Deletes all compile jobs that are inactive in the Game folder exceptThisOne

- -

Implements Tgstation.Server.Host.Components.Compiler.IDmbFactory.

- -

Definition at line 243 of file DmbFactory.cs.

-
244  {
245  List<long> jobIdsToSkip;
246 
247  // don't clean locked directories
248  lock (this)
249  jobIdsToSkip = jobLockCounts.Select(x => x.Key).ToList();
250 
251  List<string> jobUidsToNotErase = null;
252 
253  // find the uids of locked directories
254  await databaseContextFactory.UseContext(async db =>
255  {
256  jobUidsToNotErase = await db.CompileJobs.Where(x => x.Job.Instance.Id == instance.Id && jobIdsToSkip.Contains(x.Id)).Select(x => x.DirectoryName.Value.ToString().ToUpperInvariant()).ToListAsync(cancellationToken).ConfigureAwait(false);
257  }).ConfigureAwait(false);
258 
259  // add the other exemption
260  if (exceptThisOne != null)
261  jobUidsToNotErase.Add(exceptThisOne.DirectoryName.Value.ToString().ToUpperInvariant());
262 
263  // cleanup
264  await ioManager.CreateDirectory(".", cancellationToken).ConfigureAwait(false);
265  var directories = await ioManager.GetDirectories(".", cancellationToken).ConfigureAwait(false);
266  int deleting = 0;
267  var tasks = directories.Select(async x =>
268  {
269  var nameOnly = ioManager.GetFileName(x);
270  if (jobUidsToNotErase.Contains(nameOnly.ToUpperInvariant()))
271  return;
272  try
273  {
274  ++deleting;
275  await ioManager.DeleteDirectory(x, cancellationToken).ConfigureAwait(false);
276  }
277  catch (OperationCanceledException)
278  {
279  throw;
280  }
281  catch (Exception e)
282  {
283  logger.LogWarning("Error deleting directory {0}! Exception: {1}", x, e);
284  }
285  }).ToList();
286  if (deleting > 0)
287  {
288  logger.LogDebug("Cleaning {0} unused game folders...", deleting);
289  await Task.WhenAll().ConfigureAwait(false);
290  }
291  }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
-
Task< IReadOnlyList< string > > GetDirectories(string path, CancellationToken cancellationToken)
Returns directory names in a given path
-
readonly IIOManager ioManager
The IIOManager for the DmbFactory
Definition: DmbFactory.cs:40
-
Guid? DirectoryName
The Game folder the results were compiled into
Definition: CompileJob.cs:27
-
Task CreateDirectory(string path, CancellationToken cancellationToken)
Create a directory at path
-
string GetFileName(string path)
Gets the file name portion of a path
-
readonly ILogger< DmbFactory > logger
The ILogger for the DmbFactory
Definition: DmbFactory.cs:45
-
readonly IDictionary< long, int > jobLockCounts
Map of CompileJob.JobIds to locks on them.
Definition: DmbFactory.cs:60
-
readonly Api.Models.Instance instance
The Api.Models.Instance for the DmbFactory
Definition: DmbFactory.cs:50
-
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the DmbFactory
Definition: DmbFactory.cs:35
-
-

References Tgstation.Server.Host.IO.IIOManager.CreateDirectory(), Tgstation.Server.Host.Components.Compiler.DmbFactory.databaseContextFactory, Tgstation.Server.Host.IO.IIOManager.DeleteDirectory(), Tgstation.Server.Api.Models.Internal.CompileJob.DirectoryName, Tgstation.Server.Host.IO.IIOManager.GetDirectories(), Tgstation.Server.Host.IO.IIOManager.GetFileName(), Tgstation.Server.Host.Components.Compiler.DmbFactory.instance, Tgstation.Server.Host.Components.Compiler.DmbFactory.ioManager, Tgstation.Server.Host.Components.Compiler.DmbFactory.jobLockCounts, Tgstation.Server.Host.Components.Compiler.DmbFactory.logger, and Tgstation.Server.Host.Core.IDatabaseContextFactory.UseContext().

- -
-
- -

◆ Dispose()

- -
-
- - - - - - - -
void Tgstation.Server.Host.Components.Compiler.DmbFactory.Dispose ()
-
- -

- -
-
- -

◆ FromCompileJob()

- -
-
- - - - - - - - - - - - - - - - - - -
async Task<IDmbProvider> Tgstation.Server.Host.Components.Compiler.DmbFactory.FromCompileJob (CompileJob compileJob,
CancellationToken cancellationToken 
)
-
- -

Gets a IDmbProvider for a given CompileJob

- -

Implements Tgstation.Server.Host.Components.Compiler.IDmbFactory.

- -

Definition at line 186 of file DmbFactory.cs.

-
187  {
188  if (compileJob == null)
189  throw new ArgumentNullException(nameof(compileJob));
190 
191  // ensure we have the entire compile job tree
192  await databaseContextFactory.UseContext(async db => compileJob = await db.CompileJobs.Where(x => x.Id == compileJob.Id)
193  .Include(x => x.Job).ThenInclude(x => x.StartedBy)
194  .Include(x => x.RevisionInformation).ThenInclude(x => x.PrimaryTestMerge).ThenInclude(x => x.MergedBy)
195  .Include(x => x.RevisionInformation).ThenInclude(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).ThenInclude(x => x.MergedBy)
196  .FirstAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false); // can't wait to see that query
197 
198  logger.LogTrace("Loading compile job {0}...", compileJob.Id);
199  var providerSubmitted = false;
200  var newProvider = new DmbProvider(compileJob, ioManager, () =>
201  {
202  if (providerSubmitted)
203  CleanJob(compileJob);
204  });
205 
206  try
207  {
208  var primaryCheckTask = ioManager.FileExists(ioManager.ConcatPath(newProvider.PrimaryDirectory, newProvider.DmbName), cancellationToken);
209  var secondaryCheckTask = ioManager.FileExists(ioManager.ConcatPath(newProvider.PrimaryDirectory, newProvider.DmbName), cancellationToken);
210 
211  if (!(await primaryCheckTask.ConfigureAwait(false) && await secondaryCheckTask.ConfigureAwait(false)))
212  {
213  logger.LogWarning("Error loading compile job, .dmb missing!");
214  return null; // omae wa mou shinderu
215  }
216 
217  lock (this)
218  {
219  if (!jobLockCounts.TryGetValue(compileJob.Id, out int value))
220  {
221  value = 1;
222  jobLockCounts.Add(compileJob.Id, 1);
223  }
224  else
225  jobLockCounts[compileJob.Id] = ++value;
226 
227  logger.LogTrace("Compile job {0} lock count now: {1}", compileJob.Id, value);
228 
229  providerSubmitted = true;
230  return newProvider;
231  }
232  }
233  finally
234  {
235  if (!providerSubmitted)
236  newProvider.Dispose();
237  }
238  }
long Id
The ID of the entity.
Definition: EntityId.cs:11
-
readonly IIOManager ioManager
The IIOManager for the DmbFactory
Definition: DmbFactory.cs:40
-
Task< bool > FileExists(string path, CancellationToken cancellationToken)
Check that the file at path exists
-
readonly ILogger< DmbFactory > logger
The ILogger for the DmbFactory
Definition: DmbFactory.cs:45
-
readonly IDictionary< long, int > jobLockCounts
Map of CompileJob.JobIds to locks on them.
Definition: DmbFactory.cs:60
-
void CleanJob(CompileJob job)
Delete the Api.Models.Internal.CompileJob.DirectoryName of job
Definition: DmbFactory.cs:104
-
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the DmbFactory
Definition: DmbFactory.cs:35
-
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
-
string ConcatPath(params string[] paths)
Combines an array of strings into a path
-
-

References Tgstation.Server.Host.Components.Compiler.DmbFactory.CleanJob(), Tgstation.Server.Host.IO.IIOManager.ConcatPath(), Tgstation.Server.Host.Components.Compiler.DmbFactory.databaseContextFactory, Tgstation.Server.Host.IO.IIOManager.FileExists(), Tgstation.Server.Api.Models.EntityId.Id, Tgstation.Server.Host.Components.Compiler.DmbFactory.ioManager, Tgstation.Server.Host.Components.Compiler.DmbFactory.jobLockCounts, Tgstation.Server.Host.Components.Compiler.DmbFactory.logger, and Tgstation.Server.Host.Core.IDatabaseContextFactory.UseContext().

- -

Referenced by Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.HandlerMonitorWakeup(), and Tgstation.Server.Host.Components.Compiler.DmbFactory.LoadCompileJob().

- -
-
- -

◆ LoadCompileJob()

- -
-
- - - - - - - - - - - - - - - - - - -
async Task Tgstation.Server.Host.Components.Compiler.DmbFactory.LoadCompileJob (CompileJob job,
CancellationToken cancellationToken 
)
-
- -

Load a new job into the ICompileJobConsumer

- -

Implements Tgstation.Server.Host.Components.Compiler.ICompileJobConsumer.

- -

Definition at line 131 of file DmbFactory.cs.

-
132  {
133  if (job == null)
134  throw new ArgumentNullException(nameof(job));
135 
136  var newProvider = await FromCompileJob(job, cancellationToken).ConfigureAwait(false);
137  if (newProvider == null)
138  return;
139  lock (this)
140  {
141  nextDmbProvider?.Dispose();
142  nextDmbProvider = newProvider;
143  newerDmbTcs.SetResult(nextDmbProvider);
144  newerDmbTcs = new TaskCompletionSource<object>();
145  }
146  }
IDmbProvider nextDmbProvider
The latest DmbProvider
Definition: DmbFactory.cs:75
-
async Task< IDmbProvider > FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken)
Gets a IDmbProvider for a given CompileJob
Definition: DmbFactory.cs:186
-
TaskCompletionSource< object > newerDmbTcs
TaskCompletionSource<TResult> resulting in the latest DmbProvider yet to exist
Definition: DmbFactory.cs:70
-
-

References Tgstation.Server.Host.Components.Compiler.DmbFactory.FromCompileJob(), Tgstation.Server.Host.Components.Compiler.DmbFactory.newerDmbTcs, and Tgstation.Server.Host.Components.Compiler.DmbFactory.nextDmbProvider.

- -
-
- -

◆ LockNextDmb()

- -
-
- - - - - - - - -
IDmbProvider Tgstation.Server.Host.Components.Compiler.DmbFactory.LockNextDmb (int lockCount)
-
- -

Gets the next IDmbProvider

- -

Implements Tgstation.Server.Host.Components.Compiler.IDmbFactory.

- -

Definition at line 149 of file DmbFactory.cs.

-
150  {
151  if (!DmbAvailable)
152  throw new InvalidOperationException("No .dmb available!");
153  if (lockCount < 0)
154  throw new ArgumentOutOfRangeException(nameof(lockCount), lockCount, "lockCount must be greater than or equal to 0!");
155  lock (this)
156  {
157  var jobId = nextDmbProvider.CompileJob.Id;
158  var incremented = jobLockCounts[jobId] += lockCount;
159  logger.LogTrace("Compile job {0} lock count now: {1}", jobId, incremented);
160  return nextDmbProvider;
161  }
162  }
IDmbProvider nextDmbProvider
The latest DmbProvider
Definition: DmbFactory.cs:75
-
CompileJob CompileJob
The CompileJob of the .dmb
Definition: IDmbProvider.cs:29
-
long Id
The ID of the entity.
Definition: EntityId.cs:11
-
readonly ILogger< DmbFactory > logger
The ILogger for the DmbFactory
Definition: DmbFactory.cs:45
-
readonly IDictionary< long, int > jobLockCounts
Map of CompileJob.JobIds to locks on them.
Definition: DmbFactory.cs:60
- -
-

References Tgstation.Server.Host.Components.IDmbProvider.CompileJob, Tgstation.Server.Host.Components.Compiler.DmbFactory.DmbAvailable, Tgstation.Server.Api.Models.EntityId.Id, Tgstation.Server.Host.Components.Compiler.DmbFactory.jobLockCounts, Tgstation.Server.Host.Components.Compiler.DmbFactory.logger, and Tgstation.Server.Host.Components.Compiler.DmbFactory.nextDmbProvider.

- -

Referenced by Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.HandlerMonitorWakeup(), Tgstation.Server.Host.Components.Watchdog.BasicWatchdog.InitControllers(), and Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.InitControllers().

- -
-
- -

◆ StartAsync()

- -
-
- - - - - - - - -
Task Tgstation.Server.Host.Components.Compiler.DmbFactory.StartAsync (CancellationToken cancellationToken)
-
- -

- -
-
- -

◆ StopAsync()

- -
-
- - - - - - - - -
async Task Tgstation.Server.Host.Components.Compiler.DmbFactory.StopAsync (CancellationToken cancellationToken)
-
- -

- -

Definition at line 178 of file DmbFactory.cs.

-
179  {
180  using (cancellationToken.Register(() => cleanupCts.Cancel()))
181  await cleanupTask.ConfigureAwait(false);
182  }
Task cleanupTask
Task representing calls to CleanJob(CompileJob)
Definition: DmbFactory.cs:65
-
readonly CancellationTokenSource cleanupCts
The CancellationTokenSource for cleanupTask
Definition: DmbFactory.cs:55
-
-

References Tgstation.Server.Host.Components.Compiler.DmbFactory.cleanupCts, and Tgstation.Server.Host.Components.Compiler.DmbFactory.cleanupTask.

- -
-
-

Member Data Documentation

- -

◆ cleanupCts

- -
-
- - - - - -
- - - - -
readonly CancellationTokenSource Tgstation.Server.Host.Components.Compiler.DmbFactory.cleanupCts
-
-private
-
-
- -

◆ cleanupTask

- -
-
- - - - - -
- - - - -
Task Tgstation.Server.Host.Components.Compiler.DmbFactory.cleanupTask
-
-private
-
-
- -

◆ databaseContextFactory

- -
-
- - - - - -
- - - - -
readonly IDatabaseContextFactory Tgstation.Server.Host.Components.Compiler.DmbFactory.databaseContextFactory
-
-private
-
-
- -

◆ DmbAvailable

- -
-
- - - - -
bool Tgstation.Server.Host.Components.Compiler.DmbFactory.DmbAvailable => nextDmbProvider != null
-
- -

- -

Definition at line 30 of file DmbFactory.cs.

- -

Referenced by Tgstation.Server.Host.Components.Compiler.DmbFactory.LockNextDmb().

- -
-
- -

◆ instance

- -
-
- - - - - -
- - - - -
readonly Api.Models.Instance Tgstation.Server.Host.Components.Compiler.DmbFactory.instance
-
-private
-
-
- -

◆ ioManager

- - - -

◆ jobLockCounts

- -
-
- - - - - -
- - - - -
readonly IDictionary<long, int> Tgstation.Server.Host.Components.Compiler.DmbFactory.jobLockCounts
-
-private
-
-
- -

◆ logger

- - - -

◆ newerDmbTcs

- -
-
- - - - - -
- - - - -
TaskCompletionSource<object> Tgstation.Server.Host.Components.Compiler.DmbFactory.newerDmbTcs
-
-private
-
- -

TaskCompletionSource<TResult> resulting in the latest DmbProvider yet to exist

- -

Definition at line 70 of file DmbFactory.cs.

- -

Referenced by Tgstation.Server.Host.Components.Compiler.DmbFactory.DmbFactory(), and Tgstation.Server.Host.Components.Compiler.DmbFactory.LoadCompileJob().

- -
-
- -

◆ nextDmbProvider

- -
-
- - - - - -
- - - - -
IDmbProvider Tgstation.Server.Host.Components.Compiler.DmbFactory.nextDmbProvider
-
-private
-
-
-

Property Documentation

- -

◆ OnNewerDmb

- -
-
- - - - - -
- - - - -
Task Tgstation.Server.Host.Components.Compiler.DmbFactory.OnNewerDmb
-
-get
-
- -

- -

Definition at line 21 of file DmbFactory.cs.

-
21  {
22  get
23  {
24  lock (this)
25  return newerDmbTcs.Task;
26  }
27  }
TaskCompletionSource< object > newerDmbTcs
TaskCompletionSource<TResult> resulting in the latest DmbProvider yet to exist
Definition: DmbFactory.cs:70
-
-

Referenced by Tgstation.Server.Host.Components.Watchdog.BasicWatchdog.MonitorLifetimes(), and Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.MonitorLifetimes().

- -
-
-
The documentation for this class was generated from the following file: -
- - - - diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_factory.png b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_factory.png deleted file mode 100644 index 2f35a35f7a870580053ed4b86afae6efb8a4676a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2710 zcmdUxcT^Mk7RM=xVj`dvrRT6jf+$iH2}+Z?krs+X=?aL_k&@t2mZ*TsO4f)X9X3*Y zf*>FW$pR4t0|*Mz7DD2Nwv-S;F+d(zwIO=OlXCWa`CSa$Di2_G-edHu?l0)0MS_uRKz?_+1jUl}L0kC%W*49?= z-7y$&DHiSQ;35Ph?Q8>`u6ja3kRvF|bFMhy1^Q_0FBB=O&xA=`oWN#0KY}YP#vi34 ztJ4C_YP7m8=$CllpedK-I(7E9*K z4N?FCT5Y1%UU>>^AAPQ1l}(;pT&e5QS2Ie_%6S0h0XC9ziKJbk9e+w^pr{Z<~r6(_LJMAX}dp7xHRXT^8Y z4yGn-%$>Zy(o~lvex)-YsfvlJk+P*CRAG0vIz_ywp9`0AV>z`QE{ljc>eFC@XLbEF z_=rl22Zy$ChBkm5M&QHG{9b7Y)Y5zmc1MMrXvKk#9B=XDtPduT!fRe2Xt4k)E~e4@ zY?hwkf|v^xF&Xm{o9G|RcczxbU7DEcdyIwCN_Ugwq1$EV65tq~aTu&uC3m_;5yPDD zCx#GwGO zsYDDPuosiLnCd1SlBN!VRGgdJciQsb(}O?U#EXBtZI-Nm&6t{U&Ag~pp{~H!;y>>4 zuQIm=|GSKD3uCb>v4s&1)<73UPu~&&j}svhU*Ec6yB^dL&zE8O2bZ*+`FHJ;6R({~SE!c8WM50i~Ln z%sMiV`+5YM60rJP+N9_sIjHsyRT~sn?ThWg-DILÜlY>^^f+aVw1NCeM`Z7(?` zZL|kOY!k4&uc?BH6h^XXNDwJ0b=<>_9Fpi9HjkkdV{RujT-bXyUoe zA*lhvp2{9bW=GvU z!u$%)1PQ53mC2e0Oy3p%J-|92=_0W7kd-Q~}IS)eepF?OP#%$-^KmNnALFhsE< zTsV@14U&Na!#}4Ww?Fs$Gr812h{@3}w&*OYQ=0W&M0wU!2 zSYF9;r}{GEe5g~c9~k!Z@#I(-G%+%$?(PY&U}O;n7JMogoG(%yVxm-)Ba6ulT_(3 zQgf@%ez}k0wYsVCs#gM?4_BJ9HUl@?wWwA5xk=FNY^S8z_K_i^ zdP5l&y9cJh!T^jpGC0Y>m!*RVj1%)d*}N> zh1mu0s=$|x{DrKID!jogs)ot1WQl?c=P#kSR}#~ilHy4&9BX6RL^+d#BrGz?^hcTt z4Px8FGY!}sKX2C$-PQc*`W?NWDEynf|Np2etQ}Rk|5qaMw^gOsj5;yA5KFEZU5M2N zLu4)z9v!0OTor~?*x5q8?Q4a=ZlxvQs?tl}iX7|j!(;l7n%V@QoE)O7mgAnZ_{)OSLn&lTi$W$gvwy2_1;pq2#snz$%lj7AMY}& znPkC>*FS0Vq(v{^@YG#qn+<_{RtiC>U_dcLZXrN|TAze1-p}>TU!E_wSS)@KEY_xr z^FEk(BNuWYi91r!l$oazNm=7n{Q97yk_E~N?i)yUs8oz1-&kMSDviu;)*0K;*N4C` zCmmbMCY^?u*-sly_#?>u-n%3Tr zeab}p1{6r~orklyg`*}TM_+j8g{c^{RQ0~M>9%iLd*|Up8sQs#c-g2mzDzMu!p<(` zO{)PK&-tq0Q2dhxRHp~t(Gr;v*|hY?vfsu?n|Gx|&V!f6#7@=Y*l}@9YCM*33NW%h z$59tUll;M9DgmLgzk6N62ntZ4~-vPHYmd(Ui10#m1Z{(Deq`66sa1_Kcl&8m))s>nu z0@caCz6!4SSP*V#{0naNTG9RQYT1)U615bgS+*I%ATa7IqmIIt%d-Gw+$u=2_m*P= zgQ~UD2;=Ud`DS2>i}CpffHaGPyKY~vh0|>@=j`oxz6(mDk{;#~!&3w$Mb7|D`oEf{ zu8uiy3JTD5cjpAaWIDUVEcqVC)VtWazEkAv4Db^vgtBt5d~WWG{|#@h BAjALw diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_provider.html b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_provider.html deleted file mode 100644 index edbde92081..0000000000 --- a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_provider.html +++ /dev/null @@ -1,387 +0,0 @@ - - - - - - - -tgstation-server: Tgstation.Server.Host.Components.Compiler.DmbProvider Class Reference - - - - - - - - - -
-
- - - - - - - -
-
tgstation-server -
-
The /tg/station 13 server suite
-
-
- - - - - - - - -
-
- - -
- -
- - -
-
- -
-
Tgstation.Server.Host.Components.Compiler.DmbProvider Class Reference
-
-
- -

- More...

-
-Inheritance diagram for Tgstation.Server.Host.Components.Compiler.DmbProvider:
-
-
- - -Tgstation.Server.Host.Components.IDmbProvider -IDisposable - -
- - - - - - - - - - -

-Public Member Functions

 DmbProvider (CompileJob compileJob, IIOManager ioManager, Action onDispose)
 Construct a DmbProvider More...
 
void Dispose ()
 
void KeepAlive ()
 Disposing the IDmbProvider won't cause a cleanup of the working directory More...
 
- - - - - - - -

-Public Attributes

string DmbName => String.Concat(CompileJob.DmeName, DreamMaker.DmbExtension)
 
string PrimaryDirectory => ioManager.ResolvePath(ioManager.ConcatPath(CompileJob.DirectoryName.ToString(), DreamMaker.ADirectoryName))
 
string SecondaryDirectory => ioManager.ResolvePath(ioManager.ConcatPath(CompileJob.DirectoryName.ToString(), DreamMaker.BDirectoryName))
 
- - - - - - - - - - - - - - - - - -

-Properties

CompileJob CompileJob [get]
 The CompileJob for the DmbProvider More...
 
- Properties inherited from Tgstation.Server.Host.Components.IDmbProvider
string DmbName [get]
 The file name of the .dmb More...
 
string PrimaryDirectory [get]
 The primary game directory with a trailing directory separator More...
 
string SecondaryDirectory [get]
 The secondary game directory with a trailing directory separator More...
 
CompileJob CompileJob [get]
 The CompileJob of the .dmb More...
 
- - - - - - - -

-Private Attributes

readonly IIOManager ioManager
 The IIOManager for the DmbProvider More...
 
Action onDispose
 The Action to run when Dispose is called More...
 
-

Detailed Description

-
-

Definition at line 8 of file DmbProvider.cs.

-

Constructor & Destructor Documentation

- -

◆ DmbProvider()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - -
Tgstation.Server.Host.Components.Compiler.DmbProvider.DmbProvider (CompileJob compileJob,
IIOManager ioManager,
Action onDispose 
)
-
- -

Construct a DmbProvider

-
Parameters
- - - - -
compileJobThe value of CompileJob
ioManagerThe value of ioManager
onDisposeThe value of onDispose
-
-
- -

Definition at line 40 of file DmbProvider.cs.

-
41  {
42  CompileJob = compileJob ?? throw new ArgumentNullException(nameof(compileJob));
43  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
44  this.onDispose = onDispose ?? throw new ArgumentNullException(nameof(onDispose));
45  }
Action onDispose
The Action to run when Dispose is called
Definition: DmbProvider.cs:32
-
readonly IIOManager ioManager
The IIOManager for the DmbProvider
Definition: DmbProvider.cs:27
- -
-

References Tgstation.Server.Host.Components.Compiler.DmbProvider.ioManager, and Tgstation.Server.Host.Components.Compiler.DmbProvider.onDispose.

- -
-
-

Member Function Documentation

- -

◆ Dispose()

- -
-
- - - - - - - -
void Tgstation.Server.Host.Components.Compiler.DmbProvider.Dispose ()
-
- -

- -
-
- -

◆ KeepAlive()

- -
-
- - - - - - - -
void Tgstation.Server.Host.Components.Compiler.DmbProvider.KeepAlive ()
-
- -

Disposing the IDmbProvider won't cause a cleanup of the working directory

- -

Implements Tgstation.Server.Host.Components.IDmbProvider.

- -
-
-

Member Data Documentation

- -

◆ DmbName

- -
-
- - - - -
string Tgstation.Server.Host.Components.Compiler.DmbProvider.DmbName => String.Concat(CompileJob.DmeName, DreamMaker.DmbExtension)
-
- -

- -

Definition at line 11 of file DmbProvider.cs.

- -
-
- -

◆ ioManager

- -
-
- - - - - -
- - - - -
readonly IIOManager Tgstation.Server.Host.Components.Compiler.DmbProvider.ioManager
-
-private
-
- -

The IIOManager for the DmbProvider

- -

Definition at line 27 of file DmbProvider.cs.

- -

Referenced by Tgstation.Server.Host.Components.Compiler.DmbProvider.DmbProvider().

- -
-
- -

◆ onDispose

- -
-
- - - - - -
- - - - -
Action Tgstation.Server.Host.Components.Compiler.DmbProvider.onDispose
-
-private
-
- -

The Action to run when Dispose is called

- -

Definition at line 32 of file DmbProvider.cs.

- -

Referenced by Tgstation.Server.Host.Components.Compiler.DmbProvider.DmbProvider().

- -
-
- -

◆ PrimaryDirectory

- -
-
- - - - -
string Tgstation.Server.Host.Components.Compiler.DmbProvider.PrimaryDirectory => ioManager.ResolvePath(ioManager.ConcatPath(CompileJob.DirectoryName.ToString(), DreamMaker.ADirectoryName))
-
- -

- -

Definition at line 14 of file DmbProvider.cs.

- -
-
- -

◆ SecondaryDirectory

- -
-
- - - - -
string Tgstation.Server.Host.Components.Compiler.DmbProvider.SecondaryDirectory => ioManager.ResolvePath(ioManager.ConcatPath(CompileJob.DirectoryName.ToString(), DreamMaker.BDirectoryName))
-
- -

- -

Definition at line 17 of file DmbProvider.cs.

- -
-
-

Property Documentation

- -

◆ CompileJob

- -
-
- - - - - -
- - - - -
CompileJob Tgstation.Server.Host.Components.Compiler.DmbProvider.CompileJob
-
-get
-
- -

The CompileJob for the DmbProvider

- -

Definition at line 22 of file DmbProvider.cs.

-
22 { get; }
-
-
-
The documentation for this class was generated from the following file: -
- - - - diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_provider.png b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_provider.png deleted file mode 100644 index 35195ae16937054ca10b6a00d39298eccd6bdc46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1539 zcmb`Hdr*>D7{)&{$}DEP+NNz-VWp;)S&pD-mMNB);3d&=*VQdk^M+t5SXo=HCWfw* z0=9;JnPs`&7TpAM%-iM-H99RZ1?7y9vbI$XedC$xl^9=0076h9l`;C4qmIT>gj6NNTc~p+U?t8N4;G%8jV(tPs-wHkF&Ju(^O~2$83`qc`$K&W_ z*QUJbnRdsO4WerKZGr4`HU}}5&5~>%Z>ZQsF@ZouZ``o51gWx9ZJ|;mj%wu)gF{x_ z3$?&l{TGEsHpB2%{4Zg?fDpd7sy`3LmyRsw1Dqc~pd^{%Z|1a(q@UI1QBt%B84Lo# zfgMhk+Jkh~qQAA4J7D@%Ew3f)epMbJ+#}TtbC^zl`1$$P|C{z4RB5llh}}zHNJ!FJ zUN+~Meg2eDlx*Sx^73l+Bzt`2nG%os=wWAiS!^gfQzsRVF-)-M<+gGKwu>`5egomQoOv(Po&1{5sIgL>LLmTDR;eVS2zDO@k)_qakGM; z*Ne(qY}XQNn*HGd8hh}hMQ69~sVX;7w_jr>rOSnglD-?a7S5;lG9Gqk`eTbPB3bXs z1RcHNmn~s#H39oxc89P@6K^BI#*vNpRJ+{*eJq3r-fKo?iBq&ewdBr*6Idp@OvRX) zC3>jR1ntc}5-N&p80gWj7E)`!sT_WF@_~va5bn2&7tL*y<1whwfH5`cURe^w-n{Pq zZ)gjpo08ca$77Lq9|O}H!+nlMS6Q8UD(OmlMOft@rz7Q*f zs=}-=DOXY&plT!%(w*PVbf;hE_zjdGM}t9nPCCmSXGt={aEF-v9~)vPKwTOHEHQ?o zVQ!-n?KmCla{PJkv+fq_j8~yyEl&>XXq)7G;N)84^;+A6{i;^sf<0o|l!J3OTnp%C zUHX#Qb}`YR{JbwgMzSS4s#ozdiV(M~0#u2{#yON8@WLB}HC2hrcN5kCSBW#kWFzLH z7540)xERUoH7BPXYc_xviVftQNk2+m2kjog+f{G&qiCB&RJJFAN2_VH321c4zvS8t zEd*cN<99B2GE=dx8d!J&o*gj(qyV-;VfZBTMNMA6PoN?=~LX&V{R6JG-d7#7FW6OHl-61tnHoDcw2= zuJ2Gy9Y0|!NtligI7ptAU6(J*7^9-4!M7w6WLmSmh?}yxOFe|Bc}kgikx1U+*{N!P z{^- SOlW^>0ONu^RObBs#eV?A;0Bxk diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dream_maker-members.html b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dream_maker-members.html deleted file mode 100644 index 2118cd2c73..0000000000 --- a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dream_maker-members.html +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - -tgstation-server: Member List - - - - - - - - - -
-
- - - - - - - -
-
tgstation-server -
-
The /tg/station 13 server suite
-
-
- - - - - - - - -
-
- - -
- -
- - -
-
-
-
Tgstation.Server.Host.Components.Compiler.DreamMaker Member List
-
-
- -

This is the complete list of members for Tgstation.Server.Host.Components.Compiler.DreamMaker, including all inherited members.

- - - - - - - - - - - - - - - - - - - - - - - - - - - -
ADirectoryNameTgstation.Server.Host.Components.Compiler.DreamMaker
applicationTgstation.Server.Host.Components.Compiler.DreamMakerprivate
BDirectoryNameTgstation.Server.Host.Components.Compiler.DreamMaker
byondTgstation.Server.Host.Components.Compiler.DreamMakerprivate
chatTgstation.Server.Host.Components.Compiler.DreamMakerprivate
CleanupFailedCompile(Models.CompileJob job, bool cancelled, CancellationToken cancellationToken)Tgstation.Server.Host.Components.Compiler.DreamMakerprivate
Compile(Models.RevisionInformation revisionInformation, Api.Models.DreamMaker dreamMakerSettings, uint apiValidateTimeout, IRepository repository, Action< int > progressReporter, TimeSpan? estimatedDuration, CancellationToken cancellationToken)Tgstation.Server.Host.Components.Compiler.DreamMaker
Tgstation::Server::Host::Components::Compiler::IDreamMaker.Compile(Models.RevisionInformation revisionInformation, Api.Models.DreamMaker dreamMakerSettings, uint apiValidateTimeout, IRepository repository, Action< int > progressReporter, TimeSpan? estimatedDuration, CancellationToken cancellationToken)Tgstation.Server.Host.Components.Compiler.IDreamMaker
compileJobConsumerTgstation.Server.Host.Components.Compiler.DreamMakerprivate
compilingTgstation.Server.Host.Components.Compiler.DreamMakerprivate
configurationTgstation.Server.Host.Components.Compiler.DreamMakerprivate
DmbExtensionTgstation.Server.Host.Components.Compiler.DreamMaker
DmeExtensionTgstation.Server.Host.Components.Compiler.DreamMakerprivate
DreamMaker(IByondManager byond, IIOManager ioManager, StaticFiles.IConfiguration configuration, ISessionControllerFactory sessionControllerFactory, ICompileJobConsumer compileJobConsumer, IApplication application, IEventConsumer eventConsumer, IChat chat, IProcessExecutor processExecutor, IWatchdog watchdog, ILogger< DreamMaker > logger)Tgstation.Server.Host.Components.Compiler.DreamMaker
eventConsumerTgstation.Server.Host.Components.Compiler.DreamMakerprivate
ioManagerTgstation.Server.Host.Components.Compiler.DreamMakerprivate
loggerTgstation.Server.Host.Components.Compiler.DreamMakerprivate
ModifyDme(Models.CompileJob job, CancellationToken cancellationToken)Tgstation.Server.Host.Components.Compiler.DreamMakerprivate
processExecutorTgstation.Server.Host.Components.Compiler.DreamMakerprivate
ProgressTask(Action< int > progressReporter, TimeSpan estimatedDuration, CancellationToken cancellationToken)Tgstation.Server.Host.Components.Compiler.DreamMakerprivatestatic
RunCompileJob(Models.CompileJob job, Api.Models.DreamMaker dreamMakerSettings, IByondExecutableLock byondLock, IRepository repository, uint apiValidateTimeout, CancellationToken cancellationToken)Tgstation.Server.Host.Components.Compiler.DreamMakerprivate
RunDreamMaker(string dreamMakerPath, Models.CompileJob job, CancellationToken cancellationToken)Tgstation.Server.Host.Components.Compiler.DreamMakerprivate
SendDeploymentMessage(Models.RevisionInformation revisionInformation, IByondExecutableLock byondLock, CancellationToken cancellationToken)Tgstation.Server.Host.Components.Compiler.DreamMakerprivate
sessionControllerFactoryTgstation.Server.Host.Components.Compiler.DreamMakerprivate
VerifyApi(uint timeout, DreamDaemonSecurity securityLevel, Models.CompileJob job, IByondExecutableLock byondLock, ushort portToUse, CancellationToken cancellationToken)Tgstation.Server.Host.Components.Compiler.DreamMakerprivate
watchdogTgstation.Server.Host.Components.Compiler.DreamMakerprivate
- - - - diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dream_maker.html b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dream_maker.html deleted file mode 100644 index c17dbcb902..0000000000 --- a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dream_maker.html +++ /dev/null @@ -1,1331 +0,0 @@ - - - - - - - -tgstation-server: Tgstation.Server.Host.Components.Compiler.DreamMaker Class Reference - - - - - - - - - -
-
- - - - - - - -
-
tgstation-server -
-
The /tg/station 13 server suite
-
-
- - - - - - - - -
-
- - -
- -
- - -
-
- -
-
Tgstation.Server.Host.Components.Compiler.DreamMaker Class Reference
-
-
- -

- More...

-
-Inheritance diagram for Tgstation.Server.Host.Components.Compiler.DreamMaker:
-
-
- - -Tgstation.Server.Host.Components.Compiler.IDreamMaker - -
- - - - - - - - - - - -

-Public Member Functions

 DreamMaker (IByondManager byond, IIOManager ioManager, StaticFiles.IConfiguration configuration, ISessionControllerFactory sessionControllerFactory, ICompileJobConsumer compileJobConsumer, IApplication application, IEventConsumer eventConsumer, IChat chat, IProcessExecutor processExecutor, IWatchdog watchdog, ILogger< DreamMaker > logger)
 Construct DreamMaker More...
 
async Task< Models.CompileJobCompile (Models.RevisionInformation revisionInformation, Api.Models.DreamMaker dreamMakerSettings, uint apiValidateTimeout, IRepository repository, Action< int > progressReporter, TimeSpan? estimatedDuration, CancellationToken cancellationToken)
 
- Public Member Functions inherited from Tgstation.Server.Host.Components.Compiler.IDreamMaker
Task< Models.CompileJobCompile (Models.RevisionInformation revisionInformation, Api.Models.DreamMaker dreamMakerSettings, uint apiValidateTimeout, IRepository repository, Action< int > progressReporter, TimeSpan? estimatedDuration, CancellationToken cancellationToken)
 Starts a compile More...
 
- - - - - - - - - - -

-Public Attributes

const string ADirectoryName = "A"
 Name of the primary directory used for compilation More...
 
const string BDirectoryName = "B"
 Name of the secondary directory used for compilation More...
 
const string DmbExtension = ".dmb"
 Extension for .dmbs More...
 
- - - - - - - - - - - - - - - - - - - -

-Private Member Functions

async Task VerifyApi (uint timeout, DreamDaemonSecurity securityLevel, Models.CompileJob job, IByondExecutableLock byondLock, ushort portToUse, CancellationToken cancellationToken)
 Run a quick DD instance to test the DMAPI is installed on the target code More...
 
async Task< int > RunDreamMaker (string dreamMakerPath, Models.CompileJob job, CancellationToken cancellationToken)
 Compiles a .dme with DreamMaker More...
 
async Task ModifyDme (Models.CompileJob job, CancellationToken cancellationToken)
 Adds server side includes to the .dme being compiled More...
 
async Task CleanupFailedCompile (Models.CompileJob job, bool cancelled, CancellationToken cancellationToken)
 Cleans up a failed compile job More...
 
async Task SendDeploymentMessage (Models.RevisionInformation revisionInformation, IByondExecutableLock byondLock, CancellationToken cancellationToken)
 Send a message to chat about a deployment More...
 
async Task RunCompileJob (Models.CompileJob job, Api.Models.DreamMaker dreamMakerSettings, IByondExecutableLock byondLock, IRepository repository, uint apiValidateTimeout, CancellationToken cancellationToken)
 Executes and populate a given job More...
 
- - - - -

-Static Private Member Functions

static async Task ProgressTask (Action< int > progressReporter, TimeSpan estimatedDuration, CancellationToken cancellationToken)
 Gradually triggers a given progressReporter over a given estimatedDuration More...
 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

-Private Attributes

const string DmeExtension = "dme"
 Extension for .dmes More...
 
readonly IByondManager byond
 The IByondManager for DreamMaker More...
 
readonly IIOManager ioManager
 The IIOManager for DreamMaker More...
 
readonly StaticFiles.IConfiguration configuration
 The StaticFiles.IConfiguration for DreamMaker More...
 
readonly ISessionControllerFactory sessionControllerFactory
 The ISessionControllerFactory for DreamMaker More...
 
readonly ICompileJobConsumer compileJobConsumer
 The ICompileJobConsumer for DreamMaker More...
 
readonly IApplication application
 The IApplication for DreamMaker More...
 
readonly IEventConsumer eventConsumer
 The IEventConsumer for DreamMaker More...
 
readonly IChat chat
 The IChat for DreamMaker More...
 
readonly IProcessExecutor processExecutor
 The IProcessExecutor for DreamMaker More...
 
readonly IWatchdog watchdog
 The IWatchdog for DreamMaker More...
 
readonly ILogger< DreamMakerlogger
 The ILogger for DreamMaker More...
 
bool compiling
 If a compile job is running More...
 
-

Detailed Description

-
-

Definition at line 21 of file DreamMaker.cs.

-

Constructor & Destructor Documentation

- -

◆ DreamMaker()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Tgstation.Server.Host.Components.Compiler.DreamMaker.DreamMaker (IByondManager byond,
IIOManager ioManager,
StaticFiles.IConfiguration configuration,
ISessionControllerFactory sessionControllerFactory,
ICompileJobConsumer compileJobConsumer,
IApplication application,
IEventConsumer eventConsumer,
IChat chat,
IProcessExecutor processExecutor,
IWatchdog watchdog,
ILogger< DreamMakerlogger 
)
-
- -

Construct DreamMaker

-
Parameters
- - - - - - - - - - - - -
byondThe value of byond
ioManagerThe value of ioManager
configurationThe value of configuration
sessionControllerFactoryThe value of sessionControllerFactory
compileJobConsumerThe value of compileJobConsumer
applicationThe value of application
eventConsumerThe value of eventConsumer
chatThe value of chat
processExecutorThe value of processExecutor
watchdogThe value of watchdog
loggerThe value of logger
-
-
- -

Definition at line 140 of file DreamMaker.cs.

-
141  {
142  this.byond = byond ?? throw new ArgumentNullException(nameof(byond));
143  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
144  this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
145  this.sessionControllerFactory = sessionControllerFactory ?? throw new ArgumentNullException(nameof(sessionControllerFactory));
146  this.compileJobConsumer = compileJobConsumer ?? throw new ArgumentNullException(nameof(compileJobConsumer));
147  this.application = application ?? throw new ArgumentNullException(nameof(application));
148  this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
149  this.chat = chat ?? throw new ArgumentNullException(nameof(chat));
150  this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor));
151  this.watchdog = watchdog ?? throw new ArgumentNullException(nameof(watchdog));
152  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
153  }
readonly ILogger< DreamMaker > logger
The ILogger for DreamMaker
Definition: DreamMaker.cs:96
-
readonly StaticFiles.IConfiguration configuration
The StaticFiles.IConfiguration for DreamMaker
Definition: DreamMaker.cs:56
-
readonly IProcessExecutor processExecutor
The IProcessExecutor for DreamMaker
Definition: DreamMaker.cs:86
-
readonly ISessionControllerFactory sessionControllerFactory
The ISessionControllerFactory for DreamMaker
Definition: DreamMaker.cs:61
-
readonly IEventConsumer eventConsumer
The IEventConsumer for DreamMaker
Definition: DreamMaker.cs:76
-
readonly IChat chat
The IChat for DreamMaker
Definition: DreamMaker.cs:81
-
readonly IWatchdog watchdog
The IWatchdog for DreamMaker
Definition: DreamMaker.cs:91
-
readonly ICompileJobConsumer compileJobConsumer
The ICompileJobConsumer for DreamMaker
Definition: DreamMaker.cs:66
-
readonly IIOManager ioManager
The IIOManager for DreamMaker
Definition: DreamMaker.cs:51
-
readonly IApplication application
The IApplication for DreamMaker
Definition: DreamMaker.cs:71
-
readonly IByondManager byond
The IByondManager for DreamMaker
Definition: DreamMaker.cs:46
-
-

References Tgstation.Server.Host.Components.Compiler.DreamMaker.application, Tgstation.Server.Host.Components.Compiler.DreamMaker.byond, Tgstation.Server.Host.Components.Compiler.DreamMaker.chat, Tgstation.Server.Host.Components.Compiler.DreamMaker.compileJobConsumer, Tgstation.Server.Host.Components.Compiler.DreamMaker.configuration, Tgstation.Server.Host.Components.Compiler.DreamMaker.eventConsumer, Tgstation.Server.Host.Components.Compiler.DreamMaker.ioManager, Tgstation.Server.Host.Components.Compiler.DreamMaker.logger, Tgstation.Server.Host.Components.Compiler.DreamMaker.processExecutor, Tgstation.Server.Host.Components.Compiler.DreamMaker.sessionControllerFactory, and Tgstation.Server.Host.Components.Compiler.DreamMaker.watchdog.

- -
-
-

Member Function Documentation

- -

◆ CleanupFailedCompile()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
async Task Tgstation.Server.Host.Components.Compiler.DreamMaker.CleanupFailedCompile (Models.CompileJob job,
bool cancelled,
CancellationToken cancellationToken 
)
-
-private
-
- -

Cleans up a failed compile job

-
Parameters
- - - - -
jobThe running Models.CompileJob
cancelledIf the job was cancelled
cancellationTokenThe CancellationToken for the operation
-
-
-
Returns
A Task representing the running operation
- -

Definition at line 312 of file DreamMaker.cs.

-
313  {
314  logger.LogTrace("Cleaning compile directory...");
315  var chatTask = chat.SendUpdateMessage(cancelled ? "Deploy cancelled!" : "Deploy failed!", cancellationToken);
316  var jobPath = job.DirectoryName.ToString();
317  try
318  {
319  await ioManager.DeleteDirectory(jobPath, CancellationToken.None).ConfigureAwait(false);
320  }
321  catch (Exception e)
322  {
323  logger.LogWarning("Error cleaning up compile directory {0}! Exception: {1}", ioManager.ResolvePath(jobPath), e);
324  }
325 
326  await chatTask.ConfigureAwait(false);
327  }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
-
readonly ILogger< DreamMaker > logger
The ILogger for DreamMaker
Definition: DreamMaker.cs:96
-
Task SendUpdateMessage(string message, CancellationToken cancellationToken)
Send a chat message to configured update channels
-
string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
-
readonly IChat chat
The IChat for DreamMaker
Definition: DreamMaker.cs:81
-
readonly IIOManager ioManager
The IIOManager for DreamMaker
Definition: DreamMaker.cs:51
-
-

References Tgstation.Server.Host.Components.Compiler.DreamMaker.chat, Tgstation.Server.Host.IO.IIOManager.DeleteDirectory(), Tgstation.Server.Host.Components.Compiler.DreamMaker.ioManager, Tgstation.Server.Host.Components.Compiler.DreamMaker.logger, Tgstation.Server.Host.IO.IIOManager.ResolvePath(), and Tgstation.Server.Host.Components.Chat.IChat.SendUpdateMessage().

- -

Referenced by Tgstation.Server.Host.Components.Compiler.DreamMaker.RunCompileJob().

- -
-
- -

◆ Compile()

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
async Task<Models.CompileJob> Tgstation.Server.Host.Components.Compiler.DreamMaker.Compile (Models.RevisionInformation revisionInformation,
Api.Models.DreamMaker dreamMakerSettings,
uint apiValidateTimeout,
IRepository repository,
Action< int > progressReporter,
TimeSpan? estimatedDuration,
CancellationToken cancellationToken 
)
-
- -

- -

Definition at line 461 of file DreamMaker.cs.

-
462  {
463  if (revisionInformation == null)
464  throw new ArgumentNullException(nameof(revisionInformation));
465 
466  if (dreamMakerSettings == null)
467  throw new ArgumentNullException(nameof(dreamMakerSettings));
468 
469  if (repository == null)
470  throw new ArgumentNullException(nameof(repository));
471 
472  if (progressReporter == null)
473  throw new ArgumentNullException(nameof(progressReporter));
474 
475  if (dreamMakerSettings.ApiValidationSecurityLevel == DreamDaemonSecurity.Ultrasafe)
476  throw new ArgumentOutOfRangeException(nameof(dreamMakerSettings), dreamMakerSettings, "Cannot compile with ultrasafe security!");
477 
478  logger.LogTrace("Begin Compile");
479 
480  lock (this)
481  {
482  if (compiling)
483  throw new JobException("There is already a compile job in progress!");
484  compiling = true;
485  }
486 
487  using (var progressCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
488  {
489  var progressTask = estimatedDuration.HasValue ? ProgressTask(progressReporter, estimatedDuration.Value, cancellationToken) : Task.CompletedTask;
490  try
491  {
492  using (var byondLock = await byond.UseExecutables(null, cancellationToken).ConfigureAwait(false))
493  {
494  await SendDeploymentMessage(revisionInformation, byondLock, cancellationToken).ConfigureAwait(false);
495 
496  var job = new Models.CompileJob
497  {
498  DirectoryName = Guid.NewGuid(),
499  DmeName = dreamMakerSettings.ProjectName,
500  RevisionInformation = revisionInformation,
501  ByondVersion = byondLock.Version.ToString()
502  };
503 
504  await RunCompileJob(job, dreamMakerSettings, byondLock, repository, apiValidateTimeout, cancellationToken).ConfigureAwait(false);
505 
506  return job;
507  }
508  }
509  catch (OperationCanceledException)
510  {
511  await eventConsumer.HandleEvent(EventType.CompileCancelled, null, default).ConfigureAwait(false);
512  throw;
513  }
514  finally
515  {
516  compiling = false;
517  progressCts.Cancel();
518  await progressTask.ConfigureAwait(false);
519  }
520  }
521  }
readonly ILogger< DreamMaker > logger
The ILogger for DreamMaker
Definition: DreamMaker.cs:96
-
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
-
async Task RunCompileJob(Models.CompileJob job, Api.Models.DreamMaker dreamMakerSettings, IByondExecutableLock byondLock, IRepository repository, uint apiValidateTimeout, CancellationToken cancellationToken)
Executes and populate a given job
Definition: DreamMaker.cs:370
-
bool compiling
If a compile job is running
Definition: DreamMaker.cs:101
-
readonly IEventConsumer eventConsumer
The IEventConsumer for DreamMaker
Definition: DreamMaker.cs:76
-
DreamDaemonSecurity
DreamDaemon's security level
-
static async Task ProgressTask(Action< int > progressReporter, TimeSpan estimatedDuration, CancellationToken cancellationToken)
Gradually triggers a given progressReporter over a given estimatedDuration
Definition: DreamMaker.cs:110
-
Task< IByondExecutableLock > UseExecutables(Version requiredVersion, CancellationToken cancellationToken)
Lock the current installation's location and return a IByondExecutableLock
-
Represents information about a current git revison
-
Task< bool > HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
Handle a given eventType
-
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
-
readonly IByondManager byond
The IByondManager for DreamMaker
Definition: DreamMaker.cs:46
-
async Task SendDeploymentMessage(Models.RevisionInformation revisionInformation, IByondExecutableLock byondLock, CancellationToken cancellationToken)
Send a message to chat about a deployment
Definition: DreamMaker.cs:336
-
-

References Tgstation.Server.Host.Components.Compiler.DreamMaker.byond, Tgstation.Server.Host.Components.Compiler.DreamMaker.compiling, Tgstation.Server.Host.Components.Compiler.DreamMaker.eventConsumer, Tgstation.Server.Host.Components.IEventConsumer.HandleEvent(), Tgstation.Server.Host.Components.Compiler.DreamMaker.logger, Tgstation.Server.Host.Components.Compiler.DreamMaker.ProgressTask(), Tgstation.Server.Host.Components.Compiler.DreamMaker.RunCompileJob(), Tgstation.Server.Host.Components.Compiler.DreamMaker.SendDeploymentMessage(), and Tgstation.Server.Host.Components.Byond.IByondManager.UseExecutables().

- -
-
- -

◆ ModifyDme()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - -
async Task Tgstation.Server.Host.Components.Compiler.DreamMaker.ModifyDme (Models.CompileJob job,
CancellationToken cancellationToken 
)
-
-private
-
- -

Adds server side includes to the .dme being compiled

-
Parameters
- - - -
jobThe Models.CompileJob for the operation
cancellationTokenThe CancellationToken for the operation
-
-
-
Returns
A Task representing the running operation
- -

Definition at line 257 of file DreamMaker.cs.

-
258  {
259  var dirA = ioManager.ConcatPath(job.DirectoryName.ToString(), ADirectoryName);
260  var dmeFileName = String.Join('.', job.DmeName, DmeExtension);
261  var dmePath = ioManager.ConcatPath(dirA, dmeFileName);
262  var dmeReadTask = ioManager.ReadAllBytes(dmePath, cancellationToken);
263 
264  var dmeModificationsTask = configuration.CopyDMFilesTo(dmeFileName, ioManager.ResolvePath(dirA), cancellationToken);
265 
266  var dmeBytes = await dmeReadTask.ConfigureAwait(false);
267  var dme = Encoding.UTF8.GetString(dmeBytes);
268 
269  var dmeModifications = await dmeModificationsTask.ConfigureAwait(false);
270 
271  if (dmeModifications == null || dmeModifications.TotalDmeOverwrite)
272  {
273  if (dmeModifications != null)
274  logger.LogDebug(".dme replacement configured!");
275  else
276  logger.LogTrace("No .dme modifications required.");
277  return;
278  }
279 
280  if (dmeModifications.HeadIncludeLine != null)
281  logger.LogDebug("Head .dme include line: {0}", dmeModifications.HeadIncludeLine);
282  if (dmeModifications.TailIncludeLine != null)
283  logger.LogDebug("Tail .dme include line: {0}", dmeModifications.TailIncludeLine);
284 
285  var dmeLines = new List<string>(dme.Split(new[] { Environment.NewLine }, StringSplitOptions.None));
286  for (var I = 0; I < dmeLines.Count; ++I)
287  {
288  var line = dmeLines[I];
289  if (line.Contains("BEGIN_INCLUDE", StringComparison.Ordinal) && dmeModifications.HeadIncludeLine != null)
290  {
291  dmeLines.Insert(I + 1, dmeModifications.HeadIncludeLine);
292  ++I;
293  }
294  else if (line.Contains("END_INCLUDE", StringComparison.Ordinal) && dmeModifications.TailIncludeLine != null)
295  {
296  dmeLines.Insert(I, dmeModifications.TailIncludeLine);
297  break;
298  }
299  }
300 
301  dmeBytes = Encoding.UTF8.GetBytes(String.Join(Environment.NewLine, dmeLines));
302  await ioManager.WriteAllBytes(dmePath, dmeBytes, cancellationToken).ConfigureAwait(false);
303  }
readonly ILogger< DreamMaker > logger
The ILogger for DreamMaker
Definition: DreamMaker.cs:96
-
Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content
-
readonly StaticFiles.IConfiguration configuration
The StaticFiles.IConfiguration for DreamMaker
Definition: DreamMaker.cs:56
-
string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
-
const string ADirectoryName
Name of the primary directory used for compilation
Definition: DreamMaker.cs:26
-
const string DmeExtension
Extension for .dmes
Definition: DreamMaker.cs:41
-
readonly IIOManager ioManager
The IIOManager for DreamMaker
Definition: DreamMaker.cs:51
-
Task< byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
Returns all the contents of a file at path as a byte array
-
string ConcatPath(params string[] paths)
Combines an array of strings into a path
-
-

References Tgstation.Server.Host.Components.Compiler.DreamMaker.ADirectoryName, Tgstation.Server.Host.IO.IIOManager.ConcatPath(), Tgstation.Server.Host.Components.Compiler.DreamMaker.configuration, Tgstation.Server.Host.Components.Compiler.DreamMaker.DmeExtension, Tgstation.Server.Host.Components.Compiler.DreamMaker.ioManager, Tgstation.Server.Host.Components.Compiler.DreamMaker.logger, Tgstation.Server.Host.IO.IIOManager.ReadAllBytes(), Tgstation.Server.Host.IO.IIOManager.ResolvePath(), and Tgstation.Server.Host.IO.IIOManager.WriteAllBytes().

- -

Referenced by Tgstation.Server.Host.Components.Compiler.DreamMaker.RunCompileJob().

- -
-
- -

◆ ProgressTask()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
static async Task Tgstation.Server.Host.Components.Compiler.DreamMaker.ProgressTask (Action< int > progressReporter,
TimeSpan estimatedDuration,
CancellationToken cancellationToken 
)
-
-staticprivate
-
- -

Gradually triggers a given progressReporter over a given estimatedDuration

-
Parameters
- - - - -
progressReporterThe Action<T1> to report progress
estimatedDurationA TimeSpan representing the duration to give progress over
cancellationTokenThe CancellationToken for the operation
-
-
-
Returns
A Task representing the running operation
- -

Definition at line 110 of file DreamMaker.cs.

-
111  {
112  progressReporter(0);
113  var sleepInterval = estimatedDuration / 100;
114 
115  try
116  {
117  for (var I = 0; I < 99; ++I)
118  {
119  await Task.Delay(sleepInterval, cancellationToken).ConfigureAwait(false);
120  progressReporter(I + 1);
121  }
122  }
123  catch (OperationCanceledException) { }
124  }
-

Referenced by Tgstation.Server.Host.Components.Compiler.DreamMaker.Compile().

- -
-
- -

◆ RunCompileJob()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
async Task Tgstation.Server.Host.Components.Compiler.DreamMaker.RunCompileJob (Models.CompileJob job,
Api.Models.DreamMaker dreamMakerSettings,
IByondExecutableLock byondLock,
IRepository repository,
uint apiValidateTimeout,
CancellationToken cancellationToken 
)
-
-private
-
- -

Executes and populate a given job

-
Parameters
- - - - - - - -
jobThe Models.CompileJob to run and populate
dreamMakerSettingsThe Api.Models.DreamMaker settings to use
byondLockThe IByondExecutableLock to use
repositoryThe IRepository to use
apiValidateTimeoutThe timeout for validating the DMAPI
cancellationTokenThe CancellationToken for the operation
-
-
-
Returns
A Task representing the running operation
- -

Definition at line 370 of file DreamMaker.cs.

-
371  {
372  var jobPath = job.DirectoryName.ToString();
373  logger.LogTrace("Compile output GUID: {0}", jobPath);
374 
375  try
376  {
377  var dirA = ioManager.ConcatPath(jobPath, ADirectoryName);
378  var dirB = ioManager.ConcatPath(jobPath, BDirectoryName);
379 
380  // copy the repository
381  logger.LogTrace("Copying repository to game directory...");
382  var resolvedADirectory = ioManager.ResolvePath(dirA);
383  var repoOrigin = repository.Origin;
384  using (repository)
385  await repository.CopyTo(resolvedADirectory, cancellationToken).ConfigureAwait(false);
386 
387  // repository closed now
388 
389  // run precompile scripts
390  await eventConsumer.HandleEvent(EventType.CompileStart, new List<string> { resolvedADirectory, repoOrigin }, cancellationToken).ConfigureAwait(false);
391 
392  // determine the dme
393  if (job.DmeName == null)
394  {
395  logger.LogTrace("Searching for available .dmes...");
396  var foundPaths = await ioManager.GetFilesWithExtension(dirA, DmeExtension, cancellationToken).ConfigureAwait(false);
397  var foundPath = foundPaths.FirstOrDefault();
398  if (foundPath == default)
399  throw new JobException("Unable to find any .dme!");
400  var dmeWithExtension = ioManager.GetFileName(foundPath);
401  job.DmeName = dmeWithExtension.Substring(0, dmeWithExtension.Length - DmeExtension.Length - 1);
402  }
403  else
404  {
405  var targetDme = ioManager.ConcatPath(dirA, String.Join('.', job.DmeName, DmeExtension));
406  var targetDmeExists = await ioManager.FileExists(targetDme, cancellationToken).ConfigureAwait(false);
407  if (!targetDmeExists)
408  throw new JobException("Unable to locate specified .dme!");
409  }
410 
411  logger.LogDebug("Selected {0}.dme for compilation!", job.DmeName);
412 
413  await ModifyDme(job, cancellationToken).ConfigureAwait(false);
414 
415  // run compiler
416  var exitCode = await RunDreamMaker(byondLock.DreamMakerPath, job, cancellationToken).ConfigureAwait(false);
417 
418  // verify api
419  try
420  {
421  if (exitCode != 0)
422  throw new JobException(String.Format(CultureInfo.InvariantCulture, "DM exited with a non-zero code: {0}{1}{2}", exitCode, Environment.NewLine, job.Output));
423 
424  await VerifyApi(apiValidateTimeout, dreamMakerSettings.ApiValidationSecurityLevel.Value, job, byondLock, dreamMakerSettings.ApiValidationPort.Value, cancellationToken).ConfigureAwait(false);
425  }
426  catch (JobException)
427  {
428  // DD never validated or compile failed
429  await eventConsumer.HandleEvent(EventType.CompileFailure, new List<string> { resolvedADirectory, exitCode == 0 ? "1" : "0" }, cancellationToken).ConfigureAwait(false);
430  throw;
431  }
432 
433  logger.LogTrace("Running post compile event...");
434  await eventConsumer.HandleEvent(EventType.CompileComplete, new List<string> { resolvedADirectory }, cancellationToken).ConfigureAwait(false);
435 
436  logger.LogTrace("Duplicating compiled game...");
437 
438  // duplicate the dmb et al
439  await ioManager.CopyDirectory(dirA, dirB, null, cancellationToken).ConfigureAwait(false);
440 
441  logger.LogTrace("Applying static game file symlinks...");
442 
443  // symlink in the static data
444  var symATask = configuration.SymlinkStaticFilesTo(resolvedADirectory, cancellationToken);
445  var symBTask = configuration.SymlinkStaticFilesTo(ioManager.ResolvePath(dirB), cancellationToken);
446 
447  await Task.WhenAll(symATask, symBTask).ConfigureAwait(false);
448 
449  await chat.SendUpdateMessage(String.Format(CultureInfo.InvariantCulture, "Deployment complete!{0}", watchdog.Running ? " Changes will be applied on next server reboot." : String.Empty), cancellationToken).ConfigureAwait(false);
450 
451  logger.LogDebug("Compile complete!");
452  }
453  catch (Exception e)
454  {
455  await CleanupFailedCompile(job, e is OperationCanceledException, cancellationToken).ConfigureAwait(false);
456  throw;
457  }
458  }
Task< List< string > > GetFilesWithExtension(string path, string extension, CancellationToken cancellationToken)
Gets a list of files in path with the given extension
-
readonly ILogger< DreamMaker > logger
The ILogger for DreamMaker
Definition: DreamMaker.cs:96
-
readonly StaticFiles.IConfiguration configuration
The StaticFiles.IConfiguration for DreamMaker
Definition: DreamMaker.cs:56
-
Task CopyDirectory(string src, string dest, IEnumerable< string > ignore, CancellationToken cancellationToken)
Copies a directory from src to dest
-
Task SendUpdateMessage(string message, CancellationToken cancellationToken)
Send a chat message to configured update channels
-
const string BDirectoryName
Name of the secondary directory used for compilation
Definition: DreamMaker.cs:31
-
async Task CleanupFailedCompile(Models.CompileJob job, bool cancelled, CancellationToken cancellationToken)
Cleans up a failed compile job
Definition: DreamMaker.cs:312
-
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
-
string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
-
const string ADirectoryName
Name of the primary directory used for compilation
Definition: DreamMaker.cs:26
-
readonly IEventConsumer eventConsumer
The IEventConsumer for DreamMaker
Definition: DreamMaker.cs:76
-
string GetFileName(string path)
Gets the file name portion of a path
-
Task< bool > FileExists(string path, CancellationToken cancellationToken)
Check that the file at path exists
-
async Task VerifyApi(uint timeout, DreamDaemonSecurity securityLevel, Models.CompileJob job, IByondExecutableLock byondLock, ushort portToUse, CancellationToken cancellationToken)
Run a quick DD instance to test the DMAPI is installed on the target code
Definition: DreamMaker.cs:165
-
string Origin
The current origin remote the IRepository is using
Definition: IRepository.cs:46
-
string DreamMakerPath
The path to the dm/DreamMaker executable
-
async Task ModifyDme(Models.CompileJob job, CancellationToken cancellationToken)
Adds server side includes to the .dme being compiled
Definition: DreamMaker.cs:257
-
readonly IChat chat
The IChat for DreamMaker
Definition: DreamMaker.cs:81
-
readonly IWatchdog watchdog
The IWatchdog for DreamMaker
Definition: DreamMaker.cs:91
-
Task CopyTo(string path, CancellationToken cancellationToken)
Copies the current working directory to a given path
-
const string DmeExtension
Extension for .dmes
Definition: DreamMaker.cs:41
-
bool Running
If the watchdog is running
Definition: IWatchdog.cs:17
-
readonly IIOManager ioManager
The IIOManager for DreamMaker
Definition: DreamMaker.cs:51
-
Task< bool > HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
Handle a given eventType
-
async Task< int > RunDreamMaker(string dreamMakerPath, Models.CompileJob job, CancellationToken cancellationToken)
Compiles a .dme with DreamMaker
Definition: DreamMaker.cs:235
-
string ConcatPath(params string[] paths)
Combines an array of strings into a path
-
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
-
-

References Tgstation.Server.Host.Components.Compiler.DreamMaker.ADirectoryName, Tgstation.Server.Host.Components.Compiler.DreamMaker.BDirectoryName, Tgstation.Server.Host.Components.Compiler.DreamMaker.chat, Tgstation.Server.Host.Components.Compiler.DreamMaker.CleanupFailedCompile(), Tgstation.Server.Host.IO.IIOManager.ConcatPath(), Tgstation.Server.Host.Components.Compiler.DreamMaker.configuration, Tgstation.Server.Host.IO.IIOManager.CopyDirectory(), Tgstation.Server.Host.Components.Repository.IRepository.CopyTo(), Tgstation.Server.Host.Components.Compiler.DreamMaker.DmeExtension, Tgstation.Server.Host.Components.Byond.IByondExecutableLock.DreamMakerPath, Tgstation.Server.Host.Components.Compiler.DreamMaker.eventConsumer, Tgstation.Server.Host.IO.IIOManager.FileExists(), Tgstation.Server.Host.IO.IIOManager.GetFileName(), Tgstation.Server.Host.IO.IIOManager.GetFilesWithExtension(), Tgstation.Server.Host.Components.IEventConsumer.HandleEvent(), Tgstation.Server.Host.Components.Compiler.DreamMaker.ioManager, Tgstation.Server.Host.Components.Compiler.DreamMaker.logger, Tgstation.Server.Host.Components.Compiler.DreamMaker.ModifyDme(), Tgstation.Server.Host.Components.Repository.IRepository.Origin, Tgstation.Server.Host.IO.IIOManager.ResolvePath(), Tgstation.Server.Host.Components.Compiler.DreamMaker.RunDreamMaker(), Tgstation.Server.Host.Components.Watchdog.IWatchdog.Running, Tgstation.Server.Host.Components.Chat.IChat.SendUpdateMessage(), Tgstation.Server.Host.Components.Compiler.DreamMaker.VerifyApi(), and Tgstation.Server.Host.Components.Compiler.DreamMaker.watchdog.

- -

Referenced by Tgstation.Server.Host.Components.Compiler.DreamMaker.Compile().

- -
-
- -

◆ RunDreamMaker()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
async Task<int> Tgstation.Server.Host.Components.Compiler.DreamMaker.RunDreamMaker (string dreamMakerPath,
Models.CompileJob job,
CancellationToken cancellationToken 
)
-
-private
-
- -

Compiles a .dme with DreamMaker

-
Parameters
- - - - -
dreamMakerPathThe path to the DreamMaker executable
jobThe Models.CompileJob for the operation
cancellationTokenThe CancellationToken for the operation
-
-
-
Returns
A Task representing the running operation
- -

Definition at line 235 of file DreamMaker.cs.

-
236  {
237  using (var dm = processExecutor.LaunchProcess(dreamMakerPath, ioManager.ResolvePath(ioManager.ConcatPath(job.DirectoryName.ToString(), ADirectoryName)), String.Format(CultureInfo.InvariantCulture, "-clean {0}.{1}", job.DmeName, DmeExtension), true, true))
238  {
239  int exitCode;
240  using (cancellationToken.Register(() => dm.Terminate()))
241  exitCode = await dm.Lifetime.ConfigureAwait(false);
242  cancellationToken.ThrowIfCancellationRequested();
243 
244  logger.LogDebug("DreamMaker exit code: {0}", exitCode);
245  job.Output = dm.GetCombinedOutput();
246  logger.LogTrace("DreamMaker output: {0}{1}", Environment.NewLine, job.Output);
247  return exitCode;
248  }
249  }
readonly ILogger< DreamMaker > logger
The ILogger for DreamMaker
Definition: DreamMaker.cs:96
-
string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
-
readonly IProcessExecutor processExecutor
The IProcessExecutor for DreamMaker
Definition: DreamMaker.cs:86
-
const string ADirectoryName
Name of the primary directory used for compilation
Definition: DreamMaker.cs:26
-
IProcess LaunchProcess(string fileName, string workingDirectory, string arguments=null, bool readOutput=false, bool readError=false, bool noShellExecute=false)
Launch a IProcess
-
const string DmeExtension
Extension for .dmes
Definition: DreamMaker.cs:41
-
readonly IIOManager ioManager
The IIOManager for DreamMaker
Definition: DreamMaker.cs:51
-
string ConcatPath(params string[] paths)
Combines an array of strings into a path
-
-

References Tgstation.Server.Host.Components.Compiler.DreamMaker.ADirectoryName, Tgstation.Server.Host.IO.IIOManager.ConcatPath(), Tgstation.Server.Host.Components.Compiler.DreamMaker.DmeExtension, Tgstation.Server.Host.Components.Compiler.DreamMaker.ioManager, Tgstation.Server.Host.Core.IProcessExecutor.LaunchProcess(), Tgstation.Server.Host.Components.Compiler.DreamMaker.logger, Tgstation.Server.Host.Components.Compiler.DreamMaker.processExecutor, and Tgstation.Server.Host.IO.IIOManager.ResolvePath().

- -

Referenced by Tgstation.Server.Host.Components.Compiler.DreamMaker.RunCompileJob().

- -
-
- -

◆ SendDeploymentMessage()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - -
async Task Tgstation.Server.Host.Components.Compiler.DreamMaker.SendDeploymentMessage (Models.RevisionInformation revisionInformation,
IByondExecutableLock byondLock,
CancellationToken cancellationToken 
)
-
-private
-
- -

Send a message to chat about a deployment

-
Parameters
- - - - -
revisionInformationThe Models.RevisionInformation for the deployment
byondLockThe IByondExecutableLock for the deployment
cancellationTokenThe CancellationToken for the operation
-
-
-
Returns
A Task representing the running operation
- -

Definition at line 336 of file DreamMaker.cs.

-
337  {
338  var commitInsert = revisionInformation.CommitSha.Substring(0, 7);
339  string remoteCommitInsert;
340  if (revisionInformation.CommitSha == revisionInformation.OriginCommitSha)
341  {
342  commitInsert = String.Format(CultureInfo.InvariantCulture, "^{0}", commitInsert);
343  remoteCommitInsert = String.Empty;
344  }
345  else
346  remoteCommitInsert = String.Format(CultureInfo.InvariantCulture, ". Remote commit: ^{0}", revisionInformation.OriginCommitSha.Substring(0, 7));
347 
348  var testmergeInsert = revisionInformation.ActiveTestMerges.Count == 0 ? String.Empty : String.Format(CultureInfo.InvariantCulture, " (Test Merges: {0})",
349  String.Join(", ", revisionInformation.ActiveTestMerges.Select(x => x.TestMerge).Select(x =>
350  {
351  var result = String.Format(CultureInfo.InvariantCulture, "#{0} at {1}", x.Number, x.PullRequestRevision.Substring(0, 7));
352  if (x.Comment != null)
353  result += String.Format(CultureInfo.InvariantCulture, " ({0})", x.Comment);
354  return result;
355  })));
356 
357  await chat.SendUpdateMessage(String.Format(CultureInfo.InvariantCulture, "Deploying revision: {0}{1}{2} BYOND Version: {3}", commitInsert, testmergeInsert, remoteCommitInsert, byondLock.Version), cancellationToken).ConfigureAwait(false);
358  }
Task SendUpdateMessage(string message, CancellationToken cancellationToken)
Send a chat message to configured update channels
-
readonly IChat chat
The IChat for DreamMaker
Definition: DreamMaker.cs:81
-
Version Version
The System.Version of the locked executables
-
-

References Tgstation.Server.Host.Components.Compiler.DreamMaker.chat, Tgstation.Server.Host.Components.Chat.IChat.SendUpdateMessage(), and Tgstation.Server.Host.Components.Byond.IByondExecutableLock.Version.

- -

Referenced by Tgstation.Server.Host.Components.Compiler.DreamMaker.Compile().

- -
-
- -

◆ VerifyApi()

- -
-
- - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
async Task Tgstation.Server.Host.Components.Compiler.DreamMaker.VerifyApi (uint timeout,
DreamDaemonSecurity securityLevel,
Models.CompileJob job,
IByondExecutableLock byondLock,
ushort portToUse,
CancellationToken cancellationToken 
)
-
-private
-
- -

Run a quick DD instance to test the DMAPI is installed on the target code

-
Parameters
- - - - - - - -
timeoutThe timeout in seconds for validation
securityLevelThe DreamDaemonSecurity level to use to validate the API
jobThe Models.CompileJob for the operation
byondLockThe current IByondExecutableLock
portToUseThe port to use for API validation
cancellationTokenThe CancellationToken for the operation
-
-
-
Returns
A Task representing the running operation
- -

Definition at line 165 of file DreamMaker.cs.

-
166  {
167  logger.LogTrace("Verifying DMAPI...");
168  var launchParameters = new DreamDaemonLaunchParameters
169  {
170  AllowWebClient = false,
171  PrimaryPort = portToUse,
172  SecurityLevel = securityLevel,
173  StartupTimeout = timeout
174  };
175 
176  var dirA = ioManager.ConcatPath(job.DirectoryName.ToString(), ADirectoryName);
177 
178  job.MinimumSecurityLevel = securityLevel; // needed for the TempDmbProvider
179  var timeoutAt = DateTimeOffset.Now.AddSeconds(timeout);
180 
181  using (var provider = new TemporaryDmbProvider(ioManager.ResolvePath(dirA), String.Concat(job.DmeName, DmbExtension), job))
182  using (var controller = await sessionControllerFactory.LaunchNew(launchParameters, provider, byondLock, true, true, true, cancellationToken).ConfigureAwait(false))
183  {
184  var launchResult = await controller.LaunchResult.ConfigureAwait(false);
185 
186  var now = DateTimeOffset.Now;
187  if (now < timeoutAt && launchResult.StartupTime.HasValue)
188  {
189  var timeoutTask = Task.Delay(timeoutAt - now, cancellationToken);
190 
191  await Task.WhenAny(controller.Lifetime, timeoutTask).ConfigureAwait(false);
192  cancellationToken.ThrowIfCancellationRequested();
193  }
194 
195  if (controller.Lifetime.IsCompleted)
196  {
197  var validationStatus = controller.ApiValidationStatus;
198  logger.LogTrace("API validation status: {0}", validationStatus);
199  switch (validationStatus)
200  {
201  case ApiValidationStatus.RequiresUltrasafe:
202  job.MinimumSecurityLevel = DreamDaemonSecurity.Ultrasafe;
203  return;
204  case ApiValidationStatus.RequiresSafe:
205  if (securityLevel == DreamDaemonSecurity.Ultrasafe)
206  throw new JobException("This game must be run with at least the 'Safe' DreamDaemon security level!");
207  job.MinimumSecurityLevel = DreamDaemonSecurity.Safe;
208  return;
209  case ApiValidationStatus.RequiresTrusted:
210  if (securityLevel != DreamDaemonSecurity.Trusted)
211  throw new JobException("This game must be run with at least the 'Trusted' DreamDaemon security level!");
212  job.MinimumSecurityLevel = DreamDaemonSecurity.Trusted;
213  return;
214  case ApiValidationStatus.NeverValidated:
215  break;
216  case ApiValidationStatus.BadValidationRequest:
217  throw new JobException("Recieved an unrecognized API validation request from DreamDaemon!");
218  case ApiValidationStatus.UnaskedValidationRequest:
219  default:
220  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Session controller returned unexpected ApiValidationStatus: {0}", validationStatus));
221  }
222  }
223 
224  throw new JobException("DMAPI validation timed out!");
225  }
226  }
readonly ILogger< DreamMaker > logger
The ILogger for DreamMaker
Definition: DreamMaker.cs:96
- -
string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
-
const string ADirectoryName
Name of the primary directory used for compilation
Definition: DreamMaker.cs:26
-
readonly ISessionControllerFactory sessionControllerFactory
The ISessionControllerFactory for DreamMaker
Definition: DreamMaker.cs:61
-
Task< ISessionController > LaunchNew(DreamDaemonLaunchParameters launchParameters, IDmbProvider dmbProvider, IByondExecutableLock currentByondLock, bool primaryPort, bool primaryDirectory, bool apiValidate, CancellationToken cancellationToken)
Create a ISessionController from a freshly launch DreamDaemon instance
-
const string DmbExtension
Extension for .dmbs
Definition: DreamMaker.cs:36
-
DreamDaemonSecurity
DreamDaemon's security level
-
readonly IIOManager ioManager
The IIOManager for DreamMaker
Definition: DreamMaker.cs:51
-
string ConcatPath(params string[] paths)
Combines an array of strings into a path
-
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
-
ApiValidationStatus
Status of DMAPI validation
-
-

References Tgstation.Server.Host.Components.Compiler.DreamMaker.ADirectoryName, Tgstation.Server.Host.IO.IIOManager.ConcatPath(), Tgstation.Server.Host.Components.Compiler.DreamMaker.DmbExtension, Tgstation.Server.Host.Components.Compiler.DreamMaker.ioManager, Tgstation.Server.Host.Components.Watchdog.ISessionControllerFactory.LaunchNew(), Tgstation.Server.Host.Components.Compiler.DreamMaker.logger, Tgstation.Server.Host.IO.IIOManager.ResolvePath(), and Tgstation.Server.Host.Components.Compiler.DreamMaker.sessionControllerFactory.

- -

Referenced by Tgstation.Server.Host.Components.Compiler.DreamMaker.RunCompileJob().

- -
-
-

Member Data Documentation

- -

◆ ADirectoryName

- -
-
- - - - -
const string Tgstation.Server.Host.Components.Compiler.DreamMaker.ADirectoryName = "A"
-
-
- -

◆ application

- -
-
- - - - - -
- - - - -
readonly IApplication Tgstation.Server.Host.Components.Compiler.DreamMaker.application
-
-private
-
- -

The IApplication for DreamMaker

- -

Definition at line 71 of file DreamMaker.cs.

- -

Referenced by Tgstation.Server.Host.Components.Compiler.DreamMaker.DreamMaker().

- -
-
- -

◆ BDirectoryName

- -
-
- - - - -
const string Tgstation.Server.Host.Components.Compiler.DreamMaker.BDirectoryName = "B"
-
- -

Name of the secondary directory used for compilation

- -

Definition at line 31 of file DreamMaker.cs.

- -

Referenced by Tgstation.Server.Host.Components.Compiler.DreamMaker.RunCompileJob().

- -
-
- -

◆ byond

- -
-
- - - - - -
- - - - -
readonly IByondManager Tgstation.Server.Host.Components.Compiler.DreamMaker.byond
-
-private
-
-
- -

◆ chat

- - - -

◆ compileJobConsumer

- -
-
- - - - - -
- - - - -
readonly ICompileJobConsumer Tgstation.Server.Host.Components.Compiler.DreamMaker.compileJobConsumer
-
-private
-
-
- -

◆ compiling

- -
-
- - - - - -
- - - - -
bool Tgstation.Server.Host.Components.Compiler.DreamMaker.compiling
-
-private
-
- -

If a compile job is running

- -

Definition at line 101 of file DreamMaker.cs.

- -

Referenced by Tgstation.Server.Host.Components.Compiler.DreamMaker.Compile().

- -
-
- -

◆ configuration

- -
-
- - - - - -
- - - - -
readonly StaticFiles.IConfiguration Tgstation.Server.Host.Components.Compiler.DreamMaker.configuration
-
-private
-
-
- -

◆ DmbExtension

- -
-
- - - - -
const string Tgstation.Server.Host.Components.Compiler.DreamMaker.DmbExtension = ".dmb"
-
- -

Extension for .dmbs

- -

Definition at line 36 of file DreamMaker.cs.

- -

Referenced by Tgstation.Server.Host.Components.Compiler.DreamMaker.VerifyApi().

- -
-
- -

◆ DmeExtension

- -
-
- - - - - -
- - - - -
const string Tgstation.Server.Host.Components.Compiler.DreamMaker.DmeExtension = "dme"
-
-private
-
-
- -

◆ eventConsumer

- -
-
- - - - - -
- - - - -
readonly IEventConsumer Tgstation.Server.Host.Components.Compiler.DreamMaker.eventConsumer
-
-private
-
-
- -

◆ ioManager

- - - -

◆ logger

- - - -

◆ processExecutor

- -
-
- - - - - -
- - - - -
readonly IProcessExecutor Tgstation.Server.Host.Components.Compiler.DreamMaker.processExecutor
-
-private
-
-
- -

◆ sessionControllerFactory

- -
-
- - - - - -
- - - - -
readonly ISessionControllerFactory Tgstation.Server.Host.Components.Compiler.DreamMaker.sessionControllerFactory
-
-private
-
-
- -

◆ watchdog

- -
-
- - - - - -
- - - - -
readonly IWatchdog Tgstation.Server.Host.Components.Compiler.DreamMaker.watchdog
-
-private
-
-
-
The documentation for this class was generated from the following file: -
- - - - diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dream_maker.png b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dream_maker.png deleted file mode 100644 index 2d643a4f2ae6ee837bc95f0e84556ba89f29da7c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1255 zcmeAS@N?(olHy`uVBq!ia0y~yUVDskmyx7^{PH z&-beYSAG4M|6;Z5Wfjk;mzFs)cV2zx^(;y)`E}_+mGbt0y3X16-z@B}e&NRR&1%t2qiYch5g^d&j%B=JUo^R^2IHi?f^xwryXS6%i_Ay-M%;?CJ-z#5UfVUNQew ziB0#E63^0axqFJAGwlD(b*<#8%fmNsSHz_?G`9J2w7vRtx8$WWWSI!J{Ta_NQ?tDz` zzv%3VPoBtm|GzVP*+WZ<4yyMl>9gD7QF^;P zS6F^1kENW1Cd|^8Qi{QPouS{O{};I%&~VAUg`q;9mud z-<6Lo`Yag#DF0&cU}Vu+$;9&dvGPWyBVZPz=|-j&AnS)lgiBy8GIrZ)7w4eA_t%f@$L#%?B4CM)ab1sJyi`ycx<38&_44gG&TDT~ z^A-Be%X+)w+TWj7RnKjF9#xkbZ7n;8IWcp^wQc)qdnLkF7F%7twbf|bf~u+v?$)?7 z4CM{HGv+4EeL2rx?e5Dhs`J=y&fU3cZ|aLv+mEvCVr|~rm(dm@uzp3E{O?)HN#eo| zGgDXV73WX;U~tX*U7gtUqWp}fv-x|!UgHfFuHU@THuUhSNjCy*-)^_QIBmOccf?!o zJ^rOu^IW}lE!p+?Z1ubCaR+Cuo24;lBloK5k_ihEg_{=csW2{HpCxtdSEbG|)Hm00hBk;C_&zm+5tzad`0D~lgmzx84`Fnh VbFDS*2(VOQ@O1TaS?83{1OTc{Q;h%s diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_temporary_dmb_provider.png b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_temporary_dmb_provider.png deleted file mode 100644 index d8443bd5e86130427fac934b90a249cd1a2a4a06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1669 zcmcJQdoYx19LL{9c9D=>y}&RSbLmqOLbbDBAc$O)-ADG&gQOI z%4Eqp72^`2a@m#3y0%D*Toywr_w#BdbLRZtGxL3ZpWn>ynR)*BJoCi3x!TLiZkGiB zKpt`+cmMz*0p@6wB)qRCx>Uero13%Ok+roo7(Y$UUt+vkpZK2Y>gr7~?{(l772@IQ z3BW_^OVH?L3INh75aF=bWrR5611o2bqI4`Hcw|LqLEoJ&ZSFrb88Y%^uZ5D=+1=+> znZf+SeC!ep1BHWOJLwKgJ$y8X)%^iO!E`pMY>ia3Yb;?t#f;&|RJU<@Yh|>hZtncxDn4{sB&3iN9b8MsXi7g8%>NznjTnAj`}4UTv5asHenW6 z+=7JM!_4KmGW;T^xZU3}9>k8$(Yxn#`HIk@YVZ4Yc7d^zv2E_`x8r6#qZDR~k}f2v z^LHFLW{4&*wUqE+gObi(0&`Vuqul^2G``xT%&`&wVQC{yRT9A*x~j|W#_cy!XD~Dd7JV6aigzic8k8q z3r(i7+CEv$f}MmWI&>-M_^JvXVJ87aq<95yNts@d?77dIEm|_W2~M( zpY_7MF{VI^TYi%v8g!}c60}*nEep|5J5-E9HBS+iCBe&V#YX#L>dAyQgEgzMTiSV|6G)_vDevDZ-bkl^~*T59f6m{VTQE8952insWp^JncQ0L;n$0D(#lM*!B8udfK z;B7^T!Kk95eG-F_>y*ZTDFUWD?+}C0aQ&&V)dO>rZY6olB4l;~Glx)!zX<=0l1KdI z2P~gTUtWEj38LBi4WgF|%O#cEhP>Y08lv0YAenyZ8kM6R;*$wHHOG;+e(GljES05v z_p3Uo;gnXWdF6s#<~DoE{Uw2$G}`LX*Vyvjr~z?H+v2ySQrxw{-11?ic5+0LW-j$f z)#hTG@_0Y{!1L#6AFa&Ak2@%oOS8z^MdDh*3k~Pjz2ncO^&=NdiRcMYFFu=KgQ2)O(RxR*7P;ZD+{j&ojKNN>YEqlEbN>RCz~ia z=miMC@eK6j0e;l`r4&);O1yrtd}0>=h0sMvK=*K`VrJ*3>#W7s_OOW~+~}+L=5F4U z*}8p{iFNx7u%F!=)JZZGX_FLQsuj-zJR7^o(qYZ zoE}NUv2hn%$@Cp&tx^G46S8++P&zsotzWuecav+Lm?q3G&f@Z^pYe^`v-*`yahiGf zUVx{;)njL_4DY*QPT|PxOEM>x_=)os9#nZMWQk|Yv@M$2EEpFs?x__e1FftfXNsjL zqvpj_c|gw&)fI0`ozU?1S!Fqk$pmf* ypfyN*%fNJC{18&W%l|t7`|4=8$uL)RYYk}3&UUM)LHomh1^^v#B^2UM-1--% + + + + + + +tgstation-server: Member List + + + + + + + + + +
+
+ + + + + + + +
+
tgstation-server +
+
The /tg/station 13 server suite
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
Tgstation.Server.Host.Components.Deployment.DmbFactory Member List
+
+
+ +

This is the complete list of members for Tgstation.Server.Host.Components.Deployment.DmbFactory, including all inherited members.

+ + + + + + + + + + + + + + + + + + + + + +
CleanJob(CompileJob job)Tgstation.Server.Host.Components.Deployment.DmbFactoryprivate
CleanUnusedCompileJobs(CompileJob exceptThisOne, CancellationToken cancellationToken)Tgstation.Server.Host.Components.Deployment.DmbFactory
cleanupCtsTgstation.Server.Host.Components.Deployment.DmbFactoryprivate
cleanupTaskTgstation.Server.Host.Components.Deployment.DmbFactoryprivate
databaseContextFactoryTgstation.Server.Host.Components.Deployment.DmbFactoryprivate
Dispose()Tgstation.Server.Host.Components.Deployment.DmbFactory
DmbAvailableTgstation.Server.Host.Components.Deployment.DmbFactory
DmbFactory(IDatabaseContextFactory databaseContextFactory, IIOManager ioManager, ILogger< DmbFactory > logger, Api.Models.Instance instance)Tgstation.Server.Host.Components.Deployment.DmbFactory
FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken)Tgstation.Server.Host.Components.Deployment.DmbFactory
instanceTgstation.Server.Host.Components.Deployment.DmbFactoryprivate
ioManagerTgstation.Server.Host.Components.Deployment.DmbFactoryprivate
jobLockCountsTgstation.Server.Host.Components.Deployment.DmbFactoryprivate
LoadCompileJob(CompileJob job, CancellationToken cancellationToken)Tgstation.Server.Host.Components.Deployment.DmbFactory
LockNextDmb(int lockCount)Tgstation.Server.Host.Components.Deployment.DmbFactory
loggerTgstation.Server.Host.Components.Deployment.DmbFactoryprivate
newerDmbTcsTgstation.Server.Host.Components.Deployment.DmbFactoryprivate
nextDmbProviderTgstation.Server.Host.Components.Deployment.DmbFactoryprivate
OnNewerDmbTgstation.Server.Host.Components.Deployment.DmbFactory
StartAsync(CancellationToken cancellationToken)Tgstation.Server.Host.Components.Deployment.DmbFactory
StopAsync(CancellationToken cancellationToken)Tgstation.Server.Host.Components.Deployment.DmbFactory
+ + + + diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_dmb_factory.html b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_dmb_factory.html new file mode 100644 index 0000000000..246c70bfed --- /dev/null +++ b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_dmb_factory.html @@ -0,0 +1,836 @@ + + + + + + + +tgstation-server: Tgstation.Server.Host.Components.Deployment.DmbFactory Class Reference + + + + + + + + + +
+
+ + + + + + + +
+
tgstation-server +
+
The /tg/station 13 server suite
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+ +
+
Tgstation.Server.Host.Components.Deployment.DmbFactory Class Reference
+
+
+ +

Standard IDmbFactory + More...

+
+Inheritance diagram for Tgstation.Server.Host.Components.Deployment.DmbFactory:
+
+
+ + +Tgstation.Server.Host.Components.Deployment.IDmbFactory +Tgstation.Server.Host.Components.Deployment.ICompileJobConsumer +IHostedService +IDisposable + +
+ + + + + + + + + + + + + + + + + + + + + + + +

+Public Member Functions

 DmbFactory (IDatabaseContextFactory databaseContextFactory, IIOManager ioManager, ILogger< DmbFactory > logger, Api.Models.Instance instance)
 Construct a DmbFactory More...
 
void Dispose ()
 
async Task LoadCompileJob (CompileJob job, CancellationToken cancellationToken)
 Load a new job into the ICompileJobConsumer More...
 
IDmbProvider LockNextDmb (int lockCount)
 Gets the next IDmbProvider More...
 
Task StartAsync (CancellationToken cancellationToken)
 
async Task StopAsync (CancellationToken cancellationToken)
 
async Task< IDmbProviderFromCompileJob (CompileJob compileJob, CancellationToken cancellationToken)
 Gets a IDmbProvider for a given CompileJob More...
 
async Task CleanUnusedCompileJobs (CompileJob exceptThisOne, CancellationToken cancellationToken)
 Deletes all compile jobs that are inactive in the Game folder exceptThisOne More...
 
+ + + +

+Public Attributes

bool DmbAvailable => nextDmbProvider != null
 
+ + + + + + + + + + +

+Properties

Task OnNewerDmb [get]
 
- Properties inherited from Tgstation.Server.Host.Components.Deployment.IDmbFactory
Task OnNewerDmb [get]
 Get a Task that completes when the result of a call to LockNextDmb will be different than the previous call if any More...
 
bool DmbAvailable [get]
 If LockNextDmb will succeed More...
 
+ + + + +

+Private Member Functions

void CleanJob (CompileJob job)
 Delete the Api.Models.Internal.CompileJob.DirectoryName of job More...
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Private Attributes

readonly IDatabaseContextFactory databaseContextFactory
 The IDatabaseContextFactory for the DmbFactory More...
 
readonly IIOManager ioManager
 The IIOManager for the DmbFactory More...
 
readonly ILogger< DmbFactorylogger
 The ILogger for the DmbFactory More...
 
readonly Api.Models.Instance instance
 The Api.Models.Instance for the DmbFactory More...
 
readonly CancellationTokenSource cleanupCts
 The CancellationTokenSource for cleanupTask More...
 
readonly IDictionary< long, int > jobLockCounts
 Map of CompileJob.JobIds to locks on them. More...
 
Task cleanupTask
 Task representing calls to CleanJob(CompileJob) More...
 
TaskCompletionSource< object > newerDmbTcs
 TaskCompletionSource<TResult> resulting in the latest DmbProvider yet to exist More...
 
IDmbProvider nextDmbProvider
 The latest DmbProvider More...
 
+

Detailed Description

+

Standard IDmbFactory

+ +

Definition at line 17 of file DmbFactory.cs.

+

Constructor & Destructor Documentation

+ +

◆ DmbFactory()

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Tgstation.Server.Host.Components.Deployment.DmbFactory.DmbFactory (IDatabaseContextFactory databaseContextFactory,
IIOManager ioManager,
ILogger< DmbFactorylogger,
Api.Models.Instance instance 
)
+
+ +

Construct a DmbFactory

+
Parameters
+ + + + + +
databaseContextFactoryThe value of databaseContextFactory
ioManagerThe value of ioManager
loggerThe value of logger
instanceThe value of instance
+
+
+ +

Definition at line 84 of file DmbFactory.cs.

+
85  {
86  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
87  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
88  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
89  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
90 
91  cleanupTask = Task.CompletedTask;
92  newerDmbTcs = new TaskCompletionSource<object>();
93  cleanupCts = new CancellationTokenSource();
94  jobLockCounts = new Dictionary<long, int>();
95  }
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the DmbFactory
Definition: DmbFactory.cs:35
+
TaskCompletionSource< object > newerDmbTcs
TaskCompletionSource<TResult> resulting in the latest DmbProvider yet to exist
Definition: DmbFactory.cs:70
+
readonly IDictionary< long, int > jobLockCounts
Map of CompileJob.JobIds to locks on them.
Definition: DmbFactory.cs:60
+
readonly IIOManager ioManager
The IIOManager for the DmbFactory
Definition: DmbFactory.cs:40
+
readonly CancellationTokenSource cleanupCts
The CancellationTokenSource for cleanupTask
Definition: DmbFactory.cs:55
+
readonly ILogger< DmbFactory > logger
The ILogger for the DmbFactory
Definition: DmbFactory.cs:45
+
readonly Api.Models.Instance instance
The Api.Models.Instance for the DmbFactory
Definition: DmbFactory.cs:50
+
Task cleanupTask
Task representing calls to CleanJob(CompileJob)
Definition: DmbFactory.cs:65
+
+

References Tgstation.Server.Host.Components.Deployment.DmbFactory.cleanupCts, Tgstation.Server.Host.Components.Deployment.DmbFactory.cleanupTask, Tgstation.Server.Host.Components.Deployment.DmbFactory.databaseContextFactory, Tgstation.Server.Host.Components.Deployment.DmbFactory.instance, Tgstation.Server.Host.Components.Deployment.DmbFactory.ioManager, Tgstation.Server.Host.Components.Deployment.DmbFactory.jobLockCounts, Tgstation.Server.Host.Components.Deployment.DmbFactory.logger, and Tgstation.Server.Host.Components.Deployment.DmbFactory.newerDmbTcs.

+ +
+
+

Member Function Documentation

+ +

◆ CleanJob()

+ +
+
+ + + + + +
+ + + + + + + + +
void Tgstation.Server.Host.Components.Deployment.DmbFactory.CleanJob (CompileJob job)
+
+private
+
+ +

Delete the Api.Models.Internal.CompileJob.DirectoryName of job

+
Parameters
+ + +
jobThe CompileJob to clean
+
+
+ +

Definition at line 104 of file DmbFactory.cs.

+
105  {
106  async Task HandleCleanup()
107  {
108  var deleteJob = ioManager.DeleteDirectory(job.DirectoryName.ToString(), cleanupCts.Token);
109  Task otherTask;
110 
111  // lock (this) //already locked below
112  otherTask = cleanupTask;
113  await Task.WhenAll(otherTask, deleteJob).ConfigureAwait(false);
114  }
115 
116  lock (this)
117  if (!jobLockCounts.TryGetValue(job.Id, out var currentVal) || currentVal == 1)
118  {
119  jobLockCounts.Remove(job.Id);
120  logger.LogDebug("Cleaning compile job {0} => {1}", job.Id, job.DirectoryName);
121  cleanupTask = HandleCleanup();
122  }
123  else
124  {
125  var decremented = --jobLockCounts[job.Id];
126  logger.LogTrace("Compile job {0} lock count now: {1}", job.Id, decremented);
127  }
128  }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory, removes and does not enter any symlinks encounterd.
+
long Id
The ID of the entity.
Definition: EntityId.cs:11
+
Guid? DirectoryName
The Game folder the results were compiled into
Definition: CompileJob.cs:27
+
readonly IDictionary< long, int > jobLockCounts
Map of CompileJob.JobIds to locks on them.
Definition: DmbFactory.cs:60
+
readonly IIOManager ioManager
The IIOManager for the DmbFactory
Definition: DmbFactory.cs:40
+
readonly CancellationTokenSource cleanupCts
The CancellationTokenSource for cleanupTask
Definition: DmbFactory.cs:55
+
readonly ILogger< DmbFactory > logger
The ILogger for the DmbFactory
Definition: DmbFactory.cs:45
+
Task cleanupTask
Task representing calls to CleanJob(CompileJob)
Definition: DmbFactory.cs:65
+
+

References Tgstation.Server.Host.Components.Deployment.DmbFactory.cleanupCts, Tgstation.Server.Host.Components.Deployment.DmbFactory.cleanupTask, Tgstation.Server.Host.IO.IIOManager.DeleteDirectory(), Tgstation.Server.Api.Models.Internal.CompileJob.DirectoryName, Tgstation.Server.Api.Models.EntityId.Id, Tgstation.Server.Host.Components.Deployment.DmbFactory.ioManager, Tgstation.Server.Host.Components.Deployment.DmbFactory.jobLockCounts, and Tgstation.Server.Host.Components.Deployment.DmbFactory.logger.

+ +

Referenced by Tgstation.Server.Host.Components.Deployment.DmbFactory.FromCompileJob().

+ +
+
+ +

◆ CleanUnusedCompileJobs()

+ +
+
+ + + + + + + + + + + + + + + + + + +
async Task Tgstation.Server.Host.Components.Deployment.DmbFactory.CleanUnusedCompileJobs (CompileJob exceptThisOne,
CancellationToken cancellationToken 
)
+
+ +

Deletes all compile jobs that are inactive in the Game folder exceptThisOne

+ +

Implements Tgstation.Server.Host.Components.Deployment.IDmbFactory.

+ +

Definition at line 243 of file DmbFactory.cs.

+
244  {
245  List<long> jobIdsToSkip;
246 
247  // don't clean locked directories
248  lock (this)
249  jobIdsToSkip = jobLockCounts.Select(x => x.Key).ToList();
250 
251  List<string> jobUidsToNotErase = null;
252 
253  // find the uids of locked directories
254  await databaseContextFactory.UseContext(async db =>
255  {
256  jobUidsToNotErase = await db.CompileJobs.Where(x => x.Job.Instance.Id == instance.Id && jobIdsToSkip.Contains(x.Id)).Select(x => x.DirectoryName.Value.ToString().ToUpperInvariant()).ToListAsync(cancellationToken).ConfigureAwait(false);
257  }).ConfigureAwait(false);
258 
259  // add the other exemption
260  if (exceptThisOne != null)
261  jobUidsToNotErase.Add(exceptThisOne.DirectoryName.Value.ToString().ToUpperInvariant());
262 
263  // cleanup
264  await ioManager.CreateDirectory(".", cancellationToken).ConfigureAwait(false);
265  var directories = await ioManager.GetDirectories(".", cancellationToken).ConfigureAwait(false);
266  int deleting = 0;
267  var tasks = directories.Select(async x =>
268  {
269  var nameOnly = ioManager.GetFileName(x);
270  if (jobUidsToNotErase.Contains(nameOnly.ToUpperInvariant()))
271  return;
272  try
273  {
274  ++deleting;
275  await ioManager.DeleteDirectory(x, cancellationToken).ConfigureAwait(false);
276  }
277  catch (OperationCanceledException)
278  {
279  throw;
280  }
281  catch (Exception e)
282  {
283  logger.LogWarning("Error deleting directory {0}! Exception: {1}", x, e);
284  }
285  }).ToList();
286  if (deleting > 0)
287  {
288  logger.LogDebug("Cleaning {0} unused game folders...", deleting);
289  await Task.WhenAll().ConfigureAwait(false);
290  }
291  }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory, removes and does not enter any symlinks encounterd.
+
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the DmbFactory
Definition: DmbFactory.cs:35
+
Task< IReadOnlyList< string > > GetDirectories(string path, CancellationToken cancellationToken)
Returns directory names in a given path
+
Guid? DirectoryName
The Game folder the results were compiled into
Definition: CompileJob.cs:27
+
Task CreateDirectory(string path, CancellationToken cancellationToken)
Create a directory at path
+
string GetFileName(string path)
Gets the file name portion of a path
+
readonly IDictionary< long, int > jobLockCounts
Map of CompileJob.JobIds to locks on them.
Definition: DmbFactory.cs:60
+
readonly IIOManager ioManager
The IIOManager for the DmbFactory
Definition: DmbFactory.cs:40
+
readonly ILogger< DmbFactory > logger
The ILogger for the DmbFactory
Definition: DmbFactory.cs:45
+
readonly Api.Models.Instance instance
The Api.Models.Instance for the DmbFactory
Definition: DmbFactory.cs:50
+
+

References Tgstation.Server.Host.IO.IIOManager.CreateDirectory(), Tgstation.Server.Host.Components.Deployment.DmbFactory.databaseContextFactory, Tgstation.Server.Host.IO.IIOManager.DeleteDirectory(), Tgstation.Server.Api.Models.Internal.CompileJob.DirectoryName, Tgstation.Server.Host.IO.IIOManager.GetDirectories(), Tgstation.Server.Host.IO.IIOManager.GetFileName(), Tgstation.Server.Host.Components.Deployment.DmbFactory.instance, Tgstation.Server.Host.Components.Deployment.DmbFactory.ioManager, Tgstation.Server.Host.Components.Deployment.DmbFactory.jobLockCounts, Tgstation.Server.Host.Components.Deployment.DmbFactory.logger, and Tgstation.Server.Host.Database.IDatabaseContextFactory.UseContext().

+ +
+
+ +

◆ Dispose()

+ +
+
+ + + + + + + +
void Tgstation.Server.Host.Components.Deployment.DmbFactory.Dispose ()
+
+ +

+ +
+
+ +

◆ FromCompileJob()

+ +
+
+ + + + + + + + + + + + + + + + + + +
async Task<IDmbProvider> Tgstation.Server.Host.Components.Deployment.DmbFactory.FromCompileJob (CompileJob compileJob,
CancellationToken cancellationToken 
)
+
+ +

Gets a IDmbProvider for a given CompileJob

+ +

Implements Tgstation.Server.Host.Components.Deployment.IDmbFactory.

+ +

Definition at line 186 of file DmbFactory.cs.

+
187  {
188  if (compileJob == null)
189  throw new ArgumentNullException(nameof(compileJob));
190 
191  // ensure we have the entire compile job tree
192  await databaseContextFactory.UseContext(async db => compileJob = await db.CompileJobs.Where(x => x.Id == compileJob.Id)
193  .Include(x => x.Job).ThenInclude(x => x.StartedBy)
194  .Include(x => x.RevisionInformation).ThenInclude(x => x.PrimaryTestMerge).ThenInclude(x => x.MergedBy)
195  .Include(x => x.RevisionInformation).ThenInclude(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).ThenInclude(x => x.MergedBy)
196  .FirstAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false); // can't wait to see that query
197 
198  logger.LogTrace("Loading compile job {0}...", compileJob.Id);
199  var providerSubmitted = false;
200  var newProvider = new DmbProvider(compileJob, ioManager, () =>
201  {
202  if (providerSubmitted)
203  CleanJob(compileJob);
204  });
205 
206  try
207  {
208  var primaryCheckTask = ioManager.FileExists(ioManager.ConcatPath(newProvider.PrimaryDirectory, newProvider.DmbName), cancellationToken);
209  var secondaryCheckTask = ioManager.FileExists(ioManager.ConcatPath(newProvider.PrimaryDirectory, newProvider.DmbName), cancellationToken);
210 
211  if (!(await primaryCheckTask.ConfigureAwait(false) && await secondaryCheckTask.ConfigureAwait(false)))
212  {
213  logger.LogWarning("Error loading compile job, .dmb missing!");
214  return null; // omae wa mou shinderu
215  }
216 
217  lock (this)
218  {
219  if (!jobLockCounts.TryGetValue(compileJob.Id, out int value))
220  {
221  value = 1;
222  jobLockCounts.Add(compileJob.Id, 1);
223  }
224  else
225  jobLockCounts[compileJob.Id] = ++value;
226 
227  logger.LogTrace("Compile job {0} lock count now: {1}", compileJob.Id, value);
228 
229  providerSubmitted = true;
230  return newProvider;
231  }
232  }
233  finally
234  {
235  if (!providerSubmitted)
236  newProvider.Dispose();
237  }
238  }
long Id
The ID of the entity.
Definition: EntityId.cs:11
+
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the DmbFactory
Definition: DmbFactory.cs:35
+
void CleanJob(CompileJob job)
Delete the Api.Models.Internal.CompileJob.DirectoryName of job
Definition: DmbFactory.cs:104
+
readonly IDictionary< long, int > jobLockCounts
Map of CompileJob.JobIds to locks on them.
Definition: DmbFactory.cs:60
+
Task< bool > FileExists(string path, CancellationToken cancellationToken)
Check that the file at path exists
+
readonly IIOManager ioManager
The IIOManager for the DmbFactory
Definition: DmbFactory.cs:40
+
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
+
readonly ILogger< DmbFactory > logger
The ILogger for the DmbFactory
Definition: DmbFactory.cs:45
+
string ConcatPath(params string[] paths)
Combines an array of strings into a path
+
+

References Tgstation.Server.Host.Components.Deployment.DmbFactory.CleanJob(), Tgstation.Server.Host.IO.IIOManager.ConcatPath(), Tgstation.Server.Host.Components.Deployment.DmbFactory.databaseContextFactory, Tgstation.Server.Host.IO.IIOManager.FileExists(), Tgstation.Server.Api.Models.EntityId.Id, Tgstation.Server.Host.Components.Deployment.DmbFactory.ioManager, Tgstation.Server.Host.Components.Deployment.DmbFactory.jobLockCounts, Tgstation.Server.Host.Components.Deployment.DmbFactory.logger, and Tgstation.Server.Host.Database.IDatabaseContextFactory.UseContext().

+ +

Referenced by Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.HandlerMonitorWakeup(), and Tgstation.Server.Host.Components.Deployment.DmbFactory.LoadCompileJob().

+ +
+
+ +

◆ LoadCompileJob()

+ +
+
+ + + + + + + + + + + + + + + + + + +
async Task Tgstation.Server.Host.Components.Deployment.DmbFactory.LoadCompileJob (CompileJob job,
CancellationToken cancellationToken 
)
+
+ +

Load a new job into the ICompileJobConsumer

+ +

Implements Tgstation.Server.Host.Components.Deployment.ICompileJobConsumer.

+ +

Definition at line 131 of file DmbFactory.cs.

+
132  {
133  if (job == null)
134  throw new ArgumentNullException(nameof(job));
135 
136  var newProvider = await FromCompileJob(job, cancellationToken).ConfigureAwait(false);
137  if (newProvider == null)
138  return;
139  lock (this)
140  {
141  nextDmbProvider?.Dispose();
142  nextDmbProvider = newProvider;
143  newerDmbTcs.SetResult(nextDmbProvider);
144  newerDmbTcs = new TaskCompletionSource<object>();
145  }
146  }
IDmbProvider nextDmbProvider
The latest DmbProvider
Definition: DmbFactory.cs:75
+
TaskCompletionSource< object > newerDmbTcs
TaskCompletionSource<TResult> resulting in the latest DmbProvider yet to exist
Definition: DmbFactory.cs:70
+
async Task< IDmbProvider > FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken)
Gets a IDmbProvider for a given CompileJob
Definition: DmbFactory.cs:186
+
+

References Tgstation.Server.Host.Components.Deployment.DmbFactory.FromCompileJob(), Tgstation.Server.Host.Components.Deployment.DmbFactory.newerDmbTcs, and Tgstation.Server.Host.Components.Deployment.DmbFactory.nextDmbProvider.

+ +
+
+ +

◆ LockNextDmb()

+ +
+
+ + + + + + + + +
IDmbProvider Tgstation.Server.Host.Components.Deployment.DmbFactory.LockNextDmb (int lockCount)
+
+ +

Gets the next IDmbProvider

+ +

Implements Tgstation.Server.Host.Components.Deployment.IDmbFactory.

+ +

Definition at line 149 of file DmbFactory.cs.

+
150  {
151  if (!DmbAvailable)
152  throw new InvalidOperationException("No .dmb available!");
153  if (lockCount < 0)
154  throw new ArgumentOutOfRangeException(nameof(lockCount), lockCount, "lockCount must be greater than or equal to 0!");
155  lock (this)
156  {
157  var jobId = nextDmbProvider.CompileJob.Id;
158  var incremented = jobLockCounts[jobId] += lockCount;
159  logger.LogTrace("Compile job {0} lock count now: {1}", jobId, incremented);
160  return nextDmbProvider;
161  }
162  }
CompileJob CompileJob
The CompileJob of the .dmb
Definition: IDmbProvider.cs:29
+
IDmbProvider nextDmbProvider
The latest DmbProvider
Definition: DmbFactory.cs:75
+
long Id
The ID of the entity.
Definition: EntityId.cs:11
+ +
readonly IDictionary< long, int > jobLockCounts
Map of CompileJob.JobIds to locks on them.
Definition: DmbFactory.cs:60
+
readonly ILogger< DmbFactory > logger
The ILogger for the DmbFactory
Definition: DmbFactory.cs:45
+
+

References Tgstation.Server.Host.Components.Deployment.IDmbProvider.CompileJob, Tgstation.Server.Host.Components.Deployment.DmbFactory.DmbAvailable, Tgstation.Server.Api.Models.EntityId.Id, Tgstation.Server.Host.Components.Deployment.DmbFactory.jobLockCounts, Tgstation.Server.Host.Components.Deployment.DmbFactory.logger, and Tgstation.Server.Host.Components.Deployment.DmbFactory.nextDmbProvider.

+ +

Referenced by Tgstation.Server.Host.Components.Watchdog.WindowsWatchdog.HandleNewDmbAvailable(), Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.HandlerMonitorWakeup(), Tgstation.Server.Host.Components.Watchdog.BasicWatchdog.InitControllers(), and Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.InitControllers().

+ +
+
+ +

◆ StartAsync()

+ +
+
+ + + + + + + + +
Task Tgstation.Server.Host.Components.Deployment.DmbFactory.StartAsync (CancellationToken cancellationToken)
+
+ +

+ +
+
+ +

◆ StopAsync()

+ +
+
+ + + + + + + + +
async Task Tgstation.Server.Host.Components.Deployment.DmbFactory.StopAsync (CancellationToken cancellationToken)
+
+ +

+ +

Definition at line 178 of file DmbFactory.cs.

+
179  {
180  using (cancellationToken.Register(() => cleanupCts.Cancel()))
181  await cleanupTask.ConfigureAwait(false);
182  }
readonly CancellationTokenSource cleanupCts
The CancellationTokenSource for cleanupTask
Definition: DmbFactory.cs:55
+
Task cleanupTask
Task representing calls to CleanJob(CompileJob)
Definition: DmbFactory.cs:65
+
+

References Tgstation.Server.Host.Components.Deployment.DmbFactory.cleanupCts, and Tgstation.Server.Host.Components.Deployment.DmbFactory.cleanupTask.

+ +
+
+

Member Data Documentation

+ +

◆ cleanupCts

+ +
+
+ + + + + +
+ + + + +
readonly CancellationTokenSource Tgstation.Server.Host.Components.Deployment.DmbFactory.cleanupCts
+
+private
+
+
+ +

◆ cleanupTask

+ +
+
+ + + + + +
+ + + + +
Task Tgstation.Server.Host.Components.Deployment.DmbFactory.cleanupTask
+
+private
+
+
+ +

◆ databaseContextFactory

+ +
+
+ + + + + +
+ + + + +
readonly IDatabaseContextFactory Tgstation.Server.Host.Components.Deployment.DmbFactory.databaseContextFactory
+
+private
+
+
+ +

◆ DmbAvailable

+ +
+
+ + + + +
bool Tgstation.Server.Host.Components.Deployment.DmbFactory.DmbAvailable => nextDmbProvider != null
+
+
+ +

◆ instance

+ +
+
+ + + + + +
+ + + + +
readonly Api.Models.Instance Tgstation.Server.Host.Components.Deployment.DmbFactory.instance
+
+private
+
+
+ +

◆ ioManager

+ + + +

◆ jobLockCounts

+ +
+
+ + + + + +
+ + + + +
readonly IDictionary<long, int> Tgstation.Server.Host.Components.Deployment.DmbFactory.jobLockCounts
+
+private
+
+
+ +

◆ logger

+ + + +

◆ newerDmbTcs

+ +
+
+ + + + + +
+ + + + +
TaskCompletionSource<object> Tgstation.Server.Host.Components.Deployment.DmbFactory.newerDmbTcs
+
+private
+
+ +

TaskCompletionSource<TResult> resulting in the latest DmbProvider yet to exist

+ +

Definition at line 70 of file DmbFactory.cs.

+ +

Referenced by Tgstation.Server.Host.Components.Deployment.DmbFactory.DmbFactory(), and Tgstation.Server.Host.Components.Deployment.DmbFactory.LoadCompileJob().

+ +
+
+ +

◆ nextDmbProvider

+ +
+
+ + + + + +
+ + + + +
IDmbProvider Tgstation.Server.Host.Components.Deployment.DmbFactory.nextDmbProvider
+
+private
+
+
+

Property Documentation

+ +

◆ OnNewerDmb

+ +
+
+ + + + + +
+ + + + +
Task Tgstation.Server.Host.Components.Deployment.DmbFactory.OnNewerDmb
+
+get
+
+ +

+ +

Definition at line 21 of file DmbFactory.cs.

+
21  {
22  get
23  {
24  lock (this)
25  return newerDmbTcs.Task;
26  }
27  }
TaskCompletionSource< object > newerDmbTcs
TaskCompletionSource<TResult> resulting in the latest DmbProvider yet to exist
Definition: DmbFactory.cs:70
+
+

Referenced by Tgstation.Server.Host.Components.Watchdog.BasicWatchdog.MonitorLifetimes(), and Tgstation.Server.Host.Components.Watchdog.ExperimentalWatchdog.MonitorLifetimes().

+ +
+
+
The documentation for this class was generated from the following file:
    +
  • src/Tgstation.Server.Host/Components/Deployment/DmbFactory.cs
  • +
+
+ + + + diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_dmb_factory.png b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_dmb_factory.png new file mode 100644 index 0000000000000000000000000000000000000000..42f63be7dfbb007adee345f58a64a2aa56774cc2 GIT binary patch literal 2840 zcmbtW3sh3s8b(Duqj`;%ubk2urSgI4I9^Lbv_@1k@mZ5v$>?O7rj=YQ;Sj>L!mTp8aj@X_{J1OGX*69QQ;n&yJod!-PXG6&R*-Bv(Ndz{qMcM|Np;z zE(Bt|^>j>iAP|Ti#>X=l0)YZxKO4{h?*|yx)aRGM-p7l@ zVrgC&G6!FQlfl>!2nbqjZ`wm0ArPG^jOWhKG_{%GsnlD~Og-PWwT3@c`JsmATKH>( z@k73i>qISQ*6vD*o3>vL+1=xGEv~TgW-O^Pu24%$Xs&%d5-Ffw1M8H&1}b8}oieWqV6jp&Tw+ELh(3s&5$wORoY9)h@BS*0EC> zT$0=*;}P_*`!ZgHenY+cSEt-mKrtr_B47w# z2iq69eYWcI_+M=~05rIksO*l&h+-vy zE)B5qLtln(!j!(y2V;;R57I?qns$BslzSWWMFRKu*C=ITpqTltppQ|s1nocKzyMie zPQXDAYj%HTtg0LUlc3$nzsKjXM~{=ghKAgiq> zn6*^aK1}lb)u#Gqaeub+w~q>{RSImaRo1ZM%uA_x zo#`23rYHASYu>i5{R_tkBJURrPOmOyG`MqdOVyA&U5ne&Dac@+RGso`t6)&J8V5DG zjTI}Fa46UCQyG`$WC@!a^Ej$EwqK z3hv>W*}O(QF5+wz+;-x;alcZDmuD}`59oE0GwIz4WaZr|Z~c7~TwY7PMXX_yRaRqBvrX1Hmu(yOKxX}x>FWWMCh45 z_XgWI72n@|+Dc|OfwazFO5$B7MAMM`n?U%vMvD7}?y*@x^K?Oj+fbF%@z(SY<d7 zFCSWSSLVi!&Xq1aQ}sRc!7f^Qdvc8M9Jm1qD5(;m<@Q`{GfMd$9~$*8FuIf;26ZX% z@*OSHf9+wGhRE9cH3n5-aYiIb`B(P3i-L0XWF`rkG*y_h=bdaY;bq^S<*E6vo! zBxkRt4)TK6KfG@3A*lycTp@SI?kQ*G#qx1Z;f7XX_@9t2%Tul@ob;)=Qc=%qlWy)C zA4(XOr!Ft#*8QPBqUxu9jYsVzx<#GJ7S>G3VCS@7kw-&R6@;L zI@~+@E@!a4aqH}$T|>zI*48*_n2tc2O()Ef7bjzfyUETSl6>ui(+591`ZjmbL0J2! z6e7P2a*n)^bYav?zVxUs!Y|pdxGsvA){o3oA=6tVG#86hJkrdv{1s z+R@pZNPKQ8&;Da51y}#9mLj_X80qqVYg>4E4sec-NnI$i=rcLg1{_7#?K?l68}p^K4b>O%E9C*+P3{JJZxiz- zVaLz{0A`Vc4ewuq+LmT*#ecNmtfnv|-^4JI>l9oA;mViR<*F3K4w?Jgh1FRMBB?`B zgXHGdWyWj=v%5e!i!S%#W281ZL*{SPS!=B-Ut&yxcMvkRB?Z+S~fA^-pY literal 0 HcmV?d00001 diff --git a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_provider-members.html b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_dmb_provider-members.html similarity index 53% rename from class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_provider-members.html rename to class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_dmb_provider-members.html index 24844287e5..d51ea0cc41 100644 --- a/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_dmb_provider-members.html +++ b/class_tgstation_1_1_server_1_1_host_1_1_components_1_1_deployment_1_1_dmb_provider-members.html @@ -63,26 +63,26 @@ $(function() {
-
Tgstation.Server.Host.Components.Compiler.DmbProvider Member List
+
Tgstation.Server.Host.Components.Deployment.DmbProvider Member List
-

This is the complete list of members for Tgstation.Server.Host.Components.Compiler.DmbProvider, including all inherited members.

+

This is the complete list of members for Tgstation.Server.Host.Components.Deployment.DmbProvider, including all inherited members.

- - - - - - - - - + + + + + + + + +
CompileJobTgstation.Server.Host.Components.Compiler.DmbProvider
Dispose()Tgstation.Server.Host.Components.Compiler.DmbProvider
DmbNameTgstation.Server.Host.Components.Compiler.DmbProvider
DmbProvider(CompileJob compileJob, IIOManager ioManager, Action onDispose)Tgstation.Server.Host.Components.Compiler.DmbProvider
ioManagerTgstation.Server.Host.Components.Compiler.DmbProviderprivate
KeepAlive()Tgstation.Server.Host.Components.Compiler.DmbProvider
onDisposeTgstation.Server.Host.Components.Compiler.DmbProviderprivate
PrimaryDirectoryTgstation.Server.Host.Components.Compiler.DmbProvider
SecondaryDirectoryTgstation.Server.Host.Components.Compiler.DmbProvider
CompileJobTgstation.Server.Host.Components.Deployment.DmbProvider
Dispose()Tgstation.Server.Host.Components.Deployment.DmbProvider
DmbNameTgstation.Server.Host.Components.Deployment.DmbProvider
DmbProvider(CompileJob compileJob, IIOManager ioManager, Action onDispose)Tgstation.Server.Host.Components.Deployment.DmbProvider
ioManagerTgstation.Server.Host.Components.Deployment.DmbProviderprivate
KeepAlive()Tgstation.Server.Host.Components.Deployment.DmbProvider
onDisposeTgstation.Server.Host.Components.Deployment.DmbProviderprivate
PrimaryDirectoryTgstation.Server.Host.Components.Deployment.DmbProvider
SecondaryDirectoryTgstation.Server.Host.Components.Deployment.DmbProvider