From c3da20b544df3ce9e2e87ff8cfc28a97e9aca0e4 Mon Sep 17 00:00:00 2001 From: tgstation-server Date: Tue, 31 Dec 2019 16:19:30 +0000 Subject: [PATCH] Deploy code docs to GitHub Pages for Appveyor build 1069 Commit: b5fbe5dfdaf83d95cb7ad22b7af37f3d2e5ca94f --- ...3___m_s_initial_create_8_designer_8cs.html | 63 +- ..._initial_create_8_designer_8cs_source.html | 61 +- 20180906135553___m_s_initial_create_8cs.html | 63 +- ...35553___m_s_initial_create_8cs_source.html | 87 +- ...9___m_y_initial_create_8_designer_8cs.html | 63 +- ..._initial_create_8_designer_8cs_source.html | 61 +- 20180906143029___m_y_initial_create_8cs.html | 63 +- ...43029___m_y_initial_create_8cs_source.html | 87 +- ...y_add_minimum_security_8_designer_8cs.html | 65 +- ...inimum_security_8_designer_8cs_source.html | 61 +- ...020726___m_y_add_minimum_security_8cs.html | 65 +- ...__m_y_add_minimum_security_8cs_source.html | 69 +- ...s_add_minimum_security_8_designer_8cs.html | 65 +- ...inimum_security_8_designer_8cs_source.html | 61 +- ...021228___m_s_add_minimum_security_8cs.html | 65 +- ...__m_s_add_minimum_security_8cs_source.html | 71 +- ...nd_foreign_key_cleanup_8_designer_8cs.html | 63 +- ...ign_key_cleanup_8_designer_8cs_source.html | 61 +- ..._nullable_and_foreign_key_cleanup_8cs.html | 63 +- ...le_and_foreign_key_cleanup_8cs_source.html | 65 +- ...nd_foreign_key_cleanup_8_designer_8cs.html | 63 +- ...ign_key_cleanup_8_designer_8cs_source.html | 61 +- ..._nullable_and_foreign_key_cleanup_8cs.html | 63 +- ...le_and_foreign_key_cleanup_8cs_source.html | 65 +- ...h_compile_job_required_8_designer_8cs.html | 65 +- ...le_job_required_8_designer_8cs_source.html | 61 +- ...m_s_reattach_compile_job_required_8cs.html | 65 +- ...ttach_compile_job_required_8cs_source.html | 64 +- ...h_compile_job_required_8_designer_8cs.html | 65 +- ...le_job_required_8_designer_8cs_source.html | 61 +- ...m_y_reattach_compile_job_required_8cs.html | 65 +- ...ttach_compile_job_required_8cs_source.html | 64 +- ...gle_testmerge_comments_8_designer_8cs.html | 65 +- ...tmerge_comments_8_designer_8cs_source.html | 61 +- ...4___m_s_toggle_testmerge_comments_8cs.html | 65 +- ..._toggle_testmerge_comments_8cs_source.html | 64 +- ...gle_testmerge_comments_8_designer_8cs.html | 65 +- ...tmerge_comments_8_designer_8cs_source.html | 61 +- ...9___m_y_toggle_testmerge_comments_8cs.html | 65 +- ..._toggle_testmerge_comments_8cs_source.html | 64 +- ...m_s_fix_rev_info_index_8_designer_8cs.html | 65 +- ..._rev_info_index_8_designer_8cs_source.html | 61 +- ...19041825___m_s_fix_rev_info_index_8cs.html | 65 +- ...5___m_s_fix_rev_info_index_8cs_source.html | 64 +- ...m_y_fix_rev_info_index_8_designer_8cs.html | 65 +- ..._rev_info_index_8_designer_8cs_source.html | 61 +- ...19042440___m_y_fix_rev_info_index_8cs.html | 65 +- ...0___m_y_fix_rev_info_index_8cs_source.html | 64 +- _a_p_i_8dox.html | 55 +- _administration_8cs.html | 61 +- _administration_8cs_source.html | 65 +- _administration_client_8cs.html | 59 +- _administration_client_8cs_source.html | 80 +- _administration_controller_8cs.html | 63 +- _administration_controller_8cs_source.html | 131 +-- _administration_rights_8cs.html | 65 +- _administration_rights_8cs_source.html | 72 +- _administration_test_8cs.html | 59 +- _administration_test_8cs_source.html | 75 +- _api_client_8cs.html | 59 +- _api_client_8cs_source.html | 125 +- _api_client_factory_8cs.html | 59 +- _api_client_factory_8cs_source.html | 71 +- _api_conflict_exception_8cs.html | 59 +- _api_conflict_exception_8cs_source.html | 77 +- _api_controller_8cs.html | 61 +- _api_controller_8cs_source.html | 106 +- _api_headers_8cs.html | 59 +- _api_headers_8cs_source.html | 89 +- _api_mismatch_exception_8cs.html | 59 +- _api_mismatch_exception_8cs_source.html | 78 +- _api_validation_status_8cs.html | 67 +- _api_validation_status_8cs_source.html | 73 +- _application_8cs.html | 61 +- _application_8cs_source.html | 204 ++-- _application_builder_extensions_8cs.html | 61 +- ...ication_builder_extensions_8cs_source.html | 73 +- _architecture_8dox.html | 55 +- _async_delayer_8cs.html | 61 +- _async_delayer_8cs_source.html | 65 +- _authentication_context_8cs.html | 61 +- _authentication_context_8cs_source.html | 88 +- _authentication_context_factory_8cs.html | 61 +- ...entication_context_factory_8cs_source.html | 93 +- _bool_converter_8cs.html | 65 +- _bool_converter_8cs_source.html | 65 +- _byond_8cs.html | 61 +- _byond_8cs_source.html | 65 +- _byond_client_8cs.html | 61 +- _byond_client_8cs_source.html | 87 +- _byond_command_8cs.html | 65 +- _byond_command_8cs_source.html | 92 +- _byond_controller_8cs.html | 63 +- _byond_controller_8cs_source.html | 111 +- _byond_executable_lock_8cs.html | 63 +- _byond_executable_lock_8cs_source.html | 68 +- _byond_manager_8cs.html | 63 +- _byond_manager_8cs_source.html | 124 +- _byond_rights_8cs.html | 65 +- _byond_rights_8cs_source.html | 71 +- _byond_test_8cs.html | 61 +- _byond_test_8cs_source.html | 72 +- _channel_8cs.html | 65 +- _channel_8cs_source.html | 69 +- _channel_mapping_8cs.html | 65 +- _channel_mapping_8cs_source.html | 66 +- _chat_8cs.html | 63 +- _chat_8cs_source.html | 192 ++- _chat_bot_rights_8cs.html | 65 +- _chat_bot_rights_8cs_source.html | 81 +- _chat_bots_client_8cs.html | 61 +- _chat_bots_client_8cs_source.html | 93 +- _chat_command_8cs.html | 63 +- _chat_command_8cs_source.html | 73 +- _chat_connection_string_builder_8cs.html | 65 +- ..._connection_string_builder_8cs_source.html | 62 +- _chat_controller_8cs.html | 63 +- _chat_controller_8cs_source.html | 115 +- _chat_factory_8cs.html | 63 +- _chat_factory_8cs_source.html | 90 +- _chat_provider_8cs.html | 65 +- _chat_provider_8cs_source.html | 64 +- _claims_injector_8cs.html | 61 +- _claims_injector_8cs_source.html | 94 +- _client_exception_8cs.html | 61 +- _client_exception_8cs_source.html | 77 +- _comm_command_8cs.html | 63 +- _comm_command_8cs_source.html | 63 +- _comm_context_8cs.html | 63 +- _comm_context_8cs_source.html | 93 +- _command_factory_8cs.html | 65 +- _command_factory_8cs_source.html | 108 +- _components_2_watchdog_2_i_watchdog_8cs.html | 63 +- ...ts_2_watchdog_2_i_watchdog_8cs_source.html | 82 +- ...s_2_watchdog_2_i_watchdog_factory_8cs.html | 65 +- ...chdog_2_i_watchdog_factory_8cs_source.html | 86 +- ...2_watchdog_2_reattach_information_8cs.html | 65 +- ...dog_2_reattach_information_8cs_source.html | 75 +- _components_2_watchdog_2_watchdog_8cs.html | 63 +- ...ents_2_watchdog_2_watchdog_8cs_source.html | 269 ++--- ...nts_2_watchdog_2_watchdog_factory_8cs.html | 63 +- ...atchdog_2_watchdog_factory_8cs_source.html | 108 +- ...g_2_watchdog_reattach_information_8cs.html | 65 +- ...chdog_reattach_information_8cs_source.html | 79 +- _configuration_8cs.html | 63 +- _configuration_8cs_source.html | 156 +-- _configuration_client_8cs.html | 61 +- _configuration_client_8cs_source.html | 95 +- _configuration_controller_8cs.html | 63 +- _configuration_controller_8cs_source.html | 119 +- _configuration_file_8cs.html | 61 +- _configuration_file_8cs_source.html | 63 +- _configuration_rights_8cs.html | 65 +- _configuration_rights_8cs_source.html | 71 +- _configuration_test_8cs.html | 61 +- _configuration_test_8cs_source.html | 74 +- _configuration_type_8cs.html | 65 +- _configuration_type_8cs_source.html | 66 +- _conflict_exception_8cs.html | 59 +- _conflict_exception_8cs_source.html | 76 +- _console_8cs.html | 61 +- _console_8cs_source.html | 67 +- _constants_8cs.html | 65 +- _constants_8cs_source.html | 77 +- _control_panel_configuration_8cs.html | 61 +- _control_panel_configuration_8cs_source.html | 65 +- _credentials_provider_8cs.html | 63 +- _credentials_provider_8cs_source.html | 75 +- _cryptography_suite_8cs.html | 61 +- _cryptography_suite_8cs_source.html | 82 +- _custom_command_8cs.html | 65 +- _custom_command_8cs_source.html | 80 +- _d_b_connection_factory_8cs.html | 61 +- _d_b_connection_factory_8cs_source.html | 72 +- _database_configuration_8cs.html | 61 +- _database_configuration_8cs_source.html | 68 +- _database_context_8cs.html | 61 +- _database_context_8cs_source.html | 102 +- _database_context_factory_8cs.html | 61 +- _database_context_factory_8cs_source.html | 74 +- _database_seeder_8cs.html | 61 +- _database_seeder_8cs_source.html | 88 +- _database_type_8cs.html | 65 +- _database_type_8cs_source.html | 67 +- _dead_session_controller_8cs.html | 65 +- _dead_session_controller_8cs_source.html | 91 +- _default_i_o_manager_8cs.html | 63 +- _default_i_o_manager_8cs_source.html | 98 +- ...n_time_db_context_factory_helpers_8cs.html | 65 +- ...db_context_factory_helpers_8cs_source.html | 72 +- _discord_connection_string_builder_8cs.html | 63 +- ..._connection_string_builder_8cs_source.html | 76 +- _discord_provider_8cs.html | 67 +- _discord_provider_8cs_source.html | 109 +- _dmb_factory_8cs.html | 65 +- _dmb_factory_8cs_source.html | 126 +- _dmb_provider_8cs.html | 63 +- _dmb_provider_8cs_source.html | 91 +- _dream_daemon_8cs.html | 63 +- _dream_daemon_8cs_source.html | 76 +- _dream_daemon_client_8cs.html | 61 +- _dream_daemon_client_8cs_source.html | 90 +- _dream_daemon_controller_8cs.html | 63 +- _dream_daemon_controller_8cs_source.html | 134 +-- _dream_daemon_launch_parameters_8cs.html | 65 +- ...m_daemon_launch_parameters_8cs_source.html | 74 +- _dream_daemon_rights_8cs.html | 65 +- _dream_daemon_rights_8cs_source.html | 87 +- _dream_daemon_security_8cs.html | 65 +- _dream_daemon_security_8cs_source.html | 66 +- _dream_daemon_status_8cs.html | 65 +- _dream_daemon_status_8cs_source.html | 66 +- _dream_maker_client_8cs.html | 61 +- _dream_maker_client_8cs_source.html | 94 +- _dream_maker_controller_8cs.html | 61 +- _dream_maker_controller_8cs_source.html | 120 +- _dream_maker_rights_8cs.html | 65 +- _dream_maker_rights_8cs_source.html | 77 +- _dream_maker_settings_8cs.html | 61 +- _dream_maker_settings_8cs_source.html | 69 +- _error_message_8cs.html | 61 +- _error_message_8cs_source.html | 67 +- _event_consumer_8cs.html | 61 +- _event_consumer_8cs_source.html | 85 +- _event_notification_8cs.html | 65 +- _event_notification_8cs_source.html | 65 +- _event_type_8cs.html | 65 +- _event_type_8cs_source.html | 88 +- _file_logging_configuration_8cs.html | 61 +- _file_logging_configuration_8cs_source.html | 68 +- _general_configuration_8cs.html | 61 +- _general_configuration_8cs_source.html | 71 +- _git_hub_client_factory_8cs.html | 61 +- _git_hub_client_factory_8cs_source.html | 74 +- _global_suppressions_8cs.html | 55 +- _global_suppressions_8cs_source.html | 58 +- _home_controller_8cs.html | 63 +- _home_controller_8cs_source.html | 135 +-- _http_client_8cs.html | 59 +- _http_client_8cs_source.html | 69 +- _i_administration_client_8cs.html | 59 +- _i_administration_client_8cs_source.html | 69 +- _i_api_client_8cs.html | 59 +- _i_api_client_8cs_source.html | 84 +- _i_api_client_factory_8cs.html | 61 +- _i_api_client_factory_8cs_source.html | 71 +- _i_application_8cs.html | 61 +- _i_application_8cs_source.html | 65 +- _i_async_delayer_8cs.html | 61 +- _i_async_delayer_8cs_source.html | 62 +- _i_authentication_context_8cs.html | 61 +- _i_authentication_context_8cs_source.html | 72 +- _i_authentication_context_factory_8cs.html | 61 +- ...entication_context_factory_8cs_source.html | 65 +- _i_byond_client_8cs.html | 61 +- _i_byond_client_8cs_source.html | 71 +- _i_byond_executable_lock_8cs.html | 63 +- _i_byond_executable_lock_8cs_source.html | 66 +- _i_byond_installer_8cs.html | 63 +- _i_byond_installer_8cs_source.html | 67 +- _i_byond_manager_8cs.html | 63 +- _i_byond_manager_8cs_source.html | 66 +- _i_chat_8cs.html | 63 +- _i_chat_8cs_source.html | 81 +- _i_chat_bots_client_8cs.html | 61 +- _i_chat_bots_client_8cs_source.html | 71 +- _i_chat_factory_8cs.html | 65 +- _i_chat_factory_8cs_source.html | 76 +- _i_claims_injector_8cs.html | 63 +- _i_claims_injector_8cs_source.html | 62 +- _i_comm_context_8cs.html | 63 +- _i_comm_context_8cs_source.html | 64 +- _i_comm_handler_8cs.html | 65 +- _i_comm_handler_8cs_source.html | 64 +- _i_command_8cs.html | 65 +- _i_command_8cs_source.html | 67 +- _i_command_factory_8cs.html | 67 +- _i_command_factory_8cs_source.html | 62 +- _i_compile_job_consumer_8cs.html | 63 +- _i_compile_job_consumer_8cs_source.html | 67 +- _i_configuration_8cs.html | 63 +- _i_configuration_8cs_source.html | 77 +- _i_configuration_client_8cs.html | 61 +- _i_configuration_client_8cs_source.html | 71 +- _i_console_8cs.html | 61 +- _i_console_8cs_source.html | 65 +- _i_credentials_provider_8cs.html | 63 +- _i_credentials_provider_8cs_source.html | 63 +- _i_cryptography_suite_8cs.html | 61 +- _i_cryptography_suite_8cs_source.html | 69 +- _i_custom_command_handler_8cs.html | 65 +- _i_custom_command_handler_8cs_source.html | 64 +- _i_d_b_connection_factory_8cs.html | 61 +- _i_d_b_connection_factory_8cs_source.html | 69 +- _i_database_context_8cs.html | 61 +- _i_database_context_8cs_source.html | 74 +- _i_database_context_factory_8cs.html | 61 +- _i_database_context_factory_8cs_source.html | 69 +- _i_database_seeder_8cs.html | 61 +- _i_database_seeder_8cs_source.html | 65 +- _i_dmb_factory_8cs.html | 65 +- _i_dmb_factory_8cs_source.html | 73 +- _i_dmb_provider_8cs.html | 61 +- _i_dmb_provider_8cs_source.html | 70 +- _i_dream_daemon_client_8cs.html | 61 +- _i_dream_daemon_client_8cs_source.html | 73 +- _i_dream_maker_8cs.html | 63 +- _i_dream_maker_8cs_source.html | 71 +- _i_dream_maker_client_8cs.html | 61 +- _i_dream_maker_client_8cs_source.html | 71 +- _i_event_consumer_8cs.html | 63 +- _i_event_consumer_8cs_source.html | 64 +- _i_git_hub_client_factory_8cs.html | 61 +- _i_git_hub_client_factory_8cs_source.html | 62 +- _i_http_client_8cs.html | 59 +- _i_http_client_8cs_source.html | 63 +- _i_i_o_manager_8cs.html | 61 +- _i_i_o_manager_8cs_source.html | 83 +- _i_identity_cache_8cs.html | 63 +- _i_identity_cache_8cs_source.html | 70 +- _i_instance_8cs.html | 61 +- _i_instance_8cs_source.html | 83 +- _i_instance_client_8cs.html | 61 +- _i_instance_client_8cs_source.html | 95 +- _i_instance_factory_8cs.html | 63 +- _i_instance_factory_8cs_source.html | 63 +- _i_instance_manager_8cs.html | 63 +- _i_instance_manager_8cs_source.html | 72 +- _i_instance_manager_client_8cs.html | 59 +- _i_instance_manager_client_8cs_source.html | 73 +- _i_instance_user_client_8cs.html | 61 +- _i_instance_user_client_8cs_source.html | 74 +- _i_job_manager_8cs.html | 61 +- _i_job_manager_8cs_source.html | 72 +- _i_jobs_client_8cs.html | 61 +- _i_jobs_client_8cs_source.html | 72 +- _i_json_tracking_context_8cs.html | 63 +- _i_json_tracking_context_8cs_source.html | 72 +- _i_network_prompt_reaper_8cs.html | 63 +- _i_network_prompt_reaper_8cs_source.html | 68 +- _i_platform_identifier_8cs.html | 61 +- _i_platform_identifier_8cs_source.html | 62 +- _i_post_write_handler_8cs.html | 61 +- _i_post_write_handler_8cs_source.html | 61 +- _i_process_8cs.html | 61 +- _i_process_8cs_source.html | 69 +- _i_process_base_8cs.html | 61 +- _i_process_base_8cs_source.html | 63 +- _i_process_executor_8cs.html | 63 +- _i_process_executor_8cs_source.html | 64 +- _i_provider_8cs.html | 65 +- _i_provider_8cs_source.html | 68 +- _i_provider_factory_8cs.html | 63 +- _i_provider_factory_8cs_source.html | 75 +- _i_reattach_info_handler_8cs.html | 65 +- _i_reattach_info_handler_8cs_source.html | 65 +- _i_repository_8cs.html | 63 +- _i_repository_8cs_source.html | 85 +- _i_repository_client_8cs.html | 61 +- _i_repository_client_8cs_source.html | 72 +- _i_repository_manager_8cs.html | 65 +- _i_repository_manager_8cs_source.html | 67 +- _i_request_logger_8cs.html | 59 +- _i_request_logger_8cs_source.html | 63 +- _i_restart_handler_8cs.html | 61 +- _i_restart_handler_8cs_source.html | 62 +- _i_restart_registration_8cs.html | 63 +- _i_restart_registration_8cs_source.html | 61 +- _i_server_8cs.html | 59 +- _i_server_8cs_source.html | 63 +- _i_server_client_8cs.html | 59 +- _i_server_client_8cs_source.html | 82 +- _i_server_client_factory_8cs.html | 61 +- _i_server_client_factory_8cs_source.html | 71 +- _i_server_control_8cs.html | 61 +- _i_server_control_8cs_source.html | 75 +- _i_server_factory_8cs.html | 61 +- _i_server_factory_8cs_source.html | 63 +- _i_session_controller_8cs.html | 63 +- _i_session_controller_8cs_source.html | 90 +- _i_session_controller_factory_8cs.html | 65 +- _i_session_controller_factory_8cs_source.html | 85 +- _i_setup_wizard_8cs.html | 61 +- _i_setup_wizard_8cs_source.html | 62 +- _i_symlink_factory_8cs.html | 61 +- _i_symlink_factory_8cs_source.html | 62 +- _i_synchronous_i_o_manager_8cs.html | 61 +- _i_synchronous_i_o_manager_8cs_source.html | 68 +- _i_system_identity_8cs.html | 61 +- _i_system_identity_8cs_source.html | 65 +- _i_system_identity_factory_8cs.html | 63 +- _i_system_identity_factory_8cs_source.html | 67 +- _i_token_factory_8cs.html | 61 +- _i_token_factory_8cs_source.html | 68 +- _i_users_client_8cs.html | 59 +- _i_users_client_8cs_source.html | 73 +- _identity_cache_8cs.html | 61 +- _identity_cache_8cs_source.html | 90 +- _identity_cache_object_8cs.html | 63 +- _identity_cache_object_8cs_source.html | 79 +- _instance_client_8cs.html | 61 +- _instance_client_8cs_source.html | 101 +- _instance_controller_8cs.html | 61 +- _instance_controller_8cs_source.html | 173 ++- _instance_factory_8cs.html | 61 +- _instance_factory_8cs_source.html | 154 ++- _instance_manager_8cs.html | 61 +- _instance_manager_8cs_source.html | 121 +- _instance_manager_client_8cs.html | 59 +- _instance_manager_client_8cs_source.html | 94 +- _instance_manager_rights_8cs.html | 65 +- _instance_manager_rights_8cs_source.html | 81 +- _instance_manager_test_8cs.html | 59 +- _instance_manager_test_8cs_source.html | 81 +- _instance_test_8cs.html | 61 +- _instance_test_8cs_source.html | 68 +- _instance_user_client_8cs.html | 61 +- _instance_user_client_8cs_source.html | 94 +- _instance_user_controller_8cs.html | 61 +- _instance_user_controller_8cs_source.html | 118 +- _instance_user_rights_8cs.html | 65 +- _instance_user_rights_8cs_source.html | 69 +- _insufficient_permissions_exception_8cs.html | 59 +- ...ient_permissions_exception_8cs_source.html | 76 +- _integration_test_8cs.html | 59 +- _integration_test_8cs_source.html | 104 +- _irc_connection_string_builder_8cs.html | 63 +- ..._connection_string_builder_8cs_source.html | 84 +- _irc_password_type_8cs.html | 65 +- _irc_password_type_8cs_source.html | 65 +- _irc_provider_8cs.html | 67 +- _irc_provider_8cs_source.html | 124 +- _job_controller_8cs.html | 63 +- _job_controller_8cs_source.html | 100 +- _job_exception_8cs.html | 61 +- _job_exception_8cs_source.html | 67 +- _job_handler_8cs.html | 61 +- _job_handler_8cs_source.html | 72 +- _job_manager_8cs.html | 61 +- _job_manager_8cs_source.html | 120 +- _jobs_client_8cs.html | 61 +- _jobs_client_8cs_source.html | 93 +- _json_file_8cs.html | 63 +- _json_file_8cs_source.html | 79 +- _json_sub_file_list_8cs.html | 63 +- _json_sub_file_list_8cs_source.html | 71 +- _json_tracking_context_8cs.html | 63 +- _json_tracking_context_8cs_source.html | 87 +- _kek_command_8cs.html | 65 +- _kek_command_8cs_source.html | 70 +- _launch_result_8cs.html | 63 +- _launch_result_8cs_source.html | 64 +- _message_8cs.html | 67 +- _message_8cs_source.html | 64 +- _method_not_supported_exception_8cs.html | 59 +- ...od_not_supported_exception_8cs_source.html | 74 +- _model_controller_8cs.html | 63 +- _model_controller_8cs_source.html | 81 +- _models_2_reattach_information_8cs.html | 63 +- ...els_2_reattach_information_8cs_source.html | 64 +- ...s_2_watchdog_reattach_information_8cs.html | 63 +- ...chdog_reattach_information_8cs_source.html | 68 +- _monitor_action_8cs.html | 67 +- _monitor_action_8cs_source.html | 68 +- _monitor_activation_reason_8cs.html | 67 +- _monitor_activation_reason_8cs_source.html | 74 +- _monitor_state_8cs.html | 63 +- _monitor_state_8cs_source.html | 69 +- _my_sql_database_context_8cs.html | 63 +- _my_sql_database_context_8cs_source.html | 85 +- ...l_database_context_model_snapshot_8cs.html | 63 +- ...ase_context_model_snapshot_8cs_source.html | 61 +- ...ql_design_time_db_context_factory_8cs.html | 63 +- ...gn_time_db_context_factory_8cs_source.html | 70 +- _native_methods_8cs.html | 59 +- _native_methods_8cs_source.html | 69 +- _platform_identifier_8cs.html | 61 +- _platform_identifier_8cs_source.html | 65 +- _posix_byond_installer_8cs.html | 65 +- _posix_byond_installer_8cs_source.html | 101 +- _posix_network_prompt_reaper_8cs.html | 63 +- _posix_network_prompt_reaper_8cs_source.html | 69 +- _posix_post_write_handler_8cs.html | 63 +- _posix_post_write_handler_8cs_source.html | 65 +- _posix_symlink_factory_8cs.html | 63 +- _posix_symlink_factory_8cs_source.html | 64 +- _posix_system_identity_factory_8cs.html | 63 +- ...ix_system_identity_factory_8cs_source.html | 69 +- _process_8cs.html | 61 +- _process_8cs_source.html | 81 +- _process_executor_8cs.html | 61 +- _process_executor_8cs_source.html | 75 +- _provider_8cs.html | 65 +- _provider_8cs_source.html | 85 +- _provider_factory_8cs.html | 63 +- _provider_factory_8cs_source.html | 95 +- _pull_requests_command_8cs.html | 65 +- _pull_requests_command_8cs_source.html | 97 +- _r_e_a_d_m_e_8md.html | 57 +- _r_e_a_d_m_e_8md_source.html | 99 -- _rate_limit_exception_8cs.html | 59 +- _rate_limit_exception_8cs_source.html | 77 +- _reattach_info_handler_8cs.html | 61 +- _reattach_info_handler_8cs_source.html | 115 +- _reattach_information_base_8cs.html | 63 +- _reattach_information_base_8cs_source.html | 87 +- _reboot_state_8cs.html | 67 +- _reboot_state_8cs_source.html | 62 +- _release_notes_8_assembly_info_8cs.html | 59 +- ...ease_notes_8_assembly_info_8cs_source.html | 62 +- _repository_client_8cs.html | 61 +- _repository_client_8cs_source.html | 89 +- _repository_controller_8cs.html | 61 +- _repository_controller_8cs_source.html | 148 +-- _repository_manager_8cs.html | 63 +- _repository_manager_8cs_source.html | 111 +- _repository_rights_8cs.html | 65 +- _repository_rights_8cs_source.html | 89 +- _request_timeout_exception_8cs.html | 59 +- _request_timeout_exception_8cs_source.html | 74 +- _resolving_i_o_manager_8cs.html | 63 +- _resolving_i_o_manager_8cs_source.html | 70 +- _response_8cs.html | 63 +- _response_8cs_source.html | 63 +- _restart_registration_8cs.html | 61 +- _restart_registration_8cs_source.html | 66 +- _rev_info_test_merge_8cs.html | 61 +- _rev_info_test_merge_8cs_source.html | 62 +- _revision_command_8cs.html | 67 +- _revision_command_8cs_source.html | 94 +- _rights_helper_8cs.html | 63 +- _rights_helper_8cs_source.html | 87 +- _rights_type_8cs.html | 65 +- _rights_type_8cs_source.html | 78 +- _routes_8cs.html | 61 +- _routes_8cs_source.html | 77 +- _semaphore_slim_context_8cs.html | 61 +- _semaphore_slim_context_8cs_source.html | 72 +- _server_8cs.html | 59 +- _server_8cs_source.html | 113 +- _server_client_8cs.html | 59 +- _server_client_8cs_source.html | 110 +- _server_client_factory_8cs.html | 59 +- _server_client_factory_8cs_source.html | 91 +- _server_error_exception_8cs.html | 59 +- _server_error_exception_8cs_source.html | 77 +- _server_factory_8cs.html | 59 +- _server_factory_8cs_source.html | 69 +- _server_information_8cs.html | 61 +- _server_information_8cs_source.html | 63 +- _server_service_8cs.html | 61 +- _server_service_8cs_source.html | 91 +- _server_side_modifications_8cs.html | 63 +- _server_side_modifications_8cs_source.html | 65 +- _service_collection_extensions_8cs.html | 61 +- ...vice_collection_extensions_8cs_source.html | 71 +- _service_unavailable_exception_8cs.html | 59 +- ...vice_unavailable_exception_8cs_source.html | 76 +- _session_controller_8cs.html | 63 +- _session_controller_8cs_source.html | 209 ++-- _session_controller_factory_8cs.html | 63 +- _session_controller_factory_8cs_source.html | 195 ++- _setup_wizard_8cs.html | 61 +- _setup_wizard_8cs_source.html | 147 ++- _setup_wizard_mode_8cs.html | 65 +- _setup_wizard_mode_8cs_source.html | 69 +- _sql_server_database_context_8cs.html | 63 +- _sql_server_database_context_8cs_source.html | 75 +- ...r_database_context_model_snapshot_8cs.html | 63 +- ...ase_context_model_snapshot_8cs_source.html | 59 +- ...er_design_time_db_context_factory_8cs.html | 63 +- ...gn_time_db_context_factory_8cs_source.html | 70 +- _synchronous_i_o_manager_8cs.html | 61 +- _synchronous_i_o_manager_8cs_source.html | 75 +- _task_extensions_8cs.html | 105 ++ _task_extensions_8cs_source.html | 86 ++ _temporary_dmb_provider_8cs.html | 65 +- _temporary_dmb_provider_8cs_source.html | 74 +- _test_api_client_8cs.html | 61 +- _test_api_client_8cs_source.html | 73 +- _test_api_headers_8cs.html | 63 +- _test_api_headers_8cs_source.html | 65 +- _test_application_8cs.html | 63 +- _test_application_8cs_source.html | 79 +- _test_async_delayer_8cs.html | 63 +- _test_async_delayer_8cs_source.html | 61 +- _test_authentication_context_8cs.html | 65 +- _test_authentication_context_8cs_source.html | 77 +- _test_console_8cs.html | 63 +- _test_console_8cs_source.html | 61 +- _test_d_b_connection_factory_8cs.html | 63 +- _test_d_b_connection_factory_8cs_source.html | 70 +- _test_database_context_factory_8cs.html | 63 +- ...t_database_context_factory_8cs_source.html | 67 +- _test_discord_provider_8cs.html | 67 +- _test_discord_provider_8cs_source.html | 65 +- _test_dream_daemon_client_8cs.html | 63 +- _test_dream_daemon_client_8cs_source.html | 73 +- _test_git_hub_client_factory_8cs.html | 63 +- _test_git_hub_client_factory_8cs_source.html | 64 +- _test_irc_connection_string_builder_8cs.html | 63 +- ..._connection_string_builder_8cs_source.html | 64 +- _test_job_exception_8cs.html | 63 +- _test_job_exception_8cs_source.html | 63 +- _test_job_handler_8cs.html | 63 +- _test_job_handler_8cs_source.html | 63 +- _test_merge_base_8cs.html | 63 +- _test_merge_base_8cs_source.html | 79 +- _test_merge_parameters_8cs.html | 61 +- _test_merge_parameters_8cs_source.html | 64 +- _test_platform_identifier_8cs.html | 63 +- _test_platform_identifier_8cs_source.html | 61 +- _test_posix_byond_installer_8cs.html | 65 +- _test_posix_byond_installer_8cs_source.html | 69 +- _test_post_write_handler_8cs.html | 63 +- _test_post_write_handler_8cs_source.html | 69 +- _test_program_8cs.html | 63 +- _test_program_8cs_source.html | 69 +- _test_rights_8cs.html | 63 +- _test_rights_8cs_source.html | 66 +- _test_server_client_factory_8cs.html | 61 +- _test_server_client_factory_8cs_source.html | 61 +- _test_server_factory_8cs.html | 61 +- _test_server_factory_8cs_source.html | 61 +- _test_server_service_8cs.html | 65 +- _test_server_service_8cs_source.html | 73 +- _test_service_collection_extensions_8cs.html | 63 +- ...vice_collection_extensions_8cs_source.html | 67 +- _test_setup_wizard_8cs.html | 63 +- _test_setup_wizard_8cs_source.html | 71 +- _test_symlink_factory_8cs.html | 63 +- _test_symlink_factory_8cs_source.html | 67 +- _test_watchdog_factory_8cs.html | 63 +- _test_watchdog_factory_8cs_source.html | 60 +- _testing_server_8cs.html | 59 +- _testing_server_8cs_source.html | 77 +- _tgs_authorize_attribute_8cs.html | 61 +- _tgs_authorize_attribute_8cs_source.html | 104 +- ..._server_8_api_2_models_2_chat_bot_8cs.html | 61 +- ..._8_api_2_models_2_chat_bot_8cs_source.html | 65 +- ...ver_8_api_2_models_2_chat_channel_8cs.html | 61 +- ...pi_2_models_2_chat_channel_8cs_source.html | 67 +- ...rver_8_api_2_models_2_compile_job_8cs.html | 61 +- ...api_2_models_2_compile_job_8cs_source.html | 64 +- ...rver_8_api_2_models_2_dream_maker_8cs.html | 63 +- ...api_2_models_2_dream_maker_8cs_source.html | 66 +- ..._server_8_api_2_models_2_instance_8cs.html | 61 +- ..._8_api_2_models_2_instance_8cs_source.html | 74 +- ...er_8_api_2_models_2_instance_user_8cs.html | 63 +- ...i_2_models_2_instance_user_8cs_source.html | 79 +- ...pi_2_models_2_internal_2_chat_bot_8cs.html | 63 +- ...dels_2_internal_2_chat_bot_8cs_source.html | 77 +- ...2_models_2_internal_2_compile_job_8cs.html | 65 +- ...s_2_internal_2_compile_job_8cs_source.html | 68 +- ..._internal_2_dream_daemon_settings_8cs.html | 65 +- ...al_2_dream_daemon_settings_8cs_source.html | 66 +- ...r_8_api_2_models_2_internal_2_job_8cs.html | 63 +- ..._2_models_2_internal_2_job_8cs_source.html | 74 +- ..._2_internal_2_repository_settings_8cs.html | 65 +- ...rnal_2_repository_settings_8cs_source.html | 70 +- ...2_internal_2_revision_information_8cs.html | 63 +- ...nal_2_revision_information_8cs_source.html | 63 +- ..._2_models_2_internal_2_test_merge_8cs.html | 63 +- ...ls_2_internal_2_test_merge_8cs_source.html | 65 +- ..._8_api_2_models_2_internal_2_user_8cs.html | 65 +- ...2_models_2_internal_2_user_8cs_source.html | 75 +- ...ion_8_server_8_api_2_models_2_job_8cs.html | 61 +- ...erver_8_api_2_models_2_job_8cs_source.html | 63 +- ...erver_8_api_2_models_2_repository_8cs.html | 61 +- ..._api_2_models_2_repository_8cs_source.html | 71 +- ...i_2_models_2_revision_information_8cs.html | 61 +- ...els_2_revision_information_8cs_source.html | 64 +- ...erver_8_api_2_models_2_test_merge_8cs.html | 61 +- ..._api_2_models_2_test_merge_8cs_source.html | 61 +- ...on_8_server_8_api_2_models_2_user_8cs.html | 61 +- ...rver_8_api_2_models_2_user_8cs_source.html | 61 +- ...on_8_server_8_api_8_assembly_info_8cs.html | 59 +- ...rver_8_api_8_assembly_info_8cs_source.html | 62 +- ...ver_8_api_8_tests_8_assembly_info_8cs.html | 59 +- ...pi_8_tests_8_assembly_info_8cs_source.html | 62 +- ..._8_server_8_api_8_tests_8_program_8cs.html | 59 +- ...er_8_api_8_tests_8_program_8cs_source.html | 62 +- ...8_server_8_client_2_assembly_info_8cs.html | 57 +- ...r_8_client_2_assembly_info_8cs_source.html | 82 ++ ...8_server_8_client_8_assembly_info_8cs.html | 59 +- ...r_8_client_8_assembly_info_8cs_source.html | 62 +- ..._8_client_8_tests_8_assembly_info_8cs.html | 59 +- ...nt_8_tests_8_assembly_info_8cs_source.html | 62 +- ...server_8_client_8_tests_8_program_8cs.html | 59 +- ...8_client_8_tests_8_program_8cs_source.html | 62 +- ...n_8_server_8_host_2_assembly_info_8cs.html | 57 +- ...ver_8_host_2_assembly_info_8cs_source.html | 82 ++ ...8_host_2_components_2_chat_2_user_8cs.html | 63 +- ...2_components_2_chat_2_user_8cs_source.html | 67 +- ...mponents_2_compiler_2_dream_maker_8cs.html | 63 +- ...s_2_compiler_2_dream_maker_8cs_source.html | 175 ++- ...er_8_host_2_components_2_instance_8cs.html | 61 +- ...st_2_components_2_instance_8cs_source.html | 197 ++-- ...components_2_interop_2_test_merge_8cs.html | 63 +- ...nts_2_interop_2_test_merge_8cs_source.html | 76 +- ...ponents_2_repository_2_repository_8cs.html | 63 +- ..._2_repository_2_repository_8cs_source.html | 127 +- ...server_8_host_2_models_2_chat_bot_8cs.html | 61 +- ...8_host_2_models_2_chat_bot_8cs_source.html | 69 +- ...er_8_host_2_models_2_chat_channel_8cs.html | 61 +- ...st_2_models_2_chat_channel_8cs_source.html | 73 +- ...ver_8_host_2_models_2_compile_job_8cs.html | 61 +- ...ost_2_models_2_compile_job_8cs_source.html | 71 +- ..._2_models_2_dream_daemon_settings_8cs.html | 61 +- ...ls_2_dream_daemon_settings_8cs_source.html | 67 +- ...server_8_host_2_models_2_instance_8cs.html | 63 +- ...8_host_2_models_2_instance_8cs_source.html | 77 +- ...r_8_host_2_models_2_instance_user_8cs.html | 61 +- ...t_2_models_2_instance_user_8cs_source.html | 80 +- ...on_8_server_8_host_2_models_2_job_8cs.html | 61 +- ...rver_8_host_2_models_2_job_8cs_source.html | 75 +- ...st_2_models_2_repository_settings_8cs.html | 61 +- ...dels_2_repository_settings_8cs_source.html | 79 +- ...t_2_models_2_revision_information_8cs.html | 61 +- ...els_2_revision_information_8cs_source.html | 70 +- ...rver_8_host_2_models_2_test_merge_8cs.html | 61 +- ...host_2_models_2_test_merge_8cs_source.html | 75 +- ...n_8_server_8_host_2_models_2_user_8cs.html | 61 +- ...ver_8_host_2_models_2_user_8cs_source.html | 76 +- ...n_8_server_8_host_8_assembly_info_8cs.html | 59 +- ...ver_8_host_8_assembly_info_8cs_source.html | 62 +- ..._8_host_8_console_2_assembly_info_8cs.html | 57 +- ..._8_console_2_assembly_info_8cs_source.html | 82 ++ ..._8_host_8_console_8_assembly_info_8cs.html | 59 +- ..._8_console_8_assembly_info_8cs_source.html | 62 +- ...8_console_8_tests_8_assembly_info_8cs.html | 59 +- ...le_8_tests_8_assembly_info_8cs_source.html | 62 +- ..._host_8_console_8_tests_8_program_8cs.html | 59 +- ..._console_8_tests_8_program_8cs_source.html | 62 +- ...rver_8_host_8_razor_assembly_info_8cs.html | 59 +- ...host_8_razor_assembly_info_8cs_source.html | 62 +- ...vice_2_properties_2_assembly_info_8cs.html | 57 +- ...properties_2_assembly_info_8cs_source.html | 82 ++ ..._8_host_8_service_8_assembly_info_8cs.html | 84 ++ ..._8_service_8_assembly_info_8cs_source.html | 82 ++ ...8_service_8_tests_8_assembly_info_8cs.html | 63 +- ...ce_8_tests_8_assembly_info_8cs_source.html | 82 ++ ...onents_2_watchdog_2_test_watchdog_8cs.html | 65 +- ...2_watchdog_2_test_watchdog_8cs_source.html | 81 +- ...er_8_host_8_tests_8_assembly_info_8cs.html | 59 +- ...st_8_tests_8_assembly_info_8cs_source.html | 62 +- ...8_server_8_host_8_tests_8_program_8cs.html | 59 +- ...r_8_host_8_tests_8_program_8cs_source.html | 62 +- ...8_host_8_watchdog_2_assembly_info_8cs.html | 57 +- ...8_watchdog_2_assembly_info_8cs_source.html | 82 ++ ...8_host_8_watchdog_8_assembly_info_8cs.html | 59 +- ...8_watchdog_8_assembly_info_8cs_source.html | 62 +- ..._watchdog_8_tests_2_test_watchdog_8cs.html | 63 +- ...og_8_tests_2_test_watchdog_8cs_source.html | 62 +- ..._watchdog_8_tests_8_assembly_info_8cs.html | 59 +- ...og_8_tests_8_assembly_info_8cs_source.html | 62 +- ...host_8_watchdog_8_tests_8_program_8cs.html | 59 +- ...watchdog_8_tests_8_program_8cs_source.html | 62 +- ..._8_server_8_tests_8_assembly_info_8cs.html | 59 +- ...er_8_tests_8_assembly_info_8cs_source.html | 62 +- ...tation_8_server_8_tests_8_program_8cs.html | 59 +- ...8_server_8_tests_8_program_8cs_source.html | 62 +- _token_8cs.html | 61 +- _token_8cs_source.html | 63 +- _token_factory_8cs.html | 61 +- _token_factory_8cs_source.html | 87 +- _unauthorized_exception_8cs.html | 59 +- _unauthorized_exception_8cs_source.html | 76 +- _unrecognized_response_exception_8cs.html | 59 +- ...ognized_response_exception_8cs_source.html | 76 +- _updates_configuration_8cs.html | 61 +- _updates_configuration_8cs_source.html | 68 +- _user_controller_8cs.html | 61 +- _user_controller_8cs_source.html | 124 +- _user_update_8cs.html | 61 +- _user_update_8cs_source.html | 61 +- _users_client_8cs.html | 59 +- _users_client_8cs_source.html | 86 +- _version_command_8cs.html | 67 +- _version_command_8cs_source.html | 81 +- _watchdog_2_i_watchdog_8cs.html | 61 +- _watchdog_2_i_watchdog_8cs_source.html | 63 +- _watchdog_2_i_watchdog_factory_8cs.html | 63 +- ...chdog_2_i_watchdog_factory_8cs_source.html | 63 +- _watchdog_2_watchdog_8cs.html | 61 +- _watchdog_2_watchdog_8cs_source.html | 71 +- _watchdog_2_watchdog_factory_8cs.html | 61 +- _watchdog_2_watchdog_factory_8cs_source.html | 66 +- _watchdog_reattach_information_base_8cs.html | 63 +- ..._reattach_information_base_8cs_source.html | 67 +- _windows_byond_installer_8cs.html | 65 +- _windows_byond_installer_8cs_source.html | 117 +- _windows_network_prompt_reaper_8cs.html | 63 +- ...dows_network_prompt_reaper_8cs_source.html | 107 +- _windows_post_write_handler_8cs.html | 63 +- _windows_post_write_handler_8cs_source.html | 65 +- _windows_symlink_factory_8cs.html | 63 +- _windows_symlink_factory_8cs_source.html | 69 +- _windows_system_identity_8cs.html | 63 +- _windows_system_identity_8cs_source.html | 78 +- _windows_system_identity_factory_8cs.html | 63 +- ...ws_system_identity_factory_8cs_source.html | 78 +- annotated.html | 246 ++-- api.html | 69 +- architecture.html | 57 +- arrowdown.png | Bin 246 -> 0 bytes arrowright.png | Bin 229 -> 0 bytes class_authorize_attribute.html | 64 +- class_auto_generated_program-members.html | 58 +- class_auto_generated_program.html | 156 ++- class_controller.html | 68 +- class_db_context.html | 62 +- class_i_application_lifetime.html | 62 +- class_i_design_time_db_context_factory.html | 62 +- class_i_disposable.html | 110 +- class_i_event_log.html | 114 -- class_i_event_log.png | Bin 731 -> 0 bytes class_i_hosted_service.html | 78 +- class_json_converter.html | 64 +- class_migration.html | 82 +- class_model_snapshot.html | 62 +- class_release_notes_1_1_program-members.html | 58 +- class_release_notes_1_1_program.html | 74 +- class_service_base.html | 64 +- ...erver_1_1_api_1_1_api_headers-members.html | 62 +- ...on_1_1_server_1_1_api_1_1_api_headers.html | 400 ++++--- ...1_1_models_1_1_administration-members.html | 58 +- ...1_1_api_1_1_models_1_1_administration.html | 104 +- ..._1_1_api_1_1_models_1_1_byond-members.html | 58 +- ...1_server_1_1_api_1_1_models_1_1_byond.html | 84 +- ...1_api_1_1_models_1_1_chat_bot-members.html | 67 +- ...erver_1_1_api_1_1_models_1_1_chat_bot.html | 122 +- ...i_1_1_models_1_1_chat_channel-members.html | 66 +- ...r_1_1_api_1_1_models_1_1_chat_channel.html | 158 ++- ...pi_1_1_models_1_1_compile_job-members.html | 62 +- ...er_1_1_api_1_1_models_1_1_compile_job.html | 120 +- ...models_1_1_configuration_file-members.html | 62 +- ...api_1_1_models_1_1_configuration_file.html | 132 +-- ...ord_connection_string_builder-members.html | 58 +- ...1_1_discord_connection_string_builder.html | 118 +- ...i_1_1_models_1_1_dream_daemon-members.html | 82 +- ...r_1_1_api_1_1_models_1_1_dream_daemon.html | 212 ++-- ...pi_1_1_models_1_1_dream_maker-members.html | 62 +- ...er_1_1_api_1_1_models_1_1_dream_maker.html | 116 +- ..._1_1_models_1_1_error_message-members.html | 58 +- ..._1_1_api_1_1_models_1_1_error_message.html | 84 +- ...1_api_1_1_models_1_1_instance-members.html | 64 +- ...erver_1_1_api_1_1_models_1_1_instance.html | 184 ++- ..._1_1_models_1_1_instance_user-members.html | 74 +- ..._1_1_api_1_1_models_1_1_instance_user.html | 216 ++-- ...els_1_1_internal_1_1_chat_bot-members.html | 65 +- ..._1_1_models_1_1_internal_1_1_chat_bot.html | 230 ++-- ...hat_connection_string_builder-members.html | 58 +- ...al_1_1_chat_connection_string_builder.html | 96 +- ..._1_1_internal_1_1_compile_job-members.html | 62 +- ...1_models_1_1_internal_1_1_compile_job.html | 134 +-- ...ream_daemon_launch_parameters-members.html | 68 +- ...al_1_1_dream_daemon_launch_parameters.html | 180 ++- ...nal_1_1_dream_daemon_settings-members.html | 74 +- ..._1_internal_1_1_dream_daemon_settings.html | 158 ++- ...1_models_1_1_internal_1_1_job-members.html | 68 +- ...1_api_1_1_models_1_1_internal_1_1_job.html | 204 ++-- ...ernal_1_1_repository_settings-members.html | 68 +- ..._1_1_internal_1_1_repository_settings.html | 198 ++-- ...rnal_1_1_revision_information-members.html | 58 +- ...1_1_internal_1_1_revision_information.html | 84 +- ...s_1_1_internal_1_1_test_merge-members.html | 60 +- ..._1_models_1_1_internal_1_1_test_merge.html | 114 +- ..._internal_1_1_test_merge_base-members.html | 60 +- ...dels_1_1_internal_1_1_test_merge_base.html | 158 ++- ..._models_1_1_internal_1_1_user-members.html | 66 +- ..._api_1_1_models_1_1_internal_1_1_user.html | 190 ++- ...irc_connection_string_builder-members.html | 64 +- ...els_1_1_irc_connection_string_builder.html | 216 ++-- ...er_1_1_api_1_1_models_1_1_job-members.html | 70 +- ...1_1_server_1_1_api_1_1_models_1_1_job.html | 138 +-- ...api_1_1_models_1_1_repository-members.html | 70 +- ...ver_1_1_api_1_1_models_1_1_repository.html | 214 ++-- ...dels_1_1_revision_information-members.html | 58 +- ...i_1_1_models_1_1_revision_information.html | 98 +- ...models_1_1_server_information-members.html | 58 +- ...api_1_1_models_1_1_server_information.html | 78 +- ...api_1_1_models_1_1_test_merge-members.html | 60 +- ...ver_1_1_api_1_1_models_1_1_test_merge.html | 104 +- ...els_1_1_test_merge_parameters-members.html | 60 +- ..._1_1_models_1_1_test_merge_parameters.html | 108 +- ...irc_connection_string_builder-members.html | 58 +- ..._1_test_irc_connection_string_builder.html | 68 +- ..._1_1_api_1_1_models_1_1_token-members.html | 60 +- ...1_server_1_1_api_1_1_models_1_1_token.html | 90 +- ...r_1_1_api_1_1_models_1_1_user-members.html | 66 +- ..._1_server_1_1_api_1_1_models_1_1_user.html | 122 +- ...pi_1_1_models_1_1_user_update-members.html | 66 +- ...er_1_1_api_1_1_models_1_1_user_update.html | 110 +- ..._1_1_rights_1_1_rights_helper-members.html | 58 +- ..._1_1_api_1_1_rights_1_1_rights_helper.html | 122 +- ...hts_1_1_tests_1_1_test_rights-members.html | 58 +- ..._1_1_rights_1_1_tests_1_1_test_rights.html | 72 +- ...1_1_server_1_1_api_1_1_routes-members.html | 58 +- ...station_1_1_server_1_1_api_1_1_routes.html | 230 ++-- ..._1_tests_1_1_test_api_headers-members.html | 58 +- ..._1_api_1_1_tests_1_1_test_api_headers.html | 92 +- ...ent_1_1_administration_client-members.html | 58 +- ..._1_1_client_1_1_administration_client.html | 116 +- ...ver_1_1_client_1_1_api_client-members.html | 62 +- ..._1_1_server_1_1_client_1_1_api_client.html | 337 +++--- ...client_1_1_api_client_factory-members.html | 58 +- ...ver_1_1_client_1_1_api_client_factory.html | 76 +- ...nt_1_1_api_conflict_exception-members.html | 74 +- ...1_1_client_1_1_api_conflict_exception.html | 195 ++- ...nt_1_1_api_mismatch_exception-members.html | 66 +- ...1_1_client_1_1_api_mismatch_exception.html | 126 +- ...1_client_1_1_client_exception-members.html | 66 +- ...erver_1_1_client_1_1_client_exception.html | 249 ++-- ...1_components_1_1_byond_client-members.html | 60 +- ...lient_1_1_components_1_1_byond_client.html | 135 +-- ...mponents_1_1_chat_bots_client-members.html | 62 +- ...t_1_1_components_1_1_chat_bots_client.html | 163 +-- ...ents_1_1_configuration_client-members.html | 60 +- ...1_components_1_1_configuration_client.html | 187 +-- ...nents_1_1_dream_daemon_client-members.html | 60 +- ..._1_components_1_1_dream_daemon_client.html | 153 ++- ...onents_1_1_dream_maker_client-members.html | 60 +- ...1_1_components_1_1_dream_maker_client.html | 151 ++- ...omponents_1_1_instance_client-members.html | 58 +- ...nt_1_1_components_1_1_instance_client.html | 196 ++-- ...ents_1_1_instance_user_client-members.html | 62 +- ...1_components_1_1_instance_user_client.html | 171 +-- ..._1_components_1_1_jobs_client-members.html | 58 +- ...client_1_1_components_1_1_jobs_client.html | 133 +-- ...ponents_1_1_repository_client-members.html | 60 +- ..._1_1_components_1_1_repository_client.html | 150 ++- ..._1_1_test_dream_daemon_client-members.html | 58 +- ..._1_tests_1_1_test_dream_daemon_client.html | 78 +- ...client_1_1_conflict_exception-members.html | 66 +- ...ver_1_1_client_1_1_conflict_exception.html | 126 +- ...er_1_1_client_1_1_http_client-members.html | 58 +- ...1_1_server_1_1_client_1_1_http_client.html | 112 +- ...t_1_1_instance_manager_client-members.html | 62 +- ..._1_client_1_1_instance_manager_client.html | 184 +-- ...ficient_permissions_exception-members.html | 66 +- ..._1_insufficient_permissions_exception.html | 114 +- ...ethod_not_supported_exception-members.html | 66 +- ...nt_1_1_method_not_supported_exception.html | 114 +- ...ient_1_1_rate_limit_exception-members.html | 66 +- ...r_1_1_client_1_1_rate_limit_exception.html | 124 +- ...1_1_request_timeout_exception-members.html | 66 +- ..._client_1_1_request_timeout_exception.html | 114 +- ..._1_1_client_1_1_server_client-members.html | 60 +- ...1_server_1_1_client_1_1_server_client.html | 217 ++-- ...ent_1_1_server_client_factory-members.html | 58 +- ..._1_1_client_1_1_server_client_factory.html | 150 ++- ...nt_1_1_server_error_exception-members.html | 66 +- ...1_1_client_1_1_server_error_exception.html | 126 +- ...service_unavailable_exception-members.html | 66 +- ...ent_1_1_service_unavailable_exception.html | 114 +- ...1_1_tests_1_1_test_api_client-members.html | 58 +- ..._client_1_1_tests_1_1_test_api_client.html | 96 +- ..._1_test_server_client_factory-members.html | 58 +- ..._tests_1_1_test_server_client_factory.html | 68 +- ...nt_1_1_unauthorized_exception-members.html | 66 +- ...1_1_client_1_1_unauthorized_exception.html | 114 +- ...recognized_response_exception-members.html | 66 +- ...t_1_1_unrecognized_response_exception.html | 126 +- ...r_1_1_client_1_1_users_client-members.html | 62 +- ..._1_server_1_1_client_1_1_users_client.html | 152 ++- ...ond_1_1_byond_executable_lock-members.html | 58 +- ...s_1_1_byond_1_1_byond_executable_lock.html | 120 +- ...s_1_1_byond_1_1_byond_manager-members.html | 58 +- ...omponents_1_1_byond_1_1_byond_manager.html | 366 +++--- ...ond_1_1_posix_byond_installer-members.html | 58 +- ...s_1_1_byond_1_1_posix_byond_installer.html | 250 ++-- ..._1_test_posix_byond_installer-members.html | 58 +- ..._tests_1_1_test_posix_byond_installer.html | 90 +- ...d_1_1_windows_byond_installer-members.html | 58 +- ...1_1_byond_1_1_windows_byond_installer.html | 304 ++--- ...mponents_1_1_chat_1_1_channel-members.html | 58 +- ...t_1_1_components_1_1_chat_1_1_channel.html | 149 ++- ..._1_1_chat_1_1_channel_mapping-members.html | 58 +- ...mponents_1_1_chat_1_1_channel_mapping.html | 126 +- ..._components_1_1_chat_1_1_chat-members.html | 58 +- ...host_1_1_components_1_1_chat_1_1_chat.html | 656 ++++++----- ...nts_1_1_chat_1_1_chat_factory-members.html | 58 +- ..._components_1_1_chat_1_1_chat_factory.html | 132 +-- ...1_commands_1_1_bool_converter-members.html | 58 +- ..._chat_1_1_commands_1_1_bool_converter.html | 76 +- ..._1_commands_1_1_byond_command-members.html | 58 +- ...1_chat_1_1_commands_1_1_byond_command.html | 156 +-- ..._commands_1_1_command_factory-members.html | 58 +- ...chat_1_1_commands_1_1_command_factory.html | 177 +-- ...1_commands_1_1_custom_command-members.html | 58 +- ..._chat_1_1_commands_1_1_custom_command.html | 144 ++- ..._1_1_commands_1_1_kek_command-members.html | 58 +- ...1_1_chat_1_1_commands_1_1_kek_command.html | 104 +- ...nds_1_1_pull_requests_command-members.html | 58 +- ..._1_commands_1_1_pull_requests_command.html | 193 +-- ...commands_1_1_revision_command-members.html | 58 +- ...hat_1_1_commands_1_1_revision_command.html | 174 +-- ..._commands_1_1_version_command-members.html | 58 +- ...chat_1_1_commands_1_1_version_command.html | 131 +-- ...hat_1_1_json_tracking_context-members.html | 60 +- ...ts_1_1_chat_1_1_json_tracking_context.html | 216 ++-- ...1_1_chat_1_1_provider_factory-members.html | 58 +- ...ponents_1_1_chat_1_1_provider_factory.html | 134 ++- ...roviders_1_1_discord_provider-members.html | 58 +- ...at_1_1_providers_1_1_discord_provider.html | 293 +++-- ..._1_providers_1_1_irc_provider-members.html | 62 +- ...1_chat_1_1_providers_1_1_irc_provider.html | 383 +++--- ...hat_1_1_providers_1_1_message-members.html | 58 +- ...ts_1_1_chat_1_1_providers_1_1_message.html | 88 +- ...at_1_1_providers_1_1_provider-members.html | 58 +- ...s_1_1_chat_1_1_providers_1_1_provider.html | 198 ++-- ...sts_1_1_test_discord_provider-members.html | 58 +- ...s_1_1_tests_1_1_test_discord_provider.html | 102 +- ...ponents_1_1_chat_1_1_response-members.html | 58 +- ..._1_1_components_1_1_chat_1_1_response.html | 80 +- ..._components_1_1_chat_1_1_user-members.html | 58 +- ...host_1_1_components_1_1_chat_1_1_user.html | 117 +- ..._1_1_compiler_1_1_dmb_factory-members.html | 60 +- ...mponents_1_1_compiler_1_1_dmb_factory.html | 394 ++++--- ...1_1_compiler_1_1_dmb_provider-members.html | 58 +- ...ponents_1_1_compiler_1_1_dmb_provider.html | 153 ++- ..._1_1_compiler_1_1_dream_maker-members.html | 62 +- ...mponents_1_1_compiler_1_1_dream_maker.html | 493 ++++---- ...er_1_1_temporary_dmb_provider-members.html | 58 +- ...1_compiler_1_1_temporary_dmb_provider.html | 136 ++- ...components_1_1_event_consumer-members.html | 58 +- ...ost_1_1_components_1_1_event_consumer.html | 131 +-- ...t_1_1_components_1_1_instance-members.html | 58 +- ..._1_1_host_1_1_components_1_1_instance.html | 500 ++++---- ...mponents_1_1_instance_factory-members.html | 58 +- ...t_1_1_components_1_1_instance_factory.html | 342 +++--- ...mponents_1_1_instance_manager-members.html | 58 +- ...t_1_1_components_1_1_instance_manager.html | 321 ++--- ..._1_1_interop_1_1_chat_command-members.html | 58 +- ...mponents_1_1_interop_1_1_chat_command.html | 92 +- ..._1_1_interop_1_1_comm_command-members.html | 58 +- ...mponents_1_1_interop_1_1_comm_command.html | 88 +- ..._1_1_interop_1_1_comm_context-members.html | 58 +- ...mponents_1_1_interop_1_1_comm_context.html | 205 ++-- ...nts_1_1_interop_1_1_constants-members.html | 58 +- ..._components_1_1_interop_1_1_constants.html | 212 ++-- ...nterop_1_1_event_notification-members.html | 58 +- ...ts_1_1_interop_1_1_event_notification.html | 86 +- ...nts_1_1_interop_1_1_json_file-members.html | 58 +- ..._components_1_1_interop_1_1_json_file.html | 160 ++- ...nterop_1_1_json_sub_file_list-members.html | 58 +- ...ts_1_1_interop_1_1_json_sub_file_list.html | 132 +-- ...ts_1_1_interop_1_1_test_merge-members.html | 60 +- ...components_1_1_interop_1_1_test_merge.html | 128 +- ...nts_1_1_reattach_info_handler-members.html | 58 +- ..._components_1_1_reattach_info_handler.html | 160 +-- ...tory_1_1_credentials_provider-members.html | 58 +- ...1_repository_1_1_credentials_provider.html | 96 +- ...1_1_repository_1_1_repository-members.html | 58 +- ...ponents_1_1_repository_1_1_repository.html | 515 ++++---- ...sitory_1_1_repository_manager-members.html | 58 +- ...1_1_repository_1_1_repository_manager.html | 292 ++--- ...tatic_files_1_1_configuration-members.html | 58 +- ...ts_1_1_static_files_1_1_configuration.html | 558 +++++---- ...1_1_server_side_modifications-members.html | 58 +- ...c_files_1_1_server_side_modifications.html | 108 +- ...g_1_1_dead_session_controller-members.html | 60 +- ..._watchdog_1_1_dead_session_controller.html | 266 +++-- ..._1_watchdog_1_1_launch_result-members.html | 62 +- ...onents_1_1_watchdog_1_1_launch_result.html | 100 +- ..._1_watchdog_1_1_monitor_state-members.html | 58 +- ...onents_1_1_watchdog_1_1_monitor_state.html | 122 +- ...1_posix_network_prompt_reaper-members.html | 58 +- ...chdog_1_1_posix_network_prompt_reaper.html | 76 +- ...hdog_1_1_reattach_information-members.html | 58 +- ...1_1_watchdog_1_1_reattach_information.html | 138 +-- ...tchdog_1_1_session_controller-members.html | 68 +- ...s_1_1_watchdog_1_1_session_controller.html | 725 +++++++----- ..._1_session_controller_factory-members.html | 58 +- ...tchdog_1_1_session_controller_factory.html | 341 +++--- ...g_1_1_tests_1_1_test_watchdog-members.html | 58 +- ..._watchdog_1_1_tests_1_1_test_watchdog.html | 88 +- ...nts_1_1_watchdog_1_1_watchdog-members.html | 60 +- ..._components_1_1_watchdog_1_1_watchdog.html | 900 +++++++------- ...watchdog_1_1_watchdog_factory-members.html | 58 +- ...nts_1_1_watchdog_1_1_watchdog_factory.html | 152 +-- ...watchdog_reattach_information-members.html | 58 +- ...dog_1_1_watchdog_reattach_information.html | 142 +-- ...windows_network_prompt_reaper-members.html | 58 +- ...dog_1_1_windows_network_prompt_reaper.html | 241 ++-- ...1_control_panel_configuration-members.html | 58 +- ...ation_1_1_control_panel_configuration.html | 104 +- ...on_1_1_database_configuration-members.html | 58 +- ...figuration_1_1_database_configuration.html | 126 +- ..._1_file_logging_configuration-members.html | 58 +- ...ration_1_1_file_logging_configuration.html | 142 ++- ...ion_1_1_general_configuration-members.html | 58 +- ...nfiguration_1_1_general_configuration.html | 167 +-- ...ion_1_1_updates_configuration-members.html | 58 +- ...nfiguration_1_1_updates_configuration.html | 135 ++- ..._host_1_1_console_1_1_program-members.html | 60 +- ...rver_1_1_host_1_1_console_1_1_program.html | 152 ++- ...le_1_1_tests_1_1_test_program-members.html | 58 +- ..._1_console_1_1_tests_1_1_test_program.html | 68 +- ...1_1_administration_controller-members.html | 97 +- ...rollers_1_1_administration_controller.html | 375 +++--- ...ontrollers_1_1_api_controller-members.html | 58 +- ...st_1_1_controllers_1_1_api_controller.html | 220 ++-- ...trollers_1_1_byond_controller-members.html | 58 +- ..._1_1_controllers_1_1_byond_controller.html | 180 ++- ...ntrollers_1_1_chat_controller-members.html | 58 +- ...t_1_1_controllers_1_1_chat_controller.html | 255 ++-- ..._1_1_configuration_controller-members.html | 58 +- ...trollers_1_1_configuration_controller.html | 288 ++--- ...s_1_1_dream_daemon_controller-members.html | 58 +- ...ntrollers_1_1_dream_daemon_controller.html | 304 ++--- ...rs_1_1_dream_maker_controller-members.html | 58 +- ...ontrollers_1_1_dream_maker_controller.html | 248 ++-- ...ntrollers_1_1_home_controller-members.html | 58 +- ...t_1_1_controllers_1_1_home_controller.html | 279 +++-- ...llers_1_1_instance_controller-members.html | 58 +- ...1_controllers_1_1_instance_controller.html | 389 +++--- ..._1_1_instance_user_controller-members.html | 58 +- ...trollers_1_1_instance_user_controller.html | 222 ++-- ...ontrollers_1_1_job_controller-members.html | 58 +- ...st_1_1_controllers_1_1_job_controller.html | 187 ++- ...trollers_1_1_model_controller-members.html | 58 +- ..._1_1_controllers_1_1_model_controller.html | 130 +- ...ers_1_1_repository_controller-members.html | 58 +- ...controllers_1_1_repository_controller.html | 368 +++--- ...s_1_1_tgs_authorize_attribute-members.html | 58 +- ...ntrollers_1_1_tgs_authorize_attribute.html | 182 ++- ...ntrollers_1_1_user_controller-members.html | 58 +- ...t_1_1_controllers_1_1_user_controller.html | 288 ++--- ...host_1_1_core_1_1_application-members.html | 58 +- ...ver_1_1_host_1_1_core_1_1_application.html | 289 ++--- ...pplication_builder_extensions-members.html | 58 +- ...re_1_1_application_builder_extensions.html | 88 +- ...st_1_1_core_1_1_async_delayer-members.html | 58 +- ...r_1_1_host_1_1_core_1_1_async_delayer.html | 74 +- ...re_1_1_d_b_connection_factory-members.html | 58 +- ...t_1_1_core_1_1_d_b_connection_factory.html | 78 +- ..._1_1_database_context_factory-members.html | 58 +- ...1_1_core_1_1_database_context_factory.html | 104 +- ...re_1_1_git_hub_client_factory-members.html | 58 +- ...t_1_1_core_1_1_git_hub_client_factory.html | 118 +- ...st_1_1_core_1_1_job_exception-members.html | 58 +- ...r_1_1_host_1_1_core_1_1_job_exception.html | 94 +- ...host_1_1_core_1_1_job_handler-members.html | 60 +- ...ver_1_1_host_1_1_core_1_1_job_handler.html | 152 ++- ...host_1_1_core_1_1_job_manager-members.html | 60 +- ...ver_1_1_host_1_1_core_1_1_job_manager.html | 288 ++--- ..._core_1_1_platform_identifier-members.html | 58 +- ...host_1_1_core_1_1_platform_identifier.html | 94 +- ...1_1_host_1_1_core_1_1_process-members.html | 58 +- ..._server_1_1_host_1_1_core_1_1_process.html | 227 ++-- ...1_1_core_1_1_process_executor-members.html | 58 +- ..._1_host_1_1_core_1_1_process_executor.html | 144 ++- ...core_1_1_restart_registration-members.html | 58 +- ...ost_1_1_core_1_1_restart_registration.html | 90 +- ...re_1_1_semaphore_slim_context-members.html | 58 +- ...t_1_1_core_1_1_semaphore_slim_context.html | 142 +-- ...service_collection_extensions-members.html | 58 +- ...ore_1_1_service_collection_extensions.html | 76 +- ...ost_1_1_core_1_1_setup_wizard-members.html | 60 +- ...er_1_1_host_1_1_core_1_1_setup_wizard.html | 452 ++++--- ..._1_1_core_1_1_task_extensions-members.html | 87 ++ ...1_1_host_1_1_core_1_1_task_extensions.html | 208 ++++ ..._1_tests_1_1_test_application-members.html | 58 +- ...1_core_1_1_tests_1_1_test_application.html | 78 +- ...1_1_mock_application_lifetime-members.html | 58 +- ...ication_1_1_mock_application_lifetime.html | 88 +- ...ication_1_1_mock_setup_wizard-members.html | 58 +- ...est_application_1_1_mock_setup_wizard.html | 72 +- ..._tests_1_1_test_async_delayer-members.html | 58 +- ...core_1_1_tests_1_1_test_async_delayer.html | 72 +- ...1_test_d_b_connection_factory-members.html | 58 +- ...tests_1_1_test_d_b_connection_factory.html | 76 +- ...test_database_context_factory-members.html | 58 +- ...sts_1_1_test_database_context_factory.html | 76 +- ...1_test_git_hub_client_factory-members.html | 58 +- ...tests_1_1_test_git_hub_client_factory.html | 78 +- ..._tests_1_1_test_job_exception-members.html | 58 +- ...core_1_1_tests_1_1_test_job_exception.html | 66 +- ..._1_tests_1_1_test_job_handler-members.html | 58 +- ...1_core_1_1_tests_1_1_test_job_handler.html | 126 +- ..._1_1_test_platform_identifier-members.html | 58 +- ..._1_tests_1_1_test_platform_identifier.html | 66 +- ...service_collection_extensions-members.html | 58 +- ..._1_test_service_collection_extensions.html | 68 +- ...on_extensions_1_1_bad_config1-members.html | 58 +- ...collection_extensions_1_1_bad_config1.html | 66 +- ...on_extensions_1_1_bad_config2-members.html | 58 +- ...collection_extensions_1_1_bad_config2.html | 66 +- ...collection_extensions_1_1_bad_config3.html | 60 +- ...on_extensions_1_1_good_config-members.html | 58 +- ...collection_extensions_1_1_good_config.html | 66 +- ...1_tests_1_1_test_setup_wizard-members.html | 58 +- ..._core_1_1_tests_1_1_test_setup_wizard.html | 80 +- ..._1_1_host_1_1_i_o_1_1_console-members.html | 58 +- ...1_server_1_1_host_1_1_i_o_1_1_console.html | 108 +- ...1_i_o_1_1_default_i_o_manager-members.html | 58 +- ..._host_1_1_i_o_1_1_default_i_o_manager.html | 344 +++--- ..._1_1_posix_post_write_handler-members.html | 58 +- ..._1_1_i_o_1_1_posix_post_write_handler.html | 82 +- ...i_o_1_1_posix_symlink_factory-members.html | 58 +- ...ost_1_1_i_o_1_1_posix_symlink_factory.html | 78 +- ...i_o_1_1_resolving_i_o_manager-members.html | 58 +- ...ost_1_1_i_o_1_1_resolving_i_o_manager.html | 162 ++- ...o_1_1_synchronous_i_o_manager-members.html | 58 +- ...t_1_1_i_o_1_1_synchronous_i_o_manager.html | 152 ++- ..._o_1_1_tests_1_1_test_console-members.html | 58 +- ...st_1_1_i_o_1_1_tests_1_1_test_console.html | 74 +- ...s_1_1_test_post_write_handler-members.html | 58 +- ...1_1_tests_1_1_test_post_write_handler.html | 86 +- ...ests_1_1_test_symlink_factory-members.html | 58 +- ..._o_1_1_tests_1_1_test_symlink_factory.html | 124 +- ..._1_windows_post_write_handler-members.html | 58 +- ..._1_i_o_1_1_windows_post_write_handler.html | 82 +- ...o_1_1_windows_symlink_factory-members.html | 58 +- ...t_1_1_i_o_1_1_windows_symlink_factory.html | 78 +- ..._host_1_1_models_1_1_chat_bot-members.html | 67 +- ...rver_1_1_host_1_1_models_1_1_chat_bot.html | 134 +-- ...t_1_1_models_1_1_chat_channel-members.html | 66 +- ..._1_1_host_1_1_models_1_1_chat_channel.html | 130 +- ...st_1_1_models_1_1_compile_job-members.html | 62 +- ...r_1_1_host_1_1_models_1_1_compile_job.html | 138 +-- ...1_models_1_1_database_context-members.html | 58 +- ..._host_1_1_models_1_1_database_context.html | 376 +++--- ..._1_models_1_1_database_seeder-members.html | 58 +- ...1_host_1_1_models_1_1_database_seeder.html | 138 +-- ...els_1_1_dream_daemon_settings-members.html | 76 +- ..._1_1_models_1_1_dream_daemon_settings.html | 178 ++- ...dels_1_1_dream_maker_settings-members.html | 62 +- ...t_1_1_models_1_1_dream_maker_settings.html | 120 +- ..._host_1_1_models_1_1_instance-members.html | 64 +- ...rver_1_1_host_1_1_models_1_1_instance.html | 204 ++-- ..._1_1_models_1_1_instance_user-members.html | 74 +- ...1_1_host_1_1_models_1_1_instance_user.html | 162 ++- ...r_1_1_host_1_1_models_1_1_job-members.html | 68 +- ..._1_server_1_1_host_1_1_models_1_1_job.html | 164 ++- ...me_db_context_factory_helpers-members.html | 58 +- ...esign_time_db_context_factory_helpers.html | 98 +- ..._1_1_m_s_add_minimum_security-members.html | 58 +- ...grations_1_1_m_s_add_minimum_security.html | 90 +- ...ns_1_1_m_s_fix_rev_info_index-members.html | 58 +- ...migrations_1_1_m_s_fix_rev_info_index.html | 90 +- ...ations_1_1_m_s_initial_create-members.html | 58 +- ...1_1_migrations_1_1_m_s_initial_create.html | 110 +- ...lable_and_foreign_key_cleanup-members.html | 58 +- ..._m_s_nullable_and_foreign_key_cleanup.html | 86 +- ...reattach_compile_job_required-members.html | 58 +- ...1_1_m_s_reattach_compile_job_required.html | 90 +- ...m_s_toggle_testmerge_comments-members.html | 58 +- ...ons_1_1_m_s_toggle_testmerge_comments.html | 90 +- ..._1_1_m_y_add_minimum_security-members.html | 58 +- ...grations_1_1_m_y_add_minimum_security.html | 90 +- ...ns_1_1_m_y_fix_rev_info_index-members.html | 58 +- ...migrations_1_1_m_y_fix_rev_info_index.html | 90 +- ...ations_1_1_m_y_initial_create-members.html | 58 +- ...1_1_migrations_1_1_m_y_initial_create.html | 110 +- ...lable_and_foreign_key_cleanup-members.html | 58 +- ..._m_y_nullable_and_foreign_key_cleanup.html | 86 +- ...reattach_compile_job_required-members.html | 58 +- ...1_1_m_y_reattach_compile_job_required.html | 90 +- ...m_y_toggle_testmerge_comments-members.html | 58 +- ...ons_1_1_m_y_toggle_testmerge_comments.html | 90 +- ...tabase_context_model_snapshot-members.html | 58 +- ...y_sql_database_context_model_snapshot.html | 70 +- ...esign_time_db_context_factory-members.html | 58 +- ...my_sql_design_time_db_context_factory.html | 75 +- ...tabase_context_model_snapshot-members.html | 58 +- ...erver_database_context_model_snapshot.html | 70 +- ...esign_time_db_context_factory-members.html | 58 +- ...server_design_time_db_context_factory.html | 75 +- ...s_1_1_my_sql_database_context-members.html | 58 +- ..._1_models_1_1_my_sql_database_context.html | 128 +- ...dels_1_1_reattach_information-members.html | 58 +- ...t_1_1_models_1_1_reattach_information.html | 116 +- ...1_1_reattach_information_base-members.html | 58 +- ..._models_1_1_reattach_information_base.html | 178 ++- ...odels_1_1_repository_settings-members.html | 68 +- ...st_1_1_models_1_1_repository_settings.html | 142 +-- ...odels_1_1_rev_info_test_merge-members.html | 58 +- ...st_1_1_models_1_1_rev_info_test_merge.html | 88 +- ...dels_1_1_revision_information-members.html | 58 +- ...t_1_1_models_1_1_revision_information.html | 146 ++- ...1_sql_server_database_context-members.html | 58 +- ...odels_1_1_sql_server_database_context.html | 120 +- ...ost_1_1_models_1_1_test_merge-members.html | 62 +- ...er_1_1_host_1_1_models_1_1_test_merge.html | 154 ++- ..._1_1_host_1_1_models_1_1_user-members.html | 68 +- ...1_server_1_1_host_1_1_models_1_1_user.html | 190 ++- ...watchdog_reattach_information-members.html | 58 +- ...els_1_1_watchdog_reattach_information.html | 122 +- ...dog_reattach_information_base-members.html | 58 +- ..._1_watchdog_reattach_information_base.html | 110 +- ...r_1_1_host_1_1_native_methods-members.html | 58 +- ..._1_server_1_1_host_1_1_native_methods.html | 129 +- ...1_server_1_1_host_1_1_program-members.html | 59 +- ...ation_1_1_server_1_1_host_1_1_program.html | 115 +- ...ty_1_1_authentication_context-members.html | 58 +- ...1_security_1_1_authentication_context.html | 158 ++- ...uthentication_context_factory-members.html | 60 +- ...ty_1_1_authentication_context_factory.html | 159 +-- ..._security_1_1_claims_injector-members.html | 58 +- ...host_1_1_security_1_1_claims_injector.html | 136 +-- ...curity_1_1_cryptography_suite-members.html | 58 +- ...t_1_1_security_1_1_cryptography_suite.html | 156 ++- ...1_security_1_1_identity_cache-members.html | 58 +- ..._host_1_1_security_1_1_identity_cache.html | 162 +-- ...ity_1_1_identity_cache_object-members.html | 58 +- ..._1_security_1_1_identity_cache_object.html | 136 +-- ...posix_system_identity_factory-members.html | 58 +- ...ity_1_1_posix_system_identity_factory.html | 86 +- ...1_test_authentication_context-members.html | 58 +- ...tests_1_1_test_authentication_context.html | 84 +- ..._1_security_1_1_token_factory-members.html | 58 +- ...1_host_1_1_security_1_1_token_factory.html | 149 +-- ...y_1_1_windows_system_identity-members.html | 58 +- ..._security_1_1_windows_system_identity.html | 180 +-- ...ndows_system_identity_factory-members.html | 58 +- ...y_1_1_windows_system_identity_factory.html | 116 +- ..._1_server_1_1_host_1_1_server-members.html | 58 +- ...tation_1_1_server_1_1_host_1_1_server.html | 328 +++--- ...r_1_1_host_1_1_server_factory-members.html | 58 +- ..._1_server_1_1_host_1_1_server_factory.html | 84 +- ..._host_1_1_service_1_1_program-members.html | 59 +- ...rver_1_1_host_1_1_service_1_1_program.html | 176 +-- ..._1_service_1_1_server_service-members.html | 74 +- ...1_host_1_1_service_1_1_server_service.html | 250 ++-- ..._1_host_1_1_service_1_1_server_service.png | Bin 1136 -> 758 bytes ...tests_1_1_test_server_service-members.html | 58 +- ...ice_1_1_tests_1_1_test_server_service.html | 82 +- ...tests_1_1_test_server_factory-members.html | 58 +- ...ost_1_1_tests_1_1_test_server_factory.html | 76 +- ...g_1_1_tests_1_1_test_watchdog-members.html | 58 +- ..._watchdog_1_1_tests_1_1_test_watchdog.html | 68 +- ...sts_1_1_test_watchdog_factory-members.html | 58 +- ...g_1_1_tests_1_1_test_watchdog_factory.html | 66 +- ...ost_1_1_watchdog_1_1_watchdog-members.html | 65 +- ...er_1_1_host_1_1_watchdog_1_1_watchdog.html | 144 ++- ...watchdog_1_1_watchdog_factory-members.html | 58 +- ...ost_1_1_watchdog_1_1_watchdog_factory.html | 76 +- ...tests_1_1_administration_test-members.html | 58 +- ...ver_1_1_tests_1_1_administration_test.html | 113 +- ...s_1_1_instance_1_1_byond_test-members.html | 58 +- ...1_1_tests_1_1_instance_1_1_byond_test.html | 130 +- ...stance_1_1_configuration_test-members.html | 58 +- ...s_1_1_instance_1_1_configuration_test.html | 131 ++- ..._1_instance_1_1_instance_test-members.html | 58 +- ..._tests_1_1_instance_1_1_instance_test.html | 99 +- ...sts_1_1_instance_manager_test-members.html | 58 +- ...r_1_1_tests_1_1_instance_manager_test.html | 135 ++- ..._1_tests_1_1_integration_test-members.html | 58 +- ...server_1_1_tests_1_1_integration_test.html | 136 +-- ..._1_1_tests_1_1_testing_server-members.html | 58 +- ...1_server_1_1_tests_1_1_testing_server.html | 130 +- classes.html | 258 ++-- ... dir_009a3598be1715e27911e1588bdd551c.html | 59 +- ... dir_019c6d3af924151b681494cc466be1ac.html | 63 +- dir_02f69155ced6ccca99a24744a5273903.html | 55 +- dir_08963d262fa9e27215dce7b7c6e97f1b.html | 55 +- ... dir_0b6a380fe7fc1e1d640d1ac854fc3fb6.html | 63 +- dir_0c9add60ab05c04ed8367ecaedf67c01.html | 55 +- dir_0de875c2ee7edd4009e892c5045f7b3a.html | 57 +- dir_0f5073360b9ba6d1522457c65eebe36a.html | 55 +- dir_103b33cf1ab7043de6f87dfa61afa23f.html | 57 +- ... dir_1083fcf52a7d94a2efffb6ca88246acf.html | 59 +- dir_1302441b003a340c6a16c9bc1b51c94e.html | 55 +- dir_177c182c6d1f29bec543c3fdad3072d5.html | 57 +- dir_18f2820c1d411453d7d989b812e41820.html | 88 ++ dir_1cebbc1bce26b60bfb2ee26c80f86b02.html | 57 +- dir_2133157f8312226ef9ea4ce42a802cf8.html | 55 +- ... dir_2553b13cbb871373b0c30fb90d66217c.html | 59 +- dir_26764abc66ddba24c5915db53fd68d23.html | 88 ++ ... dir_2b9d136d9ffdab429a63a74fca28b300.html | 63 +- ... dir_2e39d68cad3f83629c74ea67329dead9.html | 63 +- ... dir_2e67631cb23401d696bcfdbe81f86f0f.html | 63 +- dir_2ea2465064f3ff030c6dd6700a328d91.html | 55 +- dir_34761767c1c3cd212f9d2f80ea0828a8.html | 57 +- dir_38cec1532eaed7aa1de0b599a76e3e80.html | 55 +- dir_446bdfc1cd19b69c11765b5665ebfd45.html | 57 +- ... dir_48968f849f7ddb061f7130e079fe66a6.html | 63 +- dir_49e56c817e5e54854c35e136979f97ca.html | 82 ++ ... dir_4c0c7e2f4fc60f51e2347a2d8dda94ce.html | 59 +- dir_4ddbd20a555bd1f3bf9569744c8989cc.html | 55 +- dir_4eeb864c4eec08c7d6b9d3b0352cfdde.html | 55 +- dir_59425e443f801f1f2fd8bbe4959a3ccf.html | 55 +- dir_5d46d0c3fd1cac5ce1ea23751ad25792.html | 55 +- dir_5d5b300b88421e3050db28dd037f6f39.html | 55 +- dir_5e0b464d3b4be546c63c5188ffeb96e4.html | 55 +- dir_61d7974a657c30011f457b376d274ee7.html | 55 +- dir_68267d1309a1af8e8297ef4c3efbcdba.html | 55 +- dir_685b5aa2d8a661ab5bc3f68b331887b0.html | 57 +- dir_689f0584ee97ae9ca308532531d9c5d2.html | 57 +- dir_6c60df807dd2523776d391746c262b4d.html | 55 +- dir_71f5cbd840fdd1dea9f035c7b1a066ee.html | 55 +- dir_74017a19412e2f90cc6ad11fcac82495.html | 57 +- dir_78e87f8f095a8e3bb6ef1faef94cdb78.html | 88 ++ dir_7916dda968fadc8673161597975e4c5d.html | 55 +- dir_7a3fd032a1362a6005a1fc9227a8dd86.html | 55 +- dir_7a9487ad1984d08627fcf919e6f3d801.html | 55 +- dir_7cd79c49f3850abc2141fa4adfdd1950.html | 55 +- dir_860acef72838dce8d3d54c8f98bc464b.html | 55 +- ... dir_87039fa7b841d848ca75981d64237477.html | 63 +- dir_87a4f2035ed18e30422f4b60aebc4381.html | 57 +- ... dir_9257d56e926145e494a5aa5279887044.html | 59 +- dir_9826fb2d31585a830723e6d7089b5d0e.html | 57 +- dir_9aa5991638c9344778d807333cc0bd50.html | 88 ++ dir_a01d946a2e1b048dc542232ffcdcf572.html | 57 +- dir_a24b8c5f308a77f73e7a9e43c0f243d1.html | 55 +- ... dir_a3714ab037275c284988fc90b4d045a5.html | 59 +- ... dir_a3831f1c39821b3669f8a3808652203f.html | 63 +- dir_a44a562b5a12ef1c8495ac1a63e915ea.html | 55 +- dir_a51095d0142a80f0e979ff5bf5b861be.html | 88 ++ dir_a536e49cdf631f66733cf2c9791144ce.html | 55 +- ... dir_a8807eef6592489c6a360d587f5b1a66.html | 59 +- dir_a99ad55e4d1fa76955df2299f3783cf0.html | 55 +- dir_b0d0d898ef448ca0a6a170a2896fa60e.html | 55 +- dir_b524b00ec2259c3c83b44909fd47f6e3.html | 57 +- ... dir_b551a02288ef39e099594710382363a0.html | 59 +- dir_b6324197f7ac56e30d6189c3a45eec56.html | 55 +- ... dir_b87cbb2c60cf682b61fbfcceb9bced43.html | 59 +- ... dir_b92573f47b933d7a3661c26d1af2098b.html | 63 +- dir_ba6c75cd9bd8b7a0d2af20e1cd5a80ab.html | 55 +- dir_be6161819238d55fa660c07ade960e53.html | 57 +- ... dir_be9f3ed3485a880e3213506a311823d1.html | 63 +- dir_bf23e1e49f40264f2966f02ed35d8142.html | 57 +- dir_c037ac41e54cca303e35165acb6e013d.html | 55 +- dir_c2c4d4ee47e55233c6ea5db8b96422c6.html | 55 +- dir_c50f9bd139317d744e2ee08ea9a734cc.html | 88 ++ dir_c5451d9d233744a5b09a29938f0cda9a.html | 55 +- ... dir_c5f98c05147bcbba78e71856485f5049.html | 59 +- dir_c648ff9d1a57dd8752f4ab2a7c68712c.html | 55 +- dir_c9d0608eee53bfffcc33d03463bbe2db.html | 55 +- dir_d8869fc9da5c696ed284d5c470b7210f.html | 55 +- dir_d88de13ae4b64d4d0766b0c06f1a9edf.html | 55 +- ... dir_d8a279f7113e0073f6cd65dd050c1475.html | 59 +- dir_dbb0c65ea012faeef2906502dd42dfec.html | 57 +- dir_df215ce6792635a450ba5a94b5a17942.html | 55 +- dir_e0c1bccb03249d93bc42ac0968ce43fd.html | 57 +- dir_e2ec88631ea78d6df8b37d27efa9bfe2.html | 55 +- ... dir_e97d380c3eebaf0856a4ec180d749620.html | 63 +- dir_e9975c2f0de13509bd9fb4e31ae732ab.html | 55 +- ... dir_ea36b5ab01ad6e8b607438a02ae91964.html | 63 +- dir_eb7c70823ae63176c38851687b13349d.html | 55 +- dir_ed78ff3b0fc4a7f5234cdb0b34617476.html | 55 +- dir_f0581cdd528a911f791df57d0f438bcb.html | 57 +- dir_f0d41009ce252337feb2b68822c4cfba.html | 57 +- dir_f2a82faa4c4beef364292694cefca86d.html | 55 +- ... dir_f88948f9bde0555374e8a59a663bdfc9.html | 59 +- ... dir_fab1362e86740a2c573ef875dd474a67.html | 63 +- dir_fb12273b841438c2f2c9b5bc5398c636.html | 57 +- doxygen.css | 427 +++++-- dynsections.js | 27 +- files.html | 1044 ++++++++--------- functions.html | 123 +- functions_0x7e.html | 146 --- functions_b.html | 102 +- functions_c.html | 152 +-- functions_d.html | 110 +- functions_e.html | 106 +- functions_enum.html | 67 +- functions_f.html | 98 +- functions_func.html | 104 +- functions_func_0x7e.html | 145 --- functions_func_b.html | 99 +- functions_func_c.html | 128 +- functions_func_d.html | 101 +- functions_func_e.html | 97 +- functions_func_f.html | 97 +- functions_func_g.html | 100 +- functions_func_h.html | 97 +- functions_func_i.html | 103 +- functions_func_j.html | 101 +- functions_func_k.html | 97 +- functions_func_l.html | 97 +- functions_func_m.html | 98 +- functions_func_n.html | 97 +- functions_func_o.html | 97 +- functions_func_p.html | 97 +- functions_func_r.html | 99 +- functions_func_s.html | 106 +- functions_func_t.html | 97 +- functions_func_u.html | 99 +- functions_func_v.html | 97 +- functions_func_w.html | 106 +- functions_func_z.html | 97 +- functions_func_~.html | 84 ++ functions_g.html | 101 +- functions_h.html | 104 +- functions_i.html | 118 +- functions_j.html | 104 +- functions_k.html | 98 +- functions_l.html | 102 +- functions_m.html | 104 +- functions_n.html | 102 +- functions_o.html | 100 +- functions_p.html | 126 +- functions_prop.html | 114 +- functions_prop_b.html | 96 +- functions_prop_c.html | 117 +- functions_prop_d.html | 102 +- functions_prop_e.html | 102 +- functions_prop_f.html | 94 +- functions_prop_g.html | 94 +- functions_prop_h.html | 96 +- functions_prop_i.html | 108 +- functions_prop_j.html | 94 +- functions_prop_l.html | 96 +- functions_prop_m.html | 96 +- functions_prop_n.html | 96 +- functions_prop_o.html | 96 +- functions_prop_p.html | 118 +- functions_prop_r.html | 100 +- functions_prop_s.html | 112 +- functions_prop_t.html | 96 +- functions_prop_u.html | 100 +- functions_prop_v.html | 94 +- functions_prop_w.html | 97 +- functions_q.html | 98 +- functions_r.html | 112 +- functions_s.html | 128 +- functions_t.html | 102 +- functions_u.html | 106 +- functions_v.html | 98 +- functions_vars.html | 96 +- functions_vars_b.html | 96 +- functions_vars_c.html | 96 +- functions_vars_d.html | 96 +- functions_vars_e.html | 96 +- functions_vars_f.html | 96 +- functions_vars_g.html | 96 +- functions_vars_h.html | 96 +- functions_vars_i.html | 96 +- functions_vars_j.html | 98 +- functions_vars_k.html | 96 +- functions_vars_l.html | 98 +- functions_vars_m.html | 99 +- functions_vars_n.html | 98 +- functions_vars_o.html | 96 +- functions_vars_p.html | 100 +- functions_vars_q.html | 96 +- functions_vars_r.html | 98 +- functions_vars_s.html | 99 +- functions_vars_t.html | 96 +- functions_vars_u.html | 96 +- functions_vars_v.html | 96 +- functions_vars_w.html | 99 +- functions_w.html | 111 +- functions_z.html | 98 +- functions_~.html | 84 ++ hierarchy.html | 483 ++++---- index.html | 97 +- ...components_1_1_i_byond_client-members.html | 58 +- ...ent_1_1_components_1_1_i_byond_client.html | 82 +- ...onents_1_1_i_chat_bots_client-members.html | 58 +- ...1_1_components_1_1_i_chat_bots_client.html | 84 +- ...ts_1_1_i_configuration_client-members.html | 58 +- ...components_1_1_i_configuration_client.html | 88 +- ...nts_1_1_i_dream_daemon_client-members.html | 58 +- ..._components_1_1_i_dream_daemon_client.html | 92 +- ...ents_1_1_i_dream_maker_client-members.html | 58 +- ...1_components_1_1_i_dream_maker_client.html | 90 +- ...ponents_1_1_i_instance_client-members.html | 58 +- ..._1_1_components_1_1_i_instance_client.html | 172 +-- ...ts_1_1_i_instance_user_client-members.html | 58 +- ...components_1_1_i_instance_user_client.html | 88 +- ..._components_1_1_i_jobs_client-members.html | 58 +- ...ient_1_1_components_1_1_i_jobs_client.html | 90 +- ...nents_1_1_i_repository_client-members.html | 58 +- ..._1_components_1_1_i_repository_client.html | 84 +- ...t_1_1_i_administration_client-members.html | 58 +- ..._1_client_1_1_i_administration_client.html | 86 +- ...r_1_1_client_1_1_i_api_client-members.html | 58 +- ..._1_server_1_1_client_1_1_i_api_client.html | 178 +-- ...ient_1_1_i_api_client_factory-members.html | 58 +- ...r_1_1_client_1_1_i_api_client_factory.html | 80 +- ..._1_1_client_1_1_i_http_client-members.html | 58 +- ...1_server_1_1_client_1_1_i_http_client.html | 78 +- ...1_1_i_instance_manager_client-members.html | 58 +- ..._client_1_1_i_instance_manager_client.html | 98 +- ...1_client_1_1_i_request_logger-members.html | 58 +- ...erver_1_1_client_1_1_i_request_logger.html | 68 +- ..._1_client_1_1_i_server_client-members.html | 58 +- ...server_1_1_client_1_1_i_server_client.html | 154 ++- ...t_1_1_i_server_client_factory-members.html | 58 +- ..._1_client_1_1_i_server_client_factory.html | 94 +- ...1_1_client_1_1_i_users_client-members.html | 58 +- ..._server_1_1_client_1_1_i_users_client.html | 84 +- ...d_1_1_i_byond_executable_lock-members.html | 58 +- ...1_1_byond_1_1_i_byond_executable_lock.html | 100 +- ...1_byond_1_1_i_byond_installer-members.html | 58 +- ...nents_1_1_byond_1_1_i_byond_installer.html | 100 +- ...1_1_byond_1_1_i_byond_manager-members.html | 58 +- ...ponents_1_1_byond_1_1_i_byond_manager.html | 96 +- ...at_1_1_commands_1_1_i_command-members.html | 58 +- ...s_1_1_chat_1_1_commands_1_1_i_command.html | 118 +- ...ommands_1_1_i_command_factory-members.html | 58 +- ...at_1_1_commands_1_1_i_command_factory.html | 80 +- ...omponents_1_1_chat_1_1_i_chat-members.html | 58 +- ...st_1_1_components_1_1_chat_1_1_i_chat.html | 118 +- ...s_1_1_chat_1_1_i_chat_factory-members.html | 58 +- ...omponents_1_1_chat_1_1_i_chat_factory.html | 86 +- ..._1_1_i_custom_command_handler-members.html | 58 +- ...1_1_chat_1_1_i_custom_command_handler.html | 76 +- ...t_1_1_i_json_tracking_context-members.html | 58 +- ..._1_1_chat_1_1_i_json_tracking_context.html | 98 +- ...1_chat_1_1_i_provider_factory-members.html | 58 +- ...nents_1_1_chat_1_1_i_provider_factory.html | 70 +- ..._1_1_providers_1_1_i_provider-members.html | 58 +- ...1_1_chat_1_1_providers_1_1_i_provider.html | 146 ++- ...er_1_1_i_compile_job_consumer-members.html | 58 +- ...1_compiler_1_1_i_compile_job_consumer.html | 76 +- ..._1_compiler_1_1_i_dmb_factory-members.html | 58 +- ...onents_1_1_compiler_1_1_i_dmb_factory.html | 128 +- ..._1_compiler_1_1_i_dream_maker-members.html | 60 +- ...onents_1_1_compiler_1_1_i_dream_maker.html | 80 +- ...components_1_1_i_dmb_provider-members.html | 58 +- ...ost_1_1_components_1_1_i_dmb_provider.html | 118 +- ...mponents_1_1_i_event_consumer-members.html | 58 +- ...t_1_1_components_1_1_i_event_consumer.html | 82 +- ...1_1_components_1_1_i_instance-members.html | 58 +- ..._1_host_1_1_components_1_1_i_instance.html | 156 +-- ...onents_1_1_i_instance_factory-members.html | 58 +- ...1_1_components_1_1_i_instance_factory.html | 82 +- ...onents_1_1_i_instance_manager-members.html | 58 +- ...1_1_components_1_1_i_instance_manager.html | 114 +- ..._1_interop_1_1_i_comm_context-members.html | 58 +- ...onents_1_1_interop_1_1_i_comm_context.html | 76 +- ..._1_interop_1_1_i_comm_handler-members.html | 58 +- ...onents_1_1_interop_1_1_i_comm_handler.html | 74 +- ...ry_1_1_i_credentials_provider-members.html | 58 +- ...repository_1_1_i_credentials_provider.html | 70 +- ...1_repository_1_1_i_repository-members.html | 58 +- ...nents_1_1_repository_1_1_i_repository.html | 200 ++-- ...tory_1_1_i_repository_manager-members.html | 58 +- ...1_repository_1_1_i_repository_manager.html | 110 +- ...tic_files_1_1_i_configuration-members.html | 58 +- ..._1_1_static_files_1_1_i_configuration.html | 120 +- ...g_1_1_i_network_prompt_reaper-members.html | 58 +- ..._watchdog_1_1_i_network_prompt_reaper.html | 70 +- ...g_1_1_i_reattach_info_handler-members.html | 58 +- ..._watchdog_1_1_i_reattach_info_handler.html | 84 +- ...hdog_1_1_i_session_controller-members.html | 60 +- ...1_1_watchdog_1_1_i_session_controller.html | 240 ++-- ..._i_session_controller_factory-members.html | 58 +- ...hdog_1_1_i_session_controller_factory.html | 110 +- ...s_1_1_watchdog_1_1_i_watchdog-members.html | 60 +- ...omponents_1_1_watchdog_1_1_i_watchdog.html | 166 +-- ...tchdog_1_1_i_watchdog_factory-members.html | 58 +- ...s_1_1_watchdog_1_1_i_watchdog_factory.html | 94 +- ...st_1_1_core_1_1_i_application-members.html | 58 +- ...r_1_1_host_1_1_core_1_1_i_application.html | 106 +- ..._1_1_core_1_1_i_async_delayer-members.html | 58 +- ...1_1_host_1_1_core_1_1_i_async_delayer.html | 70 +- ..._1_1_i_d_b_connection_factory-members.html | 58 +- ...1_1_core_1_1_i_d_b_connection_factory.html | 70 +- ..._1_i_database_context_factory-members.html | 58 +- ...1_core_1_1_i_database_context_factory.html | 70 +- ..._1_1_i_git_hub_client_factory-members.html | 58 +- ...1_1_core_1_1_i_git_hub_client_factory.html | 74 +- ...st_1_1_core_1_1_i_job_manager-members.html | 60 +- ...r_1_1_host_1_1_core_1_1_i_job_manager.html | 106 +- ...ore_1_1_i_platform_identifier-members.html | 58 +- ...st_1_1_core_1_1_i_platform_identifier.html | 82 +- ...1_host_1_1_core_1_1_i_process-members.html | 58 +- ...erver_1_1_host_1_1_core_1_1_i_process.html | 134 +-- ...t_1_1_core_1_1_i_process_base-members.html | 58 +- ..._1_1_host_1_1_core_1_1_i_process_base.html | 86 +- ...1_core_1_1_i_process_executor-members.html | 58 +- ..._host_1_1_core_1_1_i_process_executor.html | 98 +- ..._1_core_1_1_i_restart_handler-members.html | 58 +- ...1_host_1_1_core_1_1_i_restart_handler.html | 70 +- ...t_1_1_core_1_1_i_restart_registration.html | 68 +- ...1_1_core_1_1_i_server_control-members.html | 58 +- ..._1_host_1_1_core_1_1_i_server_control.html | 106 +- ...t_1_1_core_1_1_i_setup_wizard-members.html | 58 +- ..._1_1_host_1_1_core_1_1_i_setup_wizard.html | 72 +- ..._1_host_1_1_i_o_1_1_i_console-members.html | 58 +- ...server_1_1_host_1_1_i_o_1_1_i_console.html | 108 +- ...ost_1_1_i_o_1_1_i_i_o_manager-members.html | 58 +- ...er_1_1_host_1_1_i_o_1_1_i_i_o_manager.html | 206 ++-- ..._i_o_1_1_i_post_write_handler-members.html | 58 +- ...host_1_1_i_o_1_1_i_post_write_handler.html | 74 +- ...1_1_i_o_1_1_i_symlink_factory-members.html | 58 +- ..._1_host_1_1_i_o_1_1_i_symlink_factory.html | 74 +- ...1_1_i_synchronous_i_o_manager-members.html | 58 +- ...1_1_i_o_1_1_i_synchronous_i_o_manager.html | 112 +- ..._server_1_1_host_1_1_i_server-members.html | 58 +- ...tion_1_1_server_1_1_host_1_1_i_server.html | 86 +- ...1_1_host_1_1_i_server_factory-members.html | 58 +- ..._server_1_1_host_1_1_i_server_factory.html | 84 +- ...models_1_1_i_database_context-members.html | 58 +- ...ost_1_1_models_1_1_i_database_context.html | 256 ++-- ..._models_1_1_i_database_seeder-members.html | 58 +- ...host_1_1_models_1_1_i_database_seeder.html | 84 +- ..._1_1_i_authentication_context-members.html | 58 +- ...security_1_1_i_authentication_context.html | 104 +- ...uthentication_context_factory-members.html | 60 +- ..._1_1_i_authentication_context_factory.html | 100 +- ...ecurity_1_1_i_claims_injector-members.html | 58 +- ...st_1_1_security_1_1_i_claims_injector.html | 72 +- ...rity_1_1_i_cryptography_suite-members.html | 58 +- ...1_1_security_1_1_i_cryptography_suite.html | 92 +- ...security_1_1_i_identity_cache-members.html | 58 +- ...ost_1_1_security_1_1_i_identity_cache.html | 90 +- ...ecurity_1_1_i_system_identity-members.html | 58 +- ...st_1_1_security_1_1_i_system_identity.html | 108 +- ...1_1_i_system_identity_factory-members.html | 58 +- ...ecurity_1_1_i_system_identity_factory.html | 94 +- ..._security_1_1_i_token_factory-members.html | 58 +- ...host_1_1_security_1_1_i_token_factory.html | 86 +- ...t_1_1_watchdog_1_1_i_watchdog-members.html | 58 +- ..._1_1_host_1_1_watchdog_1_1_i_watchdog.html | 80 +- ...tchdog_1_1_i_watchdog_factory-members.html | 58 +- ...t_1_1_watchdog_1_1_i_watchdog_factory.html | 80 +- jquery.js | 29 +- menu.js | 50 + menudata.js | 137 +++ namespace_release_notes.html | 56 +- namespace_tgstation.html | 56 +- namespace_tgstation_1_1_server.html | 56 +- namespace_tgstation_1_1_server_1_1_api.html | 58 +- ...station_1_1_server_1_1_api_1_1_models.html | 194 ++- ...erver_1_1_api_1_1_models_1_1_internal.html | 68 +- ...1_server_1_1_api_1_1_models_1_1_tests.html | 56 +- ...station_1_1_server_1_1_api_1_1_rights.html | 592 ++++------ ...1_server_1_1_api_1_1_rights_1_1_tests.html | 56 +- ...gstation_1_1_server_1_1_api_1_1_tests.html | 58 +- ...space_tgstation_1_1_server_1_1_client.html | 62 +- ..._1_1_server_1_1_client_1_1_components.html | 56 +- ...r_1_1_client_1_1_components_1_1_tests.html | 56 +- ...ation_1_1_server_1_1_client_1_1_tests.html | 56 +- namespace_tgstation_1_1_server_1_1_host.html | 58 +- ...on_1_1_server_1_1_host_1_1_components.html | 142 +-- ...ver_1_1_host_1_1_components_1_1_byond.html | 60 +- ...st_1_1_components_1_1_byond_1_1_tests.html | 56 +- ...rver_1_1_host_1_1_components_1_1_chat.html | 64 +- ..._1_1_components_1_1_chat_1_1_commands.html | 62 +- ...1_1_components_1_1_chat_1_1_providers.html | 62 +- ...ents_1_1_chat_1_1_providers_1_1_tests.html | 56 +- ..._1_1_host_1_1_components_1_1_compiler.html | 62 +- ...r_1_1_host_1_1_components_1_1_interop.html | 62 +- ..._1_host_1_1_components_1_1_repository.html | 58 +- ..._host_1_1_components_1_1_static_files.html | 56 +- ..._1_1_host_1_1_components_1_1_watchdog.html | 213 ++-- ...1_1_components_1_1_watchdog_1_1_tests.html | 56 +- ...1_1_server_1_1_host_1_1_configuration.html | 113 +- ...ation_1_1_server_1_1_host_1_1_console.html | 56 +- ...server_1_1_host_1_1_console_1_1_tests.html | 56 +- ...n_1_1_server_1_1_host_1_1_controllers.html | 72 +- ...gstation_1_1_server_1_1_host_1_1_core.html | 63 +- ..._1_server_1_1_host_1_1_core_1_1_tests.html | 56 +- ...tgstation_1_1_server_1_1_host_1_1_i_o.html | 68 +- ...1_1_server_1_1_host_1_1_i_o_1_1_tests.html | 56 +- ...tation_1_1_server_1_1_host_1_1_models.html | 70 +- ...er_1_1_host_1_1_models_1_1_migrations.html | 74 +- ...tion_1_1_server_1_1_host_1_1_security.html | 70 +- ...erver_1_1_host_1_1_security_1_1_tests.html | 58 +- ...ation_1_1_server_1_1_host_1_1_service.html | 56 +- ...server_1_1_host_1_1_service_1_1_tests.html | 58 +- ...station_1_1_server_1_1_host_1_1_tests.html | 56 +- ...tion_1_1_server_1_1_host_1_1_watchdog.html | 58 +- ...erver_1_1_host_1_1_watchdog_1_1_tests.html | 56 +- namespace_tgstation_1_1_server_1_1_tests.html | 56 +- ...ion_1_1_server_1_1_tests_1_1_instance.html | 56 +- namespacemembers.html | 62 +- namespacemembers_enum.html | 62 +- namespaces.html | 56 +- search/all_0.html | 8 +- search/all_1.html | 8 +- search/all_1.js | 70 +- search/all_10.html | 8 +- search/all_10.js | 47 +- search/all_11.html | 8 +- search/all_12.html | 8 +- search/all_12.js | 71 +- search/all_13.html | 8 +- search/all_13.js | 66 +- search/all_14.html | 8 +- search/all_14.js | 65 +- search/all_15.html | 8 +- search/all_15.js | 32 +- search/all_16.html | 8 +- search/all_16.js | 3 +- search/all_17.html | 8 +- search/all_17.js | 39 +- search/all_18.html | 8 +- search/all_19.html | 8 +- search/all_2.html | 8 +- search/all_2.js | 23 +- search/all_3.html | 8 +- search/all_3.js | 109 +- search/all_4.html | 8 +- search/all_4.js | 70 +- search/all_5.html | 8 +- search/all_5.js | 9 +- search/all_6.html | 8 +- search/all_7.html | 8 +- search/all_7.js | 7 +- search/all_8.html | 8 +- search/all_8.js | 8 +- search/all_9.html | 8 +- search/all_9.js | 85 +- search/all_a.html | 8 +- search/all_a.js | 34 +- search/all_b.html | 8 +- search/all_c.html | 8 +- search/all_c.js | 9 +- search/all_d.html | 8 +- search/all_d.js | 17 +- search/all_e.html | 8 +- search/all_e.js | 4 +- search/all_f.html | 8 +- search/all_f.js | 2 +- search/classes_0.html | 8 +- search/classes_1.html | 8 +- search/classes_10.html | 8 +- search/classes_11.html | 8 +- search/classes_11.js | 9 +- search/classes_12.html | 8 +- search/classes_12.js | 5 +- search/classes_13.html | 8 +- search/classes_14.html | 8 +- search/classes_14.js | 9 +- search/classes_2.html | 8 +- search/classes_2.js | 11 +- search/classes_3.html | 8 +- search/classes_3.js | 6 +- search/classes_4.html | 8 +- search/classes_5.html | 8 +- search/classes_6.html | 8 +- search/classes_7.html | 8 +- search/classes_8.html | 8 +- search/classes_8.js | 14 +- search/classes_9.html | 8 +- search/classes_9.js | 4 +- search/classes_a.html | 8 +- search/classes_b.html | 8 +- search/classes_c.html | 8 +- search/classes_d.html | 8 +- search/classes_e.html | 8 +- search/classes_e.js | 5 +- search/classes_f.html | 8 +- search/classes_f.js | 13 +- search/enums_0.html | 8 +- search/enums_1.html | 8 +- search/enums_2.html | 8 +- search/enums_3.html | 8 +- search/enums_4.html | 8 +- search/enums_5.html | 8 +- search/enums_6.html | 8 +- search/enums_7.html | 8 +- search/enums_8.html | 8 +- search/enumvalues_0.html | 8 +- search/enumvalues_1.html | 8 +- search/enumvalues_10.html | 8 +- search/enumvalues_2.html | 8 +- search/enumvalues_3.html | 8 +- search/enumvalues_4.html | 8 +- search/enumvalues_5.html | 8 +- search/enumvalues_6.html | 8 +- search/enumvalues_7.html | 8 +- search/enumvalues_8.html | 8 +- search/enumvalues_9.html | 8 +- search/enumvalues_a.html | 8 +- search/enumvalues_b.html | 8 +- search/enumvalues_c.html | 8 +- search/enumvalues_d.html | 8 +- search/enumvalues_e.html | 8 +- search/enumvalues_f.html | 8 +- search/files_0.html | 8 +- search/files_1.html | 8 +- search/files_1.js | 7 +- search/files_10.html | 8 +- search/files_10.js | 16 +- search/files_11.html | 8 +- search/files_12.html | 8 +- search/files_12.js | 11 +- search/files_13.html | 8 +- search/files_13.js | 5 +- search/files_14.html | 8 +- search/files_15.html | 8 +- search/files_15.js | 9 +- search/files_2.html | 8 +- search/files_3.html | 8 +- search/files_3.js | 11 +- search/files_4.html | 8 +- search/files_4.js | 6 +- search/files_5.html | 8 +- search/files_6.html | 8 +- search/files_7.html | 8 +- search/files_8.html | 8 +- search/files_9.html | 8 +- search/files_9.js | 13 +- search/files_a.html | 8 +- search/files_a.js | 4 +- search/files_b.html | 8 +- search/files_c.html | 8 +- search/files_d.html | 8 +- search/files_e.html | 8 +- search/files_f.html | 8 +- search/files_f.js | 5 +- search/functions_0.html | 8 +- search/functions_0.js | 3 +- search/functions_1.html | 8 +- search/functions_1.js | 2 +- search/functions_10.html | 8 +- search/functions_10.js | 4 +- search/functions_11.html | 8 +- search/functions_11.js | 9 +- search/functions_12.html | 8 +- search/functions_13.html | 8 +- search/functions_13.js | 2 +- search/functions_14.html | 8 +- search/functions_15.html | 8 +- search/functions_15.js | 3 +- search/functions_16.html | 8 +- search/functions_17.html | 8 +- search/functions_2.html | 8 +- search/functions_2.js | 13 +- search/functions_3.html | 8 +- search/functions_3.js | 4 +- search/functions_4.html | 8 +- search/functions_5.html | 8 +- search/functions_6.html | 8 +- search/functions_6.js | 1 + search/functions_7.html | 8 +- search/functions_8.html | 8 +- search/functions_8.js | 6 +- search/functions_9.html | 8 +- search/functions_9.js | 2 +- search/functions_a.html | 8 +- search/functions_b.html | 8 +- search/functions_c.html | 8 +- search/functions_c.js | 2 +- search/functions_d.html | 8 +- search/functions_e.html | 8 +- search/functions_f.html | 8 +- search/mag_sel.png | Bin 563 -> 465 bytes search/namespaces_0.html | 8 +- search/namespaces_1.html | 8 +- search/namespaces_1.js | 26 +- search/nomatches.html | 2 +- search/pages_0.html | 8 +- search/pages_1.html | 8 +- search/pages_2.html | 8 +- search/properties_0.html | 8 +- search/properties_0.js | 20 +- search/properties_1.html | 8 +- search/properties_1.js | 2 +- search/properties_10.html | 8 +- search/properties_10.js | 18 +- search/properties_11.html | 8 +- search/properties_11.js | 2 +- search/properties_12.html | 8 +- search/properties_12.js | 6 +- search/properties_13.html | 8 +- search/properties_14.html | 8 +- search/properties_14.js | 1 + search/properties_2.html | 8 +- search/properties_2.js | 21 +- search/properties_3.html | 8 +- search/properties_3.js | 8 +- search/properties_4.html | 8 +- search/properties_4.js | 6 +- search/properties_5.html | 8 +- search/properties_6.html | 8 +- search/properties_7.html | 8 +- search/properties_7.js | 2 +- search/properties_8.html | 8 +- search/properties_8.js | 14 +- search/properties_9.html | 8 +- search/properties_a.html | 8 +- search/properties_a.js | 2 +- search/properties_b.html | 8 +- search/properties_b.js | 2 +- search/properties_c.html | 8 +- search/properties_c.js | 2 +- search/properties_d.html | 8 +- search/properties_d.js | 2 +- search/properties_e.html | 8 +- search/properties_e.js | 18 +- search/properties_f.html | 8 +- search/properties_f.js | 6 +- search/search.css | 12 +- search/search.js | 25 +- search/search_l.png | Bin 604 -> 567 bytes search/search_r.png | Bin 612 -> 553 bytes search/variables_0.html | 8 +- search/variables_1.html | 8 +- search/variables_10.html | 8 +- search/variables_11.html | 8 +- search/variables_11.js | 4 +- search/variables_12.html | 8 +- search/variables_12.js | 1 + search/variables_13.html | 8 +- search/variables_14.html | 8 +- search/variables_15.html | 8 +- search/variables_16.html | 8 +- search/variables_16.js | 2 +- search/variables_2.html | 8 +- search/variables_3.html | 8 +- search/variables_4.html | 8 +- search/variables_5.html | 8 +- search/variables_6.html | 8 +- search/variables_7.html | 8 +- search/variables_8.html | 8 +- search/variables_9.html | 8 +- search/variables_9.js | 2 +- search/variables_a.html | 8 +- search/variables_b.html | 8 +- search/variables_b.js | 2 +- search/variables_c.html | 8 +- search/variables_c.js | 1 - search/variables_d.html | 8 +- search/variables_d.js | 2 +- search/variables_e.html | 8 +- search/variables_f.html | 8 +- search/variables_f.js | 4 +- ...r_8_client_2_assembly_info_8cs_source.html | 104 -- ...ver_8_host_2_assembly_info_8cs_source.html | 104 -- ...station_8_server_8_host_2_program_8cs.html | 59 +- ..._8_server_8_host_2_program_8cs_source.html | 70 +- ..._8_console_2_assembly_info_8cs_source.html | 104 -- ...server_8_host_8_console_2_program_8cs.html | 61 +- ...8_host_8_console_2_program_8cs_source.html | 74 +- ...server_8_host_8_service_2_program_8cs.html | 61 +- ...8_host_8_service_2_program_8cs_source.html | 85 +- ...properties_2_assembly_info_8cs_source.html | 104 -- ...8_watchdog_2_assembly_info_8cs_source.html | 104 -- tabs.css | 61 +- ...properties_2_assembly_info_8cs_source.html | 104 -- tools_2_release_notes_2_program_8cs.html | 55 +- ..._2_release_notes_2_program_8cs_source.html | 63 +- tools_2_release_notes_2_r_e_a_d_m_e_8md.html | 57 +- ...elease_notes_2_r_e_a_d_m_e_8md_source.html | 99 -- 2035 files changed, 62209 insertions(+), 93369 deletions(-) delete mode 100644 _r_e_a_d_m_e_8md_source.html create mode 100644 _task_extensions_8cs.html create mode 100644 _task_extensions_8cs_source.html rename src_2_tgstation_8_server_8_client_2_assembly_info_8cs.html => _tgstation_8_server_8_client_2_assembly_info_8cs.html (60%) create mode 100644 _tgstation_8_server_8_client_2_assembly_info_8cs_source.html rename src_2_tgstation_8_server_8_host_2_assembly_info_8cs.html => _tgstation_8_server_8_host_2_assembly_info_8cs.html (60%) create mode 100644 _tgstation_8_server_8_host_2_assembly_info_8cs_source.html rename src_2_tgstation_8_server_8_host_8_console_2_assembly_info_8cs.html => _tgstation_8_server_8_host_8_console_2_assembly_info_8cs.html (60%) create mode 100644 _tgstation_8_server_8_host_8_console_2_assembly_info_8cs_source.html rename src_2_tgstation_8_server_8_host_8_service_2_properties_2_assembly_info_8cs.html => _tgstation_8_server_8_host_8_service_2_properties_2_assembly_info_8cs.html (60%) create mode 100644 _tgstation_8_server_8_host_8_service_2_properties_2_assembly_info_8cs_source.html create mode 100644 _tgstation_8_server_8_host_8_service_8_assembly_info_8cs.html create mode 100644 _tgstation_8_server_8_host_8_service_8_assembly_info_8cs_source.html rename tests_2_tgstation_8_server_8_host_8_service_8_tests_2_properties_2_assembly_info_8cs.html => _tgstation_8_server_8_host_8_service_8_tests_8_assembly_info_8cs.html (56%) create mode 100644 _tgstation_8_server_8_host_8_service_8_tests_8_assembly_info_8cs_source.html rename src_2_tgstation_8_server_8_host_8_watchdog_2_assembly_info_8cs.html => _tgstation_8_server_8_host_8_watchdog_2_assembly_info_8cs.html (60%) create mode 100644 _tgstation_8_server_8_host_8_watchdog_2_assembly_info_8cs_source.html delete mode 100644 arrowdown.png delete mode 100644 arrowright.png delete mode 100644 class_i_event_log.html delete mode 100644 class_i_event_log.png create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_task_extensions-members.html create mode 100644 class_tgstation_1_1_server_1_1_host_1_1_core_1_1_task_extensions.html rename dir_4e036e007444785d010e90b5c9a24acd.html => dir_009a3598be1715e27911e1588bdd551c.html (62%) rename dir_91e2bbee1291fcb0db7e0417b617d01e.html => dir_019c6d3af924151b681494cc466be1ac.html (60%) rename dir_53c056aa6a96f034cca75f793964be6e.html => dir_0b6a380fe7fc1e1d640d1ac854fc3fb6.html (59%) rename dir_b2c89c850c962495793d09ea3a2ee385.html => dir_1083fcf52a7d94a2efffb6ca88246acf.html (67%) create mode 100644 dir_18f2820c1d411453d7d989b812e41820.html rename dir_53aae571c66a052729f8e64ccc397130.html => dir_2553b13cbb871373b0c30fb90d66217c.html (65%) create mode 100644 dir_26764abc66ddba24c5915db53fd68d23.html rename dir_90400719279795a0c5ea912516a4c874.html => dir_2b9d136d9ffdab429a63a74fca28b300.html (59%) rename dir_ec133cefc1442f53ec97e0d7a57cf129.html => dir_2e39d68cad3f83629c74ea67329dead9.html (59%) rename dir_7ae0efc0613c36c848fa310214e0aee3.html => dir_2e67631cb23401d696bcfdbe81f86f0f.html (59%) rename dir_4122b363a9d577bed19bef337e757ff3.html => dir_48968f849f7ddb061f7130e079fe66a6.html (59%) create mode 100644 dir_49e56c817e5e54854c35e136979f97ca.html rename dir_d45f494620bc0048ee4a31fa4f7391e1.html => dir_4c0c7e2f4fc60f51e2347a2d8dda94ce.html (65%) create mode 100644 dir_78e87f8f095a8e3bb6ef1faef94cdb78.html rename dir_0e792d76844bf2d7c79795a56a50ebec.html => dir_87039fa7b841d848ca75981d64237477.html (59%) rename dir_6db5af7fcfa17a34c7abf23e195af4db.html => dir_9257d56e926145e494a5aa5279887044.html (65%) create mode 100644 dir_9aa5991638c9344778d807333cc0bd50.html rename dir_13bee0ed20ecc83b9bcd4b869b726d42.html => dir_a3714ab037275c284988fc90b4d045a5.html (63%) rename dir_bb25b36c82def1362ea245058c866cdc.html => dir_a3831f1c39821b3669f8a3808652203f.html (54%) create mode 100644 dir_a51095d0142a80f0e979ff5bf5b861be.html rename dir_fcc41a8faa41492aba200a49fc7d0aed.html => dir_a8807eef6592489c6a360d587f5b1a66.html (62%) rename dir_900257602d294c4a4799e88420919068.html => dir_b551a02288ef39e099594710382363a0.html (67%) rename dir_e928c7e494884ad322b5f6005c2954e1.html => dir_b87cbb2c60cf682b61fbfcceb9bced43.html (65%) rename dir_40138fd4849573e743490d583f6d06d6.html => dir_b92573f47b933d7a3661c26d1af2098b.html (60%) rename dir_18a5e30c14613227f95d12bd9fddc614.html => dir_be9f3ed3485a880e3213506a311823d1.html (59%) create mode 100644 dir_c50f9bd139317d744e2ee08ea9a734cc.html rename dir_298f2a364723f4f4cea115538f944a94.html => dir_c5f98c05147bcbba78e71856485f5049.html (66%) rename dir_83a6f600c846cd444f33e44bb9b4f9cb.html => dir_d8a279f7113e0073f6cd65dd050c1475.html (62%) rename dir_c65d377d3c73fb4a07b3637f9c0caf4d.html => dir_e97d380c3eebaf0856a4ec180d749620.html (60%) rename dir_6c8d8f20501e8e412458f542d0998195.html => dir_ea36b5ab01ad6e8b607438a02ae91964.html (60%) rename dir_383ca23c40357ede4cca827b4a365c76.html => dir_f88948f9bde0555374e8a59a663bdfc9.html (62%) rename dir_7a9d035dcfcd6d9c7aa1efef4b6b58a4.html => dir_fab1362e86740a2c573ef875dd474a67.html (59%) delete mode 100644 functions_0x7e.html delete mode 100644 functions_func_0x7e.html create mode 100644 functions_func_~.html create mode 100644 functions_~.html create mode 100644 menu.js create mode 100644 menudata.js delete mode 100644 src_2_tgstation_8_server_8_client_2_assembly_info_8cs_source.html delete mode 100644 src_2_tgstation_8_server_8_host_2_assembly_info_8cs_source.html delete mode 100644 src_2_tgstation_8_server_8_host_8_console_2_assembly_info_8cs_source.html delete mode 100644 src_2_tgstation_8_server_8_host_8_service_2_properties_2_assembly_info_8cs_source.html delete mode 100644 src_2_tgstation_8_server_8_host_8_watchdog_2_assembly_info_8cs_source.html delete mode 100644 tests_2_tgstation_8_server_8_host_8_service_8_tests_2_properties_2_assembly_info_8cs_source.html delete mode 100644 tools_2_release_notes_2_r_e_a_d_m_e_8md_source.html diff --git a/20180906135553___m_s_initial_create_8_designer_8cs.html b/20180906135553___m_s_initial_create_8_designer_8cs.html index db36b83d55..f021ee896c 100644 --- a/20180906135553___m_s_initial_create_8_designer_8cs.html +++ b/20180906135553___m_s_initial_create_8_designer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180906135553_MSInitialCreate.Designer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces 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 413dff62ab..2cfdb5e28f 100644 --- a/20180906135553___m_s_initial_create_8_designer_8cs_source.html +++ b/20180906135553___m_s_initial_create_8_designer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180906135553_MSInitialCreate.Designer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
9 namespace Tgstation.Server.Host.Models.Migrations
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;
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 }
- -
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
- +
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
diff --git a/20180906135553___m_s_initial_create_8cs.html b/20180906135553___m_s_initial_create_8cs.html index 9b6a15a8b8..b7e94c1342 100644 --- a/20180906135553___m_s_initial_create_8cs.html +++ b/20180906135553___m_s_initial_create_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180906135553_MSInitialCreate.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20180906135553___m_s_initial_create_8cs_source.html b/20180906135553___m_s_initial_create_8cs_source.html index 97141ce500..29a41f29d9 100644 --- a/20180906135553___m_s_initial_create_8cs_source.html +++ b/20180906135553___m_s_initial_create_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180906135553_MSInitialCreate.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20180906135553_MSInitialCreate.cs
-Go to the documentation of this file.
1 using System;
2 using Microsoft.EntityFrameworkCore.Metadata;
3 using Microsoft.EntityFrameworkCore.Migrations;
4 
5 namespace Tgstation.Server.Host.Models.Migrations
6 {
10  #pragma warning disable CA1506
11  public partial class MSInitialCreate : Migration
12  {
17  protected override void Up(MigrationBuilder migrationBuilder)
18  {
19  migrationBuilder.CreateTable(
20  name: "Users",
21  columns: table => new
22  {
23  Id = table.Column<long>(nullable: false)
24  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
25  Enabled = table.Column<bool>(nullable: false),
26  CreatedAt = table.Column<DateTimeOffset>(nullable: false),
27  SystemIdentifier = table.Column<string>(nullable: true),
28  Name = table.Column<string>(nullable: false),
29  AdministrationRights = table.Column<decimal>(nullable: false),
30  InstanceManagerRights = table.Column<decimal>(nullable: false),
31  PasswordHash = table.Column<string>(nullable: true),
32  CreatedById = table.Column<long>(nullable: true),
33  CanonicalName = table.Column<string>(nullable: false),
34  LastPasswordUpdate = table.Column<DateTimeOffset>(nullable: true)
35  },
36  constraints: table =>
37  {
38  table.PrimaryKey("PK_Users", x => x.Id);
39  table.ForeignKey(
40  name: "FK_Users_Users_CreatedById",
41  column: x => x.CreatedById,
42  principalTable: "Users",
43  principalColumn: "Id",
44  onDelete: ReferentialAction.Restrict);
45  });
46 
47  migrationBuilder.CreateTable(
48  name: "ChatChannels",
49  columns: table => new
50  {
51  IrcChannel = table.Column<string>(nullable: true),
52  DiscordChannelId = table.Column<decimal>(nullable: true),
53  IsAdminChannel = table.Column<bool>(nullable: false),
54  IsWatchdogChannel = table.Column<bool>(nullable: false),
55  IsUpdatesChannel = table.Column<bool>(nullable: false),
56  Tag = table.Column<string>(nullable: true),
57  Id = table.Column<long>(nullable: false)
58  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
59  ChatSettingsId = table.Column<long>(nullable: false)
60  },
61  constraints: table =>
62  {
63  table.PrimaryKey("PK_ChatChannels", x => x.Id);
64  });
65 
66  migrationBuilder.CreateTable(
67  name: "ReattachInformations",
68  columns: table => new
69  {
70  ChatCommandsJson = table.Column<string>(nullable: false),
71  ChatChannelsJson = table.Column<string>(nullable: false),
72  ServerCommandsJson = table.Column<string>(nullable: false),
73  AccessIdentifier = table.Column<string>(nullable: false),
74  ProcessId = table.Column<int>(nullable: false),
75  IsPrimary = table.Column<bool>(nullable: false),
76  Port = table.Column<int>(nullable: false),
77  RebootState = table.Column<int>(nullable: false),
78  Id = table.Column<long>(nullable: false)
79  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
80  CompileJobId = table.Column<long>(nullable: true)
81  },
82  constraints: table =>
83  {
84  table.PrimaryKey("PK_ReattachInformations", x => x.Id);
85  });
86 
87  migrationBuilder.CreateTable(
88  name: "WatchdogReattachInformations",
89  columns: table => new
90  {
91  AlphaIsActive = table.Column<bool>(nullable: false),
92  Id = table.Column<long>(nullable: false)
93  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
94  AlphaId = table.Column<long>(nullable: true),
95  BravoId = table.Column<long>(nullable: true)
96  },
97  constraints: table =>
98  {
99  table.PrimaryKey("PK_WatchdogReattachInformations", x => x.Id);
100  table.ForeignKey(
101  name: "FK_WatchdogReattachInformations_ReattachInformations_AlphaId",
102  column: x => x.AlphaId,
103  principalTable: "ReattachInformations",
104  principalColumn: "Id",
105  onDelete: ReferentialAction.Restrict);
106  table.ForeignKey(
107  name: "FK_WatchdogReattachInformations_ReattachInformations_BravoId",
108  column: x => x.BravoId,
109  principalTable: "ReattachInformations",
110  principalColumn: "Id",
111  onDelete: ReferentialAction.Restrict);
112  });
113 
114  migrationBuilder.CreateTable(
115  name: "Instances",
116  columns: table => new
117  {
118  Id = table.Column<long>(nullable: false)
119  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
120  Name = table.Column<string>(nullable: false),
121  Path = table.Column<string>(nullable: false),
122  Online = table.Column<bool>(nullable: false),
123  ConfigurationType = table.Column<int>(nullable: false),
124  AutoUpdateInterval = table.Column<long>(nullable: false),
125  WatchdogReattachInformationId = table.Column<long>(nullable: true)
126  },
127  constraints: table =>
128  {
129  table.PrimaryKey("PK_Instances", x => x.Id);
130  table.ForeignKey(
131  name: "FK_Instances_WatchdogReattachInformations_WatchdogReattachInformationId",
132  column: x => x.WatchdogReattachInformationId,
133  principalTable: "WatchdogReattachInformations",
134  principalColumn: "Id",
135  onDelete: ReferentialAction.Restrict);
136  });
137 
138  migrationBuilder.CreateTable(
139  name: "ChatBots",
140  columns: table => new
141  {
142  Id = table.Column<long>(nullable: false)
143  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
144  Name = table.Column<string>(nullable: false),
145  Enabled = table.Column<bool>(nullable: true),
146  Provider = table.Column<int>(nullable: true),
147  ConnectionString = table.Column<string>(nullable: false),
148  InstanceId = table.Column<long>(nullable: false)
149  },
150  constraints: table =>
151  {
152  table.PrimaryKey("PK_ChatBots", x => x.Id);
153  table.ForeignKey(
154  name: "FK_ChatBots_Instances_InstanceId",
155  column: x => x.InstanceId,
156  principalTable: "Instances",
157  principalColumn: "Id",
158  onDelete: ReferentialAction.Cascade);
159  });
160 
161  migrationBuilder.CreateTable(
162  name: "DreamDaemonSettings",
163  columns: table => new
164  {
165  AllowWebClient = table.Column<bool>(nullable: false),
166  SecurityLevel = table.Column<int>(nullable: false),
167  PrimaryPort = table.Column<int>(nullable: false),
168  SecondaryPort = table.Column<int>(nullable: false),
169  StartupTimeout = table.Column<long>(nullable: false),
170  AutoStart = table.Column<bool>(nullable: false),
171  SoftRestart = table.Column<bool>(nullable: false),
172  SoftShutdown = table.Column<bool>(nullable: false),
173  Id = table.Column<long>(nullable: false)
174  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
175  ProcessId = table.Column<int>(nullable: true),
176  AccessToken = table.Column<string>(nullable: true),
177  InstanceId = table.Column<long>(nullable: false)
178  },
179  constraints: table =>
180  {
181  table.PrimaryKey("PK_DreamDaemonSettings", x => x.Id);
182  table.ForeignKey(
183  name: "FK_DreamDaemonSettings_Instances_InstanceId",
184  column: x => x.InstanceId,
185  principalTable: "Instances",
186  principalColumn: "Id",
187  onDelete: ReferentialAction.Cascade);
188  });
189 
190  migrationBuilder.CreateTable(
191  name: "DreamMakerSettings",
192  columns: table => new
193  {
194  ProjectName = table.Column<string>(nullable: true),
195  ApiValidationPort = table.Column<int>(nullable: false),
196  Id = table.Column<long>(nullable: false)
197  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
198  InstanceId = table.Column<long>(nullable: false)
199  },
200  constraints: table =>
201  {
202  table.PrimaryKey("PK_DreamMakerSettings", x => x.Id);
203  table.ForeignKey(
204  name: "FK_DreamMakerSettings_Instances_InstanceId",
205  column: x => x.InstanceId,
206  principalTable: "Instances",
207  principalColumn: "Id",
208  onDelete: ReferentialAction.Cascade);
209  });
210 
211  migrationBuilder.CreateTable(
212  name: "InstanceUsers",
213  columns: table => new
214  {
215  UserId = table.Column<long>(nullable: false),
216  InstanceUserRights = table.Column<decimal>(nullable: false),
217  ByondRights = table.Column<decimal>(nullable: false),
218  DreamDaemonRights = table.Column<decimal>(nullable: false),
219  DreamMakerRights = table.Column<decimal>(nullable: false),
220  RepositoryRights = table.Column<decimal>(nullable: false),
221  ChatBotRights = table.Column<decimal>(nullable: false),
222  ConfigurationRights = table.Column<decimal>(nullable: false),
223  Id = table.Column<long>(nullable: false)
224  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
225  InstanceId = table.Column<long>(nullable: false)
226  },
227  constraints: table =>
228  {
229  table.PrimaryKey("PK_InstanceUsers", x => x.Id);
230  table.ForeignKey(
231  name: "FK_InstanceUsers_Instances_InstanceId",
232  column: x => x.InstanceId,
233  principalTable: "Instances",
234  principalColumn: "Id",
235  onDelete: ReferentialAction.Cascade);
236  table.ForeignKey(
237  name: "FK_InstanceUsers_Users_UserId",
238  column: x => x.UserId,
239  principalTable: "Users",
240  principalColumn: "Id",
241  onDelete: ReferentialAction.Cascade);
242  });
243 
244  migrationBuilder.CreateTable(
245  name: "Jobs",
246  columns: table => new
247  {
248  Id = table.Column<long>(nullable: false)
249  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
250  Description = table.Column<string>(nullable: false),
251  ExceptionDetails = table.Column<string>(nullable: true),
252  StartedAt = table.Column<DateTimeOffset>(nullable: false),
253  StoppedAt = table.Column<DateTimeOffset>(nullable: true),
254  Cancelled = table.Column<bool>(nullable: false),
255  CancelRightsType = table.Column<decimal>(nullable: true),
256  CancelRight = table.Column<decimal>(nullable: true),
257  StartedById = table.Column<long>(nullable: false),
258  CancelledById = table.Column<long>(nullable: true),
259  InstanceId = table.Column<long>(nullable: false)
260  },
261  constraints: table =>
262  {
263  table.PrimaryKey("PK_Jobs", x => x.Id);
264  table.ForeignKey(
265  name: "FK_Jobs_Users_CancelledById",
266  column: x => x.CancelledById,
267  principalTable: "Users",
268  principalColumn: "Id",
269  onDelete: ReferentialAction.Restrict);
270  table.ForeignKey(
271  name: "FK_Jobs_Instances_InstanceId",
272  column: x => x.InstanceId,
273  principalTable: "Instances",
274  principalColumn: "Id",
275  onDelete: ReferentialAction.Cascade);
276  table.ForeignKey(
277  name: "FK_Jobs_Users_StartedById",
278  column: x => x.StartedById,
279  principalTable: "Users",
280  principalColumn: "Id",
281  onDelete: ReferentialAction.Cascade);
282  });
283 
284  migrationBuilder.CreateTable(
285  name: "RepositorySettings",
286  columns: table => new
287  {
288  CommitterName = table.Column<string>(nullable: false),
289  CommitterEmail = table.Column<string>(nullable: false),
290  AccessUser = table.Column<string>(nullable: true),
291  AccessToken = table.Column<string>(nullable: true),
292  PushTestMergeCommits = table.Column<bool>(nullable: false),
293  ShowTestMergeCommitters = table.Column<bool>(nullable: false),
294  AutoUpdatesKeepTestMerges = table.Column<bool>(nullable: false),
295  AutoUpdatesSynchronize = table.Column<bool>(nullable: false),
296  Id = table.Column<long>(nullable: false)
297  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
298  InstanceId = table.Column<long>(nullable: false)
299  },
300  constraints: table =>
301  {
302  table.PrimaryKey("PK_RepositorySettings", x => x.Id);
303  table.ForeignKey(
304  name: "FK_RepositorySettings_Instances_InstanceId",
305  column: x => x.InstanceId,
306  principalTable: "Instances",
307  principalColumn: "Id",
308  onDelete: ReferentialAction.Cascade);
309  });
310 
311  migrationBuilder.CreateTable(
312  name: "RevisionInformations",
313  columns: table => new
314  {
315  CommitSha = table.Column<string>(maxLength: 40, nullable: false),
316  OriginCommitSha = table.Column<string>(maxLength: 40, nullable: false),
317  Id = table.Column<long>(nullable: false)
318  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
319  InstanceId = table.Column<long>(nullable: false)
320  },
321  constraints: table =>
322  {
323  table.PrimaryKey("PK_RevisionInformations", x => x.Id);
324  table.ForeignKey(
325  name: "FK_RevisionInformations_Instances_InstanceId",
326  column: x => x.InstanceId,
327  principalTable: "Instances",
328  principalColumn: "Id",
329  onDelete: ReferentialAction.Cascade);
330  });
331 
332  migrationBuilder.CreateTable(
333  name: "CompileJobs",
334  columns: table => new
335  {
336  Id = table.Column<long>(nullable: false)
337  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
338  DmeName = table.Column<string>(nullable: true),
339  Output = table.Column<string>(nullable: true),
340  DirectoryName = table.Column<Guid>(nullable: true),
341  JobId = table.Column<long>(nullable: true),
342  RevisionInformationId = table.Column<long>(nullable: false),
343  ByondVersion = table.Column<string>(nullable: false)
344  },
345  constraints: table =>
346  {
347  table.PrimaryKey("PK_CompileJobs", x => x.Id);
348  table.ForeignKey(
349  name: "FK_CompileJobs_Jobs_JobId",
350  column: x => x.JobId,
351  principalTable: "Jobs",
352  principalColumn: "Id",
353  onDelete: ReferentialAction.Restrict);
354  table.ForeignKey(
355  name: "FK_CompileJobs_RevisionInformations_RevisionInformationId",
356  column: x => x.RevisionInformationId,
357  principalTable: "RevisionInformations",
358  principalColumn: "Id",
359  onDelete: ReferentialAction.Cascade);
360  });
361 
362  migrationBuilder.CreateTable(
363  name: "TestMerges",
364  columns: table => new
365  {
366  Number = table.Column<int>(nullable: false),
367  PullRequestRevision = table.Column<string>(nullable: false),
368  Comment = table.Column<string>(nullable: true),
369  TitleAtMerge = table.Column<string>(nullable: false),
370  BodyAtMerge = table.Column<string>(nullable: false),
371  Url = table.Column<string>(nullable: false),
372  Author = table.Column<string>(nullable: false),
373  Id = table.Column<long>(nullable: false)
374  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
375  MergedAt = table.Column<DateTimeOffset>(nullable: false),
376  MergedById = table.Column<long>(nullable: false),
377  PrimaryRevisionInformationId = table.Column<long>(nullable: true)
378  },
379  constraints: table =>
380  {
381  table.PrimaryKey("PK_TestMerges", x => x.Id);
382  table.ForeignKey(
383  name: "FK_TestMerges_Users_MergedById",
384  column: x => x.MergedById,
385  principalTable: "Users",
386  principalColumn: "Id",
387  onDelete: ReferentialAction.Restrict);
388  table.ForeignKey(
389  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
390  column: x => x.PrimaryRevisionInformationId,
391  principalTable: "RevisionInformations",
392  principalColumn: "Id",
393  onDelete: ReferentialAction.SetNull);
394  });
395 
396  migrationBuilder.CreateTable(
397  name: "RevInfoTestMerges",
398  columns: table => new
399  {
400  Id = table.Column<long>(nullable: false)
401  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
402  TestMergeId = table.Column<long>(nullable: false),
403  RevisionInformationId = table.Column<long>(nullable: false)
404  },
405  constraints: table =>
406  {
407  table.PrimaryKey("PK_RevInfoTestMerges", x => x.Id);
408  table.ForeignKey(
409  name: "FK_RevInfoTestMerges_RevisionInformations_RevisionInformationId",
410  column: x => x.RevisionInformationId,
411  principalTable: "RevisionInformations",
412  principalColumn: "Id",
413  onDelete: ReferentialAction.Cascade);
414  table.ForeignKey(
415  name: "FK_RevInfoTestMerges_TestMerges_TestMergeId",
416  column: x => x.TestMergeId,
417  principalTable: "TestMerges",
418  principalColumn: "Id",
419  onDelete: ReferentialAction.Cascade);
420  });
421 
422  migrationBuilder.CreateIndex(
423  name: "IX_ChatBots_InstanceId",
424  table: "ChatBots",
425  column: "InstanceId");
426 
427  migrationBuilder.CreateIndex(
428  name: "IX_ChatBots_Name",
429  table: "ChatBots",
430  column: "Name",
431  unique: true);
432 
433  migrationBuilder.CreateIndex(
434  name: "IX_ChatChannels_ChatSettingsId_DiscordChannelId",
435  table: "ChatChannels",
436  columns: new[] { "ChatSettingsId", "DiscordChannelId" },
437  unique: true,
438  filter: "[DiscordChannelId] IS NOT NULL");
439 
440  migrationBuilder.CreateIndex(
441  name: "IX_ChatChannels_ChatSettingsId_IrcChannel",
442  table: "ChatChannels",
443  columns: new[] { "ChatSettingsId", "IrcChannel" },
444  unique: true,
445  filter: "[IrcChannel] IS NOT NULL");
446 
447  migrationBuilder.CreateIndex(
448  name: "IX_CompileJobs_DirectoryName",
449  table: "CompileJobs",
450  column: "DirectoryName");
451 
452  migrationBuilder.CreateIndex(
453  name: "IX_CompileJobs_JobId",
454  table: "CompileJobs",
455  column: "JobId");
456 
457  migrationBuilder.CreateIndex(
458  name: "IX_CompileJobs_RevisionInformationId",
459  table: "CompileJobs",
460  column: "RevisionInformationId");
461 
462  migrationBuilder.CreateIndex(
463  name: "IX_DreamDaemonSettings_InstanceId",
464  table: "DreamDaemonSettings",
465  column: "InstanceId",
466  unique: true);
467 
468  migrationBuilder.CreateIndex(
469  name: "IX_DreamMakerSettings_InstanceId",
470  table: "DreamMakerSettings",
471  column: "InstanceId",
472  unique: true);
473 
474  migrationBuilder.CreateIndex(
475  name: "IX_Instances_Path",
476  table: "Instances",
477  column: "Path",
478  unique: true);
479 
480  migrationBuilder.CreateIndex(
481  name: "IX_Instances_WatchdogReattachInformationId",
482  table: "Instances",
483  column: "WatchdogReattachInformationId");
484 
485  migrationBuilder.CreateIndex(
486  name: "IX_InstanceUsers_InstanceId",
487  table: "InstanceUsers",
488  column: "InstanceId");
489 
490  migrationBuilder.CreateIndex(
491  name: "IX_InstanceUsers_UserId_InstanceId",
492  table: "InstanceUsers",
493  columns: new[] { "UserId", "InstanceId" },
494  unique: true);
495 
496  migrationBuilder.CreateIndex(
497  name: "IX_Jobs_CancelledById",
498  table: "Jobs",
499  column: "CancelledById");
500 
501  migrationBuilder.CreateIndex(
502  name: "IX_Jobs_InstanceId",
503  table: "Jobs",
504  column: "InstanceId");
505 
506  migrationBuilder.CreateIndex(
507  name: "IX_Jobs_StartedById",
508  table: "Jobs",
509  column: "StartedById");
510 
511  migrationBuilder.CreateIndex(
512  name: "IX_ReattachInformations_CompileJobId",
513  table: "ReattachInformations",
514  column: "CompileJobId");
515 
516  migrationBuilder.CreateIndex(
517  name: "IX_RepositorySettings_InstanceId",
518  table: "RepositorySettings",
519  column: "InstanceId",
520  unique: true);
521 
522  migrationBuilder.CreateIndex(
523  name: "IX_RevInfoTestMerges_RevisionInformationId",
524  table: "RevInfoTestMerges",
525  column: "RevisionInformationId");
526 
527  migrationBuilder.CreateIndex(
528  name: "IX_RevInfoTestMerges_TestMergeId",
529  table: "RevInfoTestMerges",
530  column: "TestMergeId");
531 
532  migrationBuilder.CreateIndex(
533  name: "IX_RevisionInformations_CommitSha",
534  table: "RevisionInformations",
535  column: "CommitSha",
536  unique: true);
537 
538  migrationBuilder.CreateIndex(
539  name: "IX_RevisionInformations_InstanceId",
540  table: "RevisionInformations",
541  column: "InstanceId");
542 
543  migrationBuilder.CreateIndex(
544  name: "IX_TestMerges_MergedById",
545  table: "TestMerges",
546  column: "MergedById");
547 
548  migrationBuilder.CreateIndex(
549  name: "IX_TestMerges_PrimaryRevisionInformationId",
550  table: "TestMerges",
551  column: "PrimaryRevisionInformationId",
552  unique: true,
553  filter: "[PrimaryRevisionInformationId] IS NOT NULL");
554 
555  migrationBuilder.CreateIndex(
556  name: "IX_Users_CanonicalName",
557  table: "Users",
558  column: "CanonicalName",
559  unique: true);
560 
561  migrationBuilder.CreateIndex(
562  name: "IX_Users_CreatedById",
563  table: "Users",
564  column: "CreatedById");
565 
566  migrationBuilder.CreateIndex(
567  name: "IX_WatchdogReattachInformations_AlphaId",
568  table: "WatchdogReattachInformations",
569  column: "AlphaId");
570 
571  migrationBuilder.CreateIndex(
572  name: "IX_WatchdogReattachInformations_BravoId",
573  table: "WatchdogReattachInformations",
574  column: "BravoId");
575 
576  migrationBuilder.AddForeignKey(
577  name: "FK_ChatChannels_ChatBots_ChatSettingsId",
578  table: "ChatChannels",
579  column: "ChatSettingsId",
580  principalTable: "ChatBots",
581  principalColumn: "Id",
582  onDelete: ReferentialAction.Cascade);
583 
584  migrationBuilder.AddForeignKey(
585  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
586  table: "ReattachInformations",
587  column: "CompileJobId",
588  principalTable: "CompileJobs",
589  principalColumn: "Id",
590  onDelete: ReferentialAction.Restrict);
591  }
592 
597  protected override void Down(MigrationBuilder migrationBuilder)
598  {
599  migrationBuilder.DropForeignKey(
600  name: "FK_Jobs_Instances_InstanceId",
601  table: "Jobs");
602 
603  migrationBuilder.DropForeignKey(
604  name: "FK_RevisionInformations_Instances_InstanceId",
605  table: "RevisionInformations");
606 
607  migrationBuilder.DropTable(
608  name: "ChatChannels");
609 
610  migrationBuilder.DropTable(
611  name: "DreamDaemonSettings");
612 
613  migrationBuilder.DropTable(
614  name: "DreamMakerSettings");
615 
616  migrationBuilder.DropTable(
617  name: "InstanceUsers");
618 
619  migrationBuilder.DropTable(
620  name: "RepositorySettings");
621 
622  migrationBuilder.DropTable(
623  name: "RevInfoTestMerges");
624 
625  migrationBuilder.DropTable(
626  name: "ChatBots");
627 
628  migrationBuilder.DropTable(
629  name: "TestMerges");
630 
631  migrationBuilder.DropTable(
632  name: "Instances");
633 
634  migrationBuilder.DropTable(
635  name: "WatchdogReattachInformations");
636 
637  migrationBuilder.DropTable(
638  name: "ReattachInformations");
639 
640  migrationBuilder.DropTable(
641  name: "CompileJobs");
642 
643  migrationBuilder.DropTable(
644  name: "Jobs");
645 
646  migrationBuilder.DropTable(
647  name: "RevisionInformations");
648 
649  migrationBuilder.DropTable(
650  name: "Users");
651  }
652  }
653 }
ConfigurationRights
Rights for Models.ConfigurationFile
-
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
-
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
-
ByondRights
Rights for Models.Byond
Definition: ByondRights.cs:9
-
InstanceUserRights
Rights for an Models.Instance
- -
AdministrationRights
Rights for Models.Administration
-
ConfigurationType
The type of configuration allowed on an Instance
+Go to the documentation of this file.
1 using System;
2 using Microsoft.EntityFrameworkCore.Metadata;
3 using Microsoft.EntityFrameworkCore.Migrations;
4 
6 {
10  #pragma warning disable CA1506
11  public partial class MSInitialCreate : Migration
12  {
17  protected override void Up(MigrationBuilder migrationBuilder)
18  {
19  if (migrationBuilder == null)
20  throw new ArgumentNullException(nameof(migrationBuilder));
21 
22  migrationBuilder.CreateTable(
23  name: "Users",
24  columns: table => new
25  {
26  Id = table.Column<long>(nullable: false)
27  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
28  Enabled = table.Column<bool>(nullable: false),
29  CreatedAt = table.Column<DateTimeOffset>(nullable: false),
30  SystemIdentifier = table.Column<string>(nullable: true),
31  Name = table.Column<string>(nullable: false),
32  AdministrationRights = table.Column<decimal>(nullable: false),
33  InstanceManagerRights = table.Column<decimal>(nullable: false),
34  PasswordHash = table.Column<string>(nullable: true),
35  CreatedById = table.Column<long>(nullable: true),
36  CanonicalName = table.Column<string>(nullable: false),
37  LastPasswordUpdate = table.Column<DateTimeOffset>(nullable: true)
38  },
39  constraints: table =>
40  {
41  table.PrimaryKey("PK_Users", x => x.Id);
42  table.ForeignKey(
43  name: "FK_Users_Users_CreatedById",
44  column: x => x.CreatedById,
45  principalTable: "Users",
46  principalColumn: "Id",
47  onDelete: ReferentialAction.Restrict);
48  });
49 
50  migrationBuilder.CreateTable(
51  name: "ChatChannels",
52  columns: table => new
53  {
54  IrcChannel = table.Column<string>(nullable: true),
55  DiscordChannelId = table.Column<decimal>(nullable: true),
56  IsAdminChannel = table.Column<bool>(nullable: false),
57  IsWatchdogChannel = table.Column<bool>(nullable: false),
58  IsUpdatesChannel = table.Column<bool>(nullable: false),
59  Tag = table.Column<string>(nullable: true),
60  Id = table.Column<long>(nullable: false)
61  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
62  ChatSettingsId = table.Column<long>(nullable: false)
63  },
64  constraints: table =>
65  {
66  table.PrimaryKey("PK_ChatChannels", x => x.Id);
67  });
68 
69  migrationBuilder.CreateTable(
70  name: "ReattachInformations",
71  columns: table => new
72  {
73  ChatCommandsJson = table.Column<string>(nullable: false),
74  ChatChannelsJson = table.Column<string>(nullable: false),
75  ServerCommandsJson = table.Column<string>(nullable: false),
76  AccessIdentifier = table.Column<string>(nullable: false),
77  ProcessId = table.Column<int>(nullable: false),
78  IsPrimary = table.Column<bool>(nullable: false),
79  Port = table.Column<int>(nullable: false),
80  RebootState = table.Column<int>(nullable: false),
81  Id = table.Column<long>(nullable: false)
82  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
83  CompileJobId = table.Column<long>(nullable: true)
84  },
85  constraints: table =>
86  {
87  table.PrimaryKey("PK_ReattachInformations", x => x.Id);
88  });
89 
90  migrationBuilder.CreateTable(
91  name: "WatchdogReattachInformations",
92  columns: table => new
93  {
94  AlphaIsActive = table.Column<bool>(nullable: false),
95  Id = table.Column<long>(nullable: false)
96  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
97  AlphaId = table.Column<long>(nullable: true),
98  BravoId = table.Column<long>(nullable: true)
99  },
100  constraints: table =>
101  {
102  table.PrimaryKey("PK_WatchdogReattachInformations", x => x.Id);
103  table.ForeignKey(
104  name: "FK_WatchdogReattachInformations_ReattachInformations_AlphaId",
105  column: x => x.AlphaId,
106  principalTable: "ReattachInformations",
107  principalColumn: "Id",
108  onDelete: ReferentialAction.Restrict);
109  table.ForeignKey(
110  name: "FK_WatchdogReattachInformations_ReattachInformations_BravoId",
111  column: x => x.BravoId,
112  principalTable: "ReattachInformations",
113  principalColumn: "Id",
114  onDelete: ReferentialAction.Restrict);
115  });
116 
117  migrationBuilder.CreateTable(
118  name: "Instances",
119  columns: table => new
120  {
121  Id = table.Column<long>(nullable: false)
122  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
123  Name = table.Column<string>(nullable: false),
124  Path = table.Column<string>(nullable: false),
125  Online = table.Column<bool>(nullable: false),
126  ConfigurationType = table.Column<int>(nullable: false),
127  AutoUpdateInterval = table.Column<long>(nullable: false),
128  WatchdogReattachInformationId = table.Column<long>(nullable: true)
129  },
130  constraints: table =>
131  {
132  table.PrimaryKey("PK_Instances", x => x.Id);
133  table.ForeignKey(
134  name: "FK_Instances_WatchdogReattachInformations_WatchdogReattachInformationId",
135  column: x => x.WatchdogReattachInformationId,
136  principalTable: "WatchdogReattachInformations",
137  principalColumn: "Id",
138  onDelete: ReferentialAction.Restrict);
139  });
140 
141  migrationBuilder.CreateTable(
142  name: "ChatBots",
143  columns: table => new
144  {
145  Id = table.Column<long>(nullable: false)
146  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
147  Name = table.Column<string>(nullable: false),
148  Enabled = table.Column<bool>(nullable: true),
149  Provider = table.Column<int>(nullable: true),
150  ConnectionString = table.Column<string>(nullable: false),
151  InstanceId = table.Column<long>(nullable: false)
152  },
153  constraints: table =>
154  {
155  table.PrimaryKey("PK_ChatBots", x => x.Id);
156  table.ForeignKey(
157  name: "FK_ChatBots_Instances_InstanceId",
158  column: x => x.InstanceId,
159  principalTable: "Instances",
160  principalColumn: "Id",
161  onDelete: ReferentialAction.Cascade);
162  });
163 
164  migrationBuilder.CreateTable(
165  name: "DreamDaemonSettings",
166  columns: table => new
167  {
168  AllowWebClient = table.Column<bool>(nullable: false),
169  SecurityLevel = table.Column<int>(nullable: false),
170  PrimaryPort = table.Column<int>(nullable: false),
171  SecondaryPort = table.Column<int>(nullable: false),
172  StartupTimeout = table.Column<long>(nullable: false),
173  AutoStart = table.Column<bool>(nullable: false),
174  SoftRestart = table.Column<bool>(nullable: false),
175  SoftShutdown = table.Column<bool>(nullable: false),
176  Id = table.Column<long>(nullable: false)
177  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
178  ProcessId = table.Column<int>(nullable: true),
179  AccessToken = table.Column<string>(nullable: true),
180  InstanceId = table.Column<long>(nullable: false)
181  },
182  constraints: table =>
183  {
184  table.PrimaryKey("PK_DreamDaemonSettings", x => x.Id);
185  table.ForeignKey(
186  name: "FK_DreamDaemonSettings_Instances_InstanceId",
187  column: x => x.InstanceId,
188  principalTable: "Instances",
189  principalColumn: "Id",
190  onDelete: ReferentialAction.Cascade);
191  });
192 
193  migrationBuilder.CreateTable(
194  name: "DreamMakerSettings",
195  columns: table => new
196  {
197  ProjectName = table.Column<string>(nullable: true),
198  ApiValidationPort = table.Column<int>(nullable: false),
199  Id = table.Column<long>(nullable: false)
200  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
201  InstanceId = table.Column<long>(nullable: false)
202  },
203  constraints: table =>
204  {
205  table.PrimaryKey("PK_DreamMakerSettings", x => x.Id);
206  table.ForeignKey(
207  name: "FK_DreamMakerSettings_Instances_InstanceId",
208  column: x => x.InstanceId,
209  principalTable: "Instances",
210  principalColumn: "Id",
211  onDelete: ReferentialAction.Cascade);
212  });
213 
214  migrationBuilder.CreateTable(
215  name: "InstanceUsers",
216  columns: table => new
217  {
218  UserId = table.Column<long>(nullable: false),
219  InstanceUserRights = table.Column<decimal>(nullable: false),
220  ByondRights = table.Column<decimal>(nullable: false),
221  DreamDaemonRights = table.Column<decimal>(nullable: false),
222  DreamMakerRights = table.Column<decimal>(nullable: false),
223  RepositoryRights = table.Column<decimal>(nullable: false),
224  ChatBotRights = table.Column<decimal>(nullable: false),
225  ConfigurationRights = table.Column<decimal>(nullable: false),
226  Id = table.Column<long>(nullable: false)
227  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
228  InstanceId = table.Column<long>(nullable: false)
229  },
230  constraints: table =>
231  {
232  table.PrimaryKey("PK_InstanceUsers", x => x.Id);
233  table.ForeignKey(
234  name: "FK_InstanceUsers_Instances_InstanceId",
235  column: x => x.InstanceId,
236  principalTable: "Instances",
237  principalColumn: "Id",
238  onDelete: ReferentialAction.Cascade);
239  table.ForeignKey(
240  name: "FK_InstanceUsers_Users_UserId",
241  column: x => x.UserId,
242  principalTable: "Users",
243  principalColumn: "Id",
244  onDelete: ReferentialAction.Cascade);
245  });
246 
247  migrationBuilder.CreateTable(
248  name: "Jobs",
249  columns: table => new
250  {
251  Id = table.Column<long>(nullable: false)
252  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
253  Description = table.Column<string>(nullable: false),
254  ExceptionDetails = table.Column<string>(nullable: true),
255  StartedAt = table.Column<DateTimeOffset>(nullable: false),
256  StoppedAt = table.Column<DateTimeOffset>(nullable: true),
257  Cancelled = table.Column<bool>(nullable: false),
258  CancelRightsType = table.Column<decimal>(nullable: true),
259  CancelRight = table.Column<decimal>(nullable: true),
260  StartedById = table.Column<long>(nullable: false),
261  CancelledById = table.Column<long>(nullable: true),
262  InstanceId = table.Column<long>(nullable: false)
263  },
264  constraints: table =>
265  {
266  table.PrimaryKey("PK_Jobs", x => x.Id);
267  table.ForeignKey(
268  name: "FK_Jobs_Users_CancelledById",
269  column: x => x.CancelledById,
270  principalTable: "Users",
271  principalColumn: "Id",
272  onDelete: ReferentialAction.Restrict);
273  table.ForeignKey(
274  name: "FK_Jobs_Instances_InstanceId",
275  column: x => x.InstanceId,
276  principalTable: "Instances",
277  principalColumn: "Id",
278  onDelete: ReferentialAction.Cascade);
279  table.ForeignKey(
280  name: "FK_Jobs_Users_StartedById",
281  column: x => x.StartedById,
282  principalTable: "Users",
283  principalColumn: "Id",
284  onDelete: ReferentialAction.Cascade);
285  });
286 
287  migrationBuilder.CreateTable(
288  name: "RepositorySettings",
289  columns: table => new
290  {
291  CommitterName = table.Column<string>(nullable: false),
292  CommitterEmail = table.Column<string>(nullable: false),
293  AccessUser = table.Column<string>(nullable: true),
294  AccessToken = table.Column<string>(nullable: true),
295  PushTestMergeCommits = table.Column<bool>(nullable: false),
296  ShowTestMergeCommitters = table.Column<bool>(nullable: false),
297  AutoUpdatesKeepTestMerges = table.Column<bool>(nullable: false),
298  AutoUpdatesSynchronize = table.Column<bool>(nullable: false),
299  Id = table.Column<long>(nullable: false)
300  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
301  InstanceId = table.Column<long>(nullable: false)
302  },
303  constraints: table =>
304  {
305  table.PrimaryKey("PK_RepositorySettings", x => x.Id);
306  table.ForeignKey(
307  name: "FK_RepositorySettings_Instances_InstanceId",
308  column: x => x.InstanceId,
309  principalTable: "Instances",
310  principalColumn: "Id",
311  onDelete: ReferentialAction.Cascade);
312  });
313 
314  migrationBuilder.CreateTable(
315  name: "RevisionInformations",
316  columns: table => new
317  {
318  CommitSha = table.Column<string>(maxLength: 40, nullable: false),
319  OriginCommitSha = table.Column<string>(maxLength: 40, nullable: false),
320  Id = table.Column<long>(nullable: false)
321  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
322  InstanceId = table.Column<long>(nullable: false)
323  },
324  constraints: table =>
325  {
326  table.PrimaryKey("PK_RevisionInformations", x => x.Id);
327  table.ForeignKey(
328  name: "FK_RevisionInformations_Instances_InstanceId",
329  column: x => x.InstanceId,
330  principalTable: "Instances",
331  principalColumn: "Id",
332  onDelete: ReferentialAction.Cascade);
333  });
334 
335  migrationBuilder.CreateTable(
336  name: "CompileJobs",
337  columns: table => new
338  {
339  Id = table.Column<long>(nullable: false)
340  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
341  DmeName = table.Column<string>(nullable: true),
342  Output = table.Column<string>(nullable: true),
343  DirectoryName = table.Column<Guid>(nullable: true),
344  JobId = table.Column<long>(nullable: true),
345  RevisionInformationId = table.Column<long>(nullable: false),
346  ByondVersion = table.Column<string>(nullable: false)
347  },
348  constraints: table =>
349  {
350  table.PrimaryKey("PK_CompileJobs", x => x.Id);
351  table.ForeignKey(
352  name: "FK_CompileJobs_Jobs_JobId",
353  column: x => x.JobId,
354  principalTable: "Jobs",
355  principalColumn: "Id",
356  onDelete: ReferentialAction.Restrict);
357  table.ForeignKey(
358  name: "FK_CompileJobs_RevisionInformations_RevisionInformationId",
359  column: x => x.RevisionInformationId,
360  principalTable: "RevisionInformations",
361  principalColumn: "Id",
362  onDelete: ReferentialAction.Cascade);
363  });
364 
365  migrationBuilder.CreateTable(
366  name: "TestMerges",
367  columns: table => new
368  {
369  Number = table.Column<int>(nullable: false),
370  PullRequestRevision = table.Column<string>(nullable: false),
371  Comment = table.Column<string>(nullable: true),
372  TitleAtMerge = table.Column<string>(nullable: false),
373  BodyAtMerge = table.Column<string>(nullable: false),
374  Url = table.Column<string>(nullable: false),
375  Author = table.Column<string>(nullable: false),
376  Id = table.Column<long>(nullable: false)
377  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
378  MergedAt = table.Column<DateTimeOffset>(nullable: false),
379  MergedById = table.Column<long>(nullable: false),
380  PrimaryRevisionInformationId = table.Column<long>(nullable: true)
381  },
382  constraints: table =>
383  {
384  table.PrimaryKey("PK_TestMerges", x => x.Id);
385  table.ForeignKey(
386  name: "FK_TestMerges_Users_MergedById",
387  column: x => x.MergedById,
388  principalTable: "Users",
389  principalColumn: "Id",
390  onDelete: ReferentialAction.Restrict);
391  table.ForeignKey(
392  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
393  column: x => x.PrimaryRevisionInformationId,
394  principalTable: "RevisionInformations",
395  principalColumn: "Id",
396  onDelete: ReferentialAction.SetNull);
397  });
398 
399  migrationBuilder.CreateTable(
400  name: "RevInfoTestMerges",
401  columns: table => new
402  {
403  Id = table.Column<long>(nullable: false)
404  .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
405  TestMergeId = table.Column<long>(nullable: false),
406  RevisionInformationId = table.Column<long>(nullable: false)
407  },
408  constraints: table =>
409  {
410  table.PrimaryKey("PK_RevInfoTestMerges", x => x.Id);
411  table.ForeignKey(
412  name: "FK_RevInfoTestMerges_RevisionInformations_RevisionInformationId",
413  column: x => x.RevisionInformationId,
414  principalTable: "RevisionInformations",
415  principalColumn: "Id",
416  onDelete: ReferentialAction.Cascade);
417  table.ForeignKey(
418  name: "FK_RevInfoTestMerges_TestMerges_TestMergeId",
419  column: x => x.TestMergeId,
420  principalTable: "TestMerges",
421  principalColumn: "Id",
422  onDelete: ReferentialAction.Cascade);
423  });
424 
425  migrationBuilder.CreateIndex(
426  name: "IX_ChatBots_InstanceId",
427  table: "ChatBots",
428  column: "InstanceId");
429 
430  migrationBuilder.CreateIndex(
431  name: "IX_ChatBots_Name",
432  table: "ChatBots",
433  column: "Name",
434  unique: true);
435 
436  migrationBuilder.CreateIndex(
437  name: "IX_ChatChannels_ChatSettingsId_DiscordChannelId",
438  table: "ChatChannels",
439  columns: new[] { "ChatSettingsId", "DiscordChannelId" },
440  unique: true,
441  filter: "[DiscordChannelId] IS NOT NULL");
442 
443  migrationBuilder.CreateIndex(
444  name: "IX_ChatChannels_ChatSettingsId_IrcChannel",
445  table: "ChatChannels",
446  columns: new[] { "ChatSettingsId", "IrcChannel" },
447  unique: true,
448  filter: "[IrcChannel] IS NOT NULL");
449 
450  migrationBuilder.CreateIndex(
451  name: "IX_CompileJobs_DirectoryName",
452  table: "CompileJobs",
453  column: "DirectoryName");
454 
455  migrationBuilder.CreateIndex(
456  name: "IX_CompileJobs_JobId",
457  table: "CompileJobs",
458  column: "JobId");
459 
460  migrationBuilder.CreateIndex(
461  name: "IX_CompileJobs_RevisionInformationId",
462  table: "CompileJobs",
463  column: "RevisionInformationId");
464 
465  migrationBuilder.CreateIndex(
466  name: "IX_DreamDaemonSettings_InstanceId",
467  table: "DreamDaemonSettings",
468  column: "InstanceId",
469  unique: true);
470 
471  migrationBuilder.CreateIndex(
472  name: "IX_DreamMakerSettings_InstanceId",
473  table: "DreamMakerSettings",
474  column: "InstanceId",
475  unique: true);
476 
477  migrationBuilder.CreateIndex(
478  name: "IX_Instances_Path",
479  table: "Instances",
480  column: "Path",
481  unique: true);
482 
483  migrationBuilder.CreateIndex(
484  name: "IX_Instances_WatchdogReattachInformationId",
485  table: "Instances",
486  column: "WatchdogReattachInformationId");
487 
488  migrationBuilder.CreateIndex(
489  name: "IX_InstanceUsers_InstanceId",
490  table: "InstanceUsers",
491  column: "InstanceId");
492 
493  migrationBuilder.CreateIndex(
494  name: "IX_InstanceUsers_UserId_InstanceId",
495  table: "InstanceUsers",
496  columns: new[] { "UserId", "InstanceId" },
497  unique: true);
498 
499  migrationBuilder.CreateIndex(
500  name: "IX_Jobs_CancelledById",
501  table: "Jobs",
502  column: "CancelledById");
503 
504  migrationBuilder.CreateIndex(
505  name: "IX_Jobs_InstanceId",
506  table: "Jobs",
507  column: "InstanceId");
508 
509  migrationBuilder.CreateIndex(
510  name: "IX_Jobs_StartedById",
511  table: "Jobs",
512  column: "StartedById");
513 
514  migrationBuilder.CreateIndex(
515  name: "IX_ReattachInformations_CompileJobId",
516  table: "ReattachInformations",
517  column: "CompileJobId");
518 
519  migrationBuilder.CreateIndex(
520  name: "IX_RepositorySettings_InstanceId",
521  table: "RepositorySettings",
522  column: "InstanceId",
523  unique: true);
524 
525  migrationBuilder.CreateIndex(
526  name: "IX_RevInfoTestMerges_RevisionInformationId",
527  table: "RevInfoTestMerges",
528  column: "RevisionInformationId");
529 
530  migrationBuilder.CreateIndex(
531  name: "IX_RevInfoTestMerges_TestMergeId",
532  table: "RevInfoTestMerges",
533  column: "TestMergeId");
534 
535  migrationBuilder.CreateIndex(
536  name: "IX_RevisionInformations_CommitSha",
537  table: "RevisionInformations",
538  column: "CommitSha",
539  unique: true);
540 
541  migrationBuilder.CreateIndex(
542  name: "IX_RevisionInformations_InstanceId",
543  table: "RevisionInformations",
544  column: "InstanceId");
545 
546  migrationBuilder.CreateIndex(
547  name: "IX_TestMerges_MergedById",
548  table: "TestMerges",
549  column: "MergedById");
550 
551  migrationBuilder.CreateIndex(
552  name: "IX_TestMerges_PrimaryRevisionInformationId",
553  table: "TestMerges",
554  column: "PrimaryRevisionInformationId",
555  unique: true,
556  filter: "[PrimaryRevisionInformationId] IS NOT NULL");
557 
558  migrationBuilder.CreateIndex(
559  name: "IX_Users_CanonicalName",
560  table: "Users",
561  column: "CanonicalName",
562  unique: true);
563 
564  migrationBuilder.CreateIndex(
565  name: "IX_Users_CreatedById",
566  table: "Users",
567  column: "CreatedById");
568 
569  migrationBuilder.CreateIndex(
570  name: "IX_WatchdogReattachInformations_AlphaId",
571  table: "WatchdogReattachInformations",
572  column: "AlphaId");
573 
574  migrationBuilder.CreateIndex(
575  name: "IX_WatchdogReattachInformations_BravoId",
576  table: "WatchdogReattachInformations",
577  column: "BravoId");
578 
579  migrationBuilder.AddForeignKey(
580  name: "FK_ChatChannels_ChatBots_ChatSettingsId",
581  table: "ChatChannels",
582  column: "ChatSettingsId",
583  principalTable: "ChatBots",
584  principalColumn: "Id",
585  onDelete: ReferentialAction.Cascade);
586 
587  migrationBuilder.AddForeignKey(
588  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
589  table: "ReattachInformations",
590  column: "CompileJobId",
591  principalTable: "CompileJobs",
592  principalColumn: "Id",
593  onDelete: ReferentialAction.Restrict);
594  }
595 
600  protected override void Down(MigrationBuilder migrationBuilder)
601  {
602  if (migrationBuilder == null)
603  throw new ArgumentNullException(nameof(migrationBuilder));
604 
605  migrationBuilder.DropForeignKey(
606  name: "FK_Jobs_Instances_InstanceId",
607  table: "Jobs");
608 
609  migrationBuilder.DropForeignKey(
610  name: "FK_RevisionInformations_Instances_InstanceId",
611  table: "RevisionInformations");
612 
613  migrationBuilder.DropTable(
614  name: "ChatChannels");
615 
616  migrationBuilder.DropTable(
617  name: "DreamDaemonSettings");
618 
619  migrationBuilder.DropTable(
620  name: "DreamMakerSettings");
621 
622  migrationBuilder.DropTable(
623  name: "InstanceUsers");
624 
625  migrationBuilder.DropTable(
626  name: "RepositorySettings");
627 
628  migrationBuilder.DropTable(
629  name: "RevInfoTestMerges");
630 
631  migrationBuilder.DropTable(
632  name: "ChatBots");
633 
634  migrationBuilder.DropTable(
635  name: "TestMerges");
636 
637  migrationBuilder.DropTable(
638  name: "Instances");
639 
640  migrationBuilder.DropTable(
641  name: "WatchdogReattachInformations");
642 
643  migrationBuilder.DropTable(
644  name: "ReattachInformations");
645 
646  migrationBuilder.DropTable(
647  name: "CompileJobs");
648 
649  migrationBuilder.DropTable(
650  name: "Jobs");
651 
652  migrationBuilder.DropTable(
653  name: "RevisionInformations");
654 
655  migrationBuilder.DropTable(
656  name: "Users");
657  }
658  }
659 }
ConfigurationRights
Rights for Models.ConfigurationFile
+
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
+
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
+
ByondRights
Rights for Models.Byond
Definition: ByondRights.cs:9
+
InstanceUserRights
Rights for an Models.Instance
+ +
AdministrationRights
Rights for Models.Administration
+
ConfigurationType
The type of configuration allowed on an Instance
-
DreamDaemonRights
Rights for Models.DreamDaemon
-
InstanceManagerRights
Rights for managing Models.Instances
-
DreamMakerRights
Rights for Models.DreamMaker
-
RepositoryRights
Rights for a Models.Repository
- - -
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
-
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
- +
DreamDaemonRights
Rights for Models.DreamDaemon
+
InstanceManagerRights
Rights for managing Models.Instances
+
DreamMakerRights
Rights for Models.DreamMaker
+
RepositoryRights
Rights for a Models.Repository
+ +
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
+
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
diff --git a/20180906143029___m_y_initial_create_8_designer_8cs.html b/20180906143029___m_y_initial_create_8_designer_8cs.html index 647859b138..8bc67d7463 100644 --- a/20180906143029___m_y_initial_create_8_designer_8cs.html +++ b/20180906143029___m_y_initial_create_8_designer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180906143029_MYInitialCreate.Designer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20180906143029___m_y_initial_create_8_designer_8cs_source.html b/20180906143029___m_y_initial_create_8_designer_8cs_source.html index 6432c06cda..c76e9ca9c4 100644 --- a/20180906143029___m_y_initial_create_8_designer_8cs_source.html +++ b/20180906143029___m_y_initial_create_8_designer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180906143029_MYInitialCreate.Designer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20180906143029_MYInitialCreate.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.Migrations;
6 
7 namespace Tgstation.Server.Host.Models.Migrations
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;
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 }
- -
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
- +
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
diff --git a/20180906143029___m_y_initial_create_8cs.html b/20180906143029___m_y_initial_create_8cs.html index 570d9affe4..ecf32454bb 100644 --- a/20180906143029___m_y_initial_create_8cs.html +++ b/20180906143029___m_y_initial_create_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180906143029_MYInitialCreate.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20180906143029___m_y_initial_create_8cs_source.html b/20180906143029___m_y_initial_create_8cs_source.html index f3d34f2f84..077118ef47 100644 --- a/20180906143029___m_y_initial_create_8cs_source.html +++ b/20180906143029___m_y_initial_create_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180906143029_MYInitialCreate.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20180906143029_MYInitialCreate.cs
-Go to the documentation of this file.
1 using System;
2 using Microsoft.EntityFrameworkCore.Metadata;
3 using Microsoft.EntityFrameworkCore.Migrations;
4 
5 namespace Tgstation.Server.Host.Models.Migrations
6 {
10  #pragma warning disable CA1506
11  public partial class MYInitialCreate : Migration
12  {
17  protected override void Up(MigrationBuilder migrationBuilder)
18  {
19  migrationBuilder.CreateTable(
20  name: "Users",
21  columns: table => new
22  {
23  Id = table.Column<long>(nullable: false)
24  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
25  Enabled = table.Column<bool>(nullable: false),
26  CreatedAt = table.Column<DateTimeOffset>(nullable: false),
27  SystemIdentifier = table.Column<string>(nullable: true),
28  Name = table.Column<string>(nullable: false),
29  AdministrationRights = table.Column<ulong>(nullable: false),
30  InstanceManagerRights = table.Column<ulong>(nullable: false),
31  PasswordHash = table.Column<string>(nullable: true),
32  CreatedById = table.Column<long>(nullable: true),
33  CanonicalName = table.Column<string>(nullable: false),
34  LastPasswordUpdate = table.Column<DateTimeOffset>(nullable: true)
35  },
36  constraints: table =>
37  {
38  table.PrimaryKey("PK_Users", x => x.Id);
39  table.ForeignKey(
40  name: "FK_Users_Users_CreatedById",
41  column: x => x.CreatedById,
42  principalTable: "Users",
43  principalColumn: "Id",
44  onDelete: ReferentialAction.Restrict);
45  });
46 
47  migrationBuilder.CreateTable(
48  name: "ChatChannels",
49  columns: table => new
50  {
51  IrcChannel = table.Column<string>(nullable: true),
52  DiscordChannelId = table.Column<ulong>(nullable: true),
53  IsAdminChannel = table.Column<bool>(nullable: false),
54  IsWatchdogChannel = table.Column<bool>(nullable: false),
55  IsUpdatesChannel = table.Column<bool>(nullable: false),
56  Tag = table.Column<string>(nullable: true),
57  Id = table.Column<long>(nullable: false)
58  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
59  ChatSettingsId = table.Column<long>(nullable: false)
60  },
61  constraints: table =>
62  {
63  table.PrimaryKey("PK_ChatChannels", x => x.Id);
64  });
65 
66  migrationBuilder.CreateTable(
67  name: "ReattachInformations",
68  columns: table => new
69  {
70  ChatCommandsJson = table.Column<string>(nullable: false),
71  ChatChannelsJson = table.Column<string>(nullable: false),
72  ServerCommandsJson = table.Column<string>(nullable: false),
73  AccessIdentifier = table.Column<string>(nullable: false),
74  ProcessId = table.Column<int>(nullable: false),
75  IsPrimary = table.Column<bool>(nullable: false),
76  Port = table.Column<ushort>(nullable: false),
77  RebootState = table.Column<int>(nullable: false),
78  Id = table.Column<long>(nullable: false)
79  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
80  CompileJobId = table.Column<long>(nullable: true)
81  },
82  constraints: table =>
83  {
84  table.PrimaryKey("PK_ReattachInformations", x => x.Id);
85  });
86 
87  migrationBuilder.CreateTable(
88  name: "WatchdogReattachInformations",
89  columns: table => new
90  {
91  AlphaIsActive = table.Column<bool>(nullable: false),
92  Id = table.Column<long>(nullable: false)
93  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
94  AlphaId = table.Column<long>(nullable: true),
95  BravoId = table.Column<long>(nullable: true)
96  },
97  constraints: table =>
98  {
99  table.PrimaryKey("PK_WatchdogReattachInformations", x => x.Id);
100  table.ForeignKey(
101  name: "FK_WatchdogReattachInformations_ReattachInformations_AlphaId",
102  column: x => x.AlphaId,
103  principalTable: "ReattachInformations",
104  principalColumn: "Id",
105  onDelete: ReferentialAction.Restrict);
106  table.ForeignKey(
107  name: "FK_WatchdogReattachInformations_ReattachInformations_BravoId",
108  column: x => x.BravoId,
109  principalTable: "ReattachInformations",
110  principalColumn: "Id",
111  onDelete: ReferentialAction.Restrict);
112  });
113 
114  migrationBuilder.CreateTable(
115  name: "Instances",
116  columns: table => new
117  {
118  Id = table.Column<long>(nullable: false)
119  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
120  Name = table.Column<string>(nullable: false),
121  Path = table.Column<string>(nullable: false),
122  Online = table.Column<bool>(nullable: false),
123  ConfigurationType = table.Column<int>(nullable: false),
124  AutoUpdateInterval = table.Column<uint>(nullable: false),
125  WatchdogReattachInformationId = table.Column<long>(nullable: true)
126  },
127  constraints: table =>
128  {
129  table.PrimaryKey("PK_Instances", x => x.Id);
130  table.ForeignKey(
131  name: "FK_Instances_WatchdogReattachInformations_WatchdogReattachInfor~",
132  column: x => x.WatchdogReattachInformationId,
133  principalTable: "WatchdogReattachInformations",
134  principalColumn: "Id",
135  onDelete: ReferentialAction.Restrict);
136  });
137 
138  migrationBuilder.CreateTable(
139  name: "ChatBots",
140  columns: table => new
141  {
142  Id = table.Column<long>(nullable: false)
143  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
144  Name = table.Column<string>(nullable: false),
145  Enabled = table.Column<bool>(nullable: true),
146  Provider = table.Column<int>(nullable: true),
147  ConnectionString = table.Column<string>(nullable: false),
148  InstanceId = table.Column<long>(nullable: false)
149  },
150  constraints: table =>
151  {
152  table.PrimaryKey("PK_ChatBots", x => x.Id);
153  table.ForeignKey(
154  name: "FK_ChatBots_Instances_InstanceId",
155  column: x => x.InstanceId,
156  principalTable: "Instances",
157  principalColumn: "Id",
158  onDelete: ReferentialAction.Cascade);
159  });
160 
161  migrationBuilder.CreateTable(
162  name: "DreamDaemonSettings",
163  columns: table => new
164  {
165  AllowWebClient = table.Column<bool>(nullable: false),
166  SecurityLevel = table.Column<int>(nullable: false),
167  PrimaryPort = table.Column<ushort>(nullable: false),
168  SecondaryPort = table.Column<ushort>(nullable: false),
169  StartupTimeout = table.Column<uint>(nullable: false),
170  AutoStart = table.Column<bool>(nullable: false),
171  SoftRestart = table.Column<bool>(nullable: false),
172  SoftShutdown = table.Column<bool>(nullable: false),
173  Id = table.Column<long>(nullable: false)
174  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
175  ProcessId = table.Column<int>(nullable: true),
176  AccessToken = table.Column<string>(nullable: true),
177  InstanceId = table.Column<long>(nullable: false)
178  },
179  constraints: table =>
180  {
181  table.PrimaryKey("PK_DreamDaemonSettings", x => x.Id);
182  table.ForeignKey(
183  name: "FK_DreamDaemonSettings_Instances_InstanceId",
184  column: x => x.InstanceId,
185  principalTable: "Instances",
186  principalColumn: "Id",
187  onDelete: ReferentialAction.Cascade);
188  });
189 
190  migrationBuilder.CreateTable(
191  name: "DreamMakerSettings",
192  columns: table => new
193  {
194  ProjectName = table.Column<string>(nullable: true),
195  ApiValidationPort = table.Column<ushort>(nullable: false),
196  Id = table.Column<long>(nullable: false)
197  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
198  InstanceId = table.Column<long>(nullable: false)
199  },
200  constraints: table =>
201  {
202  table.PrimaryKey("PK_DreamMakerSettings", x => x.Id);
203  table.ForeignKey(
204  name: "FK_DreamMakerSettings_Instances_InstanceId",
205  column: x => x.InstanceId,
206  principalTable: "Instances",
207  principalColumn: "Id",
208  onDelete: ReferentialAction.Cascade);
209  });
210 
211  migrationBuilder.CreateTable(
212  name: "InstanceUsers",
213  columns: table => new
214  {
215  UserId = table.Column<long>(nullable: false),
216  InstanceUserRights = table.Column<ulong>(nullable: false),
217  ByondRights = table.Column<ulong>(nullable: false),
218  DreamDaemonRights = table.Column<ulong>(nullable: false),
219  DreamMakerRights = table.Column<ulong>(nullable: false),
220  RepositoryRights = table.Column<ulong>(nullable: false),
221  ChatBotRights = table.Column<ulong>(nullable: false),
222  ConfigurationRights = table.Column<ulong>(nullable: false),
223  Id = table.Column<long>(nullable: false)
224  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
225  InstanceId = table.Column<long>(nullable: false)
226  },
227  constraints: table =>
228  {
229  table.PrimaryKey("PK_InstanceUsers", x => x.Id);
230  table.ForeignKey(
231  name: "FK_InstanceUsers_Instances_InstanceId",
232  column: x => x.InstanceId,
233  principalTable: "Instances",
234  principalColumn: "Id",
235  onDelete: ReferentialAction.Cascade);
236  table.ForeignKey(
237  name: "FK_InstanceUsers_Users_UserId",
238  column: x => x.UserId,
239  principalTable: "Users",
240  principalColumn: "Id",
241  onDelete: ReferentialAction.Cascade);
242  });
243 
244  migrationBuilder.CreateTable(
245  name: "Jobs",
246  columns: table => new
247  {
248  Id = table.Column<long>(nullable: false)
249  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
250  Description = table.Column<string>(nullable: false),
251  ExceptionDetails = table.Column<string>(nullable: true),
252  StartedAt = table.Column<DateTimeOffset>(nullable: false),
253  StoppedAt = table.Column<DateTimeOffset>(nullable: true),
254  Cancelled = table.Column<bool>(nullable: false),
255  CancelRightsType = table.Column<ulong>(nullable: true),
256  CancelRight = table.Column<ulong>(nullable: true),
257  StartedById = table.Column<long>(nullable: false),
258  CancelledById = table.Column<long>(nullable: true),
259  InstanceId = table.Column<long>(nullable: false)
260  },
261  constraints: table =>
262  {
263  table.PrimaryKey("PK_Jobs", x => x.Id);
264  table.ForeignKey(
265  name: "FK_Jobs_Users_CancelledById",
266  column: x => x.CancelledById,
267  principalTable: "Users",
268  principalColumn: "Id",
269  onDelete: ReferentialAction.Restrict);
270  table.ForeignKey(
271  name: "FK_Jobs_Instances_InstanceId",
272  column: x => x.InstanceId,
273  principalTable: "Instances",
274  principalColumn: "Id",
275  onDelete: ReferentialAction.Cascade);
276  table.ForeignKey(
277  name: "FK_Jobs_Users_StartedById",
278  column: x => x.StartedById,
279  principalTable: "Users",
280  principalColumn: "Id",
281  onDelete: ReferentialAction.Cascade);
282  });
283 
284  migrationBuilder.CreateTable(
285  name: "RepositorySettings",
286  columns: table => new
287  {
288  CommitterName = table.Column<string>(nullable: false),
289  CommitterEmail = table.Column<string>(nullable: false),
290  AccessUser = table.Column<string>(nullable: true),
291  AccessToken = table.Column<string>(nullable: true),
292  PushTestMergeCommits = table.Column<bool>(nullable: false),
293  ShowTestMergeCommitters = table.Column<bool>(nullable: false),
294  AutoUpdatesKeepTestMerges = table.Column<bool>(nullable: false),
295  AutoUpdatesSynchronize = table.Column<bool>(nullable: false),
296  Id = table.Column<long>(nullable: false)
297  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
298  InstanceId = table.Column<long>(nullable: false)
299  },
300  constraints: table =>
301  {
302  table.PrimaryKey("PK_RepositorySettings", x => x.Id);
303  table.ForeignKey(
304  name: "FK_RepositorySettings_Instances_InstanceId",
305  column: x => x.InstanceId,
306  principalTable: "Instances",
307  principalColumn: "Id",
308  onDelete: ReferentialAction.Cascade);
309  });
310 
311  migrationBuilder.CreateTable(
312  name: "RevisionInformations",
313  columns: table => new
314  {
315  CommitSha = table.Column<string>(maxLength: 40, nullable: false),
316  OriginCommitSha = table.Column<string>(maxLength: 40, nullable: false),
317  Id = table.Column<long>(nullable: false)
318  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
319  InstanceId = table.Column<long>(nullable: false)
320  },
321  constraints: table =>
322  {
323  table.PrimaryKey("PK_RevisionInformations", x => x.Id);
324  table.ForeignKey(
325  name: "FK_RevisionInformations_Instances_InstanceId",
326  column: x => x.InstanceId,
327  principalTable: "Instances",
328  principalColumn: "Id",
329  onDelete: ReferentialAction.Cascade);
330  });
331 
332  migrationBuilder.CreateTable(
333  name: "CompileJobs",
334  columns: table => new
335  {
336  Id = table.Column<long>(nullable: false)
337  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
338  DmeName = table.Column<string>(nullable: true),
339  Output = table.Column<string>(nullable: true),
340  DirectoryName = table.Column<Guid>(nullable: true),
341  JobId = table.Column<long>(nullable: true),
342  RevisionInformationId = table.Column<long>(nullable: false),
343  ByondVersion = table.Column<string>(nullable: false)
344  },
345  constraints: table =>
346  {
347  table.PrimaryKey("PK_CompileJobs", x => x.Id);
348  table.ForeignKey(
349  name: "FK_CompileJobs_Jobs_JobId",
350  column: x => x.JobId,
351  principalTable: "Jobs",
352  principalColumn: "Id",
353  onDelete: ReferentialAction.Restrict);
354  table.ForeignKey(
355  name: "FK_CompileJobs_RevisionInformations_RevisionInformationId",
356  column: x => x.RevisionInformationId,
357  principalTable: "RevisionInformations",
358  principalColumn: "Id",
359  onDelete: ReferentialAction.Cascade);
360  });
361 
362  migrationBuilder.CreateTable(
363  name: "TestMerges",
364  columns: table => new
365  {
366  Number = table.Column<int>(nullable: false),
367  PullRequestRevision = table.Column<string>(nullable: false),
368  Comment = table.Column<string>(nullable: true),
369  TitleAtMerge = table.Column<string>(nullable: false),
370  BodyAtMerge = table.Column<string>(nullable: false),
371  Url = table.Column<string>(nullable: false),
372  Author = table.Column<string>(nullable: false),
373  Id = table.Column<long>(nullable: false)
374  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
375  MergedAt = table.Column<DateTimeOffset>(nullable: false),
376  MergedById = table.Column<long>(nullable: false),
377  PrimaryRevisionInformationId = table.Column<long>(nullable: true)
378  },
379  constraints: table =>
380  {
381  table.PrimaryKey("PK_TestMerges", x => x.Id);
382  table.ForeignKey(
383  name: "FK_TestMerges_Users_MergedById",
384  column: x => x.MergedById,
385  principalTable: "Users",
386  principalColumn: "Id",
387  onDelete: ReferentialAction.Restrict);
388  table.ForeignKey(
389  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
390  column: x => x.PrimaryRevisionInformationId,
391  principalTable: "RevisionInformations",
392  principalColumn: "Id",
393  onDelete: ReferentialAction.SetNull);
394  });
395 
396  migrationBuilder.CreateTable(
397  name: "RevInfoTestMerges",
398  columns: table => new
399  {
400  Id = table.Column<long>(nullable: false)
401  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
402  TestMergeId = table.Column<long>(nullable: false),
403  RevisionInformationId = table.Column<long>(nullable: false)
404  },
405  constraints: table =>
406  {
407  table.PrimaryKey("PK_RevInfoTestMerges", x => x.Id);
408  table.ForeignKey(
409  name: "FK_RevInfoTestMerges_RevisionInformations_RevisionInformationId",
410  column: x => x.RevisionInformationId,
411  principalTable: "RevisionInformations",
412  principalColumn: "Id",
413  onDelete: ReferentialAction.Cascade);
414  table.ForeignKey(
415  name: "FK_RevInfoTestMerges_TestMerges_TestMergeId",
416  column: x => x.TestMergeId,
417  principalTable: "TestMerges",
418  principalColumn: "Id",
419  onDelete: ReferentialAction.Cascade);
420  });
421 
422  migrationBuilder.CreateIndex(
423  name: "IX_ChatBots_InstanceId",
424  table: "ChatBots",
425  column: "InstanceId");
426 
427  migrationBuilder.CreateIndex(
428  name: "IX_ChatBots_Name",
429  table: "ChatBots",
430  column: "Name",
431  unique: true);
432 
433  migrationBuilder.CreateIndex(
434  name: "IX_ChatChannels_ChatSettingsId_DiscordChannelId",
435  table: "ChatChannels",
436  columns: new[] { "ChatSettingsId", "DiscordChannelId" },
437  unique: true);
438 
439  migrationBuilder.CreateIndex(
440  name: "IX_ChatChannels_ChatSettingsId_IrcChannel",
441  table: "ChatChannels",
442  columns: new[] { "ChatSettingsId", "IrcChannel" },
443  unique: true);
444 
445  migrationBuilder.CreateIndex(
446  name: "IX_CompileJobs_DirectoryName",
447  table: "CompileJobs",
448  column: "DirectoryName");
449 
450  migrationBuilder.CreateIndex(
451  name: "IX_CompileJobs_JobId",
452  table: "CompileJobs",
453  column: "JobId");
454 
455  migrationBuilder.CreateIndex(
456  name: "IX_CompileJobs_RevisionInformationId",
457  table: "CompileJobs",
458  column: "RevisionInformationId");
459 
460  migrationBuilder.CreateIndex(
461  name: "IX_DreamDaemonSettings_InstanceId",
462  table: "DreamDaemonSettings",
463  column: "InstanceId",
464  unique: true);
465 
466  migrationBuilder.CreateIndex(
467  name: "IX_DreamMakerSettings_InstanceId",
468  table: "DreamMakerSettings",
469  column: "InstanceId",
470  unique: true);
471 
472  migrationBuilder.CreateIndex(
473  name: "IX_Instances_Path",
474  table: "Instances",
475  column: "Path",
476  unique: true);
477 
478  migrationBuilder.CreateIndex(
479  name: "IX_Instances_WatchdogReattachInformationId",
480  table: "Instances",
481  column: "WatchdogReattachInformationId");
482 
483  migrationBuilder.CreateIndex(
484  name: "IX_InstanceUsers_InstanceId",
485  table: "InstanceUsers",
486  column: "InstanceId");
487 
488  migrationBuilder.CreateIndex(
489  name: "IX_InstanceUsers_UserId_InstanceId",
490  table: "InstanceUsers",
491  columns: new[] { "UserId", "InstanceId" },
492  unique: true);
493 
494  migrationBuilder.CreateIndex(
495  name: "IX_Jobs_CancelledById",
496  table: "Jobs",
497  column: "CancelledById");
498 
499  migrationBuilder.CreateIndex(
500  name: "IX_Jobs_InstanceId",
501  table: "Jobs",
502  column: "InstanceId");
503 
504  migrationBuilder.CreateIndex(
505  name: "IX_Jobs_StartedById",
506  table: "Jobs",
507  column: "StartedById");
508 
509  migrationBuilder.CreateIndex(
510  name: "IX_ReattachInformations_CompileJobId",
511  table: "ReattachInformations",
512  column: "CompileJobId");
513 
514  migrationBuilder.CreateIndex(
515  name: "IX_RepositorySettings_InstanceId",
516  table: "RepositorySettings",
517  column: "InstanceId",
518  unique: true);
519 
520  migrationBuilder.CreateIndex(
521  name: "IX_RevInfoTestMerges_RevisionInformationId",
522  table: "RevInfoTestMerges",
523  column: "RevisionInformationId");
524 
525  migrationBuilder.CreateIndex(
526  name: "IX_RevInfoTestMerges_TestMergeId",
527  table: "RevInfoTestMerges",
528  column: "TestMergeId");
529 
530  migrationBuilder.CreateIndex(
531  name: "IX_RevisionInformations_CommitSha",
532  table: "RevisionInformations",
533  column: "CommitSha",
534  unique: true);
535 
536  migrationBuilder.CreateIndex(
537  name: "IX_RevisionInformations_InstanceId",
538  table: "RevisionInformations",
539  column: "InstanceId");
540 
541  migrationBuilder.CreateIndex(
542  name: "IX_TestMerges_MergedById",
543  table: "TestMerges",
544  column: "MergedById");
545 
546  migrationBuilder.CreateIndex(
547  name: "IX_TestMerges_PrimaryRevisionInformationId",
548  table: "TestMerges",
549  column: "PrimaryRevisionInformationId",
550  unique: true);
551 
552  migrationBuilder.CreateIndex(
553  name: "IX_Users_CanonicalName",
554  table: "Users",
555  column: "CanonicalName",
556  unique: true);
557 
558  migrationBuilder.CreateIndex(
559  name: "IX_Users_CreatedById",
560  table: "Users",
561  column: "CreatedById");
562 
563  migrationBuilder.CreateIndex(
564  name: "IX_WatchdogReattachInformations_AlphaId",
565  table: "WatchdogReattachInformations",
566  column: "AlphaId");
567 
568  migrationBuilder.CreateIndex(
569  name: "IX_WatchdogReattachInformations_BravoId",
570  table: "WatchdogReattachInformations",
571  column: "BravoId");
572 
573  migrationBuilder.AddForeignKey(
574  name: "FK_ChatChannels_ChatBots_ChatSettingsId",
575  table: "ChatChannels",
576  column: "ChatSettingsId",
577  principalTable: "ChatBots",
578  principalColumn: "Id",
579  onDelete: ReferentialAction.Cascade);
580 
581  migrationBuilder.AddForeignKey(
582  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
583  table: "ReattachInformations",
584  column: "CompileJobId",
585  principalTable: "CompileJobs",
586  principalColumn: "Id",
587  onDelete: ReferentialAction.Restrict);
588  }
589 
594  protected override void Down(MigrationBuilder migrationBuilder)
595  {
596  migrationBuilder.DropForeignKey(
597  name: "FK_Jobs_Instances_InstanceId",
598  table: "Jobs");
599 
600  migrationBuilder.DropForeignKey(
601  name: "FK_RevisionInformations_Instances_InstanceId",
602  table: "RevisionInformations");
603 
604  migrationBuilder.DropTable(
605  name: "ChatChannels");
606 
607  migrationBuilder.DropTable(
608  name: "DreamDaemonSettings");
609 
610  migrationBuilder.DropTable(
611  name: "DreamMakerSettings");
612 
613  migrationBuilder.DropTable(
614  name: "InstanceUsers");
615 
616  migrationBuilder.DropTable(
617  name: "RepositorySettings");
618 
619  migrationBuilder.DropTable(
620  name: "RevInfoTestMerges");
621 
622  migrationBuilder.DropTable(
623  name: "ChatBots");
624 
625  migrationBuilder.DropTable(
626  name: "TestMerges");
627 
628  migrationBuilder.DropTable(
629  name: "Instances");
630 
631  migrationBuilder.DropTable(
632  name: "WatchdogReattachInformations");
633 
634  migrationBuilder.DropTable(
635  name: "ReattachInformations");
636 
637  migrationBuilder.DropTable(
638  name: "CompileJobs");
639 
640  migrationBuilder.DropTable(
641  name: "Jobs");
642 
643  migrationBuilder.DropTable(
644  name: "RevisionInformations");
645 
646  migrationBuilder.DropTable(
647  name: "Users");
648  }
649  }
650 }
ConfigurationRights
Rights for Models.ConfigurationFile
-
ByondRights
Rights for Models.Byond
Definition: ByondRights.cs:9
-
InstanceUserRights
Rights for an Models.Instance
- - -
AdministrationRights
Rights for Models.Administration
-
ConfigurationType
The type of configuration allowed on an Instance
+Go to the documentation of this file.
1 using System;
2 using Microsoft.EntityFrameworkCore.Metadata;
3 using Microsoft.EntityFrameworkCore.Migrations;
4 
6 {
10  #pragma warning disable CA1506
11  public partial class MYInitialCreate : Migration
12  {
17  protected override void Up(MigrationBuilder migrationBuilder)
18  {
19  if (migrationBuilder == null)
20  throw new ArgumentNullException(nameof(migrationBuilder));
21 
22  migrationBuilder.CreateTable(
23  name: "Users",
24  columns: table => new
25  {
26  Id = table.Column<long>(nullable: false)
27  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
28  Enabled = table.Column<bool>(nullable: false),
29  CreatedAt = table.Column<DateTimeOffset>(nullable: false),
30  SystemIdentifier = table.Column<string>(nullable: true),
31  Name = table.Column<string>(nullable: false),
32  AdministrationRights = table.Column<ulong>(nullable: false),
33  InstanceManagerRights = table.Column<ulong>(nullable: false),
34  PasswordHash = table.Column<string>(nullable: true),
35  CreatedById = table.Column<long>(nullable: true),
36  CanonicalName = table.Column<string>(nullable: false),
37  LastPasswordUpdate = table.Column<DateTimeOffset>(nullable: true)
38  },
39  constraints: table =>
40  {
41  table.PrimaryKey("PK_Users", x => x.Id);
42  table.ForeignKey(
43  name: "FK_Users_Users_CreatedById",
44  column: x => x.CreatedById,
45  principalTable: "Users",
46  principalColumn: "Id",
47  onDelete: ReferentialAction.Restrict);
48  });
49 
50  migrationBuilder.CreateTable(
51  name: "ChatChannels",
52  columns: table => new
53  {
54  IrcChannel = table.Column<string>(nullable: true),
55  DiscordChannelId = table.Column<ulong>(nullable: true),
56  IsAdminChannel = table.Column<bool>(nullable: false),
57  IsWatchdogChannel = table.Column<bool>(nullable: false),
58  IsUpdatesChannel = table.Column<bool>(nullable: false),
59  Tag = table.Column<string>(nullable: true),
60  Id = table.Column<long>(nullable: false)
61  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
62  ChatSettingsId = table.Column<long>(nullable: false)
63  },
64  constraints: table =>
65  {
66  table.PrimaryKey("PK_ChatChannels", x => x.Id);
67  });
68 
69  migrationBuilder.CreateTable(
70  name: "ReattachInformations",
71  columns: table => new
72  {
73  ChatCommandsJson = table.Column<string>(nullable: false),
74  ChatChannelsJson = table.Column<string>(nullable: false),
75  ServerCommandsJson = table.Column<string>(nullable: false),
76  AccessIdentifier = table.Column<string>(nullable: false),
77  ProcessId = table.Column<int>(nullable: false),
78  IsPrimary = table.Column<bool>(nullable: false),
79  Port = table.Column<ushort>(nullable: false),
80  RebootState = table.Column<int>(nullable: false),
81  Id = table.Column<long>(nullable: false)
82  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
83  CompileJobId = table.Column<long>(nullable: true)
84  },
85  constraints: table =>
86  {
87  table.PrimaryKey("PK_ReattachInformations", x => x.Id);
88  });
89 
90  migrationBuilder.CreateTable(
91  name: "WatchdogReattachInformations",
92  columns: table => new
93  {
94  AlphaIsActive = table.Column<bool>(nullable: false),
95  Id = table.Column<long>(nullable: false)
96  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
97  AlphaId = table.Column<long>(nullable: true),
98  BravoId = table.Column<long>(nullable: true)
99  },
100  constraints: table =>
101  {
102  table.PrimaryKey("PK_WatchdogReattachInformations", x => x.Id);
103  table.ForeignKey(
104  name: "FK_WatchdogReattachInformations_ReattachInformations_AlphaId",
105  column: x => x.AlphaId,
106  principalTable: "ReattachInformations",
107  principalColumn: "Id",
108  onDelete: ReferentialAction.Restrict);
109  table.ForeignKey(
110  name: "FK_WatchdogReattachInformations_ReattachInformations_BravoId",
111  column: x => x.BravoId,
112  principalTable: "ReattachInformations",
113  principalColumn: "Id",
114  onDelete: ReferentialAction.Restrict);
115  });
116 
117  migrationBuilder.CreateTable(
118  name: "Instances",
119  columns: table => new
120  {
121  Id = table.Column<long>(nullable: false)
122  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
123  Name = table.Column<string>(nullable: false),
124  Path = table.Column<string>(nullable: false),
125  Online = table.Column<bool>(nullable: false),
126  ConfigurationType = table.Column<int>(nullable: false),
127  AutoUpdateInterval = table.Column<uint>(nullable: false),
128  WatchdogReattachInformationId = table.Column<long>(nullable: true)
129  },
130  constraints: table =>
131  {
132  table.PrimaryKey("PK_Instances", x => x.Id);
133  table.ForeignKey(
134  name: "FK_Instances_WatchdogReattachInformations_WatchdogReattachInfor~",
135  column: x => x.WatchdogReattachInformationId,
136  principalTable: "WatchdogReattachInformations",
137  principalColumn: "Id",
138  onDelete: ReferentialAction.Restrict);
139  });
140 
141  migrationBuilder.CreateTable(
142  name: "ChatBots",
143  columns: table => new
144  {
145  Id = table.Column<long>(nullable: false)
146  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
147  Name = table.Column<string>(nullable: false),
148  Enabled = table.Column<bool>(nullable: true),
149  Provider = table.Column<int>(nullable: true),
150  ConnectionString = table.Column<string>(nullable: false),
151  InstanceId = table.Column<long>(nullable: false)
152  },
153  constraints: table =>
154  {
155  table.PrimaryKey("PK_ChatBots", x => x.Id);
156  table.ForeignKey(
157  name: "FK_ChatBots_Instances_InstanceId",
158  column: x => x.InstanceId,
159  principalTable: "Instances",
160  principalColumn: "Id",
161  onDelete: ReferentialAction.Cascade);
162  });
163 
164  migrationBuilder.CreateTable(
165  name: "DreamDaemonSettings",
166  columns: table => new
167  {
168  AllowWebClient = table.Column<bool>(nullable: false),
169  SecurityLevel = table.Column<int>(nullable: false),
170  PrimaryPort = table.Column<ushort>(nullable: false),
171  SecondaryPort = table.Column<ushort>(nullable: false),
172  StartupTimeout = table.Column<uint>(nullable: false),
173  AutoStart = table.Column<bool>(nullable: false),
174  SoftRestart = table.Column<bool>(nullable: false),
175  SoftShutdown = table.Column<bool>(nullable: false),
176  Id = table.Column<long>(nullable: false)
177  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
178  ProcessId = table.Column<int>(nullable: true),
179  AccessToken = table.Column<string>(nullable: true),
180  InstanceId = table.Column<long>(nullable: false)
181  },
182  constraints: table =>
183  {
184  table.PrimaryKey("PK_DreamDaemonSettings", x => x.Id);
185  table.ForeignKey(
186  name: "FK_DreamDaemonSettings_Instances_InstanceId",
187  column: x => x.InstanceId,
188  principalTable: "Instances",
189  principalColumn: "Id",
190  onDelete: ReferentialAction.Cascade);
191  });
192 
193  migrationBuilder.CreateTable(
194  name: "DreamMakerSettings",
195  columns: table => new
196  {
197  ProjectName = table.Column<string>(nullable: true),
198  ApiValidationPort = table.Column<ushort>(nullable: false),
199  Id = table.Column<long>(nullable: false)
200  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
201  InstanceId = table.Column<long>(nullable: false)
202  },
203  constraints: table =>
204  {
205  table.PrimaryKey("PK_DreamMakerSettings", x => x.Id);
206  table.ForeignKey(
207  name: "FK_DreamMakerSettings_Instances_InstanceId",
208  column: x => x.InstanceId,
209  principalTable: "Instances",
210  principalColumn: "Id",
211  onDelete: ReferentialAction.Cascade);
212  });
213 
214  migrationBuilder.CreateTable(
215  name: "InstanceUsers",
216  columns: table => new
217  {
218  UserId = table.Column<long>(nullable: false),
219  InstanceUserRights = table.Column<ulong>(nullable: false),
220  ByondRights = table.Column<ulong>(nullable: false),
221  DreamDaemonRights = table.Column<ulong>(nullable: false),
222  DreamMakerRights = table.Column<ulong>(nullable: false),
223  RepositoryRights = table.Column<ulong>(nullable: false),
224  ChatBotRights = table.Column<ulong>(nullable: false),
225  ConfigurationRights = table.Column<ulong>(nullable: false),
226  Id = table.Column<long>(nullable: false)
227  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
228  InstanceId = table.Column<long>(nullable: false)
229  },
230  constraints: table =>
231  {
232  table.PrimaryKey("PK_InstanceUsers", x => x.Id);
233  table.ForeignKey(
234  name: "FK_InstanceUsers_Instances_InstanceId",
235  column: x => x.InstanceId,
236  principalTable: "Instances",
237  principalColumn: "Id",
238  onDelete: ReferentialAction.Cascade);
239  table.ForeignKey(
240  name: "FK_InstanceUsers_Users_UserId",
241  column: x => x.UserId,
242  principalTable: "Users",
243  principalColumn: "Id",
244  onDelete: ReferentialAction.Cascade);
245  });
246 
247  migrationBuilder.CreateTable(
248  name: "Jobs",
249  columns: table => new
250  {
251  Id = table.Column<long>(nullable: false)
252  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
253  Description = table.Column<string>(nullable: false),
254  ExceptionDetails = table.Column<string>(nullable: true),
255  StartedAt = table.Column<DateTimeOffset>(nullable: false),
256  StoppedAt = table.Column<DateTimeOffset>(nullable: true),
257  Cancelled = table.Column<bool>(nullable: false),
258  CancelRightsType = table.Column<ulong>(nullable: true),
259  CancelRight = table.Column<ulong>(nullable: true),
260  StartedById = table.Column<long>(nullable: false),
261  CancelledById = table.Column<long>(nullable: true),
262  InstanceId = table.Column<long>(nullable: false)
263  },
264  constraints: table =>
265  {
266  table.PrimaryKey("PK_Jobs", x => x.Id);
267  table.ForeignKey(
268  name: "FK_Jobs_Users_CancelledById",
269  column: x => x.CancelledById,
270  principalTable: "Users",
271  principalColumn: "Id",
272  onDelete: ReferentialAction.Restrict);
273  table.ForeignKey(
274  name: "FK_Jobs_Instances_InstanceId",
275  column: x => x.InstanceId,
276  principalTable: "Instances",
277  principalColumn: "Id",
278  onDelete: ReferentialAction.Cascade);
279  table.ForeignKey(
280  name: "FK_Jobs_Users_StartedById",
281  column: x => x.StartedById,
282  principalTable: "Users",
283  principalColumn: "Id",
284  onDelete: ReferentialAction.Cascade);
285  });
286 
287  migrationBuilder.CreateTable(
288  name: "RepositorySettings",
289  columns: table => new
290  {
291  CommitterName = table.Column<string>(nullable: false),
292  CommitterEmail = table.Column<string>(nullable: false),
293  AccessUser = table.Column<string>(nullable: true),
294  AccessToken = table.Column<string>(nullable: true),
295  PushTestMergeCommits = table.Column<bool>(nullable: false),
296  ShowTestMergeCommitters = table.Column<bool>(nullable: false),
297  AutoUpdatesKeepTestMerges = table.Column<bool>(nullable: false),
298  AutoUpdatesSynchronize = table.Column<bool>(nullable: false),
299  Id = table.Column<long>(nullable: false)
300  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
301  InstanceId = table.Column<long>(nullable: false)
302  },
303  constraints: table =>
304  {
305  table.PrimaryKey("PK_RepositorySettings", x => x.Id);
306  table.ForeignKey(
307  name: "FK_RepositorySettings_Instances_InstanceId",
308  column: x => x.InstanceId,
309  principalTable: "Instances",
310  principalColumn: "Id",
311  onDelete: ReferentialAction.Cascade);
312  });
313 
314  migrationBuilder.CreateTable(
315  name: "RevisionInformations",
316  columns: table => new
317  {
318  CommitSha = table.Column<string>(maxLength: 40, nullable: false),
319  OriginCommitSha = table.Column<string>(maxLength: 40, nullable: false),
320  Id = table.Column<long>(nullable: false)
321  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
322  InstanceId = table.Column<long>(nullable: false)
323  },
324  constraints: table =>
325  {
326  table.PrimaryKey("PK_RevisionInformations", x => x.Id);
327  table.ForeignKey(
328  name: "FK_RevisionInformations_Instances_InstanceId",
329  column: x => x.InstanceId,
330  principalTable: "Instances",
331  principalColumn: "Id",
332  onDelete: ReferentialAction.Cascade);
333  });
334 
335  migrationBuilder.CreateTable(
336  name: "CompileJobs",
337  columns: table => new
338  {
339  Id = table.Column<long>(nullable: false)
340  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
341  DmeName = table.Column<string>(nullable: true),
342  Output = table.Column<string>(nullable: true),
343  DirectoryName = table.Column<Guid>(nullable: true),
344  JobId = table.Column<long>(nullable: true),
345  RevisionInformationId = table.Column<long>(nullable: false),
346  ByondVersion = table.Column<string>(nullable: false)
347  },
348  constraints: table =>
349  {
350  table.PrimaryKey("PK_CompileJobs", x => x.Id);
351  table.ForeignKey(
352  name: "FK_CompileJobs_Jobs_JobId",
353  column: x => x.JobId,
354  principalTable: "Jobs",
355  principalColumn: "Id",
356  onDelete: ReferentialAction.Restrict);
357  table.ForeignKey(
358  name: "FK_CompileJobs_RevisionInformations_RevisionInformationId",
359  column: x => x.RevisionInformationId,
360  principalTable: "RevisionInformations",
361  principalColumn: "Id",
362  onDelete: ReferentialAction.Cascade);
363  });
364 
365  migrationBuilder.CreateTable(
366  name: "TestMerges",
367  columns: table => new
368  {
369  Number = table.Column<int>(nullable: false),
370  PullRequestRevision = table.Column<string>(nullable: false),
371  Comment = table.Column<string>(nullable: true),
372  TitleAtMerge = table.Column<string>(nullable: false),
373  BodyAtMerge = table.Column<string>(nullable: false),
374  Url = table.Column<string>(nullable: false),
375  Author = table.Column<string>(nullable: false),
376  Id = table.Column<long>(nullable: false)
377  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
378  MergedAt = table.Column<DateTimeOffset>(nullable: false),
379  MergedById = table.Column<long>(nullable: false),
380  PrimaryRevisionInformationId = table.Column<long>(nullable: true)
381  },
382  constraints: table =>
383  {
384  table.PrimaryKey("PK_TestMerges", x => x.Id);
385  table.ForeignKey(
386  name: "FK_TestMerges_Users_MergedById",
387  column: x => x.MergedById,
388  principalTable: "Users",
389  principalColumn: "Id",
390  onDelete: ReferentialAction.Restrict);
391  table.ForeignKey(
392  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
393  column: x => x.PrimaryRevisionInformationId,
394  principalTable: "RevisionInformations",
395  principalColumn: "Id",
396  onDelete: ReferentialAction.SetNull);
397  });
398 
399  migrationBuilder.CreateTable(
400  name: "RevInfoTestMerges",
401  columns: table => new
402  {
403  Id = table.Column<long>(nullable: false)
404  .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
405  TestMergeId = table.Column<long>(nullable: false),
406  RevisionInformationId = table.Column<long>(nullable: false)
407  },
408  constraints: table =>
409  {
410  table.PrimaryKey("PK_RevInfoTestMerges", x => x.Id);
411  table.ForeignKey(
412  name: "FK_RevInfoTestMerges_RevisionInformations_RevisionInformationId",
413  column: x => x.RevisionInformationId,
414  principalTable: "RevisionInformations",
415  principalColumn: "Id",
416  onDelete: ReferentialAction.Cascade);
417  table.ForeignKey(
418  name: "FK_RevInfoTestMerges_TestMerges_TestMergeId",
419  column: x => x.TestMergeId,
420  principalTable: "TestMerges",
421  principalColumn: "Id",
422  onDelete: ReferentialAction.Cascade);
423  });
424 
425  migrationBuilder.CreateIndex(
426  name: "IX_ChatBots_InstanceId",
427  table: "ChatBots",
428  column: "InstanceId");
429 
430  migrationBuilder.CreateIndex(
431  name: "IX_ChatBots_Name",
432  table: "ChatBots",
433  column: "Name",
434  unique: true);
435 
436  migrationBuilder.CreateIndex(
437  name: "IX_ChatChannels_ChatSettingsId_DiscordChannelId",
438  table: "ChatChannels",
439  columns: new[] { "ChatSettingsId", "DiscordChannelId" },
440  unique: true);
441 
442  migrationBuilder.CreateIndex(
443  name: "IX_ChatChannels_ChatSettingsId_IrcChannel",
444  table: "ChatChannels",
445  columns: new[] { "ChatSettingsId", "IrcChannel" },
446  unique: true);
447 
448  migrationBuilder.CreateIndex(
449  name: "IX_CompileJobs_DirectoryName",
450  table: "CompileJobs",
451  column: "DirectoryName");
452 
453  migrationBuilder.CreateIndex(
454  name: "IX_CompileJobs_JobId",
455  table: "CompileJobs",
456  column: "JobId");
457 
458  migrationBuilder.CreateIndex(
459  name: "IX_CompileJobs_RevisionInformationId",
460  table: "CompileJobs",
461  column: "RevisionInformationId");
462 
463  migrationBuilder.CreateIndex(
464  name: "IX_DreamDaemonSettings_InstanceId",
465  table: "DreamDaemonSettings",
466  column: "InstanceId",
467  unique: true);
468 
469  migrationBuilder.CreateIndex(
470  name: "IX_DreamMakerSettings_InstanceId",
471  table: "DreamMakerSettings",
472  column: "InstanceId",
473  unique: true);
474 
475  migrationBuilder.CreateIndex(
476  name: "IX_Instances_Path",
477  table: "Instances",
478  column: "Path",
479  unique: true);
480 
481  migrationBuilder.CreateIndex(
482  name: "IX_Instances_WatchdogReattachInformationId",
483  table: "Instances",
484  column: "WatchdogReattachInformationId");
485 
486  migrationBuilder.CreateIndex(
487  name: "IX_InstanceUsers_InstanceId",
488  table: "InstanceUsers",
489  column: "InstanceId");
490 
491  migrationBuilder.CreateIndex(
492  name: "IX_InstanceUsers_UserId_InstanceId",
493  table: "InstanceUsers",
494  columns: new[] { "UserId", "InstanceId" },
495  unique: true);
496 
497  migrationBuilder.CreateIndex(
498  name: "IX_Jobs_CancelledById",
499  table: "Jobs",
500  column: "CancelledById");
501 
502  migrationBuilder.CreateIndex(
503  name: "IX_Jobs_InstanceId",
504  table: "Jobs",
505  column: "InstanceId");
506 
507  migrationBuilder.CreateIndex(
508  name: "IX_Jobs_StartedById",
509  table: "Jobs",
510  column: "StartedById");
511 
512  migrationBuilder.CreateIndex(
513  name: "IX_ReattachInformations_CompileJobId",
514  table: "ReattachInformations",
515  column: "CompileJobId");
516 
517  migrationBuilder.CreateIndex(
518  name: "IX_RepositorySettings_InstanceId",
519  table: "RepositorySettings",
520  column: "InstanceId",
521  unique: true);
522 
523  migrationBuilder.CreateIndex(
524  name: "IX_RevInfoTestMerges_RevisionInformationId",
525  table: "RevInfoTestMerges",
526  column: "RevisionInformationId");
527 
528  migrationBuilder.CreateIndex(
529  name: "IX_RevInfoTestMerges_TestMergeId",
530  table: "RevInfoTestMerges",
531  column: "TestMergeId");
532 
533  migrationBuilder.CreateIndex(
534  name: "IX_RevisionInformations_CommitSha",
535  table: "RevisionInformations",
536  column: "CommitSha",
537  unique: true);
538 
539  migrationBuilder.CreateIndex(
540  name: "IX_RevisionInformations_InstanceId",
541  table: "RevisionInformations",
542  column: "InstanceId");
543 
544  migrationBuilder.CreateIndex(
545  name: "IX_TestMerges_MergedById",
546  table: "TestMerges",
547  column: "MergedById");
548 
549  migrationBuilder.CreateIndex(
550  name: "IX_TestMerges_PrimaryRevisionInformationId",
551  table: "TestMerges",
552  column: "PrimaryRevisionInformationId",
553  unique: true);
554 
555  migrationBuilder.CreateIndex(
556  name: "IX_Users_CanonicalName",
557  table: "Users",
558  column: "CanonicalName",
559  unique: true);
560 
561  migrationBuilder.CreateIndex(
562  name: "IX_Users_CreatedById",
563  table: "Users",
564  column: "CreatedById");
565 
566  migrationBuilder.CreateIndex(
567  name: "IX_WatchdogReattachInformations_AlphaId",
568  table: "WatchdogReattachInformations",
569  column: "AlphaId");
570 
571  migrationBuilder.CreateIndex(
572  name: "IX_WatchdogReattachInformations_BravoId",
573  table: "WatchdogReattachInformations",
574  column: "BravoId");
575 
576  migrationBuilder.AddForeignKey(
577  name: "FK_ChatChannels_ChatBots_ChatSettingsId",
578  table: "ChatChannels",
579  column: "ChatSettingsId",
580  principalTable: "ChatBots",
581  principalColumn: "Id",
582  onDelete: ReferentialAction.Cascade);
583 
584  migrationBuilder.AddForeignKey(
585  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
586  table: "ReattachInformations",
587  column: "CompileJobId",
588  principalTable: "CompileJobs",
589  principalColumn: "Id",
590  onDelete: ReferentialAction.Restrict);
591  }
592 
597  protected override void Down(MigrationBuilder migrationBuilder)
598  {
599  if (migrationBuilder == null)
600  throw new ArgumentNullException(nameof(migrationBuilder));
601 
602  migrationBuilder.DropForeignKey(
603  name: "FK_Jobs_Instances_InstanceId",
604  table: "Jobs");
605 
606  migrationBuilder.DropForeignKey(
607  name: "FK_RevisionInformations_Instances_InstanceId",
608  table: "RevisionInformations");
609 
610  migrationBuilder.DropTable(
611  name: "ChatChannels");
612 
613  migrationBuilder.DropTable(
614  name: "DreamDaemonSettings");
615 
616  migrationBuilder.DropTable(
617  name: "DreamMakerSettings");
618 
619  migrationBuilder.DropTable(
620  name: "InstanceUsers");
621 
622  migrationBuilder.DropTable(
623  name: "RepositorySettings");
624 
625  migrationBuilder.DropTable(
626  name: "RevInfoTestMerges");
627 
628  migrationBuilder.DropTable(
629  name: "ChatBots");
630 
631  migrationBuilder.DropTable(
632  name: "TestMerges");
633 
634  migrationBuilder.DropTable(
635  name: "Instances");
636 
637  migrationBuilder.DropTable(
638  name: "WatchdogReattachInformations");
639 
640  migrationBuilder.DropTable(
641  name: "ReattachInformations");
642 
643  migrationBuilder.DropTable(
644  name: "CompileJobs");
645 
646  migrationBuilder.DropTable(
647  name: "Jobs");
648 
649  migrationBuilder.DropTable(
650  name: "RevisionInformations");
651 
652  migrationBuilder.DropTable(
653  name: "Users");
654  }
655  }
656 }
ConfigurationRights
Rights for Models.ConfigurationFile
+
ByondRights
Rights for Models.Byond
Definition: ByondRights.cs:9
+
InstanceUserRights
Rights for an Models.Instance
+ +
AdministrationRights
Rights for Models.Administration
+
ConfigurationType
The type of configuration allowed on an Instance
-
DreamDaemonRights
Rights for Models.DreamDaemon
-
InstanceManagerRights
Rights for managing Models.Instances
-
DreamMakerRights
Rights for Models.DreamMaker
-
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
-
RepositoryRights
Rights for a Models.Repository
-
The initial database migration for MySQL/MariaDB
-
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
-
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
-
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
- +
DreamDaemonRights
Rights for Models.DreamDaemon
+
InstanceManagerRights
Rights for managing Models.Instances
+
DreamMakerRights
Rights for Models.DreamMaker
+
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
+
RepositoryRights
Rights for a Models.Repository
+ +
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
+
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
+
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
diff --git a/20180918020726___m_y_add_minimum_security_8_designer_8cs.html b/20180918020726___m_y_add_minimum_security_8_designer_8cs.html index ccd6b40bcd..e54d81ae89 100644 --- a/20180918020726___m_y_add_minimum_security_8_designer_8cs.html +++ b/20180918020726___m_y_add_minimum_security_8_designer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180918020726_MYAddMinimumSecurity.Designer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.Migrations.MYAddMinimumSecurity - Add the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel columns for MySQL/MariaDB More...
+ Add the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel columns for MySQL/MariaDB More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20180918020726___m_y_add_minimum_security_8_designer_8cs_source.html b/20180918020726___m_y_add_minimum_security_8_designer_8cs_source.html index cc98992d8a..c9e9ddbd5a 100644 --- a/20180918020726___m_y_add_minimum_security_8_designer_8cs_source.html +++ b/20180918020726___m_y_add_minimum_security_8_designer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180918020726_MYAddMinimumSecurity.Designer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20180918020726_MYAddMinimumSecurity.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.Migrations;
6 
7 namespace Tgstation.Server.Host.Models.Migrations
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;
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
+ - -
diff --git a/20180918020726___m_y_add_minimum_security_8cs.html b/20180918020726___m_y_add_minimum_security_8cs.html index a6c12e50b8..8a1ebcf450 100644 --- a/20180918020726___m_y_add_minimum_security_8cs.html +++ b/20180918020726___m_y_add_minimum_security_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180918020726_MYAddMinimumSecurity.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.Migrations.MYAddMinimumSecurity - Add the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel columns for MySQL/MariaDB More...
+ Add the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel columns for MySQL/MariaDB More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20180918020726___m_y_add_minimum_security_8cs_source.html b/20180918020726___m_y_add_minimum_security_8cs_source.html index d0c2242406..ef7c0c3d7b 100644 --- a/20180918020726___m_y_add_minimum_security_8cs_source.html +++ b/20180918020726___m_y_add_minimum_security_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180918020726_MYAddMinimumSecurity.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20180918020726_MYAddMinimumSecurity.cs
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore.Migrations;
3 
4 namespace Tgstation.Server.Host.Models.Migrations
5 {
9  public partial class MYAddMinimumSecurity : Migration
10  {
15  protected override void Up(MigrationBuilder migrationBuilder)
16  {
17  migrationBuilder.AddColumn<int>(
18  name: "ApiValidationSecurityLevel",
19  table: "DreamMakerSettings",
20  nullable: false,
21  defaultValue: (int)DreamDaemonSecurity.Safe);
22 
23  migrationBuilder.AddColumn<int>(
24  name: "MinimumSecurityLevel",
25  table: "CompileJobs",
26  nullable: false,
27  defaultValue: (int)DreamDaemonSecurity.Safe);
28  }
29 
34  protected override void Down(MigrationBuilder migrationBuilder)
35  {
36  migrationBuilder.DropColumn(
37  name: "ApiValidationSecurityLevel",
38  table: "DreamMakerSettings");
39 
40  migrationBuilder.DropColumn(
41  name: "MinimumSecurityLevel",
42  table: "CompileJobs");
43  }
44  }
45 }
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
+Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore.Migrations;
2 using System;
4 
6 {
10  public partial class MYAddMinimumSecurity : Migration
11  {
16  protected override void Up(MigrationBuilder migrationBuilder)
17  {
18  if (migrationBuilder == null)
19  throw new ArgumentNullException(nameof(migrationBuilder));
20 
21  migrationBuilder.AddColumn<int>(
22  name: "ApiValidationSecurityLevel",
23  table: "DreamMakerSettings",
24  nullable: false,
25  defaultValue: (int)DreamDaemonSecurity.Safe);
26 
27  migrationBuilder.AddColumn<int>(
28  name: "MinimumSecurityLevel",
29  table: "CompileJobs",
30  nullable: false,
31  defaultValue: (int)DreamDaemonSecurity.Safe);
32  }
33 
38  protected override void Down(MigrationBuilder migrationBuilder)
39  {
40  if (migrationBuilder == null)
41  throw new ArgumentNullException(nameof(migrationBuilder));
42 
43  migrationBuilder.DropColumn(
44  name: "ApiValidationSecurityLevel",
45  table: "DreamMakerSettings");
46 
47  migrationBuilder.DropColumn(
48  name: "MinimumSecurityLevel",
49  table: "CompileJobs");
50  }
51  }
52 }
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
- -
Add the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel...
+ +
Add the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel...
- -
DreamDaemonSecurity
DreamDaemon&#39;s security level
- -
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
+ +
DreamDaemonSecurity
DreamDaemon's security level
+ +
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
diff --git a/20180918021228___m_s_add_minimum_security_8_designer_8cs.html b/20180918021228___m_s_add_minimum_security_8_designer_8cs.html index ab5b2adb9e..9a5278e928 100644 --- a/20180918021228___m_s_add_minimum_security_8_designer_8cs.html +++ b/20180918021228___m_s_add_minimum_security_8_designer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180918021228_MSAddMinimumSecurity.Designer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.Migrations.MSAddMinimumSecurity - Add the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel columns for MSSQL More...
+ Add the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel columns for MSSQL More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20180918021228___m_s_add_minimum_security_8_designer_8cs_source.html b/20180918021228___m_s_add_minimum_security_8_designer_8cs_source.html index 6d8dee7f1c..5ac1258774 100644 --- a/20180918021228___m_s_add_minimum_security_8_designer_8cs_source.html +++ b/20180918021228___m_s_add_minimum_security_8_designer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180918021228_MSAddMinimumSecurity.Designer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20180918021228_MSAddMinimumSecurity.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 
9 namespace Tgstation.Server.Host.Models.Migrations
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;
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 }
- -
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
- +
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
diff --git a/20180918021228___m_s_add_minimum_security_8cs.html b/20180918021228___m_s_add_minimum_security_8cs.html index 70fcf94230..3ae5a6d744 100644 --- a/20180918021228___m_s_add_minimum_security_8cs.html +++ b/20180918021228___m_s_add_minimum_security_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180918021228_MSAddMinimumSecurity.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.Migrations.MSAddMinimumSecurity - Add the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel columns for MSSQL More...
+ Add the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel columns for MSSQL More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20180918021228___m_s_add_minimum_security_8cs_source.html b/20180918021228___m_s_add_minimum_security_8cs_source.html index 5575f75a98..1335a4d8d9 100644 --- a/20180918021228___m_s_add_minimum_security_8cs_source.html +++ b/20180918021228___m_s_add_minimum_security_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180918021228_MSAddMinimumSecurity.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20180918021228_MSAddMinimumSecurity.cs
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore.Migrations;
3 
4 namespace Tgstation.Server.Host.Models.Migrations
5 {
9  public partial class MSAddMinimumSecurity : Migration
10  {
15  protected override void Up(MigrationBuilder migrationBuilder)
16  {
17  migrationBuilder.AddColumn<int>(
18  name: "ApiValidationSecurityLevel",
19  table: "DreamMakerSettings",
20  nullable: false,
21  defaultValue: (int)DreamDaemonSecurity.Safe);
22 
23  migrationBuilder.AddColumn<int>(
24  name: "MinimumSecurityLevel",
25  table: "CompileJobs",
26  nullable: false,
27  defaultValue: (int)DreamDaemonSecurity.Safe);
28  }
29 
34  protected override void Down(MigrationBuilder migrationBuilder)
35  {
36  migrationBuilder.DropColumn(
37  name: "ApiValidationSecurityLevel",
38  table: "DreamMakerSettings");
39 
40  migrationBuilder.DropColumn(
41  name: "MinimumSecurityLevel",
42  table: "CompileJobs");
43  }
44  }
45 }
- -
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
+Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore.Migrations;
2 using System;
4 
6 {
10  public partial class MSAddMinimumSecurity : Migration
11  {
16  protected override void Up(MigrationBuilder migrationBuilder)
17  {
18  if (migrationBuilder == null)
19  throw new ArgumentNullException(nameof(migrationBuilder));
20 
21  migrationBuilder.AddColumn<int>(
22  name: "ApiValidationSecurityLevel",
23  table: "DreamMakerSettings",
24  nullable: false,
25  defaultValue: (int)DreamDaemonSecurity.Safe);
26 
27  migrationBuilder.AddColumn<int>(
28  name: "MinimumSecurityLevel",
29  table: "CompileJobs",
30  nullable: false,
31  defaultValue: (int)DreamDaemonSecurity.Safe);
32  }
33 
38  protected override void Down(MigrationBuilder migrationBuilder)
39  {
40  if (migrationBuilder == null)
41  throw new ArgumentNullException(nameof(migrationBuilder));
42 
43  migrationBuilder.DropColumn(
44  name: "ApiValidationSecurityLevel",
45  table: "DreamMakerSettings");
46 
47  migrationBuilder.DropColumn(
48  name: "MinimumSecurityLevel",
49  table: "CompileJobs");
50  }
51  }
52 }
+
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
+ -
Add the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel...
- -
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
-
DreamDaemonSecurity
DreamDaemon&#39;s security level
- +
Add the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel...
+ +
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
+
DreamDaemonSecurity
DreamDaemon's security level
+
diff --git a/20180918204520___m_y_nullable_and_foreign_key_cleanup_8_designer_8cs.html b/20180918204520___m_y_nullable_and_foreign_key_cleanup_8_designer_8cs.html index 927b218703..f8d140926b 100644 --- a/20180918204520___m_y_nullable_and_foreign_key_cleanup_8_designer_8cs.html +++ b/20180918204520___m_y_nullable_and_foreign_key_cleanup_8_designer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180918204520_MYNullableAndForeignKeyCleanup.Designer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20180918204520___m_y_nullable_and_foreign_key_cleanup_8_designer_8cs_source.html b/20180918204520___m_y_nullable_and_foreign_key_cleanup_8_designer_8cs_source.html index b1decfd7fa..130d0d7750 100644 --- a/20180918204520___m_y_nullable_and_foreign_key_cleanup_8_designer_8cs_source.html +++ b/20180918204520___m_y_nullable_and_foreign_key_cleanup_8_designer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180918204520_MYNullableAndForeignKeyCleanup.Designer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20180918204520_MYNullableAndForeignKeyCleanup.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.Migrations;
6 
7 namespace Tgstation.Server.Host.Models.Migrations
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;
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 }
- - - +
diff --git a/20180918204520___m_y_nullable_and_foreign_key_cleanup_8cs.html b/20180918204520___m_y_nullable_and_foreign_key_cleanup_8cs.html index 96e7a692bd..2bfa31aebf 100644 --- a/20180918204520___m_y_nullable_and_foreign_key_cleanup_8cs.html +++ b/20180918204520___m_y_nullable_and_foreign_key_cleanup_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180918204520_MYNullableAndForeignKeyCleanup.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20180918204520___m_y_nullable_and_foreign_key_cleanup_8cs_source.html b/20180918204520___m_y_nullable_and_foreign_key_cleanup_8cs_source.html index 4ce3489673..887a5d4629 100644 --- a/20180918204520___m_y_nullable_and_foreign_key_cleanup_8cs_source.html +++ b/20180918204520___m_y_nullable_and_foreign_key_cleanup_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180918204520_MYNullableAndForeignKeyCleanup.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20180918204520_MYNullableAndForeignKeyCleanup.cs
-Go to the documentation of this file.
1 using System;
2 using Microsoft.EntityFrameworkCore.Migrations;
3 
4 namespace Tgstation.Server.Host.Models.Migrations
5 {
10  {
15  protected override void Up(MigrationBuilder migrationBuilder)
16  {
17  migrationBuilder.DropForeignKey(
18  name: "FK_Instances_WatchdogReattachInformations_WatchdogReattachInfor~",
19  table: "Instances");
20 
21  migrationBuilder.DropForeignKey(
22  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
23  table: "TestMerges");
24 
25  migrationBuilder.DropForeignKey(
26  name: "FK_CompileJobs_Jobs_JobId",
27  table: "CompileJobs");
28 
29  migrationBuilder.DropIndex(
30  name: "IX_Instances_WatchdogReattachInformationId",
31  table: "Instances");
32 
33  migrationBuilder.DropIndex(
34  name: "IX_CompileJobs_JobId",
35  table: "CompileJobs");
36 
37  migrationBuilder.DropColumn(
38  name: "WatchdogReattachInformationId",
39  table: "Instances");
40 
41  migrationBuilder.AddColumn<long>(
42  name: "InstanceId",
43  table: "WatchdogReattachInformations",
44  nullable: false,
45  defaultValue: 0L);
46 
47  migrationBuilder.AlterColumn<long>(
48  name: "PrimaryRevisionInformationId",
49  table: "TestMerges",
50  nullable: false,
51  oldClrType: typeof(long),
52  oldNullable: true);
53 
54  migrationBuilder.AlterColumn<string>(
55  name: "Output",
56  table: "CompileJobs",
57  nullable: false,
58  oldClrType: typeof(string),
59  oldNullable: true);
60 
61  migrationBuilder.AlterColumn<long>(
62  name: "JobId",
63  table: "CompileJobs",
64  nullable: false,
65  oldClrType: typeof(long),
66  oldNullable: true);
67 
68  migrationBuilder.AlterColumn<string>(
69  name: "DmeName",
70  table: "CompileJobs",
71  nullable: false,
72  oldClrType: typeof(string),
73  oldNullable: true);
74 
75  migrationBuilder.AlterColumn<Guid>(
76  name: "DirectoryName",
77  table: "CompileJobs",
78  nullable: false,
79  oldClrType: typeof(Guid),
80  oldNullable: true);
81 
82  migrationBuilder.CreateIndex(
83  name: "IX_WatchdogReattachInformations_InstanceId",
84  table: "WatchdogReattachInformations",
85  column: "InstanceId",
86  unique: true);
87 
88  migrationBuilder.CreateIndex(
89  name: "IX_CompileJobs_JobId",
90  table: "CompileJobs",
91  column: "JobId",
92  unique: true);
93 
94  migrationBuilder.AddForeignKey(
95  name: "FK_CompileJobs_Jobs_JobId",
96  table: "CompileJobs",
97  column: "JobId",
98  principalTable: "Jobs",
99  principalColumn: "Id",
100  onDelete: ReferentialAction.Restrict);
101 
102  migrationBuilder.AddForeignKey(
103  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
104  table: "TestMerges",
105  column: "PrimaryRevisionInformationId",
106  principalTable: "RevisionInformations",
107  principalColumn: "Id",
108  onDelete: ReferentialAction.Restrict);
109 
110  migrationBuilder.AddForeignKey(
111  name: "FK_WatchdogReattachInformations_Instances_InstanceId",
112  table: "WatchdogReattachInformations",
113  column: "InstanceId",
114  principalTable: "Instances",
115  principalColumn: "Id",
116  onDelete: ReferentialAction.Cascade);
117  }
118 
123  protected override void Down(MigrationBuilder migrationBuilder)
124  {
125  migrationBuilder.DropForeignKey(
126  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
127  table: "TestMerges");
128 
129  migrationBuilder.DropForeignKey(
130  name: "FK_WatchdogReattachInformations_Instances_InstanceId",
131  table: "WatchdogReattachInformations");
132 
133  migrationBuilder.DropForeignKey(
134  name: "FK_CompileJobs_Jobs_JobId",
135  table: "CompileJobs");
136 
137  migrationBuilder.DropIndex(
138  name: "IX_WatchdogReattachInformations_InstanceId",
139  table: "WatchdogReattachInformations");
140 
141  migrationBuilder.DropIndex(
142  name: "IX_CompileJobs_JobId",
143  table: "CompileJobs");
144 
145  migrationBuilder.DropColumn(
146  name: "InstanceId",
147  table: "WatchdogReattachInformations");
148 
149  migrationBuilder.AlterColumn<long>(
150  name: "PrimaryRevisionInformationId",
151  table: "TestMerges",
152  nullable: true,
153  oldClrType: typeof(long));
154 
155  migrationBuilder.AddColumn<long>(
156  name: "WatchdogReattachInformationId",
157  table: "Instances",
158  nullable: true);
159 
160  migrationBuilder.AlterColumn<string>(
161  name: "Output",
162  table: "CompileJobs",
163  nullable: true,
164  oldClrType: typeof(string));
165 
166  migrationBuilder.AlterColumn<long>(
167  name: "JobId",
168  table: "CompileJobs",
169  nullable: true,
170  oldClrType: typeof(long));
171 
172  migrationBuilder.AlterColumn<string>(
173  name: "DmeName",
174  table: "CompileJobs",
175  nullable: true,
176  oldClrType: typeof(string));
177 
178  migrationBuilder.AlterColumn<Guid>(
179  name: "DirectoryName",
180  table: "CompileJobs",
181  nullable: true,
182  oldClrType: typeof(Guid));
183 
184  migrationBuilder.CreateIndex(
185  name: "IX_Instances_WatchdogReattachInformationId",
186  table: "Instances",
187  column: "WatchdogReattachInformationId");
188 
189  migrationBuilder.CreateIndex(
190  name: "IX_CompileJobs_JobId",
191  table: "CompileJobs",
192  column: "JobId");
193 
194  migrationBuilder.AddForeignKey(
195  name: "FK_CompileJobs_Jobs_JobId",
196  table: "CompileJobs",
197  column: "JobId",
198  principalTable: "Jobs",
199  principalColumn: "Id",
200  onDelete: ReferentialAction.Restrict);
201 
202  migrationBuilder.AddForeignKey(
203  name: "FK_Instances_WatchdogReattachInformations_WatchdogReattachInfor~",
204  table: "Instances",
205  column: "WatchdogReattachInformationId",
206  principalTable: "WatchdogReattachInformations",
207  principalColumn: "Id",
208  onDelete: ReferentialAction.Restrict);
209 
210  migrationBuilder.AddForeignKey(
211  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
212  table: "TestMerges",
213  column: "PrimaryRevisionInformationId",
214  principalTable: "RevisionInformations",
215  principalColumn: "Id",
216  onDelete: ReferentialAction.SetNull);
217  }
218  }
219 }
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
- - +Go to the documentation of this file.
1 using System;
2 using Microsoft.EntityFrameworkCore.Migrations;
3 
5 {
10  {
15  protected override void Up(MigrationBuilder migrationBuilder)
16  {
17  if (migrationBuilder == null)
18  throw new ArgumentNullException(nameof(migrationBuilder));
19 
20  migrationBuilder.DropForeignKey(
21  name: "FK_Instances_WatchdogReattachInformations_WatchdogReattachInfor~",
22  table: "Instances");
23 
24  migrationBuilder.DropForeignKey(
25  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
26  table: "TestMerges");
27 
28  migrationBuilder.DropForeignKey(
29  name: "FK_CompileJobs_Jobs_JobId",
30  table: "CompileJobs");
31 
32  migrationBuilder.DropIndex(
33  name: "IX_Instances_WatchdogReattachInformationId",
34  table: "Instances");
35 
36  migrationBuilder.DropIndex(
37  name: "IX_CompileJobs_JobId",
38  table: "CompileJobs");
39 
40  migrationBuilder.DropColumn(
41  name: "WatchdogReattachInformationId",
42  table: "Instances");
43 
44  migrationBuilder.AddColumn<long>(
45  name: "InstanceId",
46  table: "WatchdogReattachInformations",
47  nullable: false,
48  defaultValue: 0L);
49 
50  migrationBuilder.AlterColumn<long>(
51  name: "PrimaryRevisionInformationId",
52  table: "TestMerges",
53  nullable: false,
54  oldClrType: typeof(long),
55  oldNullable: true);
56 
57  migrationBuilder.AlterColumn<string>(
58  name: "Output",
59  table: "CompileJobs",
60  nullable: false,
61  oldClrType: typeof(string),
62  oldNullable: true);
63 
64  migrationBuilder.AlterColumn<long>(
65  name: "JobId",
66  table: "CompileJobs",
67  nullable: false,
68  oldClrType: typeof(long),
69  oldNullable: true);
70 
71  migrationBuilder.AlterColumn<string>(
72  name: "DmeName",
73  table: "CompileJobs",
74  nullable: false,
75  oldClrType: typeof(string),
76  oldNullable: true);
77 
78  migrationBuilder.AlterColumn<Guid>(
79  name: "DirectoryName",
80  table: "CompileJobs",
81  nullable: false,
82  oldClrType: typeof(Guid),
83  oldNullable: true);
84 
85  migrationBuilder.CreateIndex(
86  name: "IX_WatchdogReattachInformations_InstanceId",
87  table: "WatchdogReattachInformations",
88  column: "InstanceId",
89  unique: true);
90 
91  migrationBuilder.CreateIndex(
92  name: "IX_CompileJobs_JobId",
93  table: "CompileJobs",
94  column: "JobId",
95  unique: true);
96 
97  migrationBuilder.AddForeignKey(
98  name: "FK_CompileJobs_Jobs_JobId",
99  table: "CompileJobs",
100  column: "JobId",
101  principalTable: "Jobs",
102  principalColumn: "Id",
103  onDelete: ReferentialAction.Restrict);
104 
105  migrationBuilder.AddForeignKey(
106  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
107  table: "TestMerges",
108  column: "PrimaryRevisionInformationId",
109  principalTable: "RevisionInformations",
110  principalColumn: "Id",
111  onDelete: ReferentialAction.Restrict);
112 
113  migrationBuilder.AddForeignKey(
114  name: "FK_WatchdogReattachInformations_Instances_InstanceId",
115  table: "WatchdogReattachInformations",
116  column: "InstanceId",
117  principalTable: "Instances",
118  principalColumn: "Id",
119  onDelete: ReferentialAction.Cascade);
120  }
121 
126  protected override void Down(MigrationBuilder migrationBuilder)
127  {
128  if (migrationBuilder == null)
129  throw new ArgumentNullException(nameof(migrationBuilder));
130 
131  migrationBuilder.DropForeignKey(
132  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
133  table: "TestMerges");
134 
135  migrationBuilder.DropForeignKey(
136  name: "FK_WatchdogReattachInformations_Instances_InstanceId",
137  table: "WatchdogReattachInformations");
138 
139  migrationBuilder.DropForeignKey(
140  name: "FK_CompileJobs_Jobs_JobId",
141  table: "CompileJobs");
142 
143  migrationBuilder.DropIndex(
144  name: "IX_WatchdogReattachInformations_InstanceId",
145  table: "WatchdogReattachInformations");
146 
147  migrationBuilder.DropIndex(
148  name: "IX_CompileJobs_JobId",
149  table: "CompileJobs");
150 
151  migrationBuilder.DropColumn(
152  name: "InstanceId",
153  table: "WatchdogReattachInformations");
154 
155  migrationBuilder.AlterColumn<long>(
156  name: "PrimaryRevisionInformationId",
157  table: "TestMerges",
158  nullable: true,
159  oldClrType: typeof(long));
160 
161  migrationBuilder.AddColumn<long>(
162  name: "WatchdogReattachInformationId",
163  table: "Instances",
164  nullable: true);
165 
166  migrationBuilder.AlterColumn<string>(
167  name: "Output",
168  table: "CompileJobs",
169  nullable: true,
170  oldClrType: typeof(string));
171 
172  migrationBuilder.AlterColumn<long>(
173  name: "JobId",
174  table: "CompileJobs",
175  nullable: true,
176  oldClrType: typeof(long));
177 
178  migrationBuilder.AlterColumn<string>(
179  name: "DmeName",
180  table: "CompileJobs",
181  nullable: true,
182  oldClrType: typeof(string));
183 
184  migrationBuilder.AlterColumn<Guid>(
185  name: "DirectoryName",
186  table: "CompileJobs",
187  nullable: true,
188  oldClrType: typeof(Guid));
189 
190  migrationBuilder.CreateIndex(
191  name: "IX_Instances_WatchdogReattachInformationId",
192  table: "Instances",
193  column: "WatchdogReattachInformationId");
194 
195  migrationBuilder.CreateIndex(
196  name: "IX_CompileJobs_JobId",
197  table: "CompileJobs",
198  column: "JobId");
199 
200  migrationBuilder.AddForeignKey(
201  name: "FK_CompileJobs_Jobs_JobId",
202  table: "CompileJobs",
203  column: "JobId",
204  principalTable: "Jobs",
205  principalColumn: "Id",
206  onDelete: ReferentialAction.Restrict);
207 
208  migrationBuilder.AddForeignKey(
209  name: "FK_Instances_WatchdogReattachInformations_WatchdogReattachInfor~",
210  table: "Instances",
211  column: "WatchdogReattachInformationId",
212  principalTable: "WatchdogReattachInformations",
213  principalColumn: "Id",
214  onDelete: ReferentialAction.Restrict);
215 
216  migrationBuilder.AddForeignKey(
217  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
218  table: "TestMerges",
219  column: "PrimaryRevisionInformationId",
220  principalTable: "RevisionInformations",
221  principalColumn: "Id",
222  onDelete: ReferentialAction.SetNull);
223  }
224  }
225 }
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
+ -
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
- - +
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
+
diff --git a/20180918205224___m_s_nullable_and_foreign_key_cleanup_8_designer_8cs.html b/20180918205224___m_s_nullable_and_foreign_key_cleanup_8_designer_8cs.html index f0531b62a0..726d33adfd 100644 --- a/20180918205224___m_s_nullable_and_foreign_key_cleanup_8_designer_8cs.html +++ b/20180918205224___m_s_nullable_and_foreign_key_cleanup_8_designer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180918205224_MSNullableAndForeignKeyCleanup.Designer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20180918205224___m_s_nullable_and_foreign_key_cleanup_8_designer_8cs_source.html b/20180918205224___m_s_nullable_and_foreign_key_cleanup_8_designer_8cs_source.html index 9f3a1505c6..fb346499cb 100644 --- a/20180918205224___m_s_nullable_and_foreign_key_cleanup_8_designer_8cs_source.html +++ b/20180918205224___m_s_nullable_and_foreign_key_cleanup_8_designer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180918205224_MSNullableAndForeignKeyCleanup.Designer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20180918205224_MSNullableAndForeignKeyCleanup.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 
9 namespace Tgstation.Server.Host.Models.Migrations
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;
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 }
- - - +
diff --git a/20180918205224___m_s_nullable_and_foreign_key_cleanup_8cs.html b/20180918205224___m_s_nullable_and_foreign_key_cleanup_8cs.html index 824a4282ab..7d0103074d 100644 --- a/20180918205224___m_s_nullable_and_foreign_key_cleanup_8cs.html +++ b/20180918205224___m_s_nullable_and_foreign_key_cleanup_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180918205224_MSNullableAndForeignKeyCleanup.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20180918205224___m_s_nullable_and_foreign_key_cleanup_8cs_source.html b/20180918205224___m_s_nullable_and_foreign_key_cleanup_8cs_source.html index a8588c5485..26d2e4ab42 100644 --- a/20180918205224___m_s_nullable_and_foreign_key_cleanup_8cs_source.html +++ b/20180918205224___m_s_nullable_and_foreign_key_cleanup_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180918205224_MSNullableAndForeignKeyCleanup.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20180918205224_MSNullableAndForeignKeyCleanup.cs
-Go to the documentation of this file.
1 using System;
2 using Microsoft.EntityFrameworkCore.Migrations;
3 
4 namespace Tgstation.Server.Host.Models.Migrations
5 {
10  {
15  protected override void Up(MigrationBuilder migrationBuilder)
16  {
17  migrationBuilder.DropForeignKey(
18  name: "FK_Instances_WatchdogReattachInformations_WatchdogReattachInformationId",
19  table: "Instances");
20 
21  migrationBuilder.DropForeignKey(
22  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
23  table: "TestMerges");
24 
25  migrationBuilder.DropIndex(
26  name: "IX_TestMerges_PrimaryRevisionInformationId",
27  table: "TestMerges");
28 
29  migrationBuilder.DropIndex(
30  name: "IX_Instances_WatchdogReattachInformationId",
31  table: "Instances");
32 
33  migrationBuilder.DropIndex(
34  name: "IX_CompileJobs_JobId",
35  table: "CompileJobs");
36 
37  migrationBuilder.DropColumn(
38  name: "WatchdogReattachInformationId",
39  table: "Instances");
40 
41  migrationBuilder.AddColumn<long>(
42  name: "InstanceId",
43  table: "WatchdogReattachInformations",
44  nullable: false,
45  defaultValue: 0L);
46 
47  migrationBuilder.AlterColumn<long>(
48  name: "PrimaryRevisionInformationId",
49  table: "TestMerges",
50  nullable: false,
51  oldClrType: typeof(long),
52  oldNullable: true);
53 
54  migrationBuilder.AlterColumn<string>(
55  name: "Output",
56  table: "CompileJobs",
57  nullable: false,
58  oldClrType: typeof(string),
59  oldNullable: true);
60 
61  migrationBuilder.AlterColumn<long>(
62  name: "JobId",
63  table: "CompileJobs",
64  nullable: false,
65  oldClrType: typeof(long),
66  oldNullable: true);
67 
68  migrationBuilder.AlterColumn<string>(
69  name: "DmeName",
70  table: "CompileJobs",
71  nullable: false,
72  oldClrType: typeof(string),
73  oldNullable: true);
74 
75  migrationBuilder.AlterColumn<Guid>(
76  name: "DirectoryName",
77  table: "CompileJobs",
78  nullable: false,
79  oldClrType: typeof(Guid),
80  oldNullable: true);
81 
82  migrationBuilder.CreateIndex(
83  name: "IX_WatchdogReattachInformations_InstanceId",
84  table: "WatchdogReattachInformations",
85  column: "InstanceId",
86  unique: true);
87 
88  migrationBuilder.CreateIndex(
89  name: "IX_TestMerges_PrimaryRevisionInformationId",
90  table: "TestMerges",
91  column: "PrimaryRevisionInformationId",
92  unique: true);
93 
94  migrationBuilder.CreateIndex(
95  name: "IX_CompileJobs_JobId",
96  table: "CompileJobs",
97  column: "JobId",
98  unique: true);
99 
100  migrationBuilder.AddForeignKey(
101  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
102  table: "TestMerges",
103  column: "PrimaryRevisionInformationId",
104  principalTable: "RevisionInformations",
105  principalColumn: "Id",
106  onDelete: ReferentialAction.Restrict);
107 
108  migrationBuilder.AddForeignKey(
109  name: "FK_WatchdogReattachInformations_Instances_InstanceId",
110  table: "WatchdogReattachInformations",
111  column: "InstanceId",
112  principalTable: "Instances",
113  principalColumn: "Id",
114  onDelete: ReferentialAction.Cascade);
115  }
116 
121  protected override void Down(MigrationBuilder migrationBuilder)
122  {
123  migrationBuilder.DropForeignKey(
124  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
125  table: "TestMerges");
126 
127  migrationBuilder.DropForeignKey(
128  name: "FK_WatchdogReattachInformations_Instances_InstanceId",
129  table: "WatchdogReattachInformations");
130 
131  migrationBuilder.DropIndex(
132  name: "IX_WatchdogReattachInformations_InstanceId",
133  table: "WatchdogReattachInformations");
134 
135  migrationBuilder.DropIndex(
136  name: "IX_TestMerges_PrimaryRevisionInformationId",
137  table: "TestMerges");
138 
139  migrationBuilder.DropIndex(
140  name: "IX_CompileJobs_JobId",
141  table: "CompileJobs");
142 
143  migrationBuilder.DropColumn(
144  name: "InstanceId",
145  table: "WatchdogReattachInformations");
146 
147  migrationBuilder.AlterColumn<long>(
148  name: "PrimaryRevisionInformationId",
149  table: "TestMerges",
150  nullable: true,
151  oldClrType: typeof(long));
152 
153  migrationBuilder.AddColumn<long>(
154  name: "WatchdogReattachInformationId",
155  table: "Instances",
156  nullable: true);
157 
158  migrationBuilder.AlterColumn<string>(
159  name: "Output",
160  table: "CompileJobs",
161  nullable: true,
162  oldClrType: typeof(string));
163 
164  migrationBuilder.AlterColumn<long>(
165  name: "JobId",
166  table: "CompileJobs",
167  nullable: true,
168  oldClrType: typeof(long));
169 
170  migrationBuilder.AlterColumn<string>(
171  name: "DmeName",
172  table: "CompileJobs",
173  nullable: true,
174  oldClrType: typeof(string));
175 
176  migrationBuilder.AlterColumn<Guid>(
177  name: "DirectoryName",
178  table: "CompileJobs",
179  nullable: true,
180  oldClrType: typeof(Guid));
181 
182  migrationBuilder.CreateIndex(
183  name: "IX_TestMerges_PrimaryRevisionInformationId",
184  table: "TestMerges",
185  column: "PrimaryRevisionInformationId",
186  unique: true,
187  filter: "[PrimaryRevisionInformationId] IS NOT NULL");
188 
189  migrationBuilder.CreateIndex(
190  name: "IX_Instances_WatchdogReattachInformationId",
191  table: "Instances",
192  column: "WatchdogReattachInformationId");
193 
194  migrationBuilder.CreateIndex(
195  name: "IX_CompileJobs_JobId",
196  table: "CompileJobs",
197  column: "JobId");
198 
199  migrationBuilder.AddForeignKey(
200  name: "FK_Instances_WatchdogReattachInformations_WatchdogReattachInformationId",
201  table: "Instances",
202  column: "WatchdogReattachInformationId",
203  principalTable: "WatchdogReattachInformations",
204  principalColumn: "Id",
205  onDelete: ReferentialAction.Restrict);
206 
207  migrationBuilder.AddForeignKey(
208  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
209  table: "TestMerges",
210  column: "PrimaryRevisionInformationId",
211  principalTable: "RevisionInformations",
212  principalColumn: "Id",
213  onDelete: ReferentialAction.SetNull);
214  }
215  }
216 }
-
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
- -
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
+Go to the documentation of this file.
1 using System;
2 using Microsoft.EntityFrameworkCore.Migrations;
3 
5 {
10  {
15  protected override void Up(MigrationBuilder migrationBuilder)
16  {
17  if (migrationBuilder == null)
18  throw new ArgumentNullException(nameof(migrationBuilder));
19 
20  migrationBuilder.DropForeignKey(
21  name: "FK_Instances_WatchdogReattachInformations_WatchdogReattachInformationId",
22  table: "Instances");
23 
24  migrationBuilder.DropForeignKey(
25  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
26  table: "TestMerges");
27 
28  migrationBuilder.DropIndex(
29  name: "IX_TestMerges_PrimaryRevisionInformationId",
30  table: "TestMerges");
31 
32  migrationBuilder.DropIndex(
33  name: "IX_Instances_WatchdogReattachInformationId",
34  table: "Instances");
35 
36  migrationBuilder.DropIndex(
37  name: "IX_CompileJobs_JobId",
38  table: "CompileJobs");
39 
40  migrationBuilder.DropColumn(
41  name: "WatchdogReattachInformationId",
42  table: "Instances");
43 
44  migrationBuilder.AddColumn<long>(
45  name: "InstanceId",
46  table: "WatchdogReattachInformations",
47  nullable: false,
48  defaultValue: 0L);
49 
50  migrationBuilder.AlterColumn<long>(
51  name: "PrimaryRevisionInformationId",
52  table: "TestMerges",
53  nullable: false,
54  oldClrType: typeof(long),
55  oldNullable: true);
56 
57  migrationBuilder.AlterColumn<string>(
58  name: "Output",
59  table: "CompileJobs",
60  nullable: false,
61  oldClrType: typeof(string),
62  oldNullable: true);
63 
64  migrationBuilder.AlterColumn<long>(
65  name: "JobId",
66  table: "CompileJobs",
67  nullable: false,
68  oldClrType: typeof(long),
69  oldNullable: true);
70 
71  migrationBuilder.AlterColumn<string>(
72  name: "DmeName",
73  table: "CompileJobs",
74  nullable: false,
75  oldClrType: typeof(string),
76  oldNullable: true);
77 
78  migrationBuilder.AlterColumn<Guid>(
79  name: "DirectoryName",
80  table: "CompileJobs",
81  nullable: false,
82  oldClrType: typeof(Guid),
83  oldNullable: true);
84 
85  migrationBuilder.CreateIndex(
86  name: "IX_WatchdogReattachInformations_InstanceId",
87  table: "WatchdogReattachInformations",
88  column: "InstanceId",
89  unique: true);
90 
91  migrationBuilder.CreateIndex(
92  name: "IX_TestMerges_PrimaryRevisionInformationId",
93  table: "TestMerges",
94  column: "PrimaryRevisionInformationId",
95  unique: true);
96 
97  migrationBuilder.CreateIndex(
98  name: "IX_CompileJobs_JobId",
99  table: "CompileJobs",
100  column: "JobId",
101  unique: true);
102 
103  migrationBuilder.AddForeignKey(
104  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
105  table: "TestMerges",
106  column: "PrimaryRevisionInformationId",
107  principalTable: "RevisionInformations",
108  principalColumn: "Id",
109  onDelete: ReferentialAction.Restrict);
110 
111  migrationBuilder.AddForeignKey(
112  name: "FK_WatchdogReattachInformations_Instances_InstanceId",
113  table: "WatchdogReattachInformations",
114  column: "InstanceId",
115  principalTable: "Instances",
116  principalColumn: "Id",
117  onDelete: ReferentialAction.Cascade);
118  }
119 
124  protected override void Down(MigrationBuilder migrationBuilder)
125  {
126  if (migrationBuilder == null)
127  throw new ArgumentNullException(nameof(migrationBuilder));
128 
129  migrationBuilder.DropForeignKey(
130  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
131  table: "TestMerges");
132 
133  migrationBuilder.DropForeignKey(
134  name: "FK_WatchdogReattachInformations_Instances_InstanceId",
135  table: "WatchdogReattachInformations");
136 
137  migrationBuilder.DropIndex(
138  name: "IX_WatchdogReattachInformations_InstanceId",
139  table: "WatchdogReattachInformations");
140 
141  migrationBuilder.DropIndex(
142  name: "IX_TestMerges_PrimaryRevisionInformationId",
143  table: "TestMerges");
144 
145  migrationBuilder.DropIndex(
146  name: "IX_CompileJobs_JobId",
147  table: "CompileJobs");
148 
149  migrationBuilder.DropColumn(
150  name: "InstanceId",
151  table: "WatchdogReattachInformations");
152 
153  migrationBuilder.AlterColumn<long>(
154  name: "PrimaryRevisionInformationId",
155  table: "TestMerges",
156  nullable: true,
157  oldClrType: typeof(long));
158 
159  migrationBuilder.AddColumn<long>(
160  name: "WatchdogReattachInformationId",
161  table: "Instances",
162  nullable: true);
163 
164  migrationBuilder.AlterColumn<string>(
165  name: "Output",
166  table: "CompileJobs",
167  nullable: true,
168  oldClrType: typeof(string));
169 
170  migrationBuilder.AlterColumn<long>(
171  name: "JobId",
172  table: "CompileJobs",
173  nullable: true,
174  oldClrType: typeof(long));
175 
176  migrationBuilder.AlterColumn<string>(
177  name: "DmeName",
178  table: "CompileJobs",
179  nullable: true,
180  oldClrType: typeof(string));
181 
182  migrationBuilder.AlterColumn<Guid>(
183  name: "DirectoryName",
184  table: "CompileJobs",
185  nullable: true,
186  oldClrType: typeof(Guid));
187 
188  migrationBuilder.CreateIndex(
189  name: "IX_TestMerges_PrimaryRevisionInformationId",
190  table: "TestMerges",
191  column: "PrimaryRevisionInformationId",
192  unique: true,
193  filter: "[PrimaryRevisionInformationId] IS NOT NULL");
194 
195  migrationBuilder.CreateIndex(
196  name: "IX_Instances_WatchdogReattachInformationId",
197  table: "Instances",
198  column: "WatchdogReattachInformationId");
199 
200  migrationBuilder.CreateIndex(
201  name: "IX_CompileJobs_JobId",
202  table: "CompileJobs",
203  column: "JobId");
204 
205  migrationBuilder.AddForeignKey(
206  name: "FK_Instances_WatchdogReattachInformations_WatchdogReattachInformationId",
207  table: "Instances",
208  column: "WatchdogReattachInformationId",
209  principalTable: "WatchdogReattachInformations",
210  principalColumn: "Id",
211  onDelete: ReferentialAction.Restrict);
212 
213  migrationBuilder.AddForeignKey(
214  name: "FK_TestMerges_RevisionInformations_PrimaryRevisionInformationId",
215  table: "TestMerges",
216  column: "PrimaryRevisionInformationId",
217  principalTable: "RevisionInformations",
218  principalColumn: "Id",
219  onDelete: ReferentialAction.SetNull);
220  }
221  }
222 }
+
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
+
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
- - +
diff --git a/20180926033145___m_s_reattach_compile_job_required_8_designer_8cs.html b/20180926033145___m_s_reattach_compile_job_required_8_designer_8cs.html index 3d72b271e0..c0f38c78f6 100644 --- a/20180926033145___m_s_reattach_compile_job_required_8_designer_8cs.html +++ b/20180926033145___m_s_reattach_compile_job_required_8_designer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180926033145_MSReattachCompileJobRequired.Designer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.Migrations.MSReattachCompileJobRequired - Marks the CompileJobs of ReattachInformations as non-nullable for MSSQL More...
+ Marks the CompileJobs of ReattachInformations as non-nullable for MSSQL More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20180926033145___m_s_reattach_compile_job_required_8_designer_8cs_source.html b/20180926033145___m_s_reattach_compile_job_required_8_designer_8cs_source.html index 0ed606ff5a..7bed682512 100644 --- a/20180926033145___m_s_reattach_compile_job_required_8_designer_8cs_source.html +++ b/20180926033145___m_s_reattach_compile_job_required_8_designer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180926033145_MSReattachCompileJobRequired.Designer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20180926033145_MSReattachCompileJobRequired.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 
9 namespace Tgstation.Server.Host.Models.Migrations
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;
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 }
- - + -
diff --git a/20180926033145___m_s_reattach_compile_job_required_8cs.html b/20180926033145___m_s_reattach_compile_job_required_8cs.html index 68f5878f66..ebf34d1976 100644 --- a/20180926033145___m_s_reattach_compile_job_required_8cs.html +++ b/20180926033145___m_s_reattach_compile_job_required_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180926033145_MSReattachCompileJobRequired.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.Migrations.MSReattachCompileJobRequired - Marks the CompileJobs of ReattachInformations as non-nullable for MSSQL More...
+ Marks the CompileJobs of ReattachInformations as non-nullable for MSSQL More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20180926033145___m_s_reattach_compile_job_required_8cs_source.html b/20180926033145___m_s_reattach_compile_job_required_8cs_source.html index c559d1d769..ed6d460166 100644 --- a/20180926033145___m_s_reattach_compile_job_required_8cs_source.html +++ b/20180926033145___m_s_reattach_compile_job_required_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180926033145_MSReattachCompileJobRequired.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20180926033145_MSReattachCompileJobRequired.cs
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore.Migrations;
2 
3 namespace Tgstation.Server.Host.Models.Migrations
4 {
8  public partial class MSReattachCompileJobRequired : Migration
9  {
14  protected override void Up(MigrationBuilder migrationBuilder)
15  {
16  migrationBuilder.DropForeignKey(
17  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
18  table: "ReattachInformations");
19 
20  migrationBuilder.AlterColumn<long>(
21  name: "CompileJobId",
22  table: "ReattachInformations",
23  nullable: false,
24  oldClrType: typeof(long),
25  oldNullable: true);
26 
27  migrationBuilder.AddForeignKey(
28  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
29  table: "ReattachInformations",
30  column: "CompileJobId",
31  principalTable: "CompileJobs",
32  principalColumn: "Id",
33  onDelete: ReferentialAction.Cascade);
34  }
35 
40  protected override void Down(MigrationBuilder migrationBuilder)
41  {
42  migrationBuilder.DropForeignKey(
43  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
44  table: "ReattachInformations");
45 
46  migrationBuilder.AlterColumn<long>(
47  name: "CompileJobId",
48  table: "ReattachInformations",
49  nullable: true,
50  oldClrType: typeof(long));
51 
52  migrationBuilder.AddForeignKey(
53  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
54  table: "ReattachInformations",
55  column: "CompileJobId",
56  principalTable: "CompileJobs",
57  principalColumn: "Id",
58  onDelete: ReferentialAction.Restrict);
59  }
60  }
61 }
+Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore.Migrations;
2 using System;
3 
5 {
9  public partial class MSReattachCompileJobRequired : Migration
10  {
15  protected override void Up(MigrationBuilder migrationBuilder)
16  {
17  if (migrationBuilder == null)
18  throw new ArgumentNullException(nameof(migrationBuilder));
19 
20  migrationBuilder.DropForeignKey(
21  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
22  table: "ReattachInformations");
23 
24  migrationBuilder.AlterColumn<long>(
25  name: "CompileJobId",
26  table: "ReattachInformations",
27  nullable: false,
28  oldClrType: typeof(long),
29  oldNullable: true);
30 
31  migrationBuilder.AddForeignKey(
32  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
33  table: "ReattachInformations",
34  column: "CompileJobId",
35  principalTable: "CompileJobs",
36  principalColumn: "Id",
37  onDelete: ReferentialAction.Cascade);
38  }
39 
44  protected override void Down(MigrationBuilder migrationBuilder)
45  {
46  if (migrationBuilder == null)
47  throw new ArgumentNullException(nameof(migrationBuilder));
48 
49  migrationBuilder.DropForeignKey(
50  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
51  table: "ReattachInformations");
52 
53  migrationBuilder.AlterColumn<long>(
54  name: "CompileJobId",
55  table: "ReattachInformations",
56  nullable: true,
57  oldClrType: typeof(long));
58 
59  migrationBuilder.AddForeignKey(
60  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
61  table: "ReattachInformations",
62  column: "CompileJobId",
63  principalTable: "CompileJobs",
64  principalColumn: "Id",
65  onDelete: ReferentialAction.Restrict);
66  }
67  }
68 }
-
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
-
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
-
Marks the CompileJobs of ReattachInformations as non-nullable for MSSQL
- +
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
+
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
+
Marks the CompileJobs of ReattachInformations as non-nullable for MSSQL
diff --git a/20180926034014___m_y_reattach_compile_job_required_8_designer_8cs.html b/20180926034014___m_y_reattach_compile_job_required_8_designer_8cs.html index 6da785980f..6eb6355b0b 100644 --- a/20180926034014___m_y_reattach_compile_job_required_8_designer_8cs.html +++ b/20180926034014___m_y_reattach_compile_job_required_8_designer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180926034014_MYReattachCompileJobRequired.Designer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.Migrations.MYReattachCompileJobRequired - Marks the CompileJobs of ReattachInformations as non-nullable for MySQL/MariaDB More...
+ Marks the CompileJobs of ReattachInformations as non-nullable for MySQL/MariaDB More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20180926034014___m_y_reattach_compile_job_required_8_designer_8cs_source.html b/20180926034014___m_y_reattach_compile_job_required_8_designer_8cs_source.html index a802c577a6..17e6ca8829 100644 --- a/20180926034014___m_y_reattach_compile_job_required_8_designer_8cs_source.html +++ b/20180926034014___m_y_reattach_compile_job_required_8_designer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180926034014_MYReattachCompileJobRequired.Designer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20180926034014_MYReattachCompileJobRequired.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.Migrations;
6 
7 namespace Tgstation.Server.Host.Models.Migrations
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;
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 }
- - - +
diff --git a/20180926034014___m_y_reattach_compile_job_required_8cs.html b/20180926034014___m_y_reattach_compile_job_required_8cs.html index 69c0259da8..afc01bfd5f 100644 --- a/20180926034014___m_y_reattach_compile_job_required_8cs.html +++ b/20180926034014___m_y_reattach_compile_job_required_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180926034014_MYReattachCompileJobRequired.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.Migrations.MYReattachCompileJobRequired - Marks the CompileJobs of ReattachInformations as non-nullable for MySQL/MariaDB More...
+ Marks the CompileJobs of ReattachInformations as non-nullable for MySQL/MariaDB More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20180926034014___m_y_reattach_compile_job_required_8cs_source.html b/20180926034014___m_y_reattach_compile_job_required_8cs_source.html index 5a7289b0bd..53509cd4d7 100644 --- a/20180926034014___m_y_reattach_compile_job_required_8cs_source.html +++ b/20180926034014___m_y_reattach_compile_job_required_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20180926034014_MYReattachCompileJobRequired.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20180926034014_MYReattachCompileJobRequired.cs
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore.Migrations;
2 
3 namespace Tgstation.Server.Host.Models.Migrations
4 {
8  public partial class MYReattachCompileJobRequired : Migration
9  {
14  protected override void Up(MigrationBuilder migrationBuilder)
15  {
16  migrationBuilder.DropForeignKey(
17  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
18  table: "ReattachInformations");
19 
20  migrationBuilder.AlterColumn<long>(
21  name: "CompileJobId",
22  table: "ReattachInformations",
23  nullable: false,
24  oldClrType: typeof(long),
25  oldNullable: true);
26 
27  migrationBuilder.AddForeignKey(
28  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
29  table: "ReattachInformations",
30  column: "CompileJobId",
31  principalTable: "CompileJobs",
32  principalColumn: "Id",
33  onDelete: ReferentialAction.Cascade);
34  }
35 
40  protected override void Down(MigrationBuilder migrationBuilder)
41  {
42  migrationBuilder.DropForeignKey(
43  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
44  table: "ReattachInformations");
45 
46  migrationBuilder.AlterColumn<long>(
47  name: "CompileJobId",
48  table: "ReattachInformations",
49  nullable: true,
50  oldClrType: typeof(long));
51 
52  migrationBuilder.AddForeignKey(
53  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
54  table: "ReattachInformations",
55  column: "CompileJobId",
56  principalTable: "CompileJobs",
57  principalColumn: "Id",
58  onDelete: ReferentialAction.Restrict);
59  }
60  }
61 }
Marks the CompileJobs of ReattachInformations as non-nullable for MySQL/MariaDB
- -
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
+Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore.Migrations;
2 using System;
3 
5 {
9  public partial class MYReattachCompileJobRequired : Migration
10  {
15  protected override void Up(MigrationBuilder migrationBuilder)
16  {
17  if (migrationBuilder == null)
18  throw new ArgumentNullException(nameof(migrationBuilder));
19 
20  migrationBuilder.DropForeignKey(
21  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
22  table: "ReattachInformations");
23 
24  migrationBuilder.AlterColumn<long>(
25  name: "CompileJobId",
26  table: "ReattachInformations",
27  nullable: false,
28  oldClrType: typeof(long),
29  oldNullable: true);
30 
31  migrationBuilder.AddForeignKey(
32  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
33  table: "ReattachInformations",
34  column: "CompileJobId",
35  principalTable: "CompileJobs",
36  principalColumn: "Id",
37  onDelete: ReferentialAction.Cascade);
38  }
39 
44  protected override void Down(MigrationBuilder migrationBuilder)
45  {
46  if (migrationBuilder == null)
47  throw new ArgumentNullException(nameof(migrationBuilder));
48 
49  migrationBuilder.DropForeignKey(
50  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
51  table: "ReattachInformations");
52 
53  migrationBuilder.AlterColumn<long>(
54  name: "CompileJobId",
55  table: "ReattachInformations",
56  nullable: true,
57  oldClrType: typeof(long));
58 
59  migrationBuilder.AddForeignKey(
60  name: "FK_ReattachInformations_CompileJobs_CompileJobId",
61  table: "ReattachInformations",
62  column: "CompileJobId",
63  principalTable: "CompileJobs",
64  principalColumn: "Id",
65  onDelete: ReferentialAction.Restrict);
66  }
67  }
68 }
Marks the CompileJobs of ReattachInformations as non-nullable for MySQL/MariaDB
+ +
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
-
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
- +
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
diff --git a/20181124231534___m_s_toggle_testmerge_comments_8_designer_8cs.html b/20181124231534___m_s_toggle_testmerge_comments_8_designer_8cs.html index 49cb047dca..c3d68c9ccf 100644 --- a/20181124231534___m_s_toggle_testmerge_comments_8_designer_8cs.html +++ b/20181124231534___m_s_toggle_testmerge_comments_8_designer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20181124231534_MSToggleTestmergeComments.Designer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.Migrations.MSToggleTestmergeComments - Add the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MSSQL More...
+ Add the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MSSQL More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20181124231534___m_s_toggle_testmerge_comments_8_designer_8cs_source.html b/20181124231534___m_s_toggle_testmerge_comments_8_designer_8cs_source.html index 08d33ee4d0..a86adf7199 100644 --- a/20181124231534___m_s_toggle_testmerge_comments_8_designer_8cs_source.html +++ b/20181124231534___m_s_toggle_testmerge_comments_8_designer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20181124231534_MSToggleTestmergeComments.Designer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20181124231534_MSToggleTestmergeComments.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 
9 namespace Tgstation.Server.Host.Models.Migrations
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;
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 }
- -
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
- +
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
diff --git a/20181124231534___m_s_toggle_testmerge_comments_8cs.html b/20181124231534___m_s_toggle_testmerge_comments_8cs.html index fbf08cf9b9..76c32254ae 100644 --- a/20181124231534___m_s_toggle_testmerge_comments_8cs.html +++ b/20181124231534___m_s_toggle_testmerge_comments_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20181124231534_MSToggleTestmergeComments.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.Migrations.MSToggleTestmergeComments - Add the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MSSQL More...
+ Add the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MSSQL More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20181124231534___m_s_toggle_testmerge_comments_8cs_source.html b/20181124231534___m_s_toggle_testmerge_comments_8cs_source.html index 4f06cfee63..05f21b5c07 100644 --- a/20181124231534___m_s_toggle_testmerge_comments_8cs_source.html +++ b/20181124231534___m_s_toggle_testmerge_comments_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20181124231534_MSToggleTestmergeComments.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20181124231534_MSToggleTestmergeComments.cs
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore.Migrations;
2 
3 namespace Tgstation.Server.Host.Models.Migrations
4 {
8  public partial class MSToggleTestmergeComments : Migration
9  {
14  protected override void Up(MigrationBuilder migrationBuilder)
15  {
16  migrationBuilder.AddColumn<bool>(
17  name: "PostTestMergeComment",
18  table: "RepositorySettings",
19  nullable: false,
20  defaultValue: true);
21  }
22 
27  protected override void Down(MigrationBuilder migrationBuilder)
28  {
29  migrationBuilder.DropColumn(
30  name: "PostTestMergeComment",
31  table: "RepositorySettings");
32  }
33  }
34 }
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
-
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
- +Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore.Migrations;
2 using System;
3 
5 {
9  public partial class MSToggleTestmergeComments : Migration
10  {
15  protected override void Up(MigrationBuilder migrationBuilder)
16  {
17  if (migrationBuilder == null)
18  throw new ArgumentNullException(nameof(migrationBuilder));
19 
20  migrationBuilder.AddColumn<bool>(
21  name: "PostTestMergeComment",
22  table: "RepositorySettings",
23  nullable: false,
24  defaultValue: true);
25  }
26 
31  protected override void Down(MigrationBuilder migrationBuilder)
32  {
33  if (migrationBuilder == null)
34  throw new ArgumentNullException(nameof(migrationBuilder));
35 
36  migrationBuilder.DropColumn(
37  name: "PostTestMergeComment",
38  table: "RepositorySettings");
39  }
40  }
41 }
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
+
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
+ -
Add the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MSSQL ...
- +
Add the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MSSQL
diff --git a/20181124231549___m_y_toggle_testmerge_comments_8_designer_8cs.html b/20181124231549___m_y_toggle_testmerge_comments_8_designer_8cs.html index 47de611061..b067cabb6a 100644 --- a/20181124231549___m_y_toggle_testmerge_comments_8_designer_8cs.html +++ b/20181124231549___m_y_toggle_testmerge_comments_8_designer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20181124231549_MYToggleTestmergeComments.Designer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.Migrations.MYToggleTestmergeComments - Add the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MySQL/MariaDB More...
+ Add the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MySQL/MariaDB More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20181124231549___m_y_toggle_testmerge_comments_8_designer_8cs_source.html b/20181124231549___m_y_toggle_testmerge_comments_8_designer_8cs_source.html index 35b5ec75c2..a5ec3ce136 100644 --- a/20181124231549___m_y_toggle_testmerge_comments_8_designer_8cs_source.html +++ b/20181124231549___m_y_toggle_testmerge_comments_8_designer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20181124231549_MYToggleTestmergeComments.Designer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20181124231549_MYToggleTestmergeComments.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.Migrations;
6 
7 namespace Tgstation.Server.Host.Models.Migrations
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;
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
+ - -
diff --git a/20181124231549___m_y_toggle_testmerge_comments_8cs.html b/20181124231549___m_y_toggle_testmerge_comments_8cs.html index 7a09449d02..55d2db719a 100644 --- a/20181124231549___m_y_toggle_testmerge_comments_8cs.html +++ b/20181124231549___m_y_toggle_testmerge_comments_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20181124231549_MYToggleTestmergeComments.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.Migrations.MYToggleTestmergeComments - Add the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MySQL/MariaDB More...
+ Add the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MySQL/MariaDB More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20181124231549___m_y_toggle_testmerge_comments_8cs_source.html b/20181124231549___m_y_toggle_testmerge_comments_8cs_source.html index 05440f6f5c..29c3cd63ba 100644 --- a/20181124231549___m_y_toggle_testmerge_comments_8cs_source.html +++ b/20181124231549___m_y_toggle_testmerge_comments_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20181124231549_MYToggleTestmergeComments.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20181124231549_MYToggleTestmergeComments.cs
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore.Migrations;
2 
3 namespace Tgstation.Server.Host.Models.Migrations
4 {
8  public partial class MYToggleTestmergeComments : Migration
9  {
14  protected override void Up(MigrationBuilder migrationBuilder)
15  {
16  migrationBuilder.AddColumn<bool>(
17  name: "PostTestMergeComment",
18  table: "RepositorySettings",
19  nullable: false,
20  defaultValue: true);
21  }
22 
27  protected override void Down(MigrationBuilder migrationBuilder)
28  {
29  migrationBuilder.DropColumn(
30  name: "PostTestMergeComment",
31  table: "RepositorySettings");
32  }
33  }
34 }
+Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore.Migrations;
2 using System;
3 
5 {
9  public partial class MYToggleTestmergeComments : Migration
10  {
15  protected override void Up(MigrationBuilder migrationBuilder)
16  {
17  if (migrationBuilder == null)
18  throw new ArgumentNullException(nameof(migrationBuilder));
19 
20  migrationBuilder.AddColumn<bool>(
21  name: "PostTestMergeComment",
22  table: "RepositorySettings",
23  nullable: false,
24  defaultValue: true);
25  }
26 
31  protected override void Down(MigrationBuilder migrationBuilder)
32  {
33  if (migrationBuilder == null)
34  throw new ArgumentNullException(nameof(migrationBuilder));
35 
36  migrationBuilder.DropColumn(
37  name: "PostTestMergeComment",
38  table: "RepositorySettings");
39  }
40  }
41 }
-
Add the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MySQL/MariaDB ...
-
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
-
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
- +
Add the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MySQL/MariaDB
+
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
+
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
diff --git a/20190219041825___m_s_fix_rev_info_index_8_designer_8cs.html b/20190219041825___m_s_fix_rev_info_index_8_designer_8cs.html index ecf1497d63..b7c918a4e8 100644 --- a/20190219041825___m_s_fix_rev_info_index_8_designer_8cs.html +++ b/20190219041825___m_s_fix_rev_info_index_8_designer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20190219041825_MSFixRevInfoIndex.Designer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.Migrations.MSFixRevInfoIndex - Make commit shas non-unique per Instance for MSSQL More...
+ Make commit shas non-unique per Instance for MSSQL More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20190219041825___m_s_fix_rev_info_index_8_designer_8cs_source.html b/20190219041825___m_s_fix_rev_info_index_8_designer_8cs_source.html index 1a331c68e1..532d092328 100644 --- a/20190219041825___m_s_fix_rev_info_index_8_designer_8cs_source.html +++ b/20190219041825___m_s_fix_rev_info_index_8_designer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20190219041825_MSFixRevInfoIndex.Designer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20190219041825_MSFixRevInfoIndex.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 
9 namespace Tgstation.Server.Host.Models.Migrations
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;
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 }
- - -
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
+
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
diff --git a/20190219041825___m_s_fix_rev_info_index_8cs.html b/20190219041825___m_s_fix_rev_info_index_8cs.html index 09f0ee77c8..d45f90deae 100644 --- a/20190219041825___m_s_fix_rev_info_index_8cs.html +++ b/20190219041825___m_s_fix_rev_info_index_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20190219041825_MSFixRevInfoIndex.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.Migrations.MSFixRevInfoIndex - Make commit shas non-unique per Instance for MSSQL More...
+ Make commit shas non-unique per Instance for MSSQL More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20190219041825___m_s_fix_rev_info_index_8cs_source.html b/20190219041825___m_s_fix_rev_info_index_8cs_source.html index 278c4b40a5..9217431df8 100644 --- a/20190219041825___m_s_fix_rev_info_index_8cs_source.html +++ b/20190219041825___m_s_fix_rev_info_index_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20190219041825_MSFixRevInfoIndex.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20190219041825_MSFixRevInfoIndex.cs
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore.Migrations;
2 
3 namespace Tgstation.Server.Host.Models.Migrations
4 {
8  public partial class MSFixRevInfoIndex : Migration
9  {
14  protected override void Up(MigrationBuilder migrationBuilder)
15  {
16  migrationBuilder.DropIndex(
17  name: "IX_RevisionInformations_CommitSha",
18  table: "RevisionInformations");
19 
20  migrationBuilder.DropIndex(
21  name: "IX_RevisionInformations_InstanceId",
22  table: "RevisionInformations");
23 
24  migrationBuilder.CreateIndex(
25  name: "IX_RevisionInformations_InstanceId_CommitSha",
26  table: "RevisionInformations",
27  columns: new[] { "InstanceId", "CommitSha" },
28  unique: true);
29  }
30 
35  protected override void Down(MigrationBuilder migrationBuilder)
36  {
37  migrationBuilder.DropIndex(
38  name: "IX_RevisionInformations_InstanceId_CommitSha",
39  table: "RevisionInformations");
40 
41  migrationBuilder.CreateIndex(
42  name: "IX_RevisionInformations_CommitSha",
43  table: "RevisionInformations",
44  column: "CommitSha",
45  unique: true);
46 
47  migrationBuilder.CreateIndex(
48  name: "IX_RevisionInformations_InstanceId",
49  table: "RevisionInformations",
50  column: "InstanceId");
51  }
52  }
53 }
+Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore.Migrations;
2 using System;
3 
5 {
9  public partial class MSFixRevInfoIndex : Migration
10  {
15  protected override void Up(MigrationBuilder migrationBuilder)
16  {
17  if (migrationBuilder == null)
18  throw new ArgumentNullException(nameof(migrationBuilder));
19 
20  migrationBuilder.DropIndex(
21  name: "IX_RevisionInformations_CommitSha",
22  table: "RevisionInformations");
23 
24  migrationBuilder.DropIndex(
25  name: "IX_RevisionInformations_InstanceId",
26  table: "RevisionInformations");
27 
28  migrationBuilder.CreateIndex(
29  name: "IX_RevisionInformations_InstanceId_CommitSha",
30  table: "RevisionInformations",
31  columns: new[] { "InstanceId", "CommitSha" },
32  unique: true);
33  }
34 
39  protected override void Down(MigrationBuilder migrationBuilder)
40  {
41  if (migrationBuilder == null)
42  throw new ArgumentNullException(nameof(migrationBuilder));
43 
44  migrationBuilder.DropIndex(
45  name: "IX_RevisionInformations_InstanceId_CommitSha",
46  table: "RevisionInformations");
47 
48  migrationBuilder.CreateIndex(
49  name: "IX_RevisionInformations_CommitSha",
50  table: "RevisionInformations",
51  column: "CommitSha",
52  unique: true);
53 
54  migrationBuilder.CreateIndex(
55  name: "IX_RevisionInformations_InstanceId",
56  table: "RevisionInformations",
57  column: "InstanceId");
58  }
59  }
60 }
-
override void Down(MigrationBuilder migrationBuilder)
Unpplies the migration
-
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
-
Make commit shas non-unique per Instance for MSSQL
- +
override void Down(MigrationBuilder migrationBuilder)
Unpplies the migration
+
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
+
diff --git a/20190219042440___m_y_fix_rev_info_index_8_designer_8cs.html b/20190219042440___m_y_fix_rev_info_index_8_designer_8cs.html index b20763b37c..5a4fec98a7 100644 --- a/20190219042440___m_y_fix_rev_info_index_8_designer_8cs.html +++ b/20190219042440___m_y_fix_rev_info_index_8_designer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20190219042440_MYFixRevInfoIndex.Designer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.Migrations.MYFixRevInfoIndex - Make commit shas non-unique per Instance for MSSQL More...
+ Make commit shas non-unique per Instance for MSSQL More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20190219042440___m_y_fix_rev_info_index_8_designer_8cs_source.html b/20190219042440___m_y_fix_rev_info_index_8_designer_8cs_source.html index 6bbbef1dce..b1413fa774 100644 --- a/20190219042440___m_y_fix_rev_info_index_8_designer_8cs_source.html +++ b/20190219042440___m_y_fix_rev_info_index_8_designer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20190219042440_MYFixRevInfoIndex.Designer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20190219042440_MYFixRevInfoIndex.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.Migrations;
6 
7 namespace Tgstation.Server.Host.Models.Migrations
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;
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 }
- -
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
+
override void BuildTargetModel(ModelBuilder modelBuilder)
Builds the target model
-
diff --git a/20190219042440___m_y_fix_rev_info_index_8cs.html b/20190219042440___m_y_fix_rev_info_index_8cs.html index fa26567b04..b7b66547fc 100644 --- a/20190219042440___m_y_fix_rev_info_index_8cs.html +++ b/20190219042440___m_y_fix_rev_info_index_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20190219042440_MYFixRevInfoIndex.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.Migrations.MYFixRevInfoIndex - Make commit shas non-unique per Instance for MSSQL More...
+ Make commit shas non-unique per Instance for MSSQL More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/20190219042440___m_y_fix_rev_info_index_8cs_source.html b/20190219042440___m_y_fix_rev_info_index_8cs_source.html index 53820b1f8a..dd0a9c4fc4 100644 --- a/20190219042440___m_y_fix_rev_info_index_8cs_source.html +++ b/20190219042440___m_y_fix_rev_info_index_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/20190219042440_MYFixRevInfoIndex.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
20190219042440_MYFixRevInfoIndex.cs
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore.Migrations;
2 
3 namespace Tgstation.Server.Host.Models.Migrations
4 {
8  public partial class MYFixRevInfoIndex : Migration
9  {
14  protected override void Up(MigrationBuilder migrationBuilder)
15  {
16  migrationBuilder.DropForeignKey(
17  name: "FK_RevisionInformations_Instances_InstanceId",
18  table: "RevisionInformations");
19 
20  migrationBuilder.DropIndex(
21  name: "IX_RevisionInformations_CommitSha",
22  table: "RevisionInformations");
23 
24  migrationBuilder.DropIndex(
25  name: "IX_RevisionInformations_InstanceId",
26  table: "RevisionInformations");
27 
28  migrationBuilder.CreateIndex(
29  name: "IX_RevisionInformations_InstanceId_CommitSha",
30  table: "RevisionInformations",
31  columns: new[] { "InstanceId", "CommitSha" },
32  unique: true);
33 
34  migrationBuilder.AddForeignKey(
35  name: "FK_RevisionInformations_Instances_InstanceId",
36  table: "RevisionInformations",
37  column: "InstanceId",
38  principalTable: "Instances",
39  principalColumn: "Id",
40  onDelete: ReferentialAction.Cascade);
41  }
42 
47  protected override void Down(MigrationBuilder migrationBuilder)
48  {
49  migrationBuilder.DropForeignKey(
50  name: "FK_RevisionInformations_Instances_InstanceId",
51  table: "RevisionInformations");
52 
53  migrationBuilder.DropIndex(
54  name: "IX_RevisionInformations_InstanceId_CommitSha",
55  table: "RevisionInformations");
56 
57  migrationBuilder.CreateIndex(
58  name: "IX_RevisionInformations_CommitSha",
59  table: "RevisionInformations",
60  column: "CommitSha",
61  unique: true);
62 
63  migrationBuilder.CreateIndex(
64  name: "IX_RevisionInformations_InstanceId",
65  table: "RevisionInformations",
66  column: "InstanceId");
67 
68  migrationBuilder.AddForeignKey(
69  name: "FK_RevisionInformations_Instances_InstanceId",
70  table: "RevisionInformations",
71  column: "InstanceId",
72  principalTable: "Instances",
73  principalColumn: "Id",
74  onDelete: ReferentialAction.Cascade);
75  }
76  }
77 }
+Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore.Migrations;
2 using System;
3 
5 {
9  public partial class MYFixRevInfoIndex : Migration
10  {
15  protected override void Up(MigrationBuilder migrationBuilder)
16  {
17  if (migrationBuilder == null)
18  throw new ArgumentNullException(nameof(migrationBuilder));
19 
20  migrationBuilder.DropForeignKey(
21  name: "FK_RevisionInformations_Instances_InstanceId",
22  table: "RevisionInformations");
23 
24  migrationBuilder.DropIndex(
25  name: "IX_RevisionInformations_CommitSha",
26  table: "RevisionInformations");
27 
28  migrationBuilder.DropIndex(
29  name: "IX_RevisionInformations_InstanceId",
30  table: "RevisionInformations");
31 
32  migrationBuilder.CreateIndex(
33  name: "IX_RevisionInformations_InstanceId_CommitSha",
34  table: "RevisionInformations",
35  columns: new[] { "InstanceId", "CommitSha" },
36  unique: true);
37 
38  migrationBuilder.AddForeignKey(
39  name: "FK_RevisionInformations_Instances_InstanceId",
40  table: "RevisionInformations",
41  column: "InstanceId",
42  principalTable: "Instances",
43  principalColumn: "Id",
44  onDelete: ReferentialAction.Cascade);
45  }
46 
51  protected override void Down(MigrationBuilder migrationBuilder)
52  {
53  if (migrationBuilder == null)
54  throw new ArgumentNullException(nameof(migrationBuilder));
55 
56  migrationBuilder.DropForeignKey(
57  name: "FK_RevisionInformations_Instances_InstanceId",
58  table: "RevisionInformations");
59 
60  migrationBuilder.DropIndex(
61  name: "IX_RevisionInformations_InstanceId_CommitSha",
62  table: "RevisionInformations");
63 
64  migrationBuilder.CreateIndex(
65  name: "IX_RevisionInformations_CommitSha",
66  table: "RevisionInformations",
67  column: "CommitSha",
68  unique: true);
69 
70  migrationBuilder.CreateIndex(
71  name: "IX_RevisionInformations_InstanceId",
72  table: "RevisionInformations",
73  column: "InstanceId");
74 
75  migrationBuilder.AddForeignKey(
76  name: "FK_RevisionInformations_Instances_InstanceId",
77  table: "RevisionInformations",
78  column: "InstanceId",
79  principalTable: "Instances",
80  principalColumn: "Id",
81  onDelete: ReferentialAction.Cascade);
82  }
83  }
84 }
-
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
-
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
-
Make commit shas non-unique per Instance for MSSQL
- +
override void Up(MigrationBuilder migrationBuilder)
Applies the migration
+
override void Down(MigrationBuilder migrationBuilder)
Unapplies the migration
+
diff --git a/_a_p_i_8dox.html b/_a_p_i_8dox.html index 7782f50d28..ad027bab77 100644 --- a/_a_p_i_8dox.html +++ b/_a_p_i_8dox.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: docs/API.dox File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + + - + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_administration_8cs_source.html b/_administration_8cs_source.html index 25ad29ed95..63a6f79ee1 100644 --- a/_administration_8cs_source.html +++ b/_administration_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Administration.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Administration.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Api.Models
4 {
8  public sealed class Administration
9  {
13  public bool WindowsHost { get; set; }
14 
18  public Uri TrackedRepositoryUrl { get; set; }
19 
23  public Version LatestVersion { get; set; }
24 
28  public Version NewVersion { get; set; }
29  }
30 }
- -
Represents administrative server information
- +Go to the documentation of this file.
1 using System;
2 
4 {
8  public sealed class Administration
9  {
13  public bool WindowsHost { get; set; }
14 
18  public Uri TrackedRepositoryUrl { get; set; }
19 
23  public Version LatestVersion { get; set; }
24 
28  public Version NewVersion { get; set; }
29  }
30 }
+
Represents administrative server information
+
Uri TrackedRepositoryUrl
The GitHub repository the server is built to recieve updates from
+
bool WindowsHost
If the server is running on a windows operating system
+
Version LatestVersion
The latest available version of the Tgstation.Server.Host assembly from the upstream repository....
+
Version NewVersion
Changes the version of Tgstation.Server.Host to the given version from the upstream repository
diff --git a/_administration_client_8cs.html b/_administration_client_8cs.html index e54ec1ce66..79bf51c886 100644 --- a/_administration_client_8cs.html +++ b/_administration_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/AdministrationClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -113,7 +96,7 @@ Namespaces diff --git a/_administration_client_8cs_source.html b/_administration_client_8cs_source.html index da2a4e7e93..4aeaf06601 100644 --- a/_administration_client_8cs_source.html +++ b/_administration_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/AdministrationClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
AdministrationClient.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 using Tgstation.Server.Api;
6 
7 namespace Tgstation.Server.Client
8 {
11  {
16 
21  public AdministrationClient(IApiClient apiClient)
22  {
23  this.apiClient = apiClient;
24  }
25 
27  public Task<Administration> Read(CancellationToken cancellationToken) => apiClient.Read<Administration>(Routes.Administration, cancellationToken);
28 
30  public Task Update(Administration administration, CancellationToken cancellationToken) => apiClient.Update(Routes.Administration, administration ?? throw new ArgumentNullException(nameof(administration)), cancellationToken);
31 
33  public Task Restart(CancellationToken cancellationToken) => apiClient.Delete(Routes.Administration, cancellationToken);
34  }
35 }
-
AdministrationClient(IApiClient apiClient)
Construct an AdministrationClient
+Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 using Tgstation.Server.Api;
6 
8 {
11  {
16 
22  {
23  this.apiClient = apiClient;
24  }
25 
27  public Task<Administration> Read(CancellationToken cancellationToken) => apiClient.Read<Administration>(Routes.Administration, cancellationToken);
28 
30  public Task Update(Administration administration, CancellationToken cancellationToken) => apiClient.Update(Routes.Administration, administration ?? throw new ArgumentNullException(nameof(administration)), cancellationToken);
31 
33  public Task Restart(CancellationToken cancellationToken) => apiClient.Delete(Routes.Administration, cancellationToken);
34  }
35 }
Task< Administration > Read(CancellationToken cancellationToken)
Get the Administration represented by the IAdministrationClient
+ +
AdministrationClient(IApiClient apiClient)
Construct an AdministrationClient
- - -
const string Administration
The Models.Administration controller
Definition: Routes.cs:19
+ +
Task Update(Administration administration, CancellationToken cancellationToken)
Updates the Administration setttings
+
const string Administration
The Models.Administration controller
Definition: Routes.cs:19
-
readonly IApiClient apiClient
The apiClient for the AdministrationClient
-
Represents administrative server information
-
Routes to a server actions
Definition: Routes.cs:9
+
readonly IApiClient apiClient
The apiClient for the AdministrationClient
+
Represents administrative server information
+
Routes to a server actions
Definition: Routes.cs:9
- -
Web interface for the API
Definition: IApiClient.cs:11
- +
Task Delete(string route, CancellationToken cancellationToken)
Run an HTTP DELETE request
+ +
Web interface for the API
Definition: IApiClient.cs:11
+
Task Restart(CancellationToken cancellationToken)
Restarts the TGS server
+
diff --git a/_administration_controller_8cs.html b/_administration_controller_8cs.html index 56b765e8a2..1b60d20c3e 100644 --- a/_administration_controller_8cs.html +++ b/_administration_controller_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/AdministrationController.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Controllers.AdministrationControllerModelController<TModel> for Administration More...
ModelController<TModel> for Administration More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Controllers
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_administration_controller_8cs_source.html b/_administration_controller_8cs_source.html index 878f7d0bcb..1b05df23da 100644 --- a/_administration_controller_8cs_source.html +++ b/_administration_controller_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/AdministrationController.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
AdministrationController.cs
-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 
22 namespace Tgstation.Server.Host.Controllers
23 {
27  [Route(Routes.Administration)]
28  public sealed class AdministrationController : ModelController<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)
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 
101  IGitHubClient GetGitHubClient() => String.IsNullOrEmpty(generalConfiguration.GitHubAccessToken) ? gitHubClientFactory.CreateClient() : gitHubClientFactory.CreateClient(generalConfiguration.GitHubAccessToken);
102 
104  [TgsAuthorize]
105  public override async Task<IActionResult> Read(CancellationToken cancellationToken)
106  {
107  try
108  {
109  Version greatestVersion = null;
110  Uri repoUrl = null;
111  try
112  {
113  var gitHubClient = GetGitHubClient();
114  var repositoryTask = gitHubClient.Repository.Get(updatesConfiguration.GitHubRepositoryId);
115  var releases = (await gitHubClient.Repository.Release.GetAll(updatesConfiguration.GitHubRepositoryId).ConfigureAwait(false)).Where(x => x.TagName.StartsWith(updatesConfiguration.GitTagPrefix, StringComparison.InvariantCulture));
116 
117  foreach (var I in releases)
118  if (Version.TryParse(I.TagName.Replace(updatesConfiguration.GitTagPrefix, String.Empty, StringComparison.Ordinal), out var version)
119  && version.Major == application.Version.Major
120  && (greatestVersion == null || version > greatestVersion))
121  greatestVersion = version;
122  repoUrl = new Uri((await repositoryTask.ConfigureAwait(false)).HtmlUrl);
123  }
124  catch (NotFoundException e)
125  {
126  Logger.LogWarning("Not found exception while retrieving upstream repository info: {0}", e);
127  }
128 
129  return Json(new Administration
130  {
131  LatestVersion = greatestVersion,
132  TrackedRepositoryUrl = repoUrl,
133  WindowsHost = platformIdentifier.IsWindows
134  });
135  }
136  catch (RateLimitExceededException e)
137  {
138  return RateLimit(e);
139  }
140  catch (ApiException e)
141  {
142  Logger.LogWarning(OctokitException, e);
143  return StatusCode((int)HttpStatusCode.FailedDependency);
144  }
145  }
146 
148  [TgsAuthorize(AdministrationRights.ChangeVersion)]
149  public override async Task<IActionResult> Update([FromBody] Administration model, CancellationToken cancellationToken)
150  {
151  if (model == null)
152  throw new ArgumentNullException(nameof(model));
153 
154  if (model.NewVersion == null)
155  return BadRequest(new ErrorMessage { Message = "Missing new version!" });
156 
157  if (model.NewVersion.Major != application.Version.Major)
158  return BadRequest(new ErrorMessage { Message = "Cannot update to a different suite version!" });
159 
160  if(!serverUpdater.WatchdogPresent)
161  return UnprocessableEntity(new ErrorMessage
162  {
163  Message = RestartNotSupportedException
164  });
165 
166  Logger.LogDebug("Looking for GitHub releases version {0}...", model.NewVersion);
167  IEnumerable<Release> releases;
168  try
169  {
170  var gitHubClient = GetGitHubClient();
171  releases = (await gitHubClient.Repository.Release.GetAll(updatesConfiguration.GitHubRepositoryId).ConfigureAwait(false)).Where(x => x.TagName.StartsWith(updatesConfiguration.GitTagPrefix, StringComparison.InvariantCulture));
172  cancellationToken.ThrowIfCancellationRequested();
173  }
174  catch (RateLimitExceededException e)
175  {
176  return RateLimit(e);
177  }
178  catch (ApiException e)
179  {
180  Logger.LogWarning(OctokitException, e);
181  return StatusCode((int)HttpStatusCode.FailedDependency);
182  }
183 
184  Logger.LogTrace("Release query complete!");
185  foreach (var release in releases)
186  if (Version.TryParse(release.TagName.Replace(updatesConfiguration.GitTagPrefix, String.Empty, StringComparison.Ordinal), out var version) && version == model.NewVersion)
187  {
188  var asset = release.Assets.Where(x => x.Name == updatesConfiguration.UpdatePackageAssetName).FirstOrDefault();
189  if (asset == default)
190  continue;
191 
192  if (!serverUpdater.ApplyUpdate(version, new Uri(asset.BrowserDownloadUrl), ioManager))
193  return Conflict(new ErrorMessage
194  {
195  Message = "An update operation is already in progress!"
196  });
197  return Accepted(); // gtfo of here before all the cancellation tokens fire
198  }
199 
200  return StatusCode((int)HttpStatusCode.Gone);
201  }
202 
207  [HttpDelete]
208  [TgsAuthorize(AdministrationRights.RestartHost)]
209  public async Task<IActionResult> Delete()
210  {
211  try
212  {
213  if (!serverUpdater.WatchdogPresent)
214  {
215  Logger.LogDebug("Restart request failed due to lack of host watchdog!");
216  return UnprocessableEntity(new ErrorMessage
217  {
218  Message = RestartNotSupportedException
219  });
220  }
221 
222  await serverUpdater.Restart().ConfigureAwait(false);
223  return Ok();
224  }
225  catch (InvalidOperationException)
226  {
227  return StatusCode((int)HttpStatusCode.ServiceUnavailable);
228  }
229  }
230  }
231 }
- -
override async Task< IActionResult > Read(CancellationToken cancellationToken)
Attempt to read a TModel
-
async Task< IActionResult > Delete()
Attempts to restart the server
+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)]
28  public sealed class AdministrationController : ModelController<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)
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 
156  [TgsAuthorize]
157  public override async Task<IActionResult> Read(CancellationToken cancellationToken)
158  {
159  try
160  {
161  Version greatestVersion = null;
162  Uri repoUrl = null;
163  try
164  {
165  var gitHubClient = GetGitHubClient();
166  var repositoryTask = gitHubClient.Repository.Get(updatesConfiguration.GitHubRepositoryId);
167  var releases = (await gitHubClient.Repository.Release.GetAll(updatesConfiguration.GitHubRepositoryId).ConfigureAwait(false)).Where(x => x.TagName.StartsWith(updatesConfiguration.GitTagPrefix, StringComparison.InvariantCulture));
168 
169  foreach (var I in releases)
170  if (Version.TryParse(I.TagName.Replace(updatesConfiguration.GitTagPrefix, String.Empty, StringComparison.Ordinal), out var version)
171  && version.Major == application.Version.Major
172  && (greatestVersion == null || version > greatestVersion))
173  greatestVersion = version;
174  repoUrl = new Uri((await repositoryTask.ConfigureAwait(false)).HtmlUrl);
175  }
176  catch (NotFoundException e)
177  {
178  Logger.LogWarning("Not found exception while retrieving upstream repository info: {0}", e);
179  }
180 
181  return Json(new Administration
182  {
183  LatestVersion = greatestVersion,
184  TrackedRepositoryUrl = repoUrl,
185  WindowsHost = platformIdentifier.IsWindows
186  });
187  }
188  catch (RateLimitExceededException e)
189  {
190  return RateLimit(e);
191  }
192  catch (ApiException e)
193  {
194  Logger.LogWarning(OctokitException, e);
195  return StatusCode((int)HttpStatusCode.FailedDependency);
196  }
197  }
198 
200  [TgsAuthorize(AdministrationRights.ChangeVersion)]
201  public override async Task<IActionResult> Update([FromBody] Administration model, CancellationToken cancellationToken)
202  {
203  if (model == null)
204  throw new ArgumentNullException(nameof(model));
205 
206  if (model.NewVersion == null)
207  return BadRequest(new ErrorMessage { Message = "Missing new version!" });
208 
209  if (model.NewVersion.Major != application.Version.Major)
210  return BadRequest(new ErrorMessage { Message = "Cannot update to a different suite version!" });
211 
213  return UnprocessableEntity(new ErrorMessage
214  {
216  });
217 
218  return await CheckReleasesAndApplyUpdate(model.NewVersion, cancellationToken).ConfigureAwait(false);
219  }
220 
225  [HttpDelete]
226  [TgsAuthorize(AdministrationRights.RestartHost)]
227  public async Task<IActionResult> Delete()
228  {
229  try
230  {
232  {
233  Logger.LogDebug("Restart request failed due to lack of host watchdog!");
234  return UnprocessableEntity(new ErrorMessage
235  {
237  });
238  }
239 
240  await serverUpdater.Restart().ConfigureAwait(false);
241  return Ok();
242  }
243  catch (InvalidOperationException)
244  {
245  return StatusCode((int)HttpStatusCode.ServiceUnavailable);
246  }
247  }
248  }
249 }
+ + +
override async Task< IActionResult > Read(CancellationToken cancellationToken)
Attempt to read a TModel
+
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 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
- -
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
-
readonly IIOManager ioManager
The IIOManager for the AdministrationController
-
readonly IGitHubClientFactory gitHubClientFactory
The IGitHubClientFactory for the AdministrationController
+
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
+
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
+
string UpdatePackageAssetName
Asset package containing the new Host assembly in zip form
-
readonly UpdatesConfiguration updatesConfiguration
The UpdatesConfiguration 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
+
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
+
AdministrationRights
Rights for Models.Administration
+
const string Administration
The Models.Administration controller
Definition: Routes.cs:19
- +
StatusCodeResult RateLimit(RateLimitExceededException exception)
-
override async Task< IActionResult > Update([FromBody] Administration model, CancellationToken cancellationToken)
+ +
override async Task< IActionResult > Update([FromBody] Administration model, CancellationToken cancellationToken)
-
Represents administrative server information
-
Configuration for the automatic update system
-
Routes to a server actions
Definition: Routes.cs:9
+
Represents administrative server information
+
Configuration for the automatic update system
+
Routes to a server actions
Definition: Routes.cs:9
+ -
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
-
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for the AdministrationController
-
An ApiController representing a TModel
+
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
+ + +
IGitHubClient CreateClient()
Create a client with anonymous authentication. Low rate limit
+
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for the AdministrationController
+
An ApiController representing a TModel
- - - -
Interface for using filesystems
Definition: IIOManager.cs:11
-
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 GeneralConfiguration generalConfiguration
The GeneralConfiguration for the AdministrationController
- + + +
Interface for using filesystems
Definition: IIOManager.cs:11
+
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
+ +
Version Version
The version of the Application
Definition: IApplication.cs:23
+
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...
@@ -139,7 +130,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_administration_rights_8cs.html b/_administration_rights_8cs.html index 971e38060b..1f48510dd9 100644 --- a/_administration_rights_8cs.html +++ b/_administration_rights_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/AdministrationRights.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Api +  namespace  Tgstation.Server.Api.Rights   @@ -114,8 +99,8 @@ Enumerations   Tgstation.Server.Api.Rights.AdministrationRights.EditOwnPassword = 8, Tgstation.Server.Api.Rights.AdministrationRights.ReadUsers = 16
- } - + } +
 Rights for Models.Administration More...
 Rights for Models.Administration More...
 
@@ -123,7 +108,7 @@ Enumerations diff --git a/_administration_rights_8cs_source.html b/_administration_rights_8cs_source.html index 449945c4bc..8964646551 100644 --- a/_administration_rights_8cs_source.html +++ b/_administration_rights_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/AdministrationRights.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
AdministrationRights.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Api.Rights
4 {
8  [Flags]
9  public enum AdministrationRights : ulong
10  {
14  None = 0,
15 
19  WriteUsers = 1,
20 
24  RestartHost = 2,
25 
29  ChangeVersion = 4,
30 
34  EditOwnPassword = 8,
35 
39  ReadUsers = 16
40  }
41 }
User can edit themself and other Models.Users and also create others
- -
AdministrationRights
Rights for Models.Administration
- - -
User can read info and rights of other users
-
User can change Models.Administration.NewVersion
- - +Go to the documentation of this file.
1 using System;
2 
4 {
8  [Flags]
9  public enum AdministrationRights : ulong
10  {
14  None = 0,
15 
19  WriteUsers = 1,
20 
24  RestartHost = 2,
25 
29  ChangeVersion = 4,
30 
34  EditOwnPassword = 8,
35 
39  ReadUsers = 16
40  }
41 }
User can edit themself and other Models.Users and also create others
+
AdministrationRights
Rights for Models.Administration
+ + +
User can read info and rights of other users
+ +
User can change Models.Administration.NewVersion
+
diff --git a/_administration_test_8cs.html b/_administration_test_8cs.html index a7f6599cf9..be0c01ac5c 100644 --- a/_administration_test_8cs.html +++ b/_administration_test_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Tests/AdministrationTest.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Tests
 
@@ -113,7 +96,7 @@ Namespaces diff --git a/_administration_test_8cs_source.html b/_administration_test_8cs_source.html index 017fb2d535..0e5c1c37d1 100644 --- a/_administration_test_8cs_source.html +++ b/_administration_test_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Tests/AdministrationTest.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
AdministrationTest.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.Runtime.InteropServices;
4 using System.Threading;
5 using System.Threading.Tasks;
8 
9 namespace Tgstation.Server.Tests
10 {
11  sealed class AdministrationTest
12  {
14 
16  {
17  this.client = client ?? throw new ArgumentNullException(nameof(client));
18  }
19 
20  public async Task Run(CancellationToken cancellationToken)
21  {
22  await TestRead(cancellationToken).ConfigureAwait(false);
23  }
24 
25  async Task TestRead(CancellationToken cancellationToken)
26  {
27  Administration model;
28  try
29  {
30  model = await client.Read(cancellationToken).ConfigureAwait(false);
31  }
32  catch (RateLimitException)
33  {
34  Assert.Inconclusive("GitHub rate limit hit while testing administration endpoint. Set environment variable TGS4_TEST_GITHUB_TOKEN to fix this!");
35  return; //c# needs the equivalent of [noreturn]
36  }
37  Assert.AreEqual(RuntimeInformation.IsOSPlatform(OSPlatform.Windows), model.WindowsHost);
38 
39  //we've released a few 4.x versions now, check the release checker is at least somewhat functional
40  Assert.AreEqual(4, model.LatestVersion.Major);
41  }
42  }
43 }
async Task Run(CancellationToken cancellationToken)
- +Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.Runtime.InteropServices;
4 using System.Threading;
5 using System.Threading.Tasks;
8 
10 {
11  sealed class AdministrationTest
12  {
14 
16  {
17  this.client = client ?? throw new ArgumentNullException(nameof(client));
18  }
19 
20  public async Task Run(CancellationToken cancellationToken)
21  {
22  await TestRead(cancellationToken).ConfigureAwait(false);
23  }
24 
25  async Task TestRead(CancellationToken cancellationToken)
26  {
27  Administration model;
28  try
29  {
30  model = await client.Read(cancellationToken).ConfigureAwait(false);
31  }
32  catch (RateLimitException)
33  {
34  Assert.Inconclusive("GitHub rate limit hit while testing administration endpoint. Set environment variable TGS4_TEST_GITHUB_TOKEN to fix this!");
35  return; //c# needs the equivalent of [noreturn]
36  }
37  Assert.AreEqual(RuntimeInformation.IsOSPlatform(OSPlatform.Windows), model.WindowsHost);
38 
39  //we've released a few 4.x versions now, check the release checker is at least somewhat functional
40  Assert.AreEqual(4, model.LatestVersion.Major);
41  }
42  }
43 }
async Task Run(CancellationToken cancellationToken)
+ -
async Task TestRead(CancellationToken cancellationToken)
-
Occurs when a GitHub rate limit occurs
- +
Occurs when a GitHub rate limit occurs
-
Represents administrative server information
+
Represents administrative server information
+
AdministrationTest(IAdministrationClient client)
-
bool WindowsHost
If the server is running on a windows operating system
-
Version LatestVersion
The latest available version of the Tgstation.Server.Host assembly from the upstream repository...
- +
bool WindowsHost
If the server is running on a windows operating system
+
Task< Administration > Read(CancellationToken cancellationToken)
Get the Administration represented by the IAdministrationClient
+
Version LatestVersion
The latest available version of the Tgstation.Server.Host assembly from the upstream repository....
+
readonly IAdministrationClient client
- +
diff --git a/_api_client_8cs.html b/_api_client_8cs.html index f2150b8b02..dc4d7af42a 100644 --- a/_api_client_8cs.html +++ b/_api_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ApiClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -113,7 +96,7 @@ Namespaces diff --git a/_api_client_8cs_source.html b/_api_client_8cs_source.html index 0881a7a3df..036f230f82 100644 --- a/_api_client_8cs_source.html +++ b/_api_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ApiClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ApiClient.cs
-Go to the documentation of this file.
1 using Newtonsoft.Json;
2 using Newtonsoft.Json.Converters;
3 using Newtonsoft.Json.Serialization;
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Net;
8 using System.Net.Http;
9 using System.Text;
10 using System.Threading;
11 using System.Threading.Tasks;
12 using Tgstation.Server.Api;
14 
15 namespace Tgstation.Server.Client
16 {
18  sealed class ApiClient : IApiClient
19  {
21  public Uri Url { get; }
22 
24  public ApiHeaders Headers
25  {
26  get => headers;
27  set => headers = value ?? throw new InvalidOperationException("Cannot set null headers!");
28  }
29 
31  public TimeSpan Timeout
32  {
33  get => httpClient.Timeout;
34  set => httpClient.Timeout = value;
35  }
36 
41 
45  readonly List<IRequestLogger> requestLoggers;
46 
51 
52  static JsonSerializerSettings GetSerializerSettings() => new JsonSerializerSettings
53  {
54  ContractResolver = new CamelCasePropertyNamesContractResolver(),
55  Converters = new[] { new VersionConverter() }
56  };
57 
58  static void HandleBadResponse(HttpResponseMessage response, string json)
59  {
60  ErrorMessage errorMessage = null;
61  try
62  {
63  // check if json serializes to an error message
64  errorMessage = JsonConvert.DeserializeObject<ErrorMessage>(json, GetSerializerSettings());
65  }
66  catch (JsonException) { }
67 
68  const string BadSpecExtension = " This is not part of TGS4 communication specification and should be reported if it was returned from a TGS4 server!";
69 
70 #pragma warning disable IDE0010 // Add missing cases
71  switch (response.StatusCode)
72 #pragma warning restore IDE0010 // Add missing cases
73  {
74  case HttpStatusCode.UpgradeRequired:
75  throw new ApiMismatchException(errorMessage ?? new ErrorMessage
76  {
77  Message = "API Mismatch but no current API version provided!" + BadSpecExtension,
78  SeverApiVersion = null
79  });
80  case HttpStatusCode.Unauthorized:
81  throw new UnauthorizedException();
82  case HttpStatusCode.RequestTimeout:
83  throw new RequestTimeoutException();
84  case HttpStatusCode.Forbidden:
86  case HttpStatusCode.ServiceUnavailable:
87  throw new ServiceUnavailableException();
88  case HttpStatusCode.Gone:
89  errorMessage = errorMessage ?? new ErrorMessage
90  {
91  Message = "The requested resource could not be found!",
92  SeverApiVersion = null
93  };
94  goto case HttpStatusCode.Conflict;
95  case HttpStatusCode.NotFound:
96  // our fault somehow
97  errorMessage = errorMessage ?? new ErrorMessage
98  {
99  Message = "This is not a valid route!" + BadSpecExtension,
100  SeverApiVersion = null
101  };
102  goto case HttpStatusCode.Conflict;
103  case HttpStatusCode.Conflict:
104  throw new ConflictException(errorMessage ?? new ErrorMessage
105  {
106  Message = "An undescribed conflict occurred!" + BadSpecExtension,
107  SeverApiVersion = null
108  }, response.StatusCode);
109  case HttpStatusCode.NotImplemented:
110  // unprocessable entity
111  case (HttpStatusCode)422:
112  throw new MethodNotSupportedException();
113  case HttpStatusCode.InternalServerError:
114  // response json is html
115  throw new ServerErrorException(json);
116  case (HttpStatusCode)429:
117  // rate limited
118  response.Headers.TryGetValues("Retry-After", out var values);
119  throw new RateLimitException(values?.FirstOrDefault());
120  default:
121  throw new ApiConflictException(errorMessage, response.StatusCode);
122  }
123  }
124 
131  public ApiClient(IHttpClient httpClient, Uri url, ApiHeaders apiHeaders)
132  {
133  this.httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
134  Url = url ?? throw new ArgumentNullException(nameof(url));
135  headers = apiHeaders ?? throw new ArgumentNullException(nameof(apiHeaders));
136 
137  requestLoggers = new List<IRequestLogger>();
138  }
139 
141  public void Dispose() => httpClient.Dispose();
142 
153  async Task<TResult> RunRequest<TResult>(string route, object body, HttpMethod method, long? instanceId, CancellationToken cancellationToken)
154  {
155  if (route == null)
156  throw new ArgumentNullException(nameof(route));
157  if (method == null)
158  throw new ArgumentNullException(nameof(method));
159  if (body == null && (method == HttpMethod.Post || method == HttpMethod.Put))
160  throw new InvalidOperationException("Body cannot be null for POST or PUT!");
161 
162  HttpResponseMessage response;
163  var fullUri = new Uri(Url, route);
164  var serializerSettings = GetSerializerSettings();
165  using (var request = new HttpRequestMessage(method, fullUri))
166  {
167  if (body != null)
168  request.Content = new StringContent(JsonConvert.SerializeObject(body, serializerSettings), Encoding.UTF8, ApiHeaders.ApplicationJson);
169 
170  headers.SetRequestHeaders(request.Headers, instanceId);
171 
172  await Task.WhenAll(requestLoggers.Select(x => x.LogRequest(request, cancellationToken))).ConfigureAwait(false);
173 
174  response = await httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
175  }
176 
177  using (response)
178  {
179  await Task.WhenAll(requestLoggers.Select(x => x.LogResponse(response, cancellationToken))).ConfigureAwait(false);
180 
181  var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
182 
183  if (!response.IsSuccessStatusCode)
184  HandleBadResponse(response, json);
185 
186  if (String.IsNullOrWhiteSpace(json))
187  json = JsonConvert.SerializeObject(new object());
188 
189  try
190  {
191  return JsonConvert.DeserializeObject<TResult>(json, serializerSettings);
192  }
193  catch (JsonException)
194  {
195  throw new UnrecognizedResponseException(json, response.StatusCode);
196  }
197  }
198  }
199 
201  public Task<TResult> Create<TResult>(string route, CancellationToken cancellationToken) => RunRequest<TResult>(route, new object(), HttpMethod.Put, null, cancellationToken);
202 
204  public Task<TResult> Read<TResult>(string route, CancellationToken cancellationToken) => RunRequest<TResult>(route, null, HttpMethod.Get, null, cancellationToken);
205 
207  public Task<TResult> Update<TResult>(string route, CancellationToken cancellationToken) => RunRequest<TResult>(route, new object(), HttpMethod.Post, null, cancellationToken);
208 
210  public Task<TResult> Update<TBody, TResult>(string route, TBody body, CancellationToken cancellationToken) => RunRequest<TResult>(route, body, HttpMethod.Post, null, cancellationToken);
211 
213  public Task Update<TBody>(string route, TBody body, CancellationToken cancellationToken) => RunRequest<object>(route, body, HttpMethod.Post, null, cancellationToken);
214 
216  public Task<TResult> Create<TBody, TResult>(string route, TBody body, CancellationToken cancellationToken) => RunRequest<TResult>(route, body, HttpMethod.Put, null, cancellationToken);
217 
219  public Task Delete(string route, CancellationToken cancellationToken) => RunRequest<object>(route, null, HttpMethod.Delete, null, cancellationToken);
220 
222  public Task<TResult> Create<TBody, TResult>(string route, TBody body, long instanceId, CancellationToken cancellationToken) => RunRequest<TResult>(route, body, HttpMethod.Put, instanceId, cancellationToken);
223 
225  public Task<TResult> Read<TResult>(string route, long instanceId, CancellationToken cancellationToken) => RunRequest<TResult>(route, null, HttpMethod.Get, instanceId, cancellationToken);
226 
228  public Task<TResult> Update<TBody, TResult>(string route, TBody body, long instanceId, CancellationToken cancellationToken) => RunRequest<TResult>(route, body, HttpMethod.Post, instanceId, cancellationToken);
229 
231  public Task Delete(string route, long instanceId, CancellationToken cancellationToken) => RunRequest<object>(route, null, HttpMethod.Delete, instanceId, cancellationToken);
232 
234  public Task Delete<TBody>(string route, TBody body, long instanceId, CancellationToken cancellationToken) => RunRequest<object>(route, body, HttpMethod.Delete, instanceId, cancellationToken);
235 
237  public Task<TResult> Delete<TResult>(string route, long instanceId, CancellationToken cancellationToken) => RunRequest<TResult>(route, null, HttpMethod.Delete, instanceId, cancellationToken);
238 
240  public Task<TResult> Create<TResult>(string route, long instanceId, CancellationToken cancellationToken) => RunRequest<TResult>(route, new object(), HttpMethod.Put, instanceId, cancellationToken);
241 
243  public Task<TResult> Patch<TResult>(string route, long instanceId, CancellationToken cancellationToken) => RunRequest<TResult>(route, new object(), new HttpMethod("PATCH"), instanceId, cancellationToken);
244 
246  public void AddRequestLogger(IRequestLogger requestLogger) => requestLoggers.Add(requestLogger ?? throw new ArgumentNullException(nameof(requestLogger)));
247  }
248 }
Occurs when a response is received that did not deserialize to one of the expected Api...
+Go to the documentation of this file.
1 using Newtonsoft.Json;
2 using Newtonsoft.Json.Converters;
3 using Newtonsoft.Json.Serialization;
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Net;
8 using System.Net.Http;
9 using System.Text;
10 using System.Threading;
11 using System.Threading.Tasks;
12 using Tgstation.Server.Api;
14 
16 {
18  sealed class ApiClient : IApiClient
19  {
21  public Uri Url { get; }
22 
24  public ApiHeaders Headers
25  {
26  get => headers;
27  set => headers = value ?? throw new InvalidOperationException("Cannot set null headers!");
28  }
29 
31  public TimeSpan Timeout
32  {
33  get => httpClient.Timeout;
34  set => httpClient.Timeout = value;
35  }
36 
41 
45  readonly List<IRequestLogger> requestLoggers;
46 
51 
52  static JsonSerializerSettings GetSerializerSettings() => new JsonSerializerSettings
53  {
54  ContractResolver = new CamelCasePropertyNamesContractResolver(),
55  Converters = new[] { new VersionConverter() }
56  };
57 
58  static void HandleBadResponse(HttpResponseMessage response, string json)
59  {
60  ErrorMessage errorMessage = null;
61  try
62  {
63  // check if json serializes to an error message
64  errorMessage = JsonConvert.DeserializeObject<ErrorMessage>(json, GetSerializerSettings());
65  }
66  catch (JsonException) { }
67 
68  const string BadSpecExtension = " This is not part of TGS4 communication specification and should be reported if it was returned from a TGS4 server!";
69 
70 #pragma warning disable IDE0010 // Add missing cases
71  switch (response.StatusCode)
72 #pragma warning restore IDE0010 // Add missing cases
73  {
74  case HttpStatusCode.UpgradeRequired:
75  throw new ApiMismatchException(errorMessage ?? new ErrorMessage
76  {
77  Message = "API Mismatch but no current API version provided!" + BadSpecExtension,
78  SeverApiVersion = null
79  });
80  case HttpStatusCode.Unauthorized:
81  throw new UnauthorizedException();
82  case HttpStatusCode.RequestTimeout:
83  throw new RequestTimeoutException();
84  case HttpStatusCode.Forbidden:
86  case HttpStatusCode.ServiceUnavailable:
87  throw new ServiceUnavailableException();
88  case HttpStatusCode.Gone:
89  errorMessage = errorMessage ?? new ErrorMessage
90  {
91  Message = "The requested resource could not be found!",
92  SeverApiVersion = null
93  };
94  goto case HttpStatusCode.Conflict;
95  case HttpStatusCode.NotFound:
96  // our fault somehow
97  errorMessage = errorMessage ?? new ErrorMessage
98  {
99  Message = "This is not a valid route!" + BadSpecExtension,
100  SeverApiVersion = null
101  };
102  goto case HttpStatusCode.Conflict;
103  case HttpStatusCode.Conflict:
104  throw new ConflictException(errorMessage ?? new ErrorMessage
105  {
106  Message = "An undescribed conflict occurred!" + BadSpecExtension,
107  SeverApiVersion = null
108  }, response.StatusCode);
109  case HttpStatusCode.NotImplemented:
110  // unprocessable entity
111  case (HttpStatusCode)422:
112  throw new MethodNotSupportedException();
113  case HttpStatusCode.InternalServerError:
114  // response json is html
115  throw new ServerErrorException(json);
116  case (HttpStatusCode)429:
117  // rate limited
118  response.Headers.TryGetValues("Retry-After", out var values);
119  throw new RateLimitException(values?.FirstOrDefault());
120  default:
121  throw new ApiConflictException(errorMessage, response.StatusCode);
122  }
123  }
124 
131  public ApiClient(IHttpClient httpClient, Uri url, ApiHeaders apiHeaders)
132  {
133  this.httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient));
134  Url = url ?? throw new ArgumentNullException(nameof(url));
135  headers = apiHeaders ?? throw new ArgumentNullException(nameof(apiHeaders));
136 
137  requestLoggers = new List<IRequestLogger>();
138  }
139 
141  public void Dispose() => httpClient.Dispose();
142 
153  async Task<TResult> RunRequest<TResult>(string route, object body, HttpMethod method, long? instanceId, CancellationToken cancellationToken)
154  {
155  if (route == null)
156  throw new ArgumentNullException(nameof(route));
157  if (method == null)
158  throw new ArgumentNullException(nameof(method));
159  if (body == null && (method == HttpMethod.Post || method == HttpMethod.Put))
160  throw new InvalidOperationException("Body cannot be null for POST or PUT!");
161 
162  HttpResponseMessage response;
163  var fullUri = new Uri(Url, route);
164  var serializerSettings = GetSerializerSettings();
165  using (var request = new HttpRequestMessage(method, fullUri))
166  {
167  if (body != null)
168  request.Content = new StringContent(JsonConvert.SerializeObject(body, serializerSettings), Encoding.UTF8, ApiHeaders.ApplicationJson);
169 
170  headers.SetRequestHeaders(request.Headers, instanceId);
171 
172  await Task.WhenAll(requestLoggers.Select(x => x.LogRequest(request, cancellationToken))).ConfigureAwait(false);
173 
174  response = await httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false);
175  }
176 
177  using (response)
178  {
179  await Task.WhenAll(requestLoggers.Select(x => x.LogResponse(response, cancellationToken))).ConfigureAwait(false);
180 
181  var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
182 
183  if (!response.IsSuccessStatusCode)
184  HandleBadResponse(response, json);
185 
186  if (String.IsNullOrWhiteSpace(json))
187  json = JsonConvert.SerializeObject(new object());
188 
189  try
190  {
191  return JsonConvert.DeserializeObject<TResult>(json, serializerSettings);
192  }
193  catch (JsonException)
194  {
195  throw new UnrecognizedResponseException(json, response.StatusCode);
196  }
197  }
198  }
199 
201  public Task<TResult> Create<TResult>(string route, CancellationToken cancellationToken) => RunRequest<TResult>(route, new object(), HttpMethod.Put, null, cancellationToken);
202 
204  public Task<TResult> Read<TResult>(string route, CancellationToken cancellationToken) => RunRequest<TResult>(route, null, HttpMethod.Get, null, cancellationToken);
205 
207  public Task<TResult> Update<TResult>(string route, CancellationToken cancellationToken) => RunRequest<TResult>(route, new object(), HttpMethod.Post, null, cancellationToken);
208 
210  public Task<TResult> Update<TBody, TResult>(string route, TBody body, CancellationToken cancellationToken) => RunRequest<TResult>(route, body, HttpMethod.Post, null, cancellationToken);
211 
213  public Task Update<TBody>(string route, TBody body, CancellationToken cancellationToken) => RunRequest<object>(route, body, HttpMethod.Post, null, cancellationToken);
214 
216  public Task<TResult> Create<TBody, TResult>(string route, TBody body, CancellationToken cancellationToken) => RunRequest<TResult>(route, body, HttpMethod.Put, null, cancellationToken);
217 
219  public Task Delete(string route, CancellationToken cancellationToken) => RunRequest<object>(route, null, HttpMethod.Delete, null, cancellationToken);
220 
222  public Task<TResult> Create<TBody, TResult>(string route, TBody body, long instanceId, CancellationToken cancellationToken) => RunRequest<TResult>(route, body, HttpMethod.Put, instanceId, cancellationToken);
223 
225  public Task<TResult> Read<TResult>(string route, long instanceId, CancellationToken cancellationToken) => RunRequest<TResult>(route, null, HttpMethod.Get, instanceId, cancellationToken);
226 
228  public Task<TResult> Update<TBody, TResult>(string route, TBody body, long instanceId, CancellationToken cancellationToken) => RunRequest<TResult>(route, body, HttpMethod.Post, instanceId, cancellationToken);
229 
231  public Task Delete(string route, long instanceId, CancellationToken cancellationToken) => RunRequest<object>(route, null, HttpMethod.Delete, instanceId, cancellationToken);
232 
234  public Task Delete<TBody>(string route, TBody body, long instanceId, CancellationToken cancellationToken) => RunRequest<object>(route, body, HttpMethod.Delete, instanceId, cancellationToken);
235 
237  public Task<TResult> Delete<TResult>(string route, long instanceId, CancellationToken cancellationToken) => RunRequest<TResult>(route, null, HttpMethod.Delete, instanceId, cancellationToken);
238 
240  public Task<TResult> Create<TResult>(string route, long instanceId, CancellationToken cancellationToken) => RunRequest<TResult>(route, new object(), HttpMethod.Put, instanceId, cancellationToken);
241 
243  public Task<TResult> Patch<TResult>(string route, long instanceId, CancellationToken cancellationToken) => RunRequest<TResult>(route, new object(), new HttpMethod("PATCH"), instanceId, cancellationToken);
244 
246  public void AddRequestLogger(IRequestLogger requestLogger) => requestLoggers.Add(requestLogger ?? throw new ArgumentNullException(nameof(requestLogger)));
247  }
248 }
+
async Task< TResult > RunRequest< TResult >(string route, object body, HttpMethod method, long? instanceId, CancellationToken cancellationToken)
Main request method
Definition: ApiClient.cs:153
+
TimeSpan Timeout
The request timeout
Definition: IHttpClient.cs:16
+
Occurs when a response is received that did not deserialize to one of the expected Api....
- -
const string ApplicationJson
TODO: Remove this when https://github.com/dotnet/corefx/pull/26701 makes it into the sdk ...
Definition: ApiHeaders.cs:21
-
Occurs when a GitHub rate limit occurs
- -
Occurs when an error occurs in the server
-
void SetRequestHeaders(HttpRequestHeaders headers, long?instanceId=null)
Set HttpRequestHeaders using the ApiHeaders. This initially clears headers
Definition: ApiHeaders.cs:229
-
Occurs when the server returns an unknown response
-
ApiHeaders headers
Backing field for Headers
Definition: ApiClient.cs:50
+
Task< TResult > Update< TResult >(string route, CancellationToken cancellationToken)
Run an HTTP POST request
+ +
const string ApplicationJson
TODO: Remove this when https://github.com/dotnet/corefx/pull/26701 makes it into the sdk
Definition: ApiHeaders.cs:21
+
Occurs when a GitHub rate limit occurs
+
Occurs when an error occurs in the server
+
Task< TResult > Read< TResult >(string route, CancellationToken cancellationToken)
Run an HTTP GET request
+
Occurs when the server returns an unknown response
+
Task< TResult > Delete< TResult >(string route, long instanceId, CancellationToken cancellationToken)
Run an HTTP DELETE request
+
ApiHeaders headers
Backing field for Headers
Definition: ApiClient.cs:50
-
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
-
Occurs when the client makes a request while the server is starting or stopping
-
For sending HTTP requests
Definition: IHttpClient.cs:11
-
readonly List< IRequestLogger > requestLoggers
The IRequestLoggers used by the ApiClient
Definition: ApiClient.cs:45
+
Task< TResult > Update< TBody, TResult >(string route, TBody body, CancellationToken cancellationToken)
Run an HTTP POST request
+
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
+
Task< TResult > Patch< TResult >(string route, long instanceId, CancellationToken cancellationToken)
Run an HTTP PATCH request
+
Task< TResult > Create< TBody, TResult >(string route, TBody body, CancellationToken cancellationToken)
Run an HTTP PUT request
+
Occurs when the client makes a request while the server is starting or stopping
+
void AddRequestLogger(IRequestLogger requestLogger)
Adds a requestLogger to the request pipeline
+
For sending HTTP requests
Definition: IHttpClient.cs:11
+ +
readonly List< IRequestLogger > requestLoggers
The IRequestLoggers used by the ApiClient
Definition: ApiClient.cs:45
+
Task Update< TBody >(string route, TBody body, CancellationToken cancellationToken)
Run an HTTP POST request
static void HandleBadResponse(HttpResponseMessage response, string json)
Definition: ApiClient.cs:58
-
Occurs when the client provides invalid credentials
-
ApiClient(IHttpClient httpClient, Uri url, ApiHeaders apiHeaders)
Construct an ApiClient
Definition: ApiClient.cs:131
-
Occurs when the API version of the client is not compatible with the server&#39;s
-
Occurs when the client performs an action that would result in data conflict
-
Occurs when the client attempts to perform an action they do not have the rights for ...
-
For logging HTTP requests and responses
-
Occurs when the client provides invalid credentials
- -
Web interface for the API
Definition: IApiClient.cs:11
-
Occurs when the client tries to use a currently unsupported API
-
readonly IHttpClient httpClient
The HttpClient for the ApiClient
Definition: ApiClient.cs:40
-
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- +
Occurs when the client provides invalid credentials
+
ApiClient(IHttpClient httpClient, Uri url, ApiHeaders apiHeaders)
Construct an ApiClient
Definition: ApiClient.cs:131
+
Task Delete(string route, CancellationToken cancellationToken)
Run an HTTP DELETE request
+
Occurs when the API version of the client is not compatible with the server's
+ +
void SetRequestHeaders(HttpRequestHeaders headers, long? instanceId=null)
Set HttpRequestHeaders using the ApiHeaders. This initially clears headers
Definition: ApiHeaders.cs:232
+
Occurs when the client performs an action that would result in data conflict
+
Occurs when the client attempts to perform an action they do not have the rights for
+ +
Task Delete< TBody >(string route, TBody body, long instanceId, CancellationToken cancellationToken)
Run an HTTP DELETE request
+
For logging HTTP requests and responses
+
Occurs when the client provides invalid credentials
+ +
Task< TResult > Create< TResult >(string route, CancellationToken cancellationToken)
Run an HTTP PUT request
+
Web interface for the API
Definition: IApiClient.cs:11
+
Occurs when the client tries to use a currently unsupported API
+
readonly IHttpClient httpClient
The HttpClient for the ApiClient
Definition: ApiClient.cs:40
+
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+
Task< HttpResponseMessage > SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
Send an HTTP request
+ +
static JsonSerializerSettings GetSerializerSettings()
diff --git a/_api_client_factory_8cs.html b/_api_client_factory_8cs.html index 63656cab57..0bc740480d 100644 --- a/_api_client_factory_8cs.html +++ b/_api_client_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ApiClientFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -113,7 +96,7 @@ Namespaces diff --git a/_api_client_factory_8cs_source.html b/_api_client_factory_8cs_source.html index 55aacd880e..59f01de3e2 100644 --- a/_api_client_factory_8cs_source.html +++ b/_api_client_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ApiClientFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ApiClientFactory.cs
-Go to the documentation of this file.
1 using System;
2 using Tgstation.Server.Api;
3 
4 namespace Tgstation.Server.Client
5 {
8  {
10  public IApiClient CreateApiClient(Uri url, ApiHeaders apiHeaders) => new ApiClient(new HttpClient(), url, apiHeaders);
11  }
12 }
+Go to the documentation of this file.
1 using System;
2 using Tgstation.Server.Api;
3 
5 {
8  {
10  public IApiClient CreateApiClient(Uri url, ApiHeaders apiHeaders) => new ApiClient(new HttpClient(), url, apiHeaders);
11  }
12 }
- - -
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
+ +
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
+
IApiClient CreateApiClient(Uri url, ApiHeaders apiHeaders)
Create an IApiClient
- + -
Web interface for the API
Definition: IApiClient.cs:11
- - +
Web interface for the API
Definition: IApiClient.cs:11
+ +
diff --git a/_api_conflict_exception_8cs.html b/_api_conflict_exception_8cs.html index 372b2cb866..1ea9d42380 100644 --- a/_api_conflict_exception_8cs.html +++ b/_api_conflict_exception_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ApiConflictException.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_api_conflict_exception_8cs_source.html b/_api_conflict_exception_8cs_source.html index 7dc710f9f7..498e2a5de2 100644 --- a/_api_conflict_exception_8cs_source.html +++ b/_api_conflict_exception_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ApiConflictException.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ApiConflictException.cs
-Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
5 namespace Tgstation.Server.Client
6 {
10  public sealed class ApiConflictException : ClientException
11  {
17  public ApiConflictException(ErrorMessage errorMessage, HttpStatusCode statusCode) : base(errorMessage ?? new ErrorMessage
18  {
19  Message = "An unknown API error occurred!",
20  SeverApiVersion = null
21  }, statusCode)
22  { }
23 
27  public ApiConflictException() { }
28 
33  public ApiConflictException(string message) : base(message) { }
34 
40  public ApiConflictException(string message, Exception innerException) : base(message, innerException) { }
41  }
42 }
- -
ApiConflictException(ErrorMessage errorMessage, HttpStatusCode statusCode)
Construct an ApiConflictException using an errorMessage
- -
Occurs when the server returns an unknown response
-
ApiConflictException(string message)
Construct an ApiConflictException with a message
+Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
6 {
10  public sealed class ApiConflictException : ClientException
11  {
17  public ApiConflictException(ErrorMessage errorMessage, HttpStatusCode statusCode) : base(errorMessage ?? new ErrorMessage
18  {
19  Message = "An unknown API error occurred!",
20  SeverApiVersion = null
21  }, statusCode)
22  { }
23 
27  public ApiConflictException() { }
28 
33  public ApiConflictException(string message) : base(message) { }
34 
40  public ApiConflictException(string message, Exception innerException) : base(message, innerException) { }
41  }
42 }
+ +
Occurs when the server returns an unknown response
+
ApiConflictException(string message)
Construct an ApiConflictException with a message
-
ApiConflictException(string message, Exception innerException)
Construct an ApiConflictException with a message and innerException
- -
ApiConflictException()
Construct an ApiConflictException
-
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- -
Exceptions thrown by IServerClients
+
ApiConflictException(string message, Exception innerException)
Construct an ApiConflictException with a message and innerException
+ +
ApiConflictException()
Construct an ApiConflictException
+
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+ +
Exceptions thrown by IServerClients
diff --git a/_api_controller_8cs.html b/_api_controller_8cs.html index 5067a42b2b..9802154efb 100644 --- a/_api_controller_8cs.html +++ b/_api_controller_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/ApiController.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Controllers
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_api_controller_8cs_source.html b/_api_controller_8cs_source.html index 10b6b7345c..34d5e2374f 100644 --- a/_api_controller_8cs_source.html +++ b/_api_controller_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/ApiController.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ApiController.cs
-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 
15 namespace Tgstation.Server.Host.Controllers
16 {
20  [Produces(ApiHeaders.ApplicationJson)]
21  [Consumes(ApiHeaders.ApplicationJson)]
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).ToList();
134 
135  // HACK
136  // do some fuckery to remove RequiredAttribute errors
137  for (var I = 0; I < errorMessages.Count; ++I)
138  {
139  var message = errorMessages[I];
140  if (message.StartsWith("The ", StringComparison.Ordinal) && message.EndsWith(" field is required.", StringComparison.Ordinal))
141  {
142  errorMessages.RemoveAt(I);
143  --I;
144  }
145  }
146 
147  if (errorMessages.Count > 0)
148  {
149  await BadRequest(new ErrorMessage { Message = String.Join(Environment.NewLine, errorMessages) }).ExecuteResultAsync(context).ConfigureAwait(false);
150  return;
151  }
152  }
153 
154  if (ApiHeaders != null)
155  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);
156 
157  try
158  {
159  await base.OnActionExecutionAsync(context, next).ConfigureAwait(false);
160  }
161  catch (OperationCanceledException e)
162  {
163  Logger.LogDebug("Request cancelled! Exception: {0}", e);
164  throw;
165  }
166  }
167  #pragma warning restore CA1506
168  }
169 }
- - -
ApiController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ILogger logger, bool requireInstance, bool requireHeaders)
Construct an ApiController
+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  public abstract class ApiController : Controller
22  {
26  protected ApiHeaders ApiHeaders { get; private set; }
27 
31  protected IDatabaseContext DatabaseContext { get; }
32 
37 
41  protected ILogger Logger { get; }
42 
46  protected Models.Instance Instance { get; }
47 
51  readonly bool requireInstance;
52 
56  readonly bool requireHeaders;
57 
66  public ApiController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ILogger logger, bool requireInstance, bool requireHeaders)
67  {
68  DatabaseContext = databaseContext ?? throw new ArgumentNullException(nameof(databaseContext));
69  if (authenticationContextFactory == null)
70  throw new ArgumentNullException(nameof(authenticationContextFactory));
71  Logger = logger ?? throw new ArgumentNullException(nameof(logger));
72  AuthenticationContext = authenticationContextFactory.CurrentAuthenticationContext;
74  this.requireInstance = requireInstance;
75  this.requireHeaders = requireHeaders;
76  }
77 
79  #pragma warning disable CA1506 // TODO: Decomplexify
80  public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
81  {
82  // ALL valid token and login requests that match a route go through this function
83  // 404 is returned before
84  if (AuthenticationContext != null && AuthenticationContext.User == null)
85  {
86  // valid token, expired password
87  await Unauthorized().ExecuteResultAsync(context).ConfigureAwait(false);
88  return;
89  }
90 
91  // validate the headers
92  try
93  {
94  ApiHeaders = new ApiHeaders(Request.GetTypedHeaders());
95 
96  if (!ApiHeaders.Compatible())
97  {
98  await StatusCode((int)HttpStatusCode.UpgradeRequired, new ErrorMessage
99  {
100  Message = "Provided API version is incompatible with server version!"
101  }).ExecuteResultAsync(context).ConfigureAwait(false);
102  return;
103  }
104 
105  if (requireInstance)
106  {
107  if (!ApiHeaders.InstanceId.HasValue)
108  {
109  await BadRequest(new ErrorMessage { Message = "Missing Instance header!" }).ExecuteResultAsync(context).ConfigureAwait(false);
110  return;
111  }
112 
114  {
115  // accessing an instance they don't have access to or one that's disabled
116  await Forbid().ExecuteResultAsync(context).ConfigureAwait(false);
117  return;
118  }
119  }
120  }
121  catch (InvalidOperationException e)
122  {
123  if (requireHeaders)
124  {
125  await BadRequest(new ErrorMessage { Message = e.Message }).ExecuteResultAsync(context).ConfigureAwait(false);
126  return;
127  }
128  }
129 
130  if (ModelState?.IsValid == false)
131  {
132  var errorMessages = ModelState.SelectMany(x => x.Value.Errors).Select(x => x.ErrorMessage).ToList();
133 
134  // HACK
135  // do some fuckery to remove RequiredAttribute errors
136  for (var I = 0; I < errorMessages.Count; ++I)
137  {
138  var message = errorMessages[I];
139  if (message.StartsWith("The ", StringComparison.Ordinal) && message.EndsWith(" field is required.", StringComparison.Ordinal))
140  {
141  errorMessages.RemoveAt(I);
142  --I;
143  }
144  }
145 
146  if (errorMessages.Count > 0)
147  {
148  await BadRequest(new ErrorMessage { Message = String.Join(Environment.NewLine, errorMessages) }).ExecuteResultAsync(context).ConfigureAwait(false);
149  return;
150  }
151  }
152 
153  if (ApiHeaders != null)
154  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);
155 
156  try
157  {
158  await base.OnActionExecutionAsync(context, next).ConfigureAwait(false);
159  }
160  catch (OperationCanceledException e)
161  {
162  Logger.LogDebug("Request cancelled! Exception: {0}", e);
163  throw;
164  }
165  }
166  #pragma warning restore CA1506
167  }
168 }
+ + +
ApiController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ILogger logger, bool requireInstance, bool requireHeaders)
Construct an ApiController
+ -
override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
- +
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:21
- -
Version ApiVersion
The client&#39;s API version
Definition: ApiHeaders.cs:76
-
bool Compatible()
Checks if the ApiVersion is compatible with Version
-
Represents the currently authenticated Api.Models.User
+
const string ApplicationJson
TODO: Remove this when https://github.com/dotnet/corefx/pull/26701 makes it into the sdk
Definition: ApiHeaders.cs:21
+
Version ApiVersion
The client's API version
Definition: ApiHeaders.cs:76
+
bool Compatible()
Checks if the ApiVersion is compatible with Version
+
Represents the currently authenticated Api.Models.User
-
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
+
ApiHeaders ApiHeaders
The ApiHeaders for the operation
+
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
-
string Message
A human readable description of the error
Definition: ErrorMessage.cs:13
+
string Message
A human readable description of the error
Definition: ErrorMessage.cs:13
- + -
string RawUserAgent
The client&#39;s raw user agent
Definition: ApiHeaders.cs:71
+
string RawUserAgent
The client's raw user agent
Definition: ApiHeaders.cs:71
-
readonly bool requireHeaders
If ApiHeaders are required
-
long Id
The ID of the User
Definition: User.cs:15
-
readonly bool requireInstance
If IAuthenticationContext.InstanceUser permissions are required to access the ApiController ...
-
Metadata about a server instance
Definition: Instance.cs:9
- -
IAuthenticationContext CurrentAuthenticationContext
The IAuthenticationContext the IAuthenticationContextFactory created
-
long InstanceId
The Models.Instance.Id being accessed
Definition: ApiHeaders.cs:61
-
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+
readonly bool requireHeaders
If ApiHeaders are required
+
long? InstanceId
The Models.Instance.Id being accessed
Definition: ApiHeaders.cs:61
+
long Id
The ID of the User
Definition: User.cs:15
+
ILogger Logger
The ILogger for the ApiController
+
readonly bool requireInstance
If IAuthenticationContext.InstanceUser permissions are required to access the ApiController
+
Metadata about a server instance
Definition: Instance.cs:9
+ +
IAuthenticationContext CurrentAuthenticationContext
The IAuthenticationContext the IAuthenticationContextFactory created
+
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- - + +
diff --git a/_api_headers_8cs.html b/_api_headers_8cs.html index 2214dc1cda..a425a072b7 100644 --- a/_api_headers_8cs.html +++ b/_api_headers_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/ApiHeaders.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_api_headers_8cs_source.html b/_api_headers_8cs_source.html index 1fb946fa04..e70f381181 100644 --- a/_api_headers_8cs_source.html +++ b/_api_headers_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/ApiHeaders.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ApiHeaders.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Http.Headers;
2 using Microsoft.Extensions.Primitives;
3 using Microsoft.Net.Http.Headers;
4 using System;
5 using System.Collections.Generic;
6 using System.Globalization;
7 using System.Linq;
8 using System.Net.Http.Headers;
9 using System.Reflection;
10 
11 namespace Tgstation.Server.Api
12 {
16  public sealed class ApiHeaders
17  {
21  public const string ApplicationJson = "application/json";
22 
26  const string ApiVersionHeader = "Api";
27 
31  const string UsernameHeader = "Username";
32 
36  const string InstanceIdHeader = "Instance";
37 
41  const string JwtAuthenticationScheme = "Bearer";
42 
46  const string PasswordAuthenticationScheme = "Password";
47 
51  static readonly AssemblyName AssemblyName = Assembly.GetExecutingAssembly().GetName();
52 
56  public static Version Version => AssemblyName.Version;
57 
61  public long? InstanceId { get; set; }
62 
66  public ProductHeaderValue UserAgent => ProductInfoHeaderValue.TryParse(RawUserAgent, out var userAgent) ? userAgent.Product : null;
67 
71  public string RawUserAgent { get; }
72 
76  public Version ApiVersion { get; }
77 
81  public string Token { get; }
82 
86  public string Username { get; }
87 
91  public string Password { get; }
92 
96  public bool IsTokenAuthentication => Token != null;
97 
103  public static bool CheckCompatibility(Version otherVersion) => !(Version.Major != otherVersion.Major || Version.Minor > otherVersion.Minor);
104 
110  public ApiHeaders(ProductHeaderValue userAgent, string token) : this(userAgent, token, null, null)
111  {
112  if (userAgent == null)
113  throw new ArgumentNullException(nameof(userAgent));
114  if (token == null)
115  throw new ArgumentNullException(nameof(token));
116  }
117 
124  public ApiHeaders(ProductHeaderValue userAgent, string username, string password) : this(userAgent, null, username, password)
125  {
126  if (userAgent == null)
127  throw new ArgumentNullException(nameof(userAgent));
128  if (username == null)
129  throw new ArgumentNullException(nameof(username));
130  if (password == null)
131  throw new ArgumentNullException(nameof(password));
132  }
133 
138  public ApiHeaders(RequestHeaders requestHeaders)
139  {
140  var jsonAccept = new Microsoft.Net.Http.Headers.MediaTypeHeaderValue(ApplicationJson);
141  if (!requestHeaders.Accept.Any(x => x.MediaType == jsonAccept.MediaType))
142  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Client does not accept {0}!", ApplicationJson));
143 
144  if (!requestHeaders.Headers.TryGetValue(HeaderNames.UserAgent, out var userAgentValues) || userAgentValues.Count == 0)
145  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Missing {0} headers!", HeaderNames.UserAgent));
146 
147  RawUserAgent = userAgentValues.First();
148  if (String.IsNullOrWhiteSpace(RawUserAgent))
149  throw new InvalidOperationException("Malformed client User-Agent!");
150 
151  // make sure the api header matches ours
152  if (!requestHeaders.Headers.TryGetValue(ApiVersionHeader, out var apiUserAgentHeaderValues) || !ProductInfoHeaderValue.TryParse(apiUserAgentHeaderValues.FirstOrDefault(), out var apiUserAgent) || apiUserAgent.Product.Name != AssemblyName.Name)
153  throw new InvalidOperationException("Missing API version!");
154 
155  if (!Version.TryParse(apiUserAgent.Product.Version, out var apiVersion))
156  throw new InvalidOperationException("Malformed API version!");
157 
158  ApiVersion = apiVersion;
159 
160  if (!requestHeaders.Headers.TryGetValue(HeaderNames.Authorization, out StringValues authorization))
161  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Missing {0} header!", HeaderNames.Authorization));
162  var auth = authorization.First();
163  var splits = new List<string>(auth.Split(' '));
164  var scheme = splits.First();
165  if (String.IsNullOrWhiteSpace(scheme))
166  throw new InvalidOperationException("Missing authentication scheme!");
167 
168  splits.RemoveAt(0);
169  var parameter = String.Concat(splits);
170  if (String.IsNullOrEmpty(parameter))
171  throw new InvalidOperationException("Missing authentication parameter!");
172 
173  if (requestHeaders.Headers.TryGetValue(InstanceIdHeader, out var instanceIdValues))
174  {
175  var instanceIdString = instanceIdValues.FirstOrDefault();
176  if (instanceIdString != default && Int64.TryParse(instanceIdString, out var instanceId))
177  InstanceId = instanceId;
178  }
179 
180  switch (scheme)
181  {
182  case JwtAuthenticationScheme:
183  Token = parameter;
184  break;
185  case PasswordAuthenticationScheme:
186  Password = parameter;
187  var fail = !requestHeaders.Headers.TryGetValue(UsernameHeader, out var values);
188  if (!fail)
189  {
190  Username = values.FirstOrDefault();
191  fail = String.IsNullOrWhiteSpace(Username);
192  }
193 
194  if (fail)
195  throw new InvalidOperationException("Missing Username header!");
196  break;
197  default:
198  throw new InvalidOperationException("Invalid authentication scheme!");
199  }
200  }
201 
209  ApiHeaders(ProductHeaderValue userAgent, string token, string username, string password)
210  {
211  RawUserAgent = userAgent?.ToString();
212  Token = token;
213  Username = username;
214  Password = password;
215  ApiVersion = Version;
216  }
217 
222  public bool Compatible() => CheckCompatibility(ApiVersion);
223 
229  public void SetRequestHeaders(HttpRequestHeaders headers, long? instanceId = null)
230  {
231  if (headers == null)
232  throw new ArgumentNullException(nameof(headers));
233  if (instanceId.HasValue && InstanceId.HasValue && instanceId != InstanceId)
234  throw new InvalidOperationException("Specified instance ID in constructor and SetRequestHeaders!");
235 
236  headers.Clear();
237  headers.Accept.Add(new MediaTypeWithQualityHeaderValue(ApplicationJson));
238  if (IsTokenAuthentication)
239  headers.Authorization = new AuthenticationHeaderValue(JwtAuthenticationScheme, Token);
240  else
241  {
242  headers.Authorization = new AuthenticationHeaderValue(PasswordAuthenticationScheme, Password);
243  headers.Add(UsernameHeader, Username);
244  }
245 
246  headers.UserAgent.Add(new ProductInfoHeaderValue(UserAgent));
247  headers.Add(ApiVersionHeader, new ProductHeaderValue(AssemblyName.Name, ApiVersion.ToString()).ToString());
248  instanceId = instanceId ?? InstanceId;
249  if (instanceId.HasValue)
250  headers.Add(InstanceIdHeader, instanceId.ToString());
251  }
252  }
253 }
-
void SetRequestHeaders(HttpRequestHeaders headers, long?instanceId=null)
Set HttpRequestHeaders using the ApiHeaders. This initially clears headers
Definition: ApiHeaders.cs:229
-
ApiHeaders(ProductHeaderValue userAgent, string username, string password)
Construct ApiHeaders for password authentication
Definition: ApiHeaders.cs:124
-
ApiHeaders(ProductHeaderValue userAgent, string token)
Construct ApiHeaders for JWT authentication
Definition: ApiHeaders.cs:110
-
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
-
ApiHeaders(ProductHeaderValue userAgent, string token, string username, string password)
Construct ApiHeaders
Definition: ApiHeaders.cs:209
-
ApiHeaders(RequestHeaders requestHeaders)
Construct and validates ApiHeaders from a set of requestHeaders
Definition: ApiHeaders.cs:138
-
static Version Version
Get the version of the Api the caller is using
Definition: ApiHeaders.cs:56
- +Go to the documentation of this file.
1 using Microsoft.AspNetCore.Http.Headers;
2 using Microsoft.Extensions.Primitives;
3 using Microsoft.Net.Http.Headers;
4 using System;
5 using System.Collections.Generic;
6 using System.Globalization;
7 using System.Linq;
8 using System.Net.Http.Headers;
9 using System.Reflection;
10 
12 {
16  public sealed class ApiHeaders
17  {
21  public const string ApplicationJson = "application/json";
22 
26  const string ApiVersionHeader = "Api";
27 
31  const string UsernameHeader = "Username";
32 
36  const string InstanceIdHeader = "Instance";
37 
41  const string JwtAuthenticationScheme = "Bearer";
42 
46  const string PasswordAuthenticationScheme = "Password";
47 
51  static readonly AssemblyName AssemblyName = Assembly.GetExecutingAssembly().GetName();
52 
56  public static Version Version => AssemblyName.Version;
57 
61  public long? InstanceId { get; set; }
62 
66  public ProductHeaderValue UserAgent => ProductInfoHeaderValue.TryParse(RawUserAgent, out var userAgent) ? userAgent.Product : null;
67 
71  public string RawUserAgent { get; }
72 
76  public Version ApiVersion { get; }
77 
81  public string Token { get; }
82 
86  public string Username { get; }
87 
91  public string Password { get; }
92 
96  public bool IsTokenAuthentication => Token != null;
97 
103  public static bool CheckCompatibility(Version otherVersion) => !(Version.Major != (otherVersion?.Major ?? throw new ArgumentNullException(nameof(otherVersion))) || Version.Minor > otherVersion.Minor);
104 
110  public ApiHeaders(ProductHeaderValue userAgent, string token) : this(userAgent, token, null, null)
111  {
112  if (userAgent == null)
113  throw new ArgumentNullException(nameof(userAgent));
114  if (token == null)
115  throw new ArgumentNullException(nameof(token));
116  }
117 
124  public ApiHeaders(ProductHeaderValue userAgent, string username, string password) : this(userAgent, null, username, password)
125  {
126  if (userAgent == null)
127  throw new ArgumentNullException(nameof(userAgent));
128  if (username == null)
129  throw new ArgumentNullException(nameof(username));
130  if (password == null)
131  throw new ArgumentNullException(nameof(password));
132  }
133 
138  public ApiHeaders(RequestHeaders requestHeaders)
139  {
140  if (requestHeaders == null)
141  throw new ArgumentNullException(nameof(requestHeaders));
142 
143  var jsonAccept = new Microsoft.Net.Http.Headers.MediaTypeHeaderValue(ApplicationJson);
144  if (!requestHeaders.Accept.Any(x => x.MediaType == jsonAccept.MediaType))
145  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Client does not accept {0}!", ApplicationJson));
146 
147  if (!requestHeaders.Headers.TryGetValue(HeaderNames.UserAgent, out var userAgentValues) || userAgentValues.Count == 0)
148  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Missing {0} headers!", HeaderNames.UserAgent));
149 
150  RawUserAgent = userAgentValues.First();
151  if (String.IsNullOrWhiteSpace(RawUserAgent))
152  throw new InvalidOperationException("Malformed client User-Agent!");
153 
154  // make sure the api header matches ours
155  if (!requestHeaders.Headers.TryGetValue(ApiVersionHeader, out var apiUserAgentHeaderValues) || !ProductInfoHeaderValue.TryParse(apiUserAgentHeaderValues.FirstOrDefault(), out var apiUserAgent) || apiUserAgent.Product.Name != AssemblyName.Name)
156  throw new InvalidOperationException("Missing API version!");
157 
158  if (!Version.TryParse(apiUserAgent.Product.Version, out var apiVersion))
159  throw new InvalidOperationException("Malformed API version!");
160 
161  ApiVersion = apiVersion;
162 
163  if (!requestHeaders.Headers.TryGetValue(HeaderNames.Authorization, out StringValues authorization))
164  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Missing {0} header!", HeaderNames.Authorization));
165  var auth = authorization.First();
166  var splits = new List<string>(auth.Split(' '));
167  var scheme = splits.First();
168  if (String.IsNullOrWhiteSpace(scheme))
169  throw new InvalidOperationException("Missing authentication scheme!");
170 
171  splits.RemoveAt(0);
172  var parameter = String.Concat(splits);
173  if (String.IsNullOrEmpty(parameter))
174  throw new InvalidOperationException("Missing authentication parameter!");
175 
176  if (requestHeaders.Headers.TryGetValue(InstanceIdHeader, out var instanceIdValues))
177  {
178  var instanceIdString = instanceIdValues.FirstOrDefault();
179  if (instanceIdString != default && Int64.TryParse(instanceIdString, out var instanceId))
180  InstanceId = instanceId;
181  }
182 
183  switch (scheme)
184  {
186  Token = parameter;
187  break;
189  Password = parameter;
190  var fail = !requestHeaders.Headers.TryGetValue(UsernameHeader, out var values);
191  if (!fail)
192  {
193  Username = values.FirstOrDefault();
194  fail = String.IsNullOrWhiteSpace(Username);
195  }
196 
197  if (fail)
198  throw new InvalidOperationException("Missing Username header!");
199  break;
200  default:
201  throw new InvalidOperationException("Invalid authentication scheme!");
202  }
203  }
204 
212  ApiHeaders(ProductHeaderValue userAgent, string token, string username, string password)
213  {
214  RawUserAgent = userAgent?.ToString();
215  Token = token;
216  Username = username;
217  Password = password;
219  }
220 
225  public bool Compatible() => CheckCompatibility(ApiVersion);
226 
232  public void SetRequestHeaders(HttpRequestHeaders headers, long? instanceId = null)
233  {
234  if (headers == null)
235  throw new ArgumentNullException(nameof(headers));
236  if (instanceId.HasValue && InstanceId.HasValue && instanceId != InstanceId)
237  throw new InvalidOperationException("Specified instance ID in constructor and SetRequestHeaders!");
238 
239  headers.Clear();
240  headers.Accept.Add(new MediaTypeWithQualityHeaderValue(ApplicationJson));
242  headers.Authorization = new AuthenticationHeaderValue(JwtAuthenticationScheme, Token);
243  else
244  {
245  headers.Authorization = new AuthenticationHeaderValue(PasswordAuthenticationScheme, Password);
246  headers.Add(UsernameHeader, Username);
247  }
248 
249  headers.UserAgent.Add(new ProductInfoHeaderValue(UserAgent));
250  headers.Add(ApiVersionHeader, new ProductHeaderValue(AssemblyName.Name, ApiVersion.ToString()).ToString());
251  instanceId = instanceId ?? InstanceId;
252  if (instanceId.HasValue)
253  headers.Add(InstanceIdHeader, instanceId.ToString());
254  }
255  }
256 }
static readonly AssemblyName AssemblyName
The current System.Reflection.AssemblyName
Definition: ApiHeaders.cs:51
+ +
const string ApplicationJson
TODO: Remove this when https://github.com/dotnet/corefx/pull/26701 makes it into the sdk
Definition: ApiHeaders.cs:21
+
Version ApiVersion
The client's API version
Definition: ApiHeaders.cs:76
+
bool Compatible()
Checks if the ApiVersion is compatible with Version
+
const string PasswordAuthenticationScheme
The password authentication header scheme
Definition: ApiHeaders.cs:46
+
string Username
The client's username
Definition: ApiHeaders.cs:86
+
ApiHeaders(ProductHeaderValue userAgent, string username, string password)
Construct ApiHeaders for password authentication
Definition: ApiHeaders.cs:124
+
ApiHeaders(ProductHeaderValue userAgent, string token)
Construct ApiHeaders for JWT authentication
Definition: ApiHeaders.cs:110
+
ProductHeaderValue UserAgent
The client's user agent as a ProductHeaderValue if valid
Definition: ApiHeaders.cs:66
+
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
+
ApiHeaders(ProductHeaderValue userAgent, string token, string username, string password)
Construct ApiHeaders
Definition: ApiHeaders.cs:212
+
string Password
The client's password
Definition: ApiHeaders.cs:91
+
bool IsTokenAuthentication
If the header uses password or JWT authentication
Definition: ApiHeaders.cs:96
+
string RawUserAgent
The client's raw user agent
Definition: ApiHeaders.cs:71
+
ApiHeaders(RequestHeaders requestHeaders)
Construct and validates ApiHeaders from a set of requestHeaders
Definition: ApiHeaders.cs:138
+
void SetRequestHeaders(HttpRequestHeaders headers, long? instanceId=null)
Set HttpRequestHeaders using the ApiHeaders. This initially clears headers
Definition: ApiHeaders.cs:232
+
long? InstanceId
The Models.Instance.Id being accessed
Definition: ApiHeaders.cs:61
+
const string JwtAuthenticationScheme
The JWT authentication header scheme
Definition: ApiHeaders.cs:41
+
static bool CheckCompatibility(Version otherVersion)
Checks if a given otherVersion is compatible with our own
+
const string ApiVersionHeader
The ApiVersion header key
Definition: ApiHeaders.cs:26
+
const string InstanceIdHeader
The InstanceId header key
Definition: ApiHeaders.cs:36
+
string Token
The client's JWT
Definition: ApiHeaders.cs:81
+
const string UsernameHeader
The Username header key
Definition: ApiHeaders.cs:31
+
static Version Version
Get the version of the Api the caller is using
Definition: ApiHeaders.cs:56
diff --git a/_api_mismatch_exception_8cs.html b/_api_mismatch_exception_8cs.html index 5c3c5b8edf..8a743f4ca2 100644 --- a/_api_mismatch_exception_8cs.html +++ b/_api_mismatch_exception_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ApiMismatchException.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_api_mismatch_exception_8cs_source.html b/_api_mismatch_exception_8cs_source.html index bf550a9559..f8a9916e11 100644 --- a/_api_mismatch_exception_8cs_source.html +++ b/_api_mismatch_exception_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ApiMismatchException.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ApiMismatchException.cs
-Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
5 namespace Tgstation.Server.Client
6 {
10  public sealed class ApiMismatchException : ClientException
11  {
16  public ApiMismatchException(ErrorMessage errorMessage) : base(errorMessage, HttpStatusCode.BadRequest)
17  {
18  if (errorMessage == null)
19  throw new ArgumentNullException(nameof(errorMessage));
20  }
21 
25  public ApiMismatchException() { }
26 
31  public ApiMismatchException(string message) : base(message) { }
32 
38  public ApiMismatchException(string message, Exception innerException) : base(message, innerException) { }
39  }
40 }
- - +Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
6 {
10  public sealed class ApiMismatchException : ClientException
11  {
16  public ApiMismatchException(ErrorMessage errorMessage) : base(errorMessage, HttpStatusCode.BadRequest)
17  {
18  if (errorMessage == null)
19  throw new ArgumentNullException(nameof(errorMessage));
20  }
21 
25  public ApiMismatchException() { }
26 
31  public ApiMismatchException(string message) : base(message) { }
32 
38  public ApiMismatchException(string message, Exception innerException) : base(message, innerException) { }
39  }
40 }
+ -
Occurs when the API version of the client is not compatible with the server&#39;s
-
ApiMismatchException(ErrorMessage errorMessage)
Construct an ApiMismatchException using an errorMessage
-
ApiMismatchException(string message, Exception innerException)
Construct an ApiMismatchException with a message and innerException
- -
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- -
ApiMismatchException()
Construct an ApiMismatchException
-
Exceptions thrown by IServerClients
-
ApiMismatchException(string message)
Construct an ApiMismatchException with a message
+
Occurs when the API version of the client is not compatible with the server's
+
ApiMismatchException(ErrorMessage errorMessage)
Construct an ApiMismatchException using an errorMessage
+
ApiMismatchException(string message, Exception innerException)
Construct an ApiMismatchException with a message and innerException
+ +
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+ +
ApiMismatchException()
Construct an ApiMismatchException
+
Exceptions thrown by IServerClients
+
ApiMismatchException(string message)
Construct an ApiMismatchException with a message
diff --git a/_api_validation_status_8cs.html b/_api_validation_status_8cs.html index dc3723f12e..465861f42e 100644 --- a/_api_validation_status_8cs.html +++ b/_api_validation_status_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/ApiValidationStatus.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Host +  +namespace  Tgstation.Server.Host.Components +  namespace  Tgstation.Server.Host.Components.Watchdog   @@ -114,8 +101,8 @@ Enumerations   Tgstation.Server.Host.Components.Watchdog.ApiValidationStatus.RequiresTrusted, Tgstation.Server.Host.Components.Watchdog.ApiValidationStatus.RequiresUltrasafe
- } - + } +
 Status of DMAPI validation More...
 Status of DMAPI validation More...
 
@@ -123,7 +110,7 @@ Enumerations diff --git a/_api_validation_status_8cs_source.html b/_api_validation_status_8cs_source.html index ddce2922ab..4da6e7bb3c 100644 --- a/_api_validation_status_8cs_source.html +++ b/_api_validation_status_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/ApiValidationStatus.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
ApiValidationStatus.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Host.Components.Watchdog
2 {
7  {
12 
17 
22 
27 
32 
37  }
38 }
The DMAPI never contacted the server for validation
-
The server was contacted for validation but it was never requested
-
Valid API. The game must be run with a minimum security level of Api.Models.DreamDaemonSecurity.Ultrasafe
- -
Valid API. The game must be run with a minimum security level of Api.Models.DreamDaemonSecurity.Safe
- -
Valid API. The game must be run with a security level of Api.Models.DreamDaemonSecurity.Trusted
- - -
ApiValidationStatus
Status of DMAPI validation
+Go to the documentation of this file.
2 {
7  {
12 
17 
22 
27 
32 
37  }
38 }
The DMAPI never contacted the server for validation
+
The server was contacted for validation but it was never requested
+ +
Valid API. The game must be run with a minimum security level of Api.Models.DreamDaemonSecurity....
+ +
Valid API. The game must be run with a minimum security level of Api.Models.DreamDaemonSecurity....
+
Valid API. The game must be run with a security level of Api.Models.DreamDaemonSecurity....
+
ApiValidationStatus
Status of DMAPI validation
diff --git a/_application_8cs.html b/_application_8cs.html index c2b46ed08e..1da67958e3 100644 --- a/_application_8cs.html +++ b/_application_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/Application.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_application_8cs_source.html b/_application_8cs_source.html index c9a62f6a93..ba763ab954 100644 --- a/_application_8cs_source.html +++ b/_application_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/Application.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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.Extensions.Configuration;
9 using Microsoft.Extensions.DependencyInjection;
10 using Microsoft.Extensions.Hosting;
11 using Microsoft.Extensions.Logging;
12 using Microsoft.Extensions.Options;
13 using Microsoft.Extensions.Primitives;
14 using Newtonsoft.Json;
15 using Newtonsoft.Json.Converters;
16 using Serilog;
17 using Serilog.Events;
18 using Serilog.Formatting.Display;
19 using System;
20 using System.Globalization;
21 using System.IdentityModel.Tokens.Jwt;
22 using System.Reflection;
23 using System.Threading.Tasks;
30 using Tgstation.Server.Host.IO;
33 
34 namespace Tgstation.Server.Host.Core
35 {
37  #pragma warning disable CA1506
38  sealed class Application : IApplication
39  {
41  public string VersionPrefix => "tgstation-server";
42 
44  public Version Version { get; }
45 
47  public string VersionString { get; }
48 
52  readonly IConfiguration configuration;
53 
57  readonly Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment;
58 
62  readonly TaskCompletionSource<object> startupTcs;
63 
68 
74  public Application(IConfiguration configuration, Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment)
75  {
76  this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
77  this.hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
78 
79  startupTcs = new TaskCompletionSource<object>();
80 
81  Version = Assembly.GetExecutingAssembly().GetName().Version;
82  VersionString = String.Format(CultureInfo.InvariantCulture, "{0} v{1}", VersionPrefix, Version);
83  }
84 
89  public void ConfigureServices(IServiceCollection services)
90  {
91  if (services == null)
92  throw new ArgumentNullException(nameof(services));
93 
94  // needful
95  services.AddSingleton<IApplication>(this);
96 
97  // configure configuration
98  services.UseStandardConfig<UpdatesConfiguration>(configuration);
99  services.UseStandardConfig<DatabaseConfiguration>(configuration);
100  services.UseStandardConfig<GeneralConfiguration>(configuration);
101  services.UseStandardConfig<FileLoggingConfiguration>(configuration);
102  services.UseStandardConfig<ControlPanelConfiguration>(configuration);
103 
104  // enable options which give us config reloading
105  services.AddOptions();
106 
107  // other stuff needed for for setup wizard and configuration
108  services.AddSingleton<IIOManager, DefaultIOManager>();
109  services.AddSingleton<IConsole, IO.Console>();
110  services.AddSingleton<IDBConnectionFactory, DBConnectionFactory>();
111  services.AddSingleton<ISetupWizard, SetupWizard>();
112  services.AddSingleton<IPlatformIdentifier, PlatformIdentifier>();
113  services.AddSingleton<IAsyncDelayer, AsyncDelayer>();
114 
115  GeneralConfiguration generalConfiguration;
116  DatabaseConfiguration databaseConfiguration;
117  FileLoggingConfiguration fileLoggingConfiguration;
118  ControlPanelConfiguration controlPanelConfiguration;
119  IIOManager ioManager;
120  IPlatformIdentifier platformIdentifier;
121 
122  // temporarily build the service provider in it's current state
123  // do it here so we can run the setup wizard if necessary
124  // also allows us to get some options and other services we need for continued configuration
125  using (var provider = services.BuildServiceProvider())
126  {
127  // run the wizard if necessary
128  var setupWizard = provider.GetRequiredService<ISetupWizard>();
129  var applicationLifetime = provider.GetRequiredService<Microsoft.AspNetCore.Hosting.IApplicationLifetime>();
130  var setupWizardRan = setupWizard.CheckRunWizard(applicationLifetime.ApplicationStopping).GetAwaiter().GetResult();
131 
132  // load the configuration options we need
133  var generalOptions = provider.GetRequiredService<IOptions<GeneralConfiguration>>();
134  generalConfiguration = generalOptions.Value;
135 
136  // unless this is set, in which case, we leave
137  if (setupWizardRan && generalConfiguration.SetupWizardMode == SetupWizardMode.Only)
138  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
139 
140  var dbOptions = provider.GetRequiredService<IOptions<DatabaseConfiguration>>();
141  databaseConfiguration = dbOptions.Value;
142 
143  var loggingOptions = provider.GetRequiredService<IOptions<FileLoggingConfiguration>>();
144  fileLoggingConfiguration = loggingOptions.Value;
145 
146  var controlPanelOptions = provider.GetRequiredService<IOptions<ControlPanelConfiguration>>();
147  controlPanelConfiguration = controlPanelOptions.Value;
148 
149  ioManager = provider.GetRequiredService<IIOManager>();
150  platformIdentifier = provider.GetRequiredService<IPlatformIdentifier>();
151  }
152 
153  // setup file logging via serilog
154  if (!fileLoggingConfiguration.Disable)
155  services.AddLogging(builder =>
156  {
157  // common app data is C:/ProgramData on windows, else /usr/shar
158  var logPath = !String.IsNullOrEmpty(fileLoggingConfiguration.Directory) ? fileLoggingConfiguration.Directory : ioManager.ConcatPath(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), VersionPrefix, "Logs");
159 
160  logPath = ioManager.ConcatPath(logPath, "tgs-{Date}.log");
161 
162  LogEventLevel? ConvertLogLevel(LogLevel logLevel)
163  {
164  switch (logLevel)
165  {
166  case LogLevel.Critical:
167  return LogEventLevel.Fatal;
168  case LogLevel.Debug:
169  return LogEventLevel.Debug;
170  case LogLevel.Error:
171  return LogEventLevel.Error;
172  case LogLevel.Information:
173  return LogEventLevel.Information;
174  case LogLevel.Trace:
175  return LogEventLevel.Verbose;
176  case LogLevel.Warning:
177  return LogEventLevel.Warning;
178  case LogLevel.None:
179  return null;
180  default:
181  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid log level {0}", logLevel));
182  }
183  }
184 
185  var logEventLevel = ConvertLogLevel(fileLoggingConfiguration.LogLevel);
186  var microsoftEventLevel = ConvertLogLevel(fileLoggingConfiguration.MicrosoftLogLevel);
187 
188  var formatter = new MessageTemplateTextFormatter("{Timestamp:o} {RequestId,13} [{Level:u3}] {SourceContext:l}: {Message} ({EventId:x8}){NewLine}{Exception}", null);
189 
190  var configuration = new LoggerConfiguration()
191  .Enrich.FromLogContext()
192  .WriteTo.Async(w => w.RollingFile(formatter, logPath, shared: true, flushToDiskInterval: TimeSpan.FromSeconds(2)));
193 
194  if (logEventLevel.HasValue)
195  configuration.MinimumLevel.Is(logEventLevel.Value);
196 
197  if (microsoftEventLevel.HasValue)
198  configuration.MinimumLevel.Override("Microsoft", microsoftEventLevel.Value);
199 
200  builder.AddSerilog(configuration.CreateLogger(), true);
201  });
202 
203  // configure bearer token validation
204  services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(jwtBearerOptions =>
205  {
206  // this line isn't actually run until the first request is made
207  // at that point tokenFactory will be populated
208  jwtBearerOptions.TokenValidationParameters = tokenFactory.ValidationParameters;
209  jwtBearerOptions.Events = new JwtBearerEvents
210  {
211  // Application is our composition root so this monstrosity of a line is okay
212  OnTokenValidated = ctx => ctx.HttpContext.RequestServices.GetRequiredService<IClaimsInjector>().InjectClaimsIntoContext(ctx, ctx.HttpContext.RequestAborted)
213  };
214  });
215 
216  // fucking prevents converting 'sub' to M$ bs
217  // can't be done in the above lambda, that's too late
218  JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
219 
220  // add mvc, configure the json serializer settings
221  services.AddMvc().AddJsonOptions(options =>
222  {
223  options.AllowInputFormatterExceptionMessages = true;
224  options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
225  options.SerializerSettings.CheckAdditionalContent = true;
226  options.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Error;
227  options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
228  options.SerializerSettings.Converters = new[] { new VersionConverter() };
229  });
230 
231  // enable browser detection
232  services.AddDetectionCore().AddBrowser();
233 
234  // enable CORS if necessary
235  if (controlPanelConfiguration.AllowAnyOrigin || controlPanelConfiguration.AllowedOrigins?.Count > 0)
236  services.AddCors();
237 
238  void AddTypedContext<TContext>() where TContext : DatabaseContext<TContext>
239  {
240  services.AddDbContext<TContext>(builder =>
241  {
242  if (hostingEnvironment.IsDevelopment())
243  builder.EnableSensitiveDataLogging();
244  });
245  services.AddScoped<IDatabaseContext>(x => x.GetRequiredService<TContext>());
246  }
247 
248  // add the correct database context type
249  var dbType = databaseConfiguration.DatabaseType;
250  switch (dbType)
251  {
252  case DatabaseType.MySql:
253  case DatabaseType.MariaDB:
254  AddTypedContext<MySqlDatabaseContext>();
255  break;
256  case DatabaseType.SqlServer:
257  AddTypedContext<SqlServerDatabaseContext>();
258  break;
259  default:
260  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid {0}: {1}!", nameof(DatabaseType), dbType));
261  }
262 
263  // configure other database services
264  services.AddSingleton<IDatabaseContextFactory, DatabaseContextFactory>();
265  services.AddSingleton<IDatabaseSeeder, DatabaseSeeder>();
266 
267  // configure security services
269  services.AddScoped<IClaimsInjector, ClaimsInjector>();
270  services.AddSingleton<IIdentityCache, IdentityCache>();
271  services.AddSingleton<ICryptographySuite, CryptographySuite>();
272  services.AddSingleton<ITokenFactory, TokenFactory>();
273  services.AddSingleton<IPasswordHasher<Models.User>, PasswordHasher<Models.User>>();
274 
275  // configure platform specific services
276  if (platformIdentifier.IsWindows)
277  {
278  services.AddSingleton<ISystemIdentityFactory, WindowsSystemIdentityFactory>();
279  services.AddSingleton<ISymlinkFactory, WindowsSymlinkFactory>();
280  services.AddSingleton<IByondInstaller, WindowsByondInstaller>();
281  services.AddSingleton<IPostWriteHandler, WindowsPostWriteHandler>();
282 
283  services.AddSingleton<WindowsNetworkPromptReaper>();
284  services.AddSingleton<INetworkPromptReaper>(x => x.GetRequiredService<WindowsNetworkPromptReaper>());
285  services.AddSingleton<IHostedService>(x => x.GetRequiredService<WindowsNetworkPromptReaper>());
286  }
287  else
288  {
289  services.AddSingleton<ISystemIdentityFactory, PosixSystemIdentityFactory>();
290  services.AddSingleton<ISymlinkFactory, PosixSymlinkFactory>();
291  services.AddSingleton<IByondInstaller, PosixByondInstaller>();
292  services.AddSingleton<IPostWriteHandler, PosixPostWriteHandler>();
293  services.AddSingleton<INetworkPromptReaper, PosixNetworkPromptReaper>();
294  }
295 
296  // configure misc services
297  services.AddSingleton<ISynchronousIOManager, SynchronousIOManager>();
298  services.AddSingleton<IGitHubClientFactory, GitHubClientFactory>();
299  services.AddSingleton<IProcessExecutor, ProcessExecutor>();
300  services.AddSingleton<IByondTopicSender>(new ByondTopicSender
301  {
302  ReceiveTimeout = generalConfiguration.ByondTopicTimeout,
303  SendTimeout = generalConfiguration.ByondTopicTimeout
304  });
305 
306  // configure component services
307  services.AddSingleton<ICredentialsProvider, CredentialsProvider>();
308  services.AddSingleton<IProviderFactory, ProviderFactory>();
309  services.AddSingleton<IChatFactory, ChatFactory>();
310  services.AddSingleton<IWatchdogFactory, WatchdogFactory>();
311  services.AddSingleton<IInstanceFactory, InstanceFactory>();
312 
313  // configure root services
314  services.AddSingleton<InstanceManager>();
315  services.AddSingleton<IInstanceManager>(x => x.GetRequiredService<InstanceManager>());
316  services.AddSingleton<IHostedService>(x => x.GetRequiredService<InstanceManager>());
317 
318  services.AddSingleton<IJobManager, JobManager>();
319  }
320 
329  public void Configure(IApplicationBuilder applicationBuilder, IServerControl serverControl, ITokenFactory tokenFactory, IOptions<ControlPanelConfiguration> controlPanelConfigurationOptions, ILogger<Application> logger)
330  {
331  if (applicationBuilder == null)
332  throw new ArgumentNullException(nameof(applicationBuilder));
333  if (serverControl == null)
334  throw new ArgumentNullException(nameof(serverControl));
335 
336  this.tokenFactory = tokenFactory ?? throw new ArgumentNullException(nameof(tokenFactory));
337 
338  var controlPanelConfiguration = controlPanelConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(controlPanelConfigurationOptions));
339 
340  if (logger == null)
341  throw new ArgumentNullException(nameof(logger));
342 
343  logger.LogInformation(VersionString);
344  logger.LogDebug("Content Root: {0}", hostingEnvironment.ContentRootPath);
345  logger.LogTrace("Web Root: {0}", hostingEnvironment.WebRootPath);
346 
347  // attempt to restart the server if the configuration changes
348  if(serverControl.WatchdogPresent)
349  ChangeToken.OnChange(configuration.GetReloadToken, () => serverControl.Restart());
350 
351  // setup the HTTP request pipeline
352 
353  // should anything after this throw an exception, catch it and display a detailed html page
354  applicationBuilder.UseDeveloperExceptionPage(); // it is not worth it to limit this, you should only ever get it if you're an authorized user
355 
356  // suppress OperationCancelledExceptions, they are just aborted HTTP requests
357  applicationBuilder.UseCancelledRequestSuppression();
358 
359  // Set up CORS based on configuration if necessary
360  Action<CorsPolicyBuilder> corsBuilder = null;
361  if (controlPanelConfiguration.AllowAnyOrigin)
362  {
363  logger.LogTrace("Access-Control-Allow-Origin: *");
364  corsBuilder = builder => builder.AllowAnyOrigin();
365  }
366  else if (controlPanelConfiguration.AllowedOrigins?.Count > 0)
367  {
368  logger.LogTrace("Access-Control-Allow-Origin: ", String.Join(',', controlPanelConfiguration.AllowedOrigins));
369  corsBuilder = builder => builder.WithOrigins(controlPanelConfiguration.AllowedOrigins.ToArray());
370  }
371 
372  if (corsBuilder != null)
373  {
374  var originalBuilder = corsBuilder;
375  corsBuilder = builder => originalBuilder(builder.AllowAnyHeader().AllowAnyMethod());
376  applicationBuilder.UseCors(corsBuilder);
377  }
378 
379  // Do not service requests until Ready is called, this will return 503 until that point
380  applicationBuilder.UseAsyncInitialization(async cancellationToken =>
381  {
382  using (cancellationToken.Register(() => startupTcs.SetCanceled()))
383  await startupTcs.Task.ConfigureAwait(false);
384  });
385 
386  // spa loading if necessary
387  if (controlPanelConfiguration.Enable)
388  {
389  logger.LogWarning("Web control panel enabled. This is a highly WIP feature!");
390  applicationBuilder.UseStaticFiles();
391  }
392  else
393  logger.LogDebug("Web control panel disabled!");
394 
395  // authenticate JWT tokens using our security pipeline if present, returns 401 if bad
396  applicationBuilder.UseAuthentication();
397 
398  // suppress and log database exceptions
399  applicationBuilder.UseDbConflictHandling();
400 
401  // majority of handling is done in the controllers
402  applicationBuilder.UseMvc();
403 
404  // 404 anything that gets this far
405  }
406 
408  public void Ready(Exception initializationError)
409  {
410  lock (startupTcs)
411  {
412  if (startupTcs.Task.IsCompleted)
413  throw new InvalidOperationException("Ready has already been called!");
414  if (initializationError == null)
415  startupTcs.SetResult(null);
416  else
417  startupTcs.SetException(initializationError);
418  }
419  }
420  }
421 }
LogLevel MicrosoftLogLevel
The minimum Microsoft.Extensions.Logging.LogLevel to display in logs for Microsoft library sources ...
- -
Manages the runtime of Jobs
Definition: IJobManager.cs:12
- - - +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.Extensions.Configuration;
9 using Microsoft.Extensions.DependencyInjection;
10 using Microsoft.Extensions.Hosting;
11 using Microsoft.Extensions.Logging;
12 using Microsoft.Extensions.Options;
13 using Microsoft.Extensions.Primitives;
14 using Newtonsoft.Json;
15 using Newtonsoft.Json.Converters;
16 using Serilog;
17 using Serilog.Events;
18 using Serilog.Formatting.Display;
19 using System;
20 using System.Globalization;
21 using System.IdentityModel.Tokens.Jwt;
22 using System.Reflection;
23 using System.Threading.Tasks;
30 using Tgstation.Server.Host.IO;
33 
35 {
37  #pragma warning disable CA1506
38  sealed class Application : IApplication
39  {
41  public string VersionPrefix => "tgstation-server";
42 
44  public Version Version { get; }
45 
47  public string VersionString { get; }
48 
52  readonly IConfiguration configuration;
53 
57  readonly Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment;
58 
62  readonly TaskCompletionSource<object> startupTcs;
63 
68 
74  public Application(IConfiguration configuration, Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment)
75  {
76  this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
77  this.hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
78 
79  startupTcs = new TaskCompletionSource<object>();
80 
81  Version = Assembly.GetExecutingAssembly().GetName().Version;
82  VersionString = String.Format(CultureInfo.InvariantCulture, "{0} v{1}", VersionPrefix, Version);
83  }
84 
89  public void ConfigureServices(IServiceCollection services)
90  {
91  if (services == null)
92  throw new ArgumentNullException(nameof(services));
93 
94  // needful
95  services.AddSingleton<IApplication>(this);
96 
97  // configure configuration
98  services.UseStandardConfig<UpdatesConfiguration>(configuration);
99  services.UseStandardConfig<DatabaseConfiguration>(configuration);
100  services.UseStandardConfig<GeneralConfiguration>(configuration);
101  services.UseStandardConfig<FileLoggingConfiguration>(configuration);
102  services.UseStandardConfig<ControlPanelConfiguration>(configuration);
103 
104  // enable options which give us config reloading
105  services.AddOptions();
106 
107  // this is needful for the setup wizard
108  services.AddLogging();
109 
110  // other stuff needed for for setup wizard and configuration
111  services.AddSingleton<IIOManager, DefaultIOManager>();
112  services.AddSingleton<IConsole, IO.Console>();
113  services.AddSingleton<IDBConnectionFactory, DBConnectionFactory>();
114  services.AddSingleton<ISetupWizard, SetupWizard>();
115  services.AddSingleton<IPlatformIdentifier, PlatformIdentifier>();
116  services.AddSingleton<IAsyncDelayer, AsyncDelayer>();
117 
118  GeneralConfiguration generalConfiguration;
119  DatabaseConfiguration databaseConfiguration;
120  FileLoggingConfiguration fileLoggingConfiguration;
121  ControlPanelConfiguration controlPanelConfiguration;
122  IIOManager ioManager;
123  IPlatformIdentifier platformIdentifier;
124 
125  // temporarily build the service provider in it's current state
126  // do it here so we can run the setup wizard if necessary
127  // also allows us to get some options and other services we need for continued configuration
128  using (var provider = services.BuildServiceProvider())
129  {
130  // run the wizard if necessary
131  var setupWizard = provider.GetRequiredService<ISetupWizard>();
132  var applicationLifetime = provider.GetRequiredService<Microsoft.AspNetCore.Hosting.IApplicationLifetime>();
133  var setupWizardRan = setupWizard.CheckRunWizard(applicationLifetime.ApplicationStopping).GetAwaiter().GetResult();
134 
135  // load the configuration options we need
136  var generalOptions = provider.GetRequiredService<IOptions<GeneralConfiguration>>();
137  generalConfiguration = generalOptions.Value;
138 
139  // unless this is set, in which case, we leave
140  if (setupWizardRan && generalConfiguration.SetupWizardMode == SetupWizardMode.Only)
141  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
142 
143  var dbOptions = provider.GetRequiredService<IOptions<DatabaseConfiguration>>();
144  databaseConfiguration = dbOptions.Value;
145 
146  var loggingOptions = provider.GetRequiredService<IOptions<FileLoggingConfiguration>>();
147  fileLoggingConfiguration = loggingOptions.Value;
148 
149  var controlPanelOptions = provider.GetRequiredService<IOptions<ControlPanelConfiguration>>();
150  controlPanelConfiguration = controlPanelOptions.Value;
151 
152  ioManager = provider.GetRequiredService<IIOManager>();
153  platformIdentifier = provider.GetRequiredService<IPlatformIdentifier>();
154  }
155 
156  // setup file logging via serilog
157  if (!fileLoggingConfiguration.Disable)
158  services.AddLogging(builder =>
159  {
160  // common app data is C:/ProgramData on windows, else /usr/shar
161  var logPath = !String.IsNullOrEmpty(fileLoggingConfiguration.Directory) ? fileLoggingConfiguration.Directory : ioManager.ConcatPath(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), VersionPrefix, "Logs");
162 
163  logPath = ioManager.ConcatPath(logPath, "tgs-{Date}.log");
164 
165  LogEventLevel? ConvertLogLevel(LogLevel logLevel)
166  {
167  switch (logLevel)
168  {
169  case LogLevel.Critical:
170  return LogEventLevel.Fatal;
171  case LogLevel.Debug:
172  return LogEventLevel.Debug;
173  case LogLevel.Error:
174  return LogEventLevel.Error;
175  case LogLevel.Information:
176  return LogEventLevel.Information;
177  case LogLevel.Trace:
178  return LogEventLevel.Verbose;
179  case LogLevel.Warning:
180  return LogEventLevel.Warning;
181  case LogLevel.None:
182  return null;
183  default:
184  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid log level {0}", logLevel));
185  }
186  }
187 
188  var logEventLevel = ConvertLogLevel(fileLoggingConfiguration.LogLevel);
189  var microsoftEventLevel = ConvertLogLevel(fileLoggingConfiguration.MicrosoftLogLevel);
190 
191  var formatter = new MessageTemplateTextFormatter("{Timestamp:o} {RequestId,13} [{Level:u3}] {SourceContext:l}: {Message} ({EventId:x8}){NewLine}{Exception}", null);
192 
193  var configuration = new LoggerConfiguration()
194  .Enrich.FromLogContext()
195  .WriteTo.Async(w => w.RollingFile(formatter, logPath, shared: true, flushToDiskInterval: TimeSpan.FromSeconds(2)));
196 
197  if (logEventLevel.HasValue)
198  configuration.MinimumLevel.Is(logEventLevel.Value);
199 
200  if (microsoftEventLevel.HasValue)
201  configuration.MinimumLevel.Override("Microsoft", microsoftEventLevel.Value);
202 
203  builder.AddSerilog(configuration.CreateLogger(), true);
204  });
205 
206  // configure bearer token validation
207  services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(jwtBearerOptions =>
208  {
209  // this line isn't actually run until the first request is made
210  // at that point tokenFactory will be populated
211  jwtBearerOptions.TokenValidationParameters = tokenFactory.ValidationParameters;
212  jwtBearerOptions.Events = new JwtBearerEvents
213  {
214  // Application is our composition root so this monstrosity of a line is okay
215  OnTokenValidated = ctx => ctx.HttpContext.RequestServices.GetRequiredService<IClaimsInjector>().InjectClaimsIntoContext(ctx, ctx.HttpContext.RequestAborted)
216  };
217  });
218 
219  // fucking prevents converting 'sub' to M$ bs
220  // can't be done in the above lambda, that's too late
221  JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
222 
223  // add mvc, configure the json serializer settings
224  services.AddMvc().AddJsonOptions(options =>
225  {
226  options.AllowInputFormatterExceptionMessages = true;
227  options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
228  options.SerializerSettings.CheckAdditionalContent = true;
229  options.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Error;
230  options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
231  options.SerializerSettings.Converters = new[] { new VersionConverter() };
232  });
233 
234  // enable browser detection
235  services.AddDetectionCore().AddBrowser();
236 
237  // CORS conditionally enabled later
238  services.AddCors();
239 
240  void AddTypedContext<TContext>() where TContext : DatabaseContext<TContext>
241  {
242  services.AddDbContext<TContext>(builder =>
243  {
244  if (hostingEnvironment.IsDevelopment())
245  builder.EnableSensitiveDataLogging();
246  });
247  services.AddScoped<IDatabaseContext>(x => x.GetRequiredService<TContext>());
248  }
249 
250  // add the correct database context type
251  var dbType = databaseConfiguration.DatabaseType;
252  switch (dbType)
253  {
254  case DatabaseType.MySql:
255  case DatabaseType.MariaDB:
256  AddTypedContext<MySqlDatabaseContext>();
257  break;
258  case DatabaseType.SqlServer:
259  AddTypedContext<SqlServerDatabaseContext>();
260  break;
261  default:
262  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid {0}: {1}!", nameof(DatabaseType), dbType));
263  }
264 
265  // configure other database services
266  services.AddSingleton<IDatabaseContextFactory, DatabaseContextFactory>();
267  services.AddSingleton<IDatabaseSeeder, DatabaseSeeder>();
268 
269  // configure security services
271  services.AddScoped<IClaimsInjector, ClaimsInjector>();
272  services.AddSingleton<IIdentityCache, IdentityCache>();
273  services.AddSingleton<ICryptographySuite, CryptographySuite>();
274  services.AddSingleton<ITokenFactory, TokenFactory>();
275  services.AddSingleton<IPasswordHasher<Models.User>, PasswordHasher<Models.User>>();
276 
277  // configure platform specific services
278  if (platformIdentifier.IsWindows)
279  {
280  services.AddSingleton<ISystemIdentityFactory, WindowsSystemIdentityFactory>();
281  services.AddSingleton<ISymlinkFactory, WindowsSymlinkFactory>();
282  services.AddSingleton<IByondInstaller, WindowsByondInstaller>();
283  services.AddSingleton<IPostWriteHandler, WindowsPostWriteHandler>();
284 
285  services.AddSingleton<WindowsNetworkPromptReaper>();
286  services.AddSingleton<INetworkPromptReaper>(x => x.GetRequiredService<WindowsNetworkPromptReaper>());
287  services.AddSingleton<IHostedService>(x => x.GetRequiredService<WindowsNetworkPromptReaper>());
288  }
289  else
290  {
291  services.AddSingleton<ISystemIdentityFactory, PosixSystemIdentityFactory>();
292  services.AddSingleton<ISymlinkFactory, PosixSymlinkFactory>();
293  services.AddSingleton<IByondInstaller, PosixByondInstaller>();
294  services.AddSingleton<IPostWriteHandler, PosixPostWriteHandler>();
295  services.AddSingleton<INetworkPromptReaper, PosixNetworkPromptReaper>();
296  }
297 
298  // configure misc services
299  services.AddSingleton<ISynchronousIOManager, SynchronousIOManager>();
300  services.AddSingleton<IGitHubClientFactory, GitHubClientFactory>();
301  services.AddSingleton<IProcessExecutor, ProcessExecutor>();
302  services.AddSingleton<IByondTopicSender>(new ByondTopicSender
303  {
304  ReceiveTimeout = generalConfiguration.ByondTopicTimeout,
305  SendTimeout = generalConfiguration.ByondTopicTimeout
306  });
307 
308  // configure component services
309  services.AddSingleton<ICredentialsProvider, CredentialsProvider>();
310  services.AddSingleton<IProviderFactory, ProviderFactory>();
311  services.AddSingleton<IChatFactory, ChatFactory>();
312  services.AddSingleton<IWatchdogFactory, WatchdogFactory>();
313  services.AddSingleton<IInstanceFactory, InstanceFactory>();
314 
315  // configure root services
316  services.AddSingleton<InstanceManager>();
317  services.AddSingleton<IInstanceManager>(x => x.GetRequiredService<InstanceManager>());
318  services.AddSingleton<IHostedService>(x => x.GetRequiredService<InstanceManager>());
319 
320  services.AddSingleton<IJobManager, JobManager>();
321  }
322 
331  public void Configure(IApplicationBuilder applicationBuilder, IServerControl serverControl, ITokenFactory tokenFactory, IOptions<ControlPanelConfiguration> controlPanelConfigurationOptions, ILogger<Application> logger)
332  {
333  if (applicationBuilder == null)
334  throw new ArgumentNullException(nameof(applicationBuilder));
335  if (serverControl == null)
336  throw new ArgumentNullException(nameof(serverControl));
337 
338  this.tokenFactory = tokenFactory ?? throw new ArgumentNullException(nameof(tokenFactory));
339 
340  var controlPanelConfiguration = controlPanelConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(controlPanelConfigurationOptions));
341 
342  if (logger == null)
343  throw new ArgumentNullException(nameof(logger));
344 
345  logger.LogInformation(VersionString);
346  logger.LogDebug("Content Root: {0}", hostingEnvironment.ContentRootPath);
347  logger.LogTrace("Web Root: {0}", hostingEnvironment.WebRootPath);
348 
349  // attempt to restart the server if the configuration changes
350  if(serverControl.WatchdogPresent)
351  ChangeToken.OnChange(configuration.GetReloadToken, () => serverControl.Restart());
352 
353  // setup the HTTP request pipeline
354 
355  // should anything after this throw an exception, catch it and display a detailed html page
356  applicationBuilder.UseDeveloperExceptionPage(); // it is not worth it to limit this, you should only ever get it if you're an authorized user
357 
358  // suppress OperationCancelledExceptions, they are just aborted HTTP requests
359  applicationBuilder.UseCancelledRequestSuppression();
360 
361  // Set up CORS based on configuration if necessary
362  Action<CorsPolicyBuilder> corsBuilder = null;
363  if (controlPanelConfiguration.AllowAnyOrigin)
364  {
365  logger.LogTrace("Access-Control-Allow-Origin: *");
366  corsBuilder = builder => builder.AllowAnyOrigin();
367  }
368  else if (controlPanelConfiguration.AllowedOrigins?.Count > 0)
369  {
370  logger.LogTrace("Access-Control-Allow-Origin: ", String.Join(',', controlPanelConfiguration.AllowedOrigins));
371  corsBuilder = builder => builder.WithOrigins(controlPanelConfiguration.AllowedOrigins.ToArray());
372  }
373 
374  var originalBuilder = corsBuilder;
375  corsBuilder = builder =>
376  {
377  builder.AllowAnyHeader().AllowAnyMethod();
378  originalBuilder?.Invoke(builder);
379  };
380  applicationBuilder.UseCors(corsBuilder);
381 
382  // Do not service requests until Ready is called, this will return 503 until that point
383  applicationBuilder.UseAsyncInitialization(async cancellationToken =>
384  {
385  using (cancellationToken.Register(() => startupTcs.SetCanceled()))
386  await startupTcs.Task.ConfigureAwait(false);
387  });
388 
389  // spa loading if necessary
390  if (controlPanelConfiguration.Enable)
391  {
392  logger.LogWarning("Web control panel enabled. This is a highly WIP feature!");
393  applicationBuilder.UseStaticFiles();
394  }
395  else
396  logger.LogDebug("Web control panel disabled!");
397 
398  // authenticate JWT tokens using our security pipeline if present, returns 401 if bad
399  applicationBuilder.UseAuthentication();
400 
401  // suppress and log database exceptions
402  applicationBuilder.UseDbConflictHandling();
403 
404  // majority of handling is done in the controllers
405  applicationBuilder.UseMvc();
406 
407  // 404 anything that gets this far
408  }
409 
411  public void Ready(Exception initializationError)
412  {
413  lock (startupTcs)
414  {
415  if (startupTcs.Task.IsCompleted)
416  throw new InvalidOperationException("Ready has already been called!");
417  if (initializationError == null)
418  startupTcs.SetResult(null);
419  else
420  startupTcs.SetException(initializationError);
421  }
422  }
423  }
424 }
LogLevel MicrosoftLogLevel
The minimum Microsoft.Extensions.Logging.LogLevel to display in logs for Microsoft library sources
+ +
Manages the runtime of Jobs
Definition: IJobManager.cs:12
+ + + -
readonly Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment
The Microsoft.AspNetCore.Hosting.IHostingEnvironment for the Application
Definition: Application.cs:57
-
IPostWriteHandler for POSIX systems
+
readonly Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment
The Microsoft.AspNetCore.Hosting.IHostingEnvironment for the Application
Definition: Application.cs:57
+
IPostWriteHandler for POSIX systems
-
Handles changing file modes/permissions after writing
- -
List< string > AllowedOrigins
Origins allowed for CORS requests
- -
void Configure(IApplicationBuilder applicationBuilder, IServerControl serverControl, ITokenFactory tokenFactory, IOptions< ControlPanelConfiguration > controlPanelConfigurationOptions, ILogger< Application > logger)
Configure the Application
Definition: Application.cs:329
-
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
+
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:331
+
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
-
SetupWizardMode
Determines if the Core.ISetupWizard will run
-
Abstraction for System.Console
Definition: IConsole.cs:9
-
bool WatchdogPresent
if live updates are supported, . ApplyUpdate(Version, Uri, IIOManager) and Restart will fail if this ...
- - -
LogLevel LogLevel
The minimum Microsoft.Extensions.Logging.LogLevel to display in logs
- -
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
- - -
ITokenFactory tokenFactory
The ITokenFactory for the Application
Definition: Application.cs:67
-
For initially seeding a database
+
SetupWizardMode
Determines if the Core.ISetupWizard will run
+
Abstraction for 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
+
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
+ + +
ITokenFactory tokenFactory
The ITokenFactory for the Application
Definition: Application.cs:67
+ +
For initially seeding a database
+ - + - - + +
ISystemIdentityFactory for windows systems. Uses long running tasks due to potential networked domain...
-
Contains various cryptographic functions
+
Contains various cryptographic functions
- - - -
bool AllowAnyOrigin
If any origin is allowed for CORS requests. This overrides AllowedOrigins
-
Configuration for the automatic update system
-
For downloading and installing BYOND extractions for a given system
+ + + + +
Configuration for the automatic update system
+
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
- +
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:408
- +
void Ready(Exception initializationError)
Mark the IApplication as ready to run
Definition: Application.cs:411
+ - -
IPostWriteHandler for Windows systems
- - - -
bool IsWindows
If the current platform is a Windows platform
-
readonly TaskCompletionSource< object > startupTcs
The TaskCompletionSource<TResult> used for determining when the Application is Ready(Exception) ...
Definition: Application.cs:62
+ +
IPostWriteHandler for Windows systems
+ + + +
bool IsWindows
If the current platform is a Windows platform
+
readonly TaskCompletionSource< object > startupTcs
The TaskCompletionSource<TResult> used for determining when the Application is Ready(Exception)
Definition: Application.cs:62
- + -
void ConfigureServices(IServiceCollection services)
Configure dependency injected services
Definition: Application.cs:89
+
void ConfigureServices(IServiceCollection services)
Configure dependency injected services
Definition: Application.cs:89
+ -
TokenValidationParameters ValidationParameters
The TokenValidationParameters for the ITokenFactory
- +
TokenValidationParameters ValidationParameters
The TokenValidationParameters for the ITokenFactory
+ - -
Configuration options for the Models.DatabaseContext<TParentContext>
- - -
IIOManager that resolves paths to Environment.CurrentDirectory
-
Application(IConfiguration configuration, Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment)
Construct an Application
Definition: Application.cs:74
-
For injecting System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look for ...
+ +
Configuration options for the Models.DatabaseContext<TParentContext>
+ + +
IIOManager that resolves paths to Environment.CurrentDirectory
+
Application(IConfiguration configuration, Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment)
Construct an Application
Definition: Application.cs:74
+
For injecting System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look for
-
DatabaseType
Type of database to user
Definition: DatabaseType.cs:6
- +
DatabaseType
Type of database to user
Definition: DatabaseType.cs:6
+ - + -
The command line Configuration setup wizard
Definition: ISetupWizard.cs:9
+
The command line Configuration setup wizard
Definition: ISetupWizard.cs:9
-
Task< bool > CheckRunWizard(CancellationToken cancellationToken)
Run the setup wizard if necessary
- -
Interface for using filesystems
Definition: IIOManager.cs:11
+
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(). This looks out for those prompts and immediately clicks "Yes" if the owning process has registered for it
-
For identifying the current platform
+
On Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort()....
+
For identifying the current platform
- - -
readonly IConfiguration configuration
The IConfiguration for the Application
Definition: Application.cs:52
+ + +
readonly IConfiguration configuration
The IConfiguration for the Application
Definition: Application.cs:52
-
string ConcatPath(params string[] paths)
Combines an array of strings into a path
- +
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...
- + - +
diff --git a/_application_builder_extensions_8cs.html b/_application_builder_extensions_8cs.html index ba00539dea..42208a160b 100644 --- a/_application_builder_extensions_8cs.html +++ b/_application_builder_extensions_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/ApplicationBuilderExtensions.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_application_builder_extensions_8cs_source.html b/_application_builder_extensions_8cs_source.html index 0f5c22416d..c40e9dc005 100644 --- a/_application_builder_extensions_8cs_source.html +++ b/_application_builder_extensions_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/ApplicationBuilderExtensions.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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;
10 
11 namespace Tgstation.Server.Host.Core
12 {
17  {
23  static ILogger GetLogger(HttpContext httpContext) => httpContext.RequestServices.GetRequiredService<ILogger<Application>>();
24 
29  public static void UseDbConflictHandling(this IApplicationBuilder applicationBuilder)
30  {
31  if (applicationBuilder == null)
32  throw new ArgumentNullException(nameof(applicationBuilder));
33  applicationBuilder.Use(async (context, next) =>
34  {
35  var logger = GetLogger(context);
36  try
37  {
38  await next().ConfigureAwait(false);
39  }
40  catch (DbUpdateException e)
41  {
42  logger.LogDebug("Database conflict: {0}", e.Message);
43  await new ConflictObjectResult(new ErrorMessage { Message = String.Format(CultureInfo.InvariantCulture, "A database conflict has occurred: {0}", (e.InnerException ?? e).Message) }).ExecuteResultAsync(new ActionContext
44  {
45  HttpContext = context
46  }).ConfigureAwait(false);
47  }
48  });
49  }
50 
55  public static void UseCancelledRequestSuppression(this IApplicationBuilder applicationBuilder)
56  {
57  if (applicationBuilder == null)
58  throw new ArgumentNullException(nameof(applicationBuilder));
59  applicationBuilder.Use(async (context, next) =>
60  {
61  var logger = GetLogger(context);
62  try
63  {
64  await next().ConfigureAwait(false);
65  }
66  catch (OperationCanceledException)
67  {
68  logger.LogDebug("Request cancelled!");
69  }
70  });
71  }
72  }
73 }
- - +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;
10 
12 {
17  {
23  static ILogger GetLogger(HttpContext httpContext) => httpContext.RequestServices.GetRequiredService<ILogger<Application>>();
24 
29  public static void UseDbConflictHandling(this IApplicationBuilder applicationBuilder)
30  {
31  if (applicationBuilder == null)
32  throw new ArgumentNullException(nameof(applicationBuilder));
33  applicationBuilder.Use(async (context, next) =>
34  {
35  var logger = GetLogger(context);
36  try
37  {
38  await next().ConfigureAwait(false);
39  }
40  catch (DbUpdateException e)
41  {
42  logger.LogDebug("Database conflict: {0}", e.Message);
43  await new ConflictObjectResult(new ErrorMessage { Message = String.Format(CultureInfo.InvariantCulture, "A database conflict has occurred: {0}", (e.InnerException ?? e).Message) }).ExecuteResultAsync(new ActionContext
44  {
45  HttpContext = context
46  }).ConfigureAwait(false);
47  }
48  });
49  }
50 
55  public static void UseCancelledRequestSuppression(this IApplicationBuilder applicationBuilder)
56  {
57  if (applicationBuilder == null)
58  throw new ArgumentNullException(nameof(applicationBuilder));
59  applicationBuilder.Use(async (context, next) =>
60  {
61  var logger = GetLogger(context);
62  try
63  {
64  await next().ConfigureAwait(false);
65  }
66  catch (OperationCanceledException)
67  {
68  logger.LogDebug("Request cancelled!");
69  }
70  });
71  }
72  }
73 }
- -
static void UseDbConflictHandling(this IApplicationBuilder applicationBuilder)
Return a ConflictObjectResult for DbUpdateExceptions
- -
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
- + +
static ILogger GetLogger(HttpContext httpContext)
Gets a ILogger from a given httpContext
+ +
static void UseDbConflictHandling(this IApplicationBuilder applicationBuilder)
Return a ConflictObjectResult for DbUpdateExceptions
+ +
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/_architecture_8dox.html b/_architecture_8dox.html index 0a2a87fa8a..1eb7065c3d 100644 --- a/_architecture_8dox.html +++ b/_architecture_8dox.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: docs/Architecture.dox File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + + - + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_async_delayer_8cs_source.html b/_async_delayer_8cs_source.html index 481321cec2..1c7ee20b9a 100644 --- a/_async_delayer_8cs_source.html +++ b/_async_delayer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/AsyncDelayer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
AsyncDelayer.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
5 namespace Tgstation.Server.Host.Core
6 {
8  sealed class AsyncDelayer : IAsyncDelayer
9  {
11  public Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken) => Task.Delay(timeSpan, cancellationToken);
12  }
13 }
- - - -
Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan
- +Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
6 {
8  sealed class AsyncDelayer : IAsyncDelayer
9  {
11  public Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken) => Task.Delay(timeSpan, cancellationToken);
12  }
13 }
+ + +
Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan
diff --git a/_authentication_context_8cs.html b/_authentication_context_8cs.html index 20295d2f8b..c7db7e6e91 100644 --- a/_authentication_context_8cs.html +++ b/_authentication_context_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/AuthenticationContext.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_authentication_context_8cs_source.html b/_authentication_context_8cs_source.html index 4d350012e7..55c7deb311 100644 --- a/_authentication_context_8cs_source.html +++ b/_authentication_context_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/AuthenticationContext.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
AuthenticationContext.cs
-Go to the documentation of this file.
1 using System;
2 using System.Linq;
5 
6 namespace Tgstation.Server.Host.Security
7 {
12  {
14  public User User { get; }
15 
17  public InstanceUser InstanceUser { get; }
18 
20  public ISystemIdentity SystemIdentity { get; }
21 
25  public AuthenticationContext() { }
26 
33  public AuthenticationContext(ISystemIdentity systemIdentity, User user, InstanceUser instanceUser)
34  {
35  User = user ?? throw new ArgumentNullException(nameof(user));
36  if (systemIdentity == null && User.SystemIdentifier != null)
37  throw new ArgumentNullException(nameof(systemIdentity));
38  InstanceUser = instanceUser;
39  SystemIdentity = systemIdentity;
40  }
41 
43  public void Dispose() => SystemIdentity?.Dispose();
44 
46  public ulong GetRight(RightsType rightsType)
47  {
48  var isInstance = RightsHelper.IsInstanceRight(rightsType);
49 
50  if (User == null)
51  throw new InvalidOperationException("Authentication context has no user!");
52 
53  if (isInstance && InstanceUser == null)
54  return 0;
55  var rightsEnum = RightsHelper.RightToType(rightsType);
56 
57  // use the api versions because they're the ones that contain the actual properties
58  var typeToCheck = isInstance ? typeof(InstanceUser) : typeof(User);
59 
60  var nullableType = typeof(Nullable<>);
61  var nullableRightsType = nullableType.MakeGenericType(rightsEnum);
62 
63  var prop = typeToCheck.GetProperties().Where(x => x.PropertyType == nullableRightsType).First();
64 
65  var right = prop.GetMethod.Invoke(isInstance ? (object)InstanceUser : User, Array.Empty<object>());
66 
67  if (right == null)
68  throw new InvalidOperationException("A user right was null!");
69  return (ulong)right;
70  }
71  }
72 }
static bool IsInstanceRight(RightsType rightsType)
Check if a given rightsType is meant for an Models.Instance
-
AuthenticationContext(ISystemIdentity systemIdentity, User user, InstanceUser instanceUser)
Construct an AuthenticationContext
- -
AuthenticationContext()
Construct an empty AuthenticationContext
- -
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
+Go to the documentation of this file.
1 using System;
2 using System.Linq;
5 
7 {
12  {
14  public User User { get; }
15 
17  public InstanceUser InstanceUser { get; }
18 
21 
25  public AuthenticationContext() { }
26 
33  public AuthenticationContext(ISystemIdentity systemIdentity, User user, InstanceUser instanceUser)
34  {
35  User = user ?? throw new ArgumentNullException(nameof(user));
36  if (systemIdentity == null && User.SystemIdentifier != null)
37  throw new ArgumentNullException(nameof(systemIdentity));
38  InstanceUser = instanceUser;
39  SystemIdentity = systemIdentity;
40  }
41 
43  public void Dispose() => SystemIdentity?.Dispose();
44 
46  public ulong GetRight(RightsType rightsType)
47  {
48  var isInstance = RightsHelper.IsInstanceRight(rightsType);
49 
50  if (User == null)
51  throw new InvalidOperationException("Authentication context has no user!");
52 
53  if (isInstance && InstanceUser == null)
54  return 0;
55  var rightsEnum = RightsHelper.RightToType(rightsType);
56 
57  // use the api versions because they're the ones that contain the actual properties
58  var typeToCheck = isInstance ? typeof(InstanceUser) : typeof(User);
59 
60  var nullableType = typeof(Nullable<>);
61  var nullableRightsType = nullableType.MakeGenericType(rightsEnum);
62 
63  var prop = typeToCheck.GetProperties().Where(x => x.PropertyType == nullableRightsType).First();
64 
65  var right = prop.GetMethod.Invoke(isInstance ? (object)InstanceUser : User, Array.Empty<object>());
66 
67  if (right == null)
68  throw new InvalidOperationException("A user right was null!");
69  return (ulong)right;
70  }
71  }
72 }
static bool IsInstanceRight(RightsType rightsType)
Check if a given rightsType is meant for an Models.Instance
+
AuthenticationContext(ISystemIdentity systemIdentity, User user, InstanceUser instanceUser)
Construct an AuthenticationContext
+ +
AuthenticationContext()
Construct an empty AuthenticationContext
+ +
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
-
Represents a user on the current System.Runtime.InteropServices.OSPlatform
+
Represents a user on the current System.Runtime.InteropServices.OSPlatform
- -
Represents the currently authenticated Api.Models.User
-
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
+
Represents the currently authenticated Api.Models.User
+
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
+ -
static Type RightToType(RightsType rightsType)
Map a given rightsType to its respective Enum Type
- - - -
string SystemIdentifier
The SID/UID of the User on Windows/POSIX respectively
Definition: User.cs:32
- + +
static Type RightToType(RightsType rightsType)
Map a given rightsType to its respective Enum Type
+ + + +
string SystemIdentifier
The SID/UID of the User on Windows/POSIX respectively
Definition: User.cs:32
+
diff --git a/_authentication_context_factory_8cs.html b/_authentication_context_factory_8cs.html index 75db130333..d9131816bc 100644 --- a/_authentication_context_factory_8cs.html +++ b/_authentication_context_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/AuthenticationContextFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_authentication_context_factory_8cs_source.html b/_authentication_context_factory_8cs_source.html index 951311cdef..f189390ff0 100644 --- a/_authentication_context_factory_8cs_source.html +++ b/_authentication_context_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/AuthenticationContextFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
AuthenticationContextFactory.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;
7 
8 namespace Tgstation.Server.Host.Security
9 {
12  {
14  public IAuthenticationContext CurrentAuthenticationContext { get; private set; }
15 
20 
25 
30 
37  public AuthenticationContextFactory(ISystemIdentityFactory systemIdentityFactory, IDatabaseContext databaseContext, IIdentityCache identityCache)
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  {
65  CurrentAuthenticationContext = new AuthenticationContext();
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  {
76  CurrentAuthenticationContext = new AuthenticationContext();
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 }
- - -
AuthenticationContextFactory(ISystemIdentityFactory systemIdentityFactory, IDatabaseContext databaseContext, IIdentityCache identityCache)
Construct an AuthenticationContextFactory
- -
Represents a user on the current System.Runtime.InteropServices.OSPlatform
+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 }
+ + +
AuthenticationContextFactory(ISystemIdentityFactory systemIdentityFactory, IDatabaseContext databaseContext, IIdentityCache identityCache)
Construct an AuthenticationContextFactory
+
Represents a user on the current System.Runtime.InteropServices.OSPlatform
- -
Represents the currently authenticated Api.Models.User
- +
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
- -
async Task CreateAuthenticationContext(long userId, long?instanceId, DateTimeOffset validAfter, CancellationToken cancellationToken)
Create an IAuthenticationContext to populate CurrentAuthenticationContext
+ + +
readonly ISystemIdentityFactory systemIdentityFactory
The ISystemIdentityFactory for the AuthenticationContextFactory
+
readonly IDatabaseContext databaseContext
The IDatabaseContext for the AuthenticationContextFactory
+ - - - + + + +
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
+
diff --git a/_bool_converter_8cs.html b/_bool_converter_8cs.html index 56a4431a23..f17b3fe39c 100644 --- a/_bool_converter_8cs.html +++ b/_bool_converter_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/BoolConverter.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
namespace  Tgstation.Server.Host.Components.Chat.Commands
 
@@ -114,7 +103,7 @@ Namespaces diff --git a/_bool_converter_8cs_source.html b/_bool_converter_8cs_source.html index 1f30964cb6..4eb85a1839 100644 --- a/_bool_converter_8cs_source.html +++ b/_bool_converter_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/BoolConverter.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
BoolConverter.cs
-Go to the documentation of this file.
1 using Newtonsoft.Json;
2 using System;
3 
4 namespace Tgstation.Server.Host.Components.Chat.Commands
5 {
9  sealed class BoolConverter : JsonConverter
10  {
12  public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => writer.WriteValue(((bool)value) ? 1 : 0);
13 
15  public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) => reader.Value.ToString() == "1";
16 
18  public override bool CanConvert(Type objectType) => objectType == typeof(bool);
19  }
20 }
- -
JsonConverter for decoding bools returned by BYOND
Definition: BoolConverter.cs:9
+Go to the documentation of this file.
1 using Newtonsoft.Json;
2 using System;
3 
5 {
9  sealed class BoolConverter : JsonConverter
10  {
12  public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => writer.WriteValue(((bool)value) ? 1 : 0);
13 
15  public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) => reader.Value.ToString() == "1";
16 
18  public override bool CanConvert(Type objectType) => objectType == typeof(bool);
19  }
20 }
JsonConverter for decoding bools returned by BYOND
Definition: BoolConverter.cs:9
- - +
override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+
override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ +
diff --git a/_byond_8cs.html b/_byond_8cs.html index bf9edcb98f..cd370476b7 100644 --- a/_byond_8cs.html +++ b/_byond_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Byond.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_byond_8cs_source.html b/_byond_8cs_source.html index 3c990821fc..05f5bd8e97 100644 --- a/_byond_8cs_source.html +++ b/_byond_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Byond.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Byond.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Api.Models
4 {
8  public sealed class Byond
9  {
13  public Version Version { get; set; }
14 
18  public Job InstallJob { get; set; }
19  }
20 }
- -
Represents a BYOND installation
Definition: Byond.cs:8
- -
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job ...
Definition: Job.cs:6
+Go to the documentation of this file.
1 using System;
2 
4 {
8  public sealed class Byond
9  {
13  public Version Version { get; set; }
14 
18  public Job InstallJob { get; set; }
19  }
20 }
Job InstallJob
The Job being used to install a new Version
Definition: Byond.cs:18
+ +
Represents a BYOND installation
Definition: Byond.cs:8
+
Version Version
The System.Version of the Byond installation used for new compiles. Will be null if the user does not...
Definition: Byond.cs:13
+
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job
Definition: Job.cs:6
diff --git a/_byond_client_8cs.html b/_byond_client_8cs.html index eeaa24598f..3f8f85624b 100644 --- a/_byond_client_8cs.html +++ b/_byond_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/ByondClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_byond_client_8cs_source.html b/_byond_client_8cs_source.html index 951395406f..04498a82fb 100644 --- a/_byond_client_8cs_source.html +++ b/_byond_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/ByondClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ByondClient.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 using Tgstation.Server.Api;
7 
8 namespace Tgstation.Server.Client.Components
9 {
11  sealed class ByondClient : IByondClient
12  {
17 
21  readonly Instance instance;
22 
28  public ByondClient(IApiClient apiClient, Instance instance)
29  {
30  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
31  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
32  }
33 
35  public Task<Byond> ActiveVersion(CancellationToken cancellationToken) => apiClient.Read<Byond>(Routes.Byond, instance.Id, cancellationToken);
36 
38  public Task<IReadOnlyList<Byond>> InstalledVersions(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<Byond>>(Routes.List(Routes.Byond), instance.Id, cancellationToken);
39 
41  public Task<Byond> SetActiveVersion(Byond byond, CancellationToken cancellationToken) => apiClient.Update<Byond, Byond>(Routes.Byond, byond ?? throw new ArgumentNullException(nameof(byond)), instance.Id, cancellationToken);
42  }
43 }
const string Byond
The Models.Byond controller
Definition: Routes.cs:34
+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 using Tgstation.Server.Api;
7 
9 {
11  sealed class ByondClient : IByondClient
12  {
17 
21  readonly Instance instance;
22 
29  {
30  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
31  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
32  }
33 
35  public Task<Byond> ActiveVersion(CancellationToken cancellationToken) => apiClient.Read<Byond>(Routes.Byond, instance.Id, cancellationToken);
36 
38  public Task<IReadOnlyList<Byond>> InstalledVersions(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<Byond>>(Routes.List(Routes.Byond), instance.Id, cancellationToken);
39 
41  public Task<Byond> SetActiveVersion(Byond byond, CancellationToken cancellationToken) => apiClient.Update<Byond, Byond>(Routes.Byond, byond ?? throw new ArgumentNullException(nameof(byond)), instance.Id, cancellationToken);
42  }
43 }
const string Byond
The Models.Byond controller
Definition: Routes.cs:34
+
Task< Byond > Byond(Routes.Byond, byond ?? throw new ArgumentNullException(nameof(byond)), instance.Id, cancellationToken)
- -
For managing the Byond installation
Definition: IByondClient.cs:11
- -
ByondClient(IApiClient apiClient, Instance instance)
Construct a ByondClient
Definition: ByondClient.cs:28
-
readonly IApiClient apiClient
The IApiClient for the ByondClient
Definition: ByondClient.cs:16
+
Task< Byond > SetActiveVersion(Byond byond, CancellationToken cancellationToken)
Updates the Byond information
+
For managing the Byond installation
Definition: IByondClient.cs:11
+
ByondClient(IApiClient apiClient, Instance instance)
Construct a ByondClient
Definition: ByondClient.cs:28
+
readonly IApiClient apiClient
The IApiClient for the ByondClient
Definition: ByondClient.cs:16
-
Routes to a server actions
Definition: Routes.cs:9
-
readonly Instance instance
The Instance for the ByondClient
Definition: ByondClient.cs:21
+
Routes to a server actions
Definition: Routes.cs:9
+ +
readonly Instance instance
The Instance for the ByondClient
Definition: ByondClient.cs:21
+
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
-
Metadata about a server instance
Definition: Instance.cs:9
-
Represents a BYOND installation
Definition: Byond.cs:8
-
static string List(string route)
Get the /List postfix for a route
- -
Web interface for the API
Definition: IApiClient.cs:11
- +
Task< IReadOnlyList< Byond > > InstalledVersions(CancellationToken cancellationToken)
Get all installed Byond System.Versions
+
Metadata about a server instance
Definition: Instance.cs:9
+
Represents a BYOND installation
Definition: Byond.cs:8
+
static string List(string route)
Get the /List postfix for a route
+ +
Web interface for the API
Definition: IApiClient.cs:11
+
Task< Byond > ActiveVersion(CancellationToken cancellationToken)
Get the Byond active System.Version information
+
diff --git a/_byond_command_8cs.html b/_byond_command_8cs.html index 13517d1bd7..b584822931 100644 --- a/_byond_command_8cs.html +++ b/_byond_command_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/ByondCommand.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
namespace  Tgstation.Server.Host.Components.Chat.Commands
 
@@ -114,7 +103,7 @@ Namespaces diff --git a/_byond_command_8cs_source.html b/_byond_command_8cs_source.html index 1bc3a7f53c..fbc5d08238 100644 --- a/_byond_command_8cs_source.html +++ b/_byond_command_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/ByondCommand.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ByondCommand.cs
-Go to the documentation of this file.
1 using System;
2 using System.Globalization;
3 using System.Linq;
4 using System.Threading;
5 using System.Threading.Tasks;
8 
9 namespace Tgstation.Server.Host.Components.Chat.Commands
10 {
14  sealed class ByondCommand : ICommand
15  {
17  public string Name => "byond";
18 
20  public string HelpText => "Displays the running Byond version. Use --active for the version used in future deployments";
21 
23  public bool AdminOnly => false;
24 
29 
33  readonly IWatchdog watchdog;
34 
40  public ByondCommand(IByondManager byondManager, IWatchdog watchdog)
41  {
42  this.byondManager = byondManager ?? throw new ArgumentNullException(nameof(byondManager));
43  this.watchdog = watchdog ?? throw new ArgumentNullException(nameof(watchdog));
44  }
45 
47  public Task<string> Invoke(string arguments, User user, CancellationToken cancellationToken)
48  {
49  if (arguments.Split(' ').Any(x => x.ToUpperInvariant() == "--ACTIVE"))
50  return Task.FromResult(byondManager.ActiveVersion == null ? "None!" : String.Format(CultureInfo.InvariantCulture, "{0}.{1}", byondManager.ActiveVersion.Major, byondManager.ActiveVersion.Minor));
51  if (!watchdog.Running)
52  return Task.FromResult("Server offline!");
53  return Task.FromResult(watchdog.ActiveCompileJob.ByondVersion);
54  }
55  }
56 }
- - -
readonly IByondManager byondManager
The IByondManager for the ByondCommand
Definition: ByondCommand.cs:28
+Go to the documentation of this file.
1 using System;
2 using System.Globalization;
3 using System.Linq;
4 using System.Threading;
5 using System.Threading.Tasks;
8 
10 {
14  sealed class ByondCommand : ICommand
15  {
17  public string Name => "byond";
18 
20  public string HelpText => "Displays the running Byond version. Use --active for the version used in future deployments";
21 
23  public bool AdminOnly => false;
24 
29 
33  readonly IWatchdog watchdog;
34 
41  {
42  this.byondManager = byondManager ?? throw new ArgumentNullException(nameof(byondManager));
43  this.watchdog = watchdog ?? throw new ArgumentNullException(nameof(watchdog));
44  }
45 
47  public Task<string> Invoke(string arguments, User user, CancellationToken cancellationToken)
48  {
49  if (arguments.Split(' ').Any(x => x.ToUpperInvariant() == "--ACTIVE"))
50  return Task.FromResult(byondManager.ActiveVersion == null ? "None!" : String.Format(CultureInfo.InvariantCulture, "{0}.{1}", byondManager.ActiveVersion.Major, byondManager.ActiveVersion.Minor));
51  if (!watchdog.Running)
52  return Task.FromResult("Server offline!");
53  return Task.FromResult(watchdog.ActiveCompileJob.ByondVersion);
54  }
55  }
56 }
+ +
readonly IByondManager byondManager
The IByondManager for the ByondCommand
Definition: ByondCommand.cs:28
-
For managing the BYOND installation
-
Represents a tgs_chat_user datum
Definition: User.cs:10
- -
For displaying the installed Byond version
Definition: ByondCommand.cs:14
-
readonly IWatchdog watchdog
The IWatchdog for the ByondCommand
Definition: ByondCommand.cs:33
- -
Task< string > Invoke(string arguments, User user, CancellationToken cancellationToken)
Invoke the ICommand
Definition: ByondCommand.cs:47
- -
Represents a command that can be invoked by talking to chat bots
Definition: ICommand.cs:9
- -
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
-
ByondCommand(IByondManager byondManager, IWatchdog watchdog)
Construct a ByondCommand
Definition: ByondCommand.cs:40
+
Models.CompileJob ActiveCompileJob
The CompileJob currently running on the server
Definition: IWatchdog.cs:27
+
Version ActiveVersion
The currently active BYOND version
+ + +
Represents a tgs_chat_user datum
Definition: User.cs:10
+ +
For displaying the installed Byond version
Definition: ByondCommand.cs:14
+ +
readonly IWatchdog watchdog
The IWatchdog for the ByondCommand
Definition: ByondCommand.cs:33
+ +
bool Running
If the watchdog is running
Definition: IWatchdog.cs:17
+ +
Task< string > Invoke(string arguments, User user, CancellationToken cancellationToken)
Invoke the ICommand
Definition: ByondCommand.cs:47
+ +
Represents a command that can be invoked by talking to chat bots
Definition: ICommand.cs:9
+ +
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
+
ByondCommand(IByondManager byondManager, IWatchdog watchdog)
Construct a ByondCommand
Definition: ByondCommand.cs:40
diff --git a/_byond_controller_8cs.html b/_byond_controller_8cs.html index 9e21cba37c..5ef764ebe6 100644 --- a/_byond_controller_8cs.html +++ b/_byond_controller_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/ByondController.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Controllers.ByondControllerController for managing Api.Models.Byond.Versions More...
Controller for managing Api.Models.Byond.Versions More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Controllers
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_byond_controller_8cs_source.html b/_byond_controller_8cs_source.html index 54559f0ab0..c9b7e53abf 100644 --- a/_byond_controller_8cs_source.html +++ b/_byond_controller_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/ByondController.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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.Globalization;
5 using System.Linq;
6 using System.Threading;
7 using System.Threading.Tasks;
8 using Tgstation.Server.Api;
15 
16 namespace Tgstation.Server.Host.Controllers
17 {
21  [Route(Routes.Byond)]
22  public sealed class ByondController : ModelController<Api.Models.Byond>
23  {
28 
33 
42  public ByondController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, IJobManager jobManager, ILogger<ByondController> logger) : base(databaseContext, authenticationContextFactory, logger, true)
43  {
44  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
45  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
46  }
47 
49  [TgsAuthorize(ByondRights.ReadActive)]
50  public override Task<IActionResult> Read(CancellationToken cancellationToken) => Task.FromResult<IActionResult>(
51  Json(new Api.Models.Byond
52  {
53  Version = instanceManager.GetInstance(Instance).ByondManager.ActiveVersion
54  }));
55 
57  [TgsAuthorize(ByondRights.ListInstalled)]
58  public override Task<IActionResult> List(CancellationToken cancellationToken) => Task.FromResult<IActionResult>(
59  Json(instanceManager.GetInstance(Instance).ByondManager.InstalledVersions.Select(x => new Api.Models.Byond
60  {
61  Version = x
62  })));
63 
65  [TgsAuthorize(ByondRights.ChangeVersion)]
66  public override async Task<IActionResult> Update([FromBody] Api.Models.Byond model, CancellationToken cancellationToken)
67  {
68  if (model == null)
69  throw new ArgumentNullException(nameof(model));
70 
71  if (model.Version == null)
72  return BadRequest(new ErrorMessage { Message = "Missing version!" });
73 
74  var byondManager = instanceManager.GetInstance(Instance).ByondManager;
75 
76  // remove cruff fields
77  var installingVersion = new Version(model.Version.Major, model.Version.Minor);
78 
79  var result = new Api.Models.Byond();
80 
81  if (byondManager.InstalledVersions.Any(x => x == model.Version))
82  {
83  Logger.LogInformation("User ID {0} changing instance ID {1} BYOND version to {2}", AuthenticationContext.User.Id, Instance.Id, installingVersion);
84  await byondManager.ChangeVersion(model.Version, cancellationToken).ConfigureAwait(false);
85  }
86  else
87  {
88  Logger.LogInformation("User ID {0} installing BYOND version to {2} on instance ID {1}", AuthenticationContext.User.Id, Instance.Id, installingVersion);
89 
90  // run the install through the job manager
91  var job = new Models.Job
92  {
93  Description = String.Format(CultureInfo.InvariantCulture, "Install BYOND version {0}", installingVersion),
94  StartedBy = AuthenticationContext.User,
95  CancelRightsType = RightsType.Byond,
96  CancelRight = (ulong)ByondRights.CancelInstall,
98  };
99  await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressHandler, ct) => byondManager.ChangeVersion(installingVersion, ct), cancellationToken).ConfigureAwait(false);
100  result.InstallJob = job.ToApi();
101  }
102 
103  if ((AuthenticationContext.GetRight(RightsType.Byond) & (ulong)ByondRights.ReadActive) != 0)
104  result.Version = byondManager.ActiveVersion;
105  return result.InstallJob != null ? (IActionResult)Accepted(result) : Json(result);
106  }
107  }
108 }
-
const string Byond
The Models.Byond controller
Definition: Routes.cs:34
-
Manages the runtime of Jobs
Definition: IJobManager.cs:12
- - -
ByondRights
Rights for Models.Byond
Definition: ByondRights.cs:9
-
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
+Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Globalization;
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 : ModelController<Api.Models.Byond>
23  {
28 
33 
42  public ByondController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, IJobManager jobManager, ILogger<ByondController> logger) : base(databaseContext, authenticationContextFactory, logger, true)
43  {
44  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
45  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
46  }
47 
49  [TgsAuthorize(ByondRights.ReadActive)]
50  public override Task<IActionResult> Read(CancellationToken cancellationToken) => Task.FromResult<IActionResult>(
51  Json(new Api.Models.Byond
52  {
53  Version = instanceManager.GetInstance(Instance).ByondManager.ActiveVersion
54  }));
55 
57  [TgsAuthorize(ByondRights.ListInstalled)]
58  public override Task<IActionResult> List(CancellationToken cancellationToken) => Task.FromResult<IActionResult>(
59  Json(instanceManager.GetInstance(Instance).ByondManager.InstalledVersions.Select(x => new Api.Models.Byond
60  {
61  Version = x
62  })));
63 
65  [TgsAuthorize(ByondRights.ChangeVersion)]
66  public override async Task<IActionResult> Update([FromBody] Api.Models.Byond model, CancellationToken cancellationToken)
67  {
68  if (model == null)
69  throw new ArgumentNullException(nameof(model));
70 
71  if (model.Version == null)
72  return BadRequest(new ErrorMessage { Message = "Missing version!" });
73 
75 
76  // remove cruff fields
77  var installingVersion = new Version(model.Version.Major, model.Version.Minor);
78 
79  var result = new Api.Models.Byond();
80 
81  if (byondManager.InstalledVersions.Any(x => x == model.Version))
82  {
83  Logger.LogInformation("User ID {0} changing instance ID {1} BYOND version to {2}", AuthenticationContext.User.Id, Instance.Id, installingVersion);
84  await byondManager.ChangeVersion(model.Version, cancellationToken).ConfigureAwait(false);
85  }
86  else
87  {
88  Logger.LogInformation("User ID {0} installing BYOND version to {2} on instance ID {1}", AuthenticationContext.User.Id, Instance.Id, installingVersion);
89 
90  // run the install through the job manager
91  var job = new Models.Job
92  {
93  Description = String.Format(CultureInfo.InvariantCulture, "Install BYOND version {0}", installingVersion),
94  StartedBy = AuthenticationContext.User,
95  CancelRightsType = RightsType.Byond,
96  CancelRight = (ulong)ByondRights.CancelInstall,
98  };
99  await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressHandler, ct) => byondManager.ChangeVersion(installingVersion, ct), cancellationToken).ConfigureAwait(false);
100  result.InstallJob = job.ToApi();
101  }
102 
103  if ((AuthenticationContext.GetRight(RightsType.Byond) & (ulong)ByondRights.ReadActive) != 0)
104  result.Version = byondManager.ActiveVersion;
105  return result.InstallJob != null ? (IActionResult)Accepted(result) : Json(result);
106  }
107  }
108 }
+
const string Byond
The Models.Byond controller
Definition: Routes.cs:34
+
Manages the runtime of Jobs
Definition: IJobManager.cs:12
+ + + +
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
-
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
+
override Task< IActionResult > List(CancellationToken cancellationToken)
Attempt to list entries of the TModel
+
Controller for managing Api.Models.Byond.Versions
+
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
-
readonly IJobManager jobManager
The IJobManager for the ByondController
+
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
-
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
-
An ApiController representing a TModel
+
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
+
An ApiController representing a TModel
- -
long Id
The ID of the User
Definition: User.cs:15
+ +
long Id
The ID of the User
Definition: User.cs:15
override async Task< IActionResult > Update([FromBody] Api.Models.Byond model, CancellationToken cancellationToken)
-
Metadata about a server instance
Definition: Instance.cs:9
- - -
User can read all chat settings except Models.Internal.ChatBot.ConnectionString
-
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+
Metadata about a server instance
Definition: Instance.cs:9
+ + +
override Task< IActionResult > Read(CancellationToken cancellationToken)
Attempt to read a TModel
+
IByondManager ByondManager
The IByondManager for the IInstance
Definition: IInstance.cs:27
+
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- - + +
diff --git a/_byond_executable_lock_8cs.html b/_byond_executable_lock_8cs.html index 9f420d8eec..0a992bfba2 100644 --- a/_byond_executable_lock_8cs.html +++ b/_byond_executable_lock_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Byond/ByondExecutableLock.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Byond
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_byond_executable_lock_8cs_source.html b/_byond_executable_lock_8cs_source.html index ae2bd982c3..d7efe6b62b 100644 --- a/_byond_executable_lock_8cs_source.html +++ b/_byond_executable_lock_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Byond/ByondExecutableLock.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ByondExecutableLock.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Host.Components.Byond
4 {
7  {
9  public Version Version { get; }
10 
12  public string DreamDaemonPath { get; }
13 
15  public string DreamMakerPath { get; }
16 
23  public ByondExecutableLock(Version version, string dreamDaemonPath, string dreamMakerPath)
24  {
25  Version = version ?? throw new ArgumentNullException(nameof(version));
26  DreamDaemonPath = dreamDaemonPath ?? throw new ArgumentNullException(nameof(dreamDaemonPath));
27  DreamMakerPath = dreamMakerPath ?? throw new ArgumentNullException(nameof(dreamMakerPath));
28  }
29 
30  // at one point in design, byond versions were to delete themselves if they weren't the active version
31  // That changed at some point so these functions are intentioanlly left blank
32 
34  public void Dispose() { }
35 
37  public void DoNotDeleteThisSession() { }
38  }
39 }
-
ByondExecutableLock(Version version, string dreamDaemonPath, string dreamMakerPath)
Construct a ByondExecutableLock
-
void DoNotDeleteThisSession()
Call if, during a detach, this version should not be deleted
-
Represents usage of the two primary BYOND server executables
+Go to the documentation of this file.
1 using System;
2 
4 {
7  {
9  public Version Version { get; }
10 
12  public string DreamDaemonPath { get; }
13 
15  public string DreamMakerPath { get; }
16 
23  public ByondExecutableLock(Version version, string dreamDaemonPath, string dreamMakerPath)
24  {
25  Version = version ?? throw new ArgumentNullException(nameof(version));
26  DreamDaemonPath = dreamDaemonPath ?? throw new ArgumentNullException(nameof(dreamDaemonPath));
27  DreamMakerPath = dreamMakerPath ?? throw new ArgumentNullException(nameof(dreamMakerPath));
28  }
29 
30  // at one point in design, byond versions were to delete themselves if they weren't the active version
31  // That changed at some point so these functions are intentioanlly left blank
32 
34  public void Dispose() { }
35 
37  public void DoNotDeleteThisSession() { }
38  }
39 }
ByondExecutableLock(Version version, string dreamDaemonPath, string dreamMakerPath)
Construct a ByondExecutableLock
+ + +
void DoNotDeleteThisSession()
Call if, during a detach, this version should not be deleted
+
Represents usage of the two primary BYOND server executables
+ - - +
diff --git a/_byond_manager_8cs.html b/_byond_manager_8cs.html index a009a2d0b8..3c2adf8b4c 100644 --- a/_byond_manager_8cs.html +++ b/_byond_manager_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Byond/ByondManager.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Byond
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_byond_manager_8cs_source.html b/_byond_manager_8cs_source.html index 0a983e89c7..338ad2e155 100644 --- a/_byond_manager_8cs_source.html +++ b/_byond_manager_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Byond/ByondManager.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
13 namespace Tgstation.Server.Host.Components.Byond
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 
90  public ByondManager(IIOManager ioManager, IByondInstaller byondInstaller, IEventConsumer eventConsumer, ILogger<ByondManager> logger)
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 
203  return new ByondExecutableLock(versionToUse, ioManager.ResolvePath(ioManager.ConcatPath(versionKey, BinPath, byondInstaller.DreamDaemonName)), ioManager.ResolvePath(ioManager.ConcatPath(versionKey, BinPath, byondInstaller.DreamMakerName)));
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 }
readonly IIOManager ioManager
The IIOManager for the ByondManager
Definition: ByondManager.cs:49
-
Consumes EventTypes and takes the appropriate actions
- - -
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
+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
+
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
+
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< IByondExecutableLock > UseExecutables(Version requiredVersion, CancellationToken cancellationToken)
Lock the current installation&#39;s location and return a IByondExecutableLock
+
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
+ -
For downloading and installing BYOND extractions for a given system
-
async Task InstallVersion(Version version, CancellationToken cancellationToken)
Installs a BYOND version if it isn&#39;t already
-
For managing the BYOND installation
-
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
+
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
+ +
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
+
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
- +
async Task ChangeVersion(Version version, CancellationToken cancellationToken)
Change the active BYOND version
+ -
readonly IByondInstaller byondInstaller
The IByondInstaller for the ByondManager
Definition: ByondManager.cs:54
-
Interface for using filesystems
Definition: IIOManager.cs:11
-
readonly SemaphoreSlim semaphore
The SemaphoreSlim for the ByondManager
Definition: ByondManager.cs:74
- -
static async Task< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore
-
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 IByondInstaller byondInstaller
The IByondInstaller for the ByondManager
Definition: ByondManager.cs:54
+
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
+ +
const string BinPath
The path to the BYOND bin folder
Definition: ByondManager.cs:21
+ +
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
+ +
diff --git a/_byond_rights_8cs.html b/_byond_rights_8cs.html index f45ead4a64..786e2d8cba 100644 --- a/_byond_rights_8cs.html +++ b/_byond_rights_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/ByondRights.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Api +  namespace  Tgstation.Server.Api.Rights   @@ -113,8 +98,8 @@ Enumerations
  Tgstation.Server.Api.Rights.ByondRights.CancelInstall = 8
- } - + } +
 Rights for Models.Byond More...
 Rights for Models.Byond More...
 
@@ -122,7 +107,7 @@ Enumerations diff --git a/_byond_rights_8cs_source.html b/_byond_rights_8cs_source.html index 2285d35a3a..74d7e057b5 100644 --- a/_byond_rights_8cs_source.html +++ b/_byond_rights_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/ByondRights.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
ByondRights.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Api.Rights
4 {
8  [Flags]
9  public enum ByondRights : ulong
10  {
14  None = 0,
15 
19  ReadActive = 1,
20 
24  ListInstalled = 2,
25 
29  ChangeVersion = 4,
30 
34  CancelInstall = 8
35  }
36 }
ByondRights
Rights for Models.Byond
Definition: ByondRights.cs:9
- -
User may list all installed BYOND versions
- -
User may check the active installed BYOND version
- -
User may cancel version installations
-
User can change Models.Administration.NewVersion
- +Go to the documentation of this file.
1 using System;
2 
4 {
8  [Flags]
9  public enum ByondRights : ulong
10  {
14  None = 0,
15 
19  ReadActive = 1,
20 
24  ListInstalled = 2,
25 
29  ChangeVersion = 4,
30 
34  CancelInstall = 8
35  }
36 }
ByondRights
Rights for Models.Byond
Definition: ByondRights.cs:9
+
User may list all installed BYOND versions
+
User may check the active installed BYOND version
+ +
User may cancel version installations
+ +
User can change Models.Administration.NewVersion
diff --git a/_byond_test_8cs.html b/_byond_test_8cs.html index ab1ffc4fe6..d4f78b95b7 100644 --- a/_byond_test_8cs.html +++ b/_byond_test_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Tests/Instance/ByondTest.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Tests
 
namespace  Tgstation.Server.Tests.Instance
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_byond_test_8cs_source.html b/_byond_test_8cs_source.html index 1f2bf9c4b8..db47f0a716 100644 --- a/_byond_test_8cs_source.html +++ b/_byond_test_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Tests/Instance/ByondTest.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ByondTest.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.Threading;
4 using System.Threading.Tasks;
6 
7 namespace Tgstation.Server.Tests.Instance
8 {
9  sealed class ByondTest
10  {
13 
14  public ByondTest(IByondClient byondClient, IJobsClient jobsClient)
15  {
16  this.byondClient = byondClient ?? throw new ArgumentNullException(nameof(byondClient));
17  this.jobsClient = jobsClient ?? throw new ArgumentNullException(nameof(jobsClient));
18  }
19 
20  public async Task Run(CancellationToken cancellationToken)
21  {
22  await TestNoVersion(cancellationToken).ConfigureAwait(false);
23  await TestInstall511(cancellationToken).ConfigureAwait(false);
24  }
25 
26  async Task TestInstall511(CancellationToken cancellationToken)
27  {
28  var newModel = new Api.Models.Byond
29  {
30  Version = new Version(511, 1385)
31  };
32  var test = await byondClient.SetActiveVersion(newModel, cancellationToken).ConfigureAwait(false);
33  Assert.IsNotNull(test.InstallJob);
34  Assert.IsNull(test.Version);
35  var job = test.InstallJob;
36  var maxWait = 60; //it's 10MB max give me a break
37  do
38  {
39  await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
40  job = await jobsClient.GetId(job, cancellationToken).ConfigureAwait(false);
41  --maxWait;
42  }
43  while (!job.StoppedAt.HasValue && maxWait > 0);
44  if (!job.StoppedAt.HasValue)
45  {
46  await jobsClient.Cancel(job, cancellationToken).ConfigureAwait(false);
47  Assert.Fail("Byond installation job timed out!");
48  }
49 
50  if (job.ExceptionDetails != null)
51  Assert.Fail(job.ExceptionDetails);
52 
53  var currentShit = await byondClient.ActiveVersion(cancellationToken).ConfigureAwait(false);
54  Assert.AreEqual(newModel.Version, currentShit.Version);
55  }
56 
57  async Task TestNoVersion(CancellationToken cancellationToken)
58  {
59  var allVersionsTask = byondClient.InstalledVersions(cancellationToken);
60  var currentShit = await byondClient.ActiveVersion(cancellationToken).ConfigureAwait(false);
61  Assert.IsNotNull(currentShit);
62  Assert.IsNull(currentShit.InstallJob);
63  Assert.IsNull(currentShit.Version);
64  var otherShit = await allVersionsTask.ConfigureAwait(false);
65  Assert.IsNotNull(otherShit);
66  Assert.AreEqual(0, otherShit.Count);
67  }
68  }
69 }
-
For managing the Byond installation
Definition: IByondClient.cs:11
+Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.Threading;
4 using System.Threading.Tasks;
6 
8 {
9  sealed class ByondTest
10  {
13 
15  {
16  this.byondClient = byondClient ?? throw new ArgumentNullException(nameof(byondClient));
17  this.jobsClient = jobsClient ?? throw new ArgumentNullException(nameof(jobsClient));
18  }
19 
20  public async Task Run(CancellationToken cancellationToken)
21  {
22  await TestNoVersion(cancellationToken).ConfigureAwait(false);
23  await TestInstall511(cancellationToken).ConfigureAwait(false);
24  }
25 
26  async Task TestInstall511(CancellationToken cancellationToken)
27  {
28  var newModel = new Api.Models.Byond
29  {
30  Version = new Version(511, 1385)
31  };
32  var test = await byondClient.SetActiveVersion(newModel, cancellationToken).ConfigureAwait(false);
33  Assert.IsNotNull(test.InstallJob);
34  Assert.IsNull(test.Version);
35  var job = test.InstallJob;
36  var maxWait = 60; //it's 10MB max give me a break
37  do
38  {
39  await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
40  job = await jobsClient.GetId(job, cancellationToken).ConfigureAwait(false);
41  --maxWait;
42  }
43  while (!job.StoppedAt.HasValue && maxWait > 0);
44  if (!job.StoppedAt.HasValue)
45  {
46  await jobsClient.Cancel(job, cancellationToken).ConfigureAwait(false);
47  Assert.Fail("Byond installation job timed out!");
48  }
49 
50  if (job.ExceptionDetails != null)
51  Assert.Fail(job.ExceptionDetails);
52 
53  var currentShit = await byondClient.ActiveVersion(cancellationToken).ConfigureAwait(false);
54  Assert.AreEqual(newModel.Version, currentShit.Version);
55  }
56 
57  async Task TestNoVersion(CancellationToken cancellationToken)
58  {
59  var allVersionsTask = byondClient.InstalledVersions(cancellationToken);
60  var currentShit = await byondClient.ActiveVersion(cancellationToken).ConfigureAwait(false);
61  Assert.IsNotNull(currentShit);
62  Assert.IsNull(currentShit.InstallJob);
63  Assert.IsNull(currentShit.Version);
64  var otherShit = await allVersionsTask.ConfigureAwait(false);
65  Assert.IsNotNull(otherShit);
66  Assert.AreEqual(0, otherShit.Count);
67  }
68  }
69 }
+
For managing the Byond installation
Definition: IByondClient.cs:11
- +
Task< IReadOnlyList< Byond > > InstalledVersions(CancellationToken cancellationToken)
Get all installed Byond System.Versions
ByondTest(IByondClient byondClient, IJobsClient jobsClient)
Definition: ByondTest.cs:14
async Task TestInstall511(CancellationToken cancellationToken)
Definition: ByondTest.cs:26
- + +
async Task TestNoVersion(CancellationToken cancellationToken)
Definition: ByondTest.cs:57
- +
Task< Byond > ActiveVersion(CancellationToken cancellationToken)
Get the Byond active System.Version information
+
Task< Byond > SetActiveVersion(Byond byond, CancellationToken cancellationToken)
Updates the Byond information
+ +
Task< Job > GetId(Job job, CancellationToken cancellationToken)
Get a job
async Task Run(CancellationToken cancellationToken)
Definition: ByondTest.cs:20
- + +
Task Cancel(Job job, CancellationToken cancellationToken)
Cancels a job
diff --git a/_channel_8cs.html b/_channel_8cs.html index 29472b720f..96d06484dc 100644 --- a/_channel_8cs.html +++ b/_channel_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Channel.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Components.Chat.Channel - Represents a Providers.IProvider channel More...
+ Represents a Providers.IProvider channel More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_channel_8cs_source.html b/_channel_8cs_source.html index c91068db65..ca556402c2 100644 --- a/_channel_8cs_source.html +++ b/_channel_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Channel.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Channel.cs
-Go to the documentation of this file.
1 using Newtonsoft.Json;
2 using System;
3 using System.Globalization;
4 
5 namespace Tgstation.Server.Host.Components.Chat
6 {
10  public sealed class Channel
11  {
15  public string Id { get; set; }
16 
21  [JsonIgnore]
22  public ulong RealId
23  {
24  get => UInt64.Parse(Id, CultureInfo.InvariantCulture);
25  set => Id = value.ToString(CultureInfo.InvariantCulture);
26  }
27 
31  public string FriendlyName { get; set; }
32 
36  public string ConnectionName { get; set; }
37 
41  public bool IsAdminChannel { get; set; }
42 
46  public bool IsPrivateChannel { get; set; }
47 
51  public string Tag { get; set; }
52  }
53 }
- -
Represents a Providers.IProvider channel
Definition: Channel.cs:10
- - +Go to the documentation of this file.
1 using Newtonsoft.Json;
2 using System;
3 using System.Globalization;
4 
6 {
10  public sealed class Channel
11  {
15  public string Id { get; set; }
16 
21  [JsonIgnore]
22  public ulong RealId
23  {
24  get => UInt64.Parse(Id, CultureInfo.InvariantCulture);
25  set => Id = value.ToString(CultureInfo.InvariantCulture);
26  }
27 
31  public string FriendlyName { get; set; }
32 
36  public string ConnectionName { get; set; }
37 
41  public bool IsAdminChannel { get; set; }
42 
46  public bool IsPrivateChannel { get; set; }
47 
51  public string Tag { get; set; }
52  }
53 }
+ +
string FriendlyName
The user friendly name of the Channel
Definition: Channel.cs:31
+
bool IsPrivateChannel
If this is a 1-to-1 chat channel
Definition: Channel.cs:46
+
Represents a Providers.IProvider channel
Definition: Channel.cs:10
+
string Id
Backing field for RealId. Represented as a string to avoid BYOND percision loss
Definition: Channel.cs:15
+
string ConnectionName
The name of the connection the Channel belongs to
Definition: Channel.cs:36
+
ulong RealId
The Providers.IProvider channel Id.
Definition: Channel.cs:23
+
bool IsAdminChannel
If this is considered a channel for admin commands
Definition: Channel.cs:41
diff --git a/_channel_mapping_8cs.html b/_channel_mapping_8cs.html index 84589bc547..e763d04bbd 100644 --- a/_channel_mapping_8cs.html +++ b/_channel_mapping_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/ChannelMapping.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Components.Chat.ChannelMapping - Represents a mapping of a Channel.RealId More...
+ Represents a mapping of a Channel.RealId More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_channel_mapping_8cs_source.html b/_channel_mapping_8cs_source.html index ecc72901c9..c979d7afbb 100644 --- a/_channel_mapping_8cs_source.html +++ b/_channel_mapping_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/ChannelMapping.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ChannelMapping.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Host.Components.Chat
2 {
6  sealed class ChannelMapping
7  {
11  public long ProviderId { get; set; }
12 
16  public ulong ProviderChannelId { get; set; }
17 
21  public bool IsWatchdogChannel { get; set; }
22 
26  public bool IsUpdatesChannel { get; set; }
27 
31  public Channel Channel { get; set; }
32  }
33 }
Represents a mapping of a Channel.RealId
- -
Represents a Providers.IProvider channel
Definition: Channel.cs:10
- +Go to the documentation of this file.
2 {
6  sealed class ChannelMapping
7  {
11  public long ProviderId { get; set; }
12 
16  public ulong ProviderChannelId { get; set; }
17 
21  public bool IsWatchdogChannel { get; set; }
22 
26  public bool IsUpdatesChannel { get; set; }
27 
31  public Channel Channel { get; set; }
32  }
33 }
bool IsWatchdogChannel
If Channel is a watchdog channel
+
Represents a mapping of a Channel.RealId
+ +
bool IsUpdatesChannel
If the Channel is an updates channel
+
long ProviderId
The Id of the Providers.IProvider
+
Represents a Providers.IProvider channel
Definition: Channel.cs:10
+
ulong ProviderChannelId
The original Components.Chat.Channel.RealId
diff --git a/_chat_8cs.html b/_chat_8cs.html index ac7ba25062..d658fc8d4a 100644 --- a/_chat_8cs.html +++ b/_chat_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Chat.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_chat_8cs_source.html b/_chat_8cs_source.html index 83a10065c5..bbb71ae2e3 100644 --- a/_chat_8cs_source.html +++ b/_chat_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Chat.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Chat.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.Globalization;
6 using System.Linq;
7 using System.Threading;
8 using System.Threading.Tasks;
13 using Tgstation.Server.Host.IO;
14 
15 namespace Tgstation.Server.Host.Components.Chat
16 {
18  // TODO: Decomplexify
19  #pragma warning disable CA1506
20  sealed class Chat : IChat, IRestartHandler
21  {
22  const string CommonMention = "!tgs";
23 
28 
33 
38 
43 
48 
52  readonly ILoggerFactory loggerFactory;
53 
57  readonly ILogger<Chat> logger;
58 
62  readonly Dictionary<string, ICommand> builtinCommands;
63 
67  readonly Dictionary<long, IProvider> providers;
68 
72  readonly Dictionary<ulong, ChannelMapping> mappedChannels;
73 
77  readonly List<IJsonTrackingContext> trackingContexts;
78 
82  readonly CancellationTokenSource handlerCts;
83 
87  readonly List<Models.ChatBot> initialChatBots;
88 
93 
98 
102  TaskCompletionSource<object> connectionsUpdated;
103 
108 
112  bool started;
113 
125  public Chat(IProviderFactory providerFactory, IIOManager ioManager, ICommandFactory commandFactory, IServerControl serverControl, IAsyncDelayer asyncDelayer, ILoggerFactory loggerFactory, ILogger<Chat> logger, IEnumerable<Models.ChatBot> initialChatBots)
126  {
127  this.providerFactory = providerFactory ?? throw new ArgumentNullException(nameof(providerFactory));
128  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
129  this.commandFactory = commandFactory ?? throw new ArgumentNullException(nameof(commandFactory));
130  if (serverControl == null)
131  throw new ArgumentNullException(nameof(serverControl));
132  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
133  this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
134  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
135  this.initialChatBots = initialChatBots?.ToList() ?? throw new ArgumentNullException(nameof(initialChatBots));
136 
137  restartRegistration = serverControl.RegisterForRestart(this);
138 
139  builtinCommands = new Dictionary<string, ICommand>();
140  providers = new Dictionary<long, IProvider>();
141  mappedChannels = new Dictionary<ulong, ChannelMapping>();
142  trackingContexts = new List<IJsonTrackingContext>();
143  handlerCts = new CancellationTokenSource();
144  connectionsUpdated = new TaskCompletionSource<object>();
145  channelIdCounter = 1;
146  }
147 
149  public void Dispose()
150  {
151  restartRegistration.Dispose();
152  handlerCts.Dispose();
153  foreach (var I in providers)
154  I.Value.Dispose();
155  }
156 
164  async Task<IProvider> RemoveProvider(long connectionId, bool updateTrackings, CancellationToken cancellationToken)
165  {
166  IProvider provider;
167  lock (providers)
168  if (!providers.TryGetValue(connectionId, out provider))
169  return null;
170  Task task;
171  lock (mappedChannels)
172  {
173  foreach (var I in mappedChannels.Where(x => x.Value.ProviderId == connectionId).Select(x => x.Key).ToList())
174  mappedChannels.Remove(I);
175 
176  if (updateTrackings)
177  lock (trackingContexts)
178  task = Task.WhenAll(trackingContexts.Select(x => x.SetChannels(mappedChannels.Select(y => y.Value.Channel), cancellationToken)));
179  else
180  task = Task.CompletedTask;
181  }
182 
183  await task.ConfigureAwait(false);
184  return provider;
185  }
186 
194  async Task ProcessMessage(IProvider provider, Message message, CancellationToken cancellationToken)
195  {
196  // map the channel if it's private and we haven't seen it
197  lock (providers)
198  {
199  var providerId = providers.Where(x => x.Value == provider).Select(x => x.Key).First();
200  var enumerable = mappedChannels.Where(x => x.Value.ProviderId == providerId && x.Value.ProviderChannelId == message.User.Channel.RealId);
201  if (message.User.Channel.IsPrivateChannel)
202  lock (mappedChannels)
203  {
204  if (!provider.Connected)
205  return;
206  if (!enumerable.Any())
207  {
208  ulong newId;
209  lock (this)
210  newId = channelIdCounter++;
211  mappedChannels.Add(newId, new ChannelMapping
212  {
213  IsWatchdogChannel = false,
214  ProviderChannelId = message.User.Channel.RealId,
215  ProviderId = providerId,
216  Channel = message.User.Channel
217  });
218  message.User.Channel.RealId = newId;
219  }
220  else
221  message.User.Channel.RealId = enumerable.First().Key;
222  }
223  else
224  {
225  // need to add tag and isAdminChannel
226  var mapping = enumerable.First().Value;
227  message.User.Channel.Id = mapping.Channel.Id;
228  message.User.Channel.Tag = mapping.Channel.Tag;
229  message.User.Channel.IsAdminChannel = mapping.Channel.IsAdminChannel;
230  }
231  }
232 
233  var splits = new List<string>(message.Content.Trim().Split(' '));
234  var address = splits[0];
235  if (address.Length > 1 && (address[address.Length - 1] == ':' || address[address.Length - 1] == ','))
236  address = address.Substring(0, address.Length - 1);
237 
238  address = address.ToUpperInvariant();
239 
240  var addressed = address == CommonMention.ToUpperInvariant() || address == provider.BotMention.ToUpperInvariant();
241 
242  // no mention
243  if (!addressed && !message.User.Channel.IsPrivateChannel)
244  return;
245 
246  logger.LogTrace("Chat command: {0}. User (True provider Id): {1}", message.Content, JsonConvert.SerializeObject(message.User));
247 
248  if (addressed)
249  splits.RemoveAt(0);
250 
251  if (splits.Count == 0)
252  {
253  // just a mention
254  await SendMessage("Hi!", new List<ulong> { message.User.Channel.RealId }, cancellationToken).ConfigureAwait(false);
255  return;
256  }
257 
258  var command = splits[0].ToUpperInvariant();
259  splits.RemoveAt(0);
260  var arguments = String.Join(" ", splits);
261 
262  try
263  {
264  async Task<ICommand> GetCommand(string commandName)
265  {
266  if (!builtinCommands.TryGetValue(commandName, out var handler))
267  {
268  var tasks = trackingContexts.Select(x => x.GetCustomCommands(cancellationToken));
269  await Task.WhenAll(tasks).ConfigureAwait(false);
270  handler = tasks.SelectMany(x => x.Result).Where(x => x.Name.ToUpperInvariant() == commandName).FirstOrDefault();
271  }
272 
273  return handler;
274  }
275 
276  const string UnknownCommandMessage = "Unknown command! Type '?' or 'help' for available commands.";
277 
278  if (command == "HELP" || command == "?")
279  {
280  string helpText;
281  if (splits.Count == 0)
282  {
283  var allCommands = builtinCommands.Select(x => x.Value).ToList();
284  var tasks = trackingContexts.Select(x => x.GetCustomCommands(cancellationToken)).ToList();
285  await Task.WhenAll(tasks).ConfigureAwait(false);
286  allCommands.AddRange(tasks.SelectMany(x => x.Result));
287  helpText = String.Format(CultureInfo.InvariantCulture, "Available commands (Type '?' or 'help' and then a command name for more details): {0}", String.Join(", ", allCommands.Select(x => x.Name)));
288  }
289  else
290  {
291  var helpHandler = await GetCommand(splits[0].ToUpperInvariant()).ConfigureAwait(false);
292  if (helpHandler != default)
293  helpText = String.Format(CultureInfo.InvariantCulture, "{0}: {1}{2}", helpHandler.Name, helpHandler.HelpText, helpHandler.AdminOnly ? " - May only be used in admin channels" : String.Empty);
294  else
295  helpText = UnknownCommandMessage;
296  }
297 
298  await SendMessage(helpText, new List<ulong> { message.User.Channel.RealId }, cancellationToken).ConfigureAwait(false);
299  return;
300  }
301 
302  var commandHandler = await GetCommand(command).ConfigureAwait(false);
303 
304  if (commandHandler == default)
305  {
306  await SendMessage(UnknownCommandMessage, new List<ulong> { message.User.Channel.RealId }, cancellationToken).ConfigureAwait(false);
307  return;
308  }
309 
310  if (commandHandler.AdminOnly && !message.User.Channel.IsAdminChannel)
311  {
312  await SendMessage("Use this command in an admin channel!", new List<ulong> { message.User.Channel.RealId }, cancellationToken).ConfigureAwait(false);
313  return;
314  }
315 
316  var result = await commandHandler.Invoke(arguments, message.User, cancellationToken).ConfigureAwait(false);
317  if (result != null)
318  await SendMessage(result, new List<ulong> { message.User.Channel.RealId }, cancellationToken).ConfigureAwait(false);
319  }
320  catch (OperationCanceledException)
321  {
322  throw;
323  }
324  catch (Exception e)
325  {
326  // error bc custom commands should reply about why it failed
327  logger.LogError("Error processing chat command: {0}", e);
328  await SendMessage("Internal error processing command!", new List<ulong> { message.User.Channel.RealId }, cancellationToken).ConfigureAwait(false);
329  }
330  }
331 
337  async Task MonitorMessages(CancellationToken cancellationToken)
338  {
339  var messageTasks = new Dictionary<IProvider, Task<Message>>();
340  try
341  {
342  while (!cancellationToken.IsCancellationRequested)
343  {
344  // prune disconnected providers
345  foreach (var I in messageTasks.Where(x => !x.Key.Connected).ToList())
346  messageTasks.Remove(I.Key);
347 
348  // add new ones
349  Task updatedTask;
350  lock (this)
351  updatedTask = connectionsUpdated.Task;
352  lock (providers)
353  foreach (var I in providers)
354  if (I.Value.Connected && !messageTasks.ContainsKey(I.Value))
355  messageTasks.Add(I.Value, I.Value.NextMessage(cancellationToken));
356 
357  if (messageTasks.Count == 0)
358  {
359  await asyncDelayer.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
360  continue;
361  }
362 
363  // wait for a message
364  await Task.WhenAny(updatedTask, Task.WhenAny(messageTasks.Select(x => x.Value))).ConfigureAwait(false);
365 
366  // process completed ones
367  foreach (var I in messageTasks.Where(x => x.Value.IsCompleted).ToList())
368  {
369  var message = await I.Value.ConfigureAwait(false);
370 
371  await ProcessMessage(I.Key, message, cancellationToken).ConfigureAwait(false);
372 
373  messageTasks.Remove(I.Key);
374  }
375  }
376  }
377  catch (OperationCanceledException)
378  {
379  logger.LogTrace("Message processing loop cancelled!");
380  }
381  catch (Exception e)
382  {
383  logger.LogError("Message monitor crashed! Exception: {0}", e);
384  }
385  }
386 
388  public async Task ChangeChannels(long connectionId, IEnumerable<Api.Models.ChatChannel> newChannels, CancellationToken cancellationToken)
389  {
390  if (newChannels == null)
391  throw new ArgumentNullException(nameof(newChannels));
392  var provider = await RemoveProvider(connectionId, false, cancellationToken).ConfigureAwait(false);
393  if (provider == null)
394  return;
395  var results = await provider.MapChannels(newChannels, cancellationToken).ConfigureAwait(false);
396  if (results == null) // aborted
397  return;
398  var mappings = Enumerable.Zip(newChannels, results, (x, y) => new ChannelMapping
399  {
400  IsWatchdogChannel = x.IsWatchdogChannel == true,
401  IsUpdatesChannel = x.IsUpdatesChannel == true,
402  ProviderChannelId = y.RealId,
403  ProviderId = connectionId,
404  Channel = y
405  });
406 
407  ulong baseId;
408  lock (this)
409  {
410  baseId = channelIdCounter;
411  channelIdCounter += (ulong)results.Count;
412  }
413 
414  Task task;
415  lock (mappedChannels)
416  {
417  lock (providers)
418  if (!providers.TryGetValue(connectionId, out IProvider verify) || verify != provider) // aborted again
419  return;
420  foreach (var I in mappings)
421  {
422  var newId = baseId++;
423  mappedChannels.Add(newId, I);
424  I.Channel.RealId = newId;
425  }
426 
427  lock (trackingContexts)
428  task = Task.WhenAll(trackingContexts.Select(x => x.SetChannels(mappedChannels.Select(y => y.Value.Channel), cancellationToken)));
429  }
430 
431  await task.ConfigureAwait(false);
432  }
433 
435  public async Task ChangeSettings(ChatBot newSettings, CancellationToken cancellationToken)
436  {
437  if (newSettings == null)
438  throw new ArgumentNullException(nameof(newSettings));
439  IProvider provider;
440 
441  async Task DisconnectProvider(IProvider p)
442  {
443  try
444  {
445  await p.Disconnect(cancellationToken).ConfigureAwait(false);
446  }
447  finally
448  {
449  p.Dispose();
450  }
451  }
452 
453  Task disconnectTask;
454  lock (providers)
455  {
456  // raw settings changes forces a rebuild of the provider
457  if (providers.TryGetValue(newSettings.Id, out provider))
458  {
459  providers.Remove(newSettings.Id);
460  disconnectTask = DisconnectProvider(provider);
461  }
462  else
463  disconnectTask = Task.CompletedTask;
464  if (newSettings.Enabled.Value)
465  {
466  provider = providerFactory.CreateProvider(newSettings);
467  providers.Add(newSettings.Id, provider);
468  }
469  }
470 
471  lock (mappedChannels)
472  foreach (var I in mappedChannels.Where(x => x.Value.ProviderId == newSettings.Id).Select(x => x.Key).ToList())
473  mappedChannels.Remove(I);
474 
475  await disconnectTask.ConfigureAwait(false);
476 
477  if (started)
478  {
479  if (newSettings.Enabled.Value)
480  await provider.Connect(cancellationToken).ConfigureAwait(false);
481  lock (this)
482  {
483  // same thread shennanigans
484  var oldOne = connectionsUpdated;
485  connectionsUpdated = new TaskCompletionSource<object>();
486  oldOne.SetResult(null);
487  }
488  }
489  }
490 
492  public Task SendMessage(string message, IEnumerable<ulong> channelIds, CancellationToken cancellationToken)
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  }
512 
514  public Task SendWatchdogMessage(string message, CancellationToken cancellationToken)
515  {
516  List<ulong> wdChannels;
517  message = String.Format(CultureInfo.InvariantCulture, "WD: {0}", message);
518  lock (mappedChannels) // so it doesn't change while we're using it
519  wdChannels = mappedChannels.Where(x => x.Value.IsWatchdogChannel).Select(x => x.Key).ToList();
520  return SendMessage(message, wdChannels, cancellationToken);
521  }
522 
524  public Task SendUpdateMessage(string message, CancellationToken cancellationToken)
525  {
526  List<ulong> wdChannels;
527  message = String.Format(CultureInfo.InvariantCulture, "DM: {0}", message);
528  lock (mappedChannels) // so it doesn't change while we're using it
529  wdChannels = mappedChannels.Where(x => x.Value.IsUpdatesChannel).Select(x => x.Key).ToList();
530  return SendMessage(message, wdChannels, cancellationToken);
531  }
532 
534  public async Task StartAsync(CancellationToken cancellationToken)
535  {
536  foreach (var I in commandFactory.GenerateCommands())
537  builtinCommands.Add(I.Name.ToUpperInvariant(), I);
538  await Task.WhenAll(initialChatBots.Select(x => ChangeSettings(x, cancellationToken))).ConfigureAwait(false);
539  await Task.WhenAll(providers.Select(x => x.Value).Select(x => x.Connect(cancellationToken))).ConfigureAwait(false);
540  await Task.WhenAll(initialChatBots.Select(x => ChangeChannels(x.Id, x.Channels, cancellationToken))).ConfigureAwait(false);
541  chatHandler = MonitorMessages(handlerCts.Token);
542  started = true;
543  }
544 
546  public async Task StopAsync(CancellationToken cancellationToken)
547  {
548  handlerCts.Cancel();
549  await chatHandler.ConfigureAwait(false);
550  await Task.WhenAll(providers.Select(x => x.Value).Select(x => x.Disconnect(cancellationToken))).ConfigureAwait(false);
551  }
552 
554  public async Task<IJsonTrackingContext> TrackJsons(string basePath, string channelsJsonName, string commandsJsonName, CancellationToken cancellationToken)
555  {
556  if (customCommandHandler == null)
557  throw new InvalidOperationException("RegisterCommandHandler() hasn't been called!");
558  JsonTrackingContext context = null;
559  context = new JsonTrackingContext(
560  ioManager,
561  customCommandHandler,
562  loggerFactory.CreateLogger<JsonTrackingContext>(),
563  () =>
564  {
565  lock (trackingContexts)
566  trackingContexts.Remove(context);
567  },
568  ioManager.ConcatPath(basePath, commandsJsonName),
569  ioManager.ConcatPath(basePath, channelsJsonName));
570  Task task;
571  lock (trackingContexts)
572  {
573  trackingContexts.Add(context);
574  lock (mappedChannels)
575  task = context.SetChannels(mappedChannels.Select(y => y.Value.Channel), cancellationToken);
576  }
577 
578  await task.ConfigureAwait(false);
579  return context;
580  }
581 
583  public bool Connected(long connectionId)
584  {
585  lock (providers)
586  return providers.TryGetValue(connectionId, out var provider) && provider.Connected;
587  }
588 
590  public void RegisterCommandHandler(ICustomCommandHandler customCommandHandler)
591  {
592  if (this.customCommandHandler != null)
593  throw new InvalidOperationException("RegisterCommandHandler() already called!");
594  this.customCommandHandler = customCommandHandler ?? throw new ArgumentNullException(nameof(customCommandHandler));
595  }
596 
598  public async Task DeleteConnection(long connectionId, CancellationToken cancellationToken)
599  {
600  var provider = await RemoveProvider(connectionId, true, cancellationToken).ConfigureAwait(false);
601  if (provider != null)
602  try
603  {
604  await provider.Disconnect(cancellationToken).ConfigureAwait(false);
605  }
606  finally
607  {
608  provider.Dispose();
609  }
610  }
611 
613  public Task HandleRestart(Version updateVersion, CancellationToken cancellationToken)
614  {
615  var message = updateVersion == null ? "TGS: Restart requested..." : String.Format(CultureInfo.InvariantCulture, "TGS: Updating to version {0}...", updateVersion);
616  List<ulong> wdChannels;
617  lock (mappedChannels) // so it doesn't change while we're using it
618  wdChannels = mappedChannels.Select(x => x.Key).ToList();
619  return SendMessage(message, wdChannels, cancellationToken);
620  }
621  }
622 }
void RegisterCommandHandler(ICustomCommandHandler customCommandHandler)
Registers a customCommandHandler to use
Definition: Chat.cs:590
-
bool IsWatchdogChannel
If Channel is a watchdog channel
-
Represents a mapping of a Channel.RealId
-
User User
The Components.Chat.User who sent the Message
Definition: Message.cs:16
-
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the Chat
Definition: Chat.cs:52
+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.Globalization;
6 using System.Linq;
7 using System.Threading;
8 using System.Threading.Tasks;
13 using Tgstation.Server.Host.IO;
14 
16 {
18  // TODO: Decomplexify
19  #pragma warning disable CA1506
20  sealed class Chat : IChat, IRestartHandler
21  {
22  const string CommonMention = "!tgs";
23 
28 
33 
38 
43 
48 
52  readonly ILoggerFactory loggerFactory;
53 
57  readonly ILogger<Chat> logger;
58 
62  readonly Dictionary<string, ICommand> builtinCommands;
63 
67  readonly Dictionary<long, IProvider> providers;
68 
72  readonly Dictionary<ulong, ChannelMapping> mappedChannels;
73 
77  readonly List<IJsonTrackingContext> trackingContexts;
78 
82  readonly CancellationTokenSource handlerCts;
83 
87  readonly List<Models.ChatBot> initialChatBots;
88 
93 
98 
102  TaskCompletionSource<object> connectionsUpdated;
103 
108 
112  bool started;
113 
126  {
127  this.providerFactory = providerFactory ?? throw new ArgumentNullException(nameof(providerFactory));
128  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
129  this.commandFactory = commandFactory ?? throw new ArgumentNullException(nameof(commandFactory));
130  if (serverControl == null)
131  throw new ArgumentNullException(nameof(serverControl));
132  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
133  this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
134  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
135  this.initialChatBots = initialChatBots?.ToList() ?? throw new ArgumentNullException(nameof(initialChatBots));
136 
137  restartRegistration = serverControl.RegisterForRestart(this);
138 
139  builtinCommands = new Dictionary<string, ICommand>();
140  providers = new Dictionary<long, IProvider>();
141  mappedChannels = new Dictionary<ulong, ChannelMapping>();
142  trackingContexts = new List<IJsonTrackingContext>();
143  handlerCts = new CancellationTokenSource();
144  connectionsUpdated = new TaskCompletionSource<object>();
145  channelIdCounter = 1;
146  }
147 
149  public void Dispose()
150  {
151  restartRegistration.Dispose();
152  handlerCts.Dispose();
153  foreach (var I in providers)
154  I.Value.Dispose();
155  }
156 
164  async Task<IProvider> RemoveProvider(long connectionId, bool updateTrackings, CancellationToken cancellationToken)
165  {
166  IProvider provider;
167  lock (providers)
168  if (!providers.TryGetValue(connectionId, out provider))
169  return null;
170  Task task;
171  lock (mappedChannels)
172  {
173  foreach (var I in mappedChannels.Where(x => x.Value.ProviderId == connectionId).Select(x => x.Key).ToList())
174  mappedChannels.Remove(I);
175 
176  if (updateTrackings)
177  lock (trackingContexts)
178  task = Task.WhenAll(trackingContexts.Select(x => x.SetChannels(mappedChannels.Select(y => y.Value.Channel), cancellationToken)));
179  else
180  task = Task.CompletedTask;
181  }
182 
183  await task.ConfigureAwait(false);
184  return provider;
185  }
186 
194  async Task ProcessMessage(IProvider provider, Message message, CancellationToken cancellationToken)
195  {
196  // map the channel if it's private and we haven't seen it
197  lock (providers)
198  {
199  var providerId = providers.Where(x => x.Value == provider).Select(x => x.Key).First();
200  var enumerable = mappedChannels.Where(x => x.Value.ProviderId == providerId && x.Value.ProviderChannelId == message.User.Channel.RealId);
201  if (message.User.Channel.IsPrivateChannel)
202  lock (mappedChannels)
203  {
204  if (!provider.Connected)
205  return;
206  if (!enumerable.Any())
207  {
208  ulong newId;
209  lock (this)
210  newId = channelIdCounter++;
211  mappedChannels.Add(newId, new ChannelMapping
212  {
213  IsWatchdogChannel = false,
214  ProviderChannelId = message.User.Channel.RealId,
215  ProviderId = providerId,
216  Channel = message.User.Channel
217  });
218  message.User.Channel.RealId = newId;
219  }
220  else
221  message.User.Channel.RealId = enumerable.First().Key;
222  }
223  else
224  {
225  // need to add tag and isAdminChannel
226  var mapping = enumerable.First().Value;
227  message.User.Channel.Id = mapping.Channel.Id;
228  message.User.Channel.Tag = mapping.Channel.Tag;
229  message.User.Channel.IsAdminChannel = mapping.Channel.IsAdminChannel;
230  }
231  }
232 
233  var splits = new List<string>(message.Content.Trim().Split(' '));
234  var address = splits[0];
235  if (address.Length > 1 && (address[address.Length - 1] == ':' || address[address.Length - 1] == ','))
236  address = address.Substring(0, address.Length - 1);
237 
238  address = address.ToUpperInvariant();
239 
240  var addressed = address == CommonMention.ToUpperInvariant() || address == provider.BotMention.ToUpperInvariant();
241 
242  // no mention
243  if (!addressed && !message.User.Channel.IsPrivateChannel)
244  return;
245 
246  logger.LogTrace("Chat command: {0}. User (True provider Id): {1}", message.Content, JsonConvert.SerializeObject(message.User));
247 
248  if (addressed)
249  splits.RemoveAt(0);
250 
251  if (splits.Count == 0)
252  {
253  // just a mention
254  await SendMessage("Hi!", new List<ulong> { message.User.Channel.RealId }, cancellationToken).ConfigureAwait(false);
255  return;
256  }
257 
258  var command = splits[0].ToUpperInvariant();
259  splits.RemoveAt(0);
260  var arguments = String.Join(" ", splits);
261 
262  try
263  {
264  async Task<ICommand> GetCommand(string commandName)
265  {
266  if (!builtinCommands.TryGetValue(commandName, out var handler))
267  {
268  var tasks = trackingContexts.Select(x => x.GetCustomCommands(cancellationToken));
269  await Task.WhenAll(tasks).ConfigureAwait(false);
270  handler = tasks.SelectMany(x => x.Result).Where(x => x.Name.ToUpperInvariant() == commandName).FirstOrDefault();
271  }
272 
273  return handler;
274  }
275 
276  const string UnknownCommandMessage = "Unknown command! Type '?' or 'help' for available commands.";
277 
278  if (command == "HELP" || command == "?")
279  {
280  string helpText;
281  if (splits.Count == 0)
282  {
283  var allCommands = builtinCommands.Select(x => x.Value).ToList();
284  var tasks = trackingContexts.Select(x => x.GetCustomCommands(cancellationToken)).ToList();
285  await Task.WhenAll(tasks).ConfigureAwait(false);
286  allCommands.AddRange(tasks.SelectMany(x => x.Result));
287  helpText = String.Format(CultureInfo.InvariantCulture, "Available commands (Type '?' or 'help' and then a command name for more details): {0}", String.Join(", ", allCommands.Select(x => x.Name)));
288  }
289  else
290  {
291  var helpHandler = await GetCommand(splits[0].ToUpperInvariant()).ConfigureAwait(false);
292  if (helpHandler != default)
293  helpText = String.Format(CultureInfo.InvariantCulture, "{0}: {1}{2}", helpHandler.Name, helpHandler.HelpText, helpHandler.AdminOnly ? " - May only be used in admin channels" : String.Empty);
294  else
295  helpText = UnknownCommandMessage;
296  }
297 
298  await SendMessage(helpText, new List<ulong> { message.User.Channel.RealId }, cancellationToken).ConfigureAwait(false);
299  return;
300  }
301 
302  var commandHandler = await GetCommand(command).ConfigureAwait(false);
303 
304  if (commandHandler == default)
305  {
306  await SendMessage(UnknownCommandMessage, new List<ulong> { message.User.Channel.RealId }, cancellationToken).ConfigureAwait(false);
307  return;
308  }
309 
310  if (commandHandler.AdminOnly && !message.User.Channel.IsAdminChannel)
311  {
312  await SendMessage("Use this command in an admin channel!", new List<ulong> { message.User.Channel.RealId }, cancellationToken).ConfigureAwait(false);
313  return;
314  }
315 
316  var result = await commandHandler.Invoke(arguments, message.User, cancellationToken).ConfigureAwait(false);
317  if (result != null)
318  await SendMessage(result, new List<ulong> { message.User.Channel.RealId }, cancellationToken).ConfigureAwait(false);
319  }
320  catch (OperationCanceledException)
321  {
322  throw;
323  }
324  catch (Exception e)
325  {
326  // error bc custom commands should reply about why it failed
327  logger.LogError("Error processing chat command: {0}", e);
328  await SendMessage("Internal error processing command!", new List<ulong> { message.User.Channel.RealId }, cancellationToken).ConfigureAwait(false);
329  }
330  }
331 
337  async Task MonitorMessages(CancellationToken cancellationToken)
338  {
339  var messageTasks = new Dictionary<IProvider, Task<Message>>();
340  try
341  {
342  while (!cancellationToken.IsCancellationRequested)
343  {
344  // prune disconnected providers
345  foreach (var I in messageTasks.Where(x => !x.Key.Connected).ToList())
346  messageTasks.Remove(I.Key);
347 
348  // add new ones
349  Task updatedTask;
350  lock (this)
351  updatedTask = connectionsUpdated.Task;
352  lock (providers)
353  foreach (var I in providers)
354  if (I.Value.Connected && !messageTasks.ContainsKey(I.Value))
355  messageTasks.Add(I.Value, I.Value.NextMessage(cancellationToken));
356 
357  if (messageTasks.Count == 0)
358  {
359  await asyncDelayer.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
360  continue;
361  }
362 
363  // wait for a message
364  await Task.WhenAny(updatedTask, Task.WhenAny(messageTasks.Select(x => x.Value))).ConfigureAwait(false);
365 
366  // process completed ones
367  foreach (var I in messageTasks.Where(x => x.Value.IsCompleted).ToList())
368  {
369  var message = await I.Value.ConfigureAwait(false);
370 
371  await ProcessMessage(I.Key, message, cancellationToken).ConfigureAwait(false);
372 
373  messageTasks.Remove(I.Key);
374  }
375  }
376  }
377  catch (OperationCanceledException)
378  {
379  logger.LogTrace("Message processing loop cancelled!");
380  }
381  catch (Exception e)
382  {
383  logger.LogError("Message monitor crashed! Exception: {0}", e);
384  }
385  }
386 
388  public async Task ChangeChannels(long connectionId, IEnumerable<Api.Models.ChatChannel> newChannels, CancellationToken cancellationToken)
389  {
390  if (newChannels == null)
391  throw new ArgumentNullException(nameof(newChannels));
392  var provider = await RemoveProvider(connectionId, false, cancellationToken).ConfigureAwait(false);
393  if (provider == null)
394  return;
395  var results = await provider.MapChannels(newChannels, cancellationToken).ConfigureAwait(false);
396  if (results == null) // aborted
397  return;
398  var mappings = Enumerable.Zip(newChannels, results, (x, y) => new ChannelMapping
399  {
400  IsWatchdogChannel = x.IsWatchdogChannel == true,
401  IsUpdatesChannel = x.IsUpdatesChannel == true,
402  ProviderChannelId = y.RealId,
403  ProviderId = connectionId,
404  Channel = y
405  });
406 
407  ulong baseId;
408  lock (this)
409  {
410  baseId = channelIdCounter;
411  channelIdCounter += (ulong)results.Count;
412  }
413 
414  Task task;
415  lock (mappedChannels)
416  {
417  lock (providers)
418  if (!providers.TryGetValue(connectionId, out IProvider verify) || verify != provider) // aborted again
419  return;
420  foreach (var I in mappings)
421  {
422  var newId = baseId++;
423  mappedChannels.Add(newId, I);
424  I.Channel.RealId = newId;
425  }
426 
427  lock (trackingContexts)
428  task = Task.WhenAll(trackingContexts.Select(x => x.SetChannels(mappedChannels.Select(y => y.Value.Channel), cancellationToken)));
429  }
430 
431  await task.ConfigureAwait(false);
432  }
433 
435  public async Task ChangeSettings(ChatBot newSettings, CancellationToken cancellationToken)
436  {
437  if (newSettings == null)
438  throw new ArgumentNullException(nameof(newSettings));
439  IProvider provider;
440 
441  async Task DisconnectProvider(IProvider p)
442  {
443  try
444  {
445  await p.Disconnect(cancellationToken).ConfigureAwait(false);
446  }
447  finally
448  {
449  p.Dispose();
450  }
451  }
452 
453  Task disconnectTask;
454  lock (providers)
455  {
456  // raw settings changes forces a rebuild of the provider
457  if (providers.TryGetValue(newSettings.Id, out provider))
458  {
459  providers.Remove(newSettings.Id);
460  disconnectTask = DisconnectProvider(provider);
461  }
462  else
463  disconnectTask = Task.CompletedTask;
464  if (newSettings.Enabled.Value)
465  {
466  provider = providerFactory.CreateProvider(newSettings);
467  providers.Add(newSettings.Id, provider);
468  }
469  }
470 
471  lock (mappedChannels)
472  foreach (var I in mappedChannels.Where(x => x.Value.ProviderId == newSettings.Id).Select(x => x.Key).ToList())
473  mappedChannels.Remove(I);
474 
475  await disconnectTask.ConfigureAwait(false);
476 
477  if (started)
478  {
479  if (newSettings.Enabled.Value)
480  await provider.Connect(cancellationToken).ConfigureAwait(false);
481  lock (this)
482  {
483  // same thread shennanigans
484  var oldOne = connectionsUpdated;
485  connectionsUpdated = new TaskCompletionSource<object>();
486  oldOne.SetResult(null);
487  }
488  }
489  }
490 
492  public Task SendMessage(string message, IEnumerable<ulong> channelIds, CancellationToken cancellationToken)
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  }
512 
514  public Task SendWatchdogMessage(string message, CancellationToken cancellationToken)
515  {
516  List<ulong> wdChannels;
517  message = String.Format(CultureInfo.InvariantCulture, "WD: {0}", message);
518  lock (mappedChannels) // so it doesn't change while we're using it
519  wdChannels = mappedChannels.Where(x => x.Value.IsWatchdogChannel).Select(x => x.Key).ToList();
520  return SendMessage(message, wdChannels, cancellationToken);
521  }
522 
524  public Task SendUpdateMessage(string message, CancellationToken cancellationToken)
525  {
526  List<ulong> wdChannels;
527  message = String.Format(CultureInfo.InvariantCulture, "DM: {0}", message);
528  lock (mappedChannels) // so it doesn't change while we're using it
529  wdChannels = mappedChannels.Where(x => x.Value.IsUpdatesChannel).Select(x => x.Key).ToList();
530  return SendMessage(message, wdChannels, cancellationToken);
531  }
532 
534  public async Task StartAsync(CancellationToken cancellationToken)
535  {
536  foreach (var I in commandFactory.GenerateCommands())
537  builtinCommands.Add(I.Name.ToUpperInvariant(), I);
538  await Task.WhenAll(initialChatBots.Select(x => ChangeSettings(x, cancellationToken))).ConfigureAwait(false);
539  await Task.WhenAll(providers.Select(x => x.Value).Select(x => x.Connect(cancellationToken))).ConfigureAwait(false);
540  await Task.WhenAll(initialChatBots.Select(x => ChangeChannels(x.Id, x.Channels, cancellationToken))).ConfigureAwait(false);
542  started = true;
543  }
544 
546  public async Task StopAsync(CancellationToken cancellationToken)
547  {
548  handlerCts.Cancel();
549  await chatHandler.ConfigureAwait(false);
550  await Task.WhenAll(providers.Select(x => x.Value).Select(x => x.Disconnect(cancellationToken))).ConfigureAwait(false);
551  }
552 
554  public async Task<IJsonTrackingContext> TrackJsons(string basePath, string channelsJsonName, string commandsJsonName, CancellationToken cancellationToken)
555  {
556  if (customCommandHandler == null)
557  throw new InvalidOperationException("RegisterCommandHandler() hasn't been called!");
558  JsonTrackingContext context = null;
559  context = new JsonTrackingContext(
560  ioManager,
562  loggerFactory.CreateLogger<JsonTrackingContext>(),
563  () =>
564  {
565  lock (trackingContexts)
566  trackingContexts.Remove(context);
567  },
568  ioManager.ConcatPath(basePath, commandsJsonName),
569  ioManager.ConcatPath(basePath, channelsJsonName));
570  Task task;
571  lock (trackingContexts)
572  {
573  trackingContexts.Add(context);
574  lock (mappedChannels)
575  task = context.SetChannels(mappedChannels.Select(y => y.Value.Channel), cancellationToken);
576  }
577 
578  await task.ConfigureAwait(false);
579  return context;
580  }
581 
583  public bool Connected(long connectionId)
584  {
585  lock (providers)
586  return providers.TryGetValue(connectionId, out var provider) && provider.Connected;
587  }
588 
591  {
592  if (this.customCommandHandler != null)
593  throw new InvalidOperationException("RegisterCommandHandler() already called!");
594  this.customCommandHandler = customCommandHandler ?? throw new ArgumentNullException(nameof(customCommandHandler));
595  }
596 
598  public async Task DeleteConnection(long connectionId, CancellationToken cancellationToken)
599  {
600  var provider = await RemoveProvider(connectionId, true, cancellationToken).ConfigureAwait(false);
601  if (provider != null)
602  try
603  {
604  await provider.Disconnect(cancellationToken).ConfigureAwait(false);
605  }
606  finally
607  {
608  provider.Dispose();
609  }
610  }
611 
613  public Task HandleRestart(Version updateVersion, CancellationToken cancellationToken)
614  {
615  var message = updateVersion == null ? "TGS: Restart requested..." : String.Format(CultureInfo.InvariantCulture, "TGS: Updating to version {0}...", updateVersion);
616  List<ulong> wdChannels;
617  lock (mappedChannels) // so it doesn't change while we're using it
618  wdChannels = mappedChannels.Select(x => x.Key).ToList();
619  return SendMessage(message, wdChannels, cancellationToken);
620  }
621  }
622 }
void RegisterCommandHandler(ICustomCommandHandler customCommandHandler)
Registers a customCommandHandler to use
Definition: Chat.cs:590
+
bool IsWatchdogChannel
If Channel is a watchdog channel
+
Represents a mapping of a Channel.RealId
+
User User
The Components.Chat.User who sent the Message
Definition: Message.cs:16
+
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the Chat
Definition: Chat.cs:52
-
async Task SetChannels(IEnumerable< Channel > channels, CancellationToken cancellationToken)
Writes information about connected channels to the IJsonTrackingContext
+
async Task SetChannels(IEnumerable< Channel > channels, CancellationToken cancellationToken)
Writes information about connected channels to the IJsonTrackingContext
- - -
Task Disconnect(CancellationToken cancellationToken)
Gracefully disconnects the provider. Implies a call to IDisposable.Dispose
-
Channel Channel
The Components.Chat.Channel the user spoke from
Definition: User.cs:40
- -
Task SendWatchdogMessage(string message, CancellationToken cancellationToken)
Send a chat message to configured watchdog channels
Definition: Chat.cs:514
-
bool started
If StartAsync(CancellationToken) has been called
Definition: Chat.cs:112
-
readonly Dictionary< long, IProvider > providers
Map of IProviders in use, keyed by ChatBot.Id
Definition: Chat.cs:67
-
Represents a message recieved by a IProvider
Definition: Message.cs:6
-
readonly List< Models.ChatBot > initialChatBots
The initial Models.ChatBot for the Chat
Definition: Chat.cs:87
-
Chat(IProviderFactory providerFactory, IIOManager ioManager, ICommandFactory commandFactory, IServerControl serverControl, IAsyncDelayer asyncDelayer, ILoggerFactory loggerFactory, ILogger< Chat > logger, IEnumerable< Models.ChatBot > initialChatBots)
Construct a Chat
Definition: Chat.cs:125
-
For interacting with a chat service
Definition: IProvider.cs:11
- + + +
Task Disconnect(CancellationToken cancellationToken)
Gracefully disconnects the provider. Implies a call to IDisposable.Dispose
+
Channel Channel
The Components.Chat.Channel the user spoke from
Definition: User.cs:40
+
Task SendWatchdogMessage(string message, CancellationToken cancellationToken)
Send a chat message to configured watchdog channels
Definition: Chat.cs:514
+
bool started
If StartAsync(CancellationToken) has been called
Definition: Chat.cs:112
+
readonly Dictionary< long, IProvider > providers
Map of IProviders in use, keyed by ChatBot.Id
Definition: Chat.cs:67
+
Represents a message recieved by a IProvider
Definition: Message.cs:6
+
readonly List< Models.ChatBot > initialChatBots
The initial Models.ChatBot for the Chat
Definition: Chat.cs:87
+
Chat(IProviderFactory providerFactory, IIOManager ioManager, ICommandFactory commandFactory, IServerControl serverControl, IAsyncDelayer asyncDelayer, ILoggerFactory loggerFactory, ILogger< Chat > logger, IEnumerable< Models.ChatBot > initialChatBots)
Construct a Chat
Definition: Chat.cs:125
+ +
IProvider CreateProvider(ChatBot settings)
Create a IProvider
+ -
Manage the server chat bots
Definition: ChatBot.cs:10
+
Manage the server chat bots
Definition: ChatBot.cs:9
- -
bool Connected(long connectionId)
If a given set of ChatBot is connected
Definition: Chat.cs:583
-
For managing connected chat services
Definition: IChat.cs:13
-
async Task DeleteConnection(long connectionId, CancellationToken cancellationToken)
Disconnects and deletes a given connection
Definition: Chat.cs:598
+ +
bool Connected(long connectionId)
If a given set of ChatBot is connected
Definition: Chat.cs:583
+
For managing connected chat services
Definition: IChat.cs:13
+
async Task DeleteConnection(long connectionId, CancellationToken cancellationToken)
Disconnects and deletes a given connection
Definition: Chat.cs:598
-
async Task< IProvider > RemoveProvider(long connectionId, bool updateTrackings, CancellationToken cancellationToken)
Remove a IProvider from providers and mappedChannels optionally updating the trackingContexts as well...
Definition: Chat.cs:164
- -
readonly IProviderFactory providerFactory
The IProviderFactory for the Chat
Definition: Chat.cs:27
- -
bool IsPrivateChannel
If this is a 1-to-1 chat channel
Definition: Channel.cs:46
-
TaskCompletionSource< object > connectionsUpdated
The TaskCompletionSource<TResult> that completes when ChatBots change
Definition: Chat.cs:102
-
readonly ILogger< Chat > logger
The ILogger for the Chat
Definition: Chat.cs:57
+
async Task< IProvider > RemoveProvider(long connectionId, bool updateTrackings, CancellationToken cancellationToken)
Remove a IProvider from providers and mappedChannels optionally updating the trackingContexts as well
Definition: Chat.cs:164
+ +
readonly IProviderFactory providerFactory
The IProviderFactory for the Chat
Definition: Chat.cs:27
+ +
IReadOnlyList< ICommand > GenerateCommands()
Generate builtin ICommands
+
Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan
+
bool IsPrivateChannel
If this is a 1-to-1 chat channel
Definition: Channel.cs:46
+
TaskCompletionSource< object > connectionsUpdated
The TaskCompletionSource<TResult> that completes when ChatBots change
Definition: Chat.cs:102
+
readonly ILogger< Chat > logger
The ILogger for the Chat
Definition: Chat.cs:57
-
readonly ICommandFactory commandFactory
The ICommandFactory for the Chat
Definition: Chat.cs:37
-
Task SendUpdateMessage(string message, CancellationToken cancellationToken)
Send a chat message to configured update channels
Definition: Chat.cs:524
- -
async Task ProcessMessage(IProvider provider, Message message, CancellationToken cancellationToken)
Processes a message
Definition: Chat.cs:194
+
readonly ICommandFactory commandFactory
The ICommandFactory for the Chat
Definition: Chat.cs:37
+
Task SendUpdateMessage(string message, CancellationToken cancellationToken)
Send a chat message to configured update channels
Definition: Chat.cs:524
+ +
async Task ProcessMessage(IProvider provider, Message message, CancellationToken cancellationToken)
Processes a message
Definition: Chat.cs:194
async Task StopAsync(CancellationToken cancellationToken)
Definition: Chat.cs:546
-
Represents a Providers.IProvider channel
Definition: Channel.cs:10
-
string Id
Backing field for RealId. Represented as a string to avoid BYOND percision loss
Definition: Channel.cs:15
- -
async Task MonitorMessages(CancellationToken cancellationToken)
Monitors active providers for new Messages
Definition: Chat.cs:337
- - -
readonly IIOManager ioManager
The IIOManager for the Chat
Definition: Chat.cs:32
-
readonly Dictionary< ulong, ChannelMapping > mappedChannels
Map of Channel.RealIds to ChannelMappings
Definition: Chat.cs:72
-
string BotMention
The string that indicates the IProvider was mentioned
Definition: IProvider.cs:21
-
ulong channelIdCounter
Used for remapping Channel.RealIds
Definition: Chat.cs:107
-
ulong RealId
The Providers.IProvider channel Id.
Definition: Channel.cs:23
- +
bool? Enabled
If the connection is enabled
Definition: ChatBot.cs:25
+
Represents a Providers.IProvider channel
Definition: Channel.cs:10
+
string Id
Backing field for RealId. Represented as a string to avoid BYOND percision loss
Definition: Channel.cs:15
+ +
async Task MonitorMessages(CancellationToken cancellationToken)
Monitors active providers for new Messages
Definition: Chat.cs:337
+ + +
readonly IIOManager ioManager
The IIOManager for the Chat
Definition: Chat.cs:32
+
readonly Dictionary< ulong, ChannelMapping > mappedChannels
Map of Channel.RealIds to ChannelMappings
Definition: Chat.cs:72
+
string BotMention
The string that indicates the IProvider was mentioned
Definition: IProvider.cs:21
+
ulong channelIdCounter
Used for remapping Channel.RealIds
Definition: Chat.cs:107
+
ulong RealId
The Providers.IProvider channel Id.
Definition: Channel.cs:23
+
async Task ChangeSettings(ChatBot newSettings, CancellationToken cancellationToken)
Change chat settings. If the ChatBot.Id is not currently in use, a new connection will be made instea...
Definition: Chat.cs:435
-
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the Chat
Definition: Chat.cs:47
-
Handles Commands.ICommands that map to those defined in a IJsonTrackingContext
+
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the Chat
Definition: Chat.cs:47
+
Handles Commands.ICommands that map to those defined in a IJsonTrackingContext
async Task StartAsync(CancellationToken cancellationToken)
Definition: Chat.cs:534
- -
Task chatHandler
The Task that monitors incoming chat messages
Definition: Chat.cs:97
-
readonly Dictionary< string, ICommand > builtinCommands
Unchanging ICommands in the Chat mapped by ICommand.Name
Definition: Chat.cs:62
-
async Task< IJsonTrackingContext > TrackJsons(string basePath, string channelsJsonName, string commandsJsonName, CancellationToken cancellationToken)
Start tracking json files for commands and channels
Definition: Chat.cs:554
-
Interface for using filesystems
Definition: IIOManager.cs:11
-
Task SendMessage(string message, IEnumerable< ulong > channelIds, CancellationToken cancellationToken)
Send a chat message to a given set of channelIds
Definition: Chat.cs:492
-
Represents the lifetime of a IRestartHandler registration
-
readonly List< IJsonTrackingContext > trackingContexts
The active IJsonTrackingContexts for the Chat
Definition: Chat.cs:77
-
bool IsAdminChannel
If this is considered a channel for admin commands
Definition: Channel.cs:41
-
IRestartRegistration RegisterForRestart(IRestartHandler handler)
Register a given handler to run before stopping the server for a restart
-
bool Enabled
If the connection is enabled
Definition: ChatBot.cs:26
- -
async Task ChangeChannels(long connectionId, IEnumerable< Api.Models.ChatChannel > newChannels, CancellationToken cancellationToken)
Change chat channels
Definition: Chat.cs:388
-
ICustomCommandHandler customCommandHandler
The ICustomCommandHandler for the ChangeChannels(long, IEnumerable<Api.Models.ChatChannel>, CancellationToken)
Definition: Chat.cs:92
-
Task HandleRestart(Version updateVersion, CancellationToken cancellationToken)
Handle a restart of the server
Definition: Chat.cs:613
-
readonly IRestartRegistration restartRegistration
The IRestartRegistration for the Chat
Definition: Chat.cs:42
-
readonly CancellationTokenSource handlerCts
The CancellationTokenSource for chatHandler
Definition: Chat.cs:82
- + +
Task chatHandler
The Task that monitors incoming chat messages
Definition: Chat.cs:97
+
readonly Dictionary< string, ICommand > builtinCommands
Unchanging ICommands in the Chat mapped by ICommand.Name
Definition: Chat.cs:62
+
async Task< IJsonTrackingContext > TrackJsons(string basePath, string channelsJsonName, string commandsJsonName, CancellationToken cancellationToken)
Start tracking json files for commands and channels
Definition: Chat.cs:554
+
Interface for using filesystems
Definition: IIOManager.cs:11
+
Task SendMessage(string message, IEnumerable< ulong > channelIds, CancellationToken cancellationToken)
Send a chat message to a given set of channelIds
Definition: Chat.cs:492
+
Represents the lifetime of a IRestartHandler registration
+
readonly List< IJsonTrackingContext > trackingContexts
The active IJsonTrackingContexts for the Chat
Definition: Chat.cs:77
+
bool IsAdminChannel
If this is considered a channel for admin commands
Definition: Channel.cs:41
+
IRestartRegistration RegisterForRestart(IRestartHandler handler)
Register a given handler to run before stopping the server for a restart
+ +
async Task ChangeChannels(long connectionId, IEnumerable< Api.Models.ChatChannel > newChannels, CancellationToken cancellationToken)
Change chat channels
Definition: Chat.cs:388
+
ICustomCommandHandler customCommandHandler
The ICustomCommandHandler for the ChangeChannels(long, IEnumerable<Api.Models.ChatChannel>,...
Definition: Chat.cs:92
+
string ConcatPath(params string[] paths)
Combines an array of strings into a path
+
Task HandleRestart(Version updateVersion, CancellationToken cancellationToken)
Handle a restart of the server
Definition: Chat.cs:613
+
readonly IRestartRegistration restartRegistration
The IRestartRegistration for the Chat
Definition: Chat.cs:42
+
readonly CancellationTokenSource handlerCts
The CancellationTokenSource for chatHandler
Definition: Chat.cs:82
+
Represents a service that may take an updated Host assembly and run it, stopping the current assembly...
@@ -178,7 +160,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_chat_bot_rights_8cs.html b/_chat_bot_rights_8cs.html index c91f0787ea..cdc71ef007 100644 --- a/_chat_bot_rights_8cs.html +++ b/_chat_bot_rights_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/ChatBotRights.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Api +  namespace  Tgstation.Server.Api.Rights   @@ -119,8 +104,8 @@ Enumerations   Tgstation.Server.Api.Rights.ChatBotRights.Delete = 128, Tgstation.Server.Api.Rights.ChatBotRights.WriteName = 256
- } - + } +
 Rights for Models.ChatBot More...
 Rights for Models.ChatBot More...
 
@@ -128,7 +113,7 @@ Enumerations diff --git a/_chat_bot_rights_8cs_source.html b/_chat_bot_rights_8cs_source.html index c63b272aa9..de63779b69 100644 --- a/_chat_bot_rights_8cs_source.html +++ b/_chat_bot_rights_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/ChatBotRights.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
ChatBotRights.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Api.Rights
4 {
8  [Flags]
9  public enum ChatBotRights : ulong
10  {
14  None = 0,
15 
19  WriteEnabled = 1,
20 
24  WriteProvider = 2,
25 
29  WriteChannels = 4,
30 
35 
40 
44  Read = 32,
45 
49  Create = 64,
50 
54  Delete = 128,
55 
59  WriteName = 256,
60  }
61 }
User can read Models.Internal.ChatBot.ConnectionString requires Read
-
User can change Models.Internal.ChatBot.Name
- -
User can change Models.Internal.ChatBot.Provider
- - - -
User can change Models.Internal.ChatBot.ConnectionString
-
User can create new Models.ChatBot
-
User can change Models.Internal.ChatBot.Enabled
-
User can change Models.ChatBot.Channels
-
User can read all chat settings except Models.Internal.ChatBot.ConnectionString
-
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
- +Go to the documentation of this file.
1 using System;
2 
4 {
8  [Flags]
9  public enum ChatBotRights : ulong
10  {
14  None = 0,
15 
19  WriteEnabled = 1,
20 
24  WriteProvider = 2,
25 
29  WriteChannels = 4,
30 
35 
40 
44  Read = 32,
45 
49  Create = 64,
50 
54  Delete = 128,
55 
59  WriteName = 256,
60  }
61 }
User can read Models.Internal.ChatBot.ConnectionString requires Read
+
User can change Models.Internal.ChatBot.Name
+
User can change Models.Internal.ChatBot.Provider
+ + +
User can change Models.Internal.ChatBot.ConnectionString
+
User can create new Models.ChatBot
+
User can change Models.Internal.ChatBot.Enabled
+ +
User can change Models.ChatBot.Channels
+
User can read all chat settings except Models.Internal.ChatBot.ConnectionString
+
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
diff --git a/_chat_bots_client_8cs.html b/_chat_bots_client_8cs.html index ff4bf70aef..adb17ed7a4 100644 --- a/_chat_bots_client_8cs.html +++ b/_chat_bots_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/ChatBotsClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_chat_bots_client_8cs_source.html b/_chat_bots_client_8cs_source.html index e85f4de402..da032b1184 100644 --- a/_chat_bots_client_8cs_source.html +++ b/_chat_bots_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/ChatBotsClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ChatBotsClient.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 using Tgstation.Server.Api;
7 
8 namespace Tgstation.Server.Client.Components
9 {
12  {
17 
21  readonly Instance instance;
22 
28  public ChatBotsClient(IApiClient apiClient, Instance instance)
29  {
30  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
31  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
32  }
33 
35  public Task<ChatBot> Create(ChatBot settings, CancellationToken cancellationToken) => apiClient.Create<ChatBot, ChatBot>(Routes.Chat, settings ?? throw new ArgumentNullException(nameof(settings)), instance.Id, cancellationToken);
36 
38  public Task Delete(ChatBot settings, CancellationToken cancellationToken) => apiClient.Delete(Routes.SetID(Routes.Chat, settings?.Id ?? throw new ArgumentNullException(nameof(settings))), instance.Id, cancellationToken);
39 
41  public Task<IReadOnlyList<ChatBot>> List(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<ChatBot>>(Routes.List(Routes.Chat), instance.Id, cancellationToken);
42 
44  public Task<ChatBot> Update(ChatBot settings, CancellationToken cancellationToken) => apiClient.Update<ChatBot, ChatBot>(Routes.Chat, settings ?? throw new ArgumentNullException(nameof(settings)), instance.Id, cancellationToken);
45 
47  public Task<ChatBot> GetId(ChatBot settings, CancellationToken cancellationToken) => apiClient.Read<ChatBot>(Routes.SetID(Routes.Chat, (settings ?? throw new ArgumentNullException(nameof(settings))).Id), instance.Id, cancellationToken);
48  }
49 }
- - - +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 using Tgstation.Server.Api;
7 
9 {
12  {
17 
21  readonly Instance instance;
22 
29  {
30  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
31  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
32  }
33 
35  public Task<ChatBot> Create(ChatBot settings, CancellationToken cancellationToken) => apiClient.Create<ChatBot, ChatBot>(Routes.Chat, settings ?? throw new ArgumentNullException(nameof(settings)), instance.Id, cancellationToken);
36 
38  public Task Delete(ChatBot settings, CancellationToken cancellationToken) => apiClient.Delete(Routes.SetID(Routes.Chat, settings?.Id ?? throw new ArgumentNullException(nameof(settings))), instance.Id, cancellationToken);
39 
41  public Task<IReadOnlyList<ChatBot>> List(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<ChatBot>>(Routes.List(Routes.Chat), instance.Id, cancellationToken);
42 
44  public Task<ChatBot> Update(ChatBot settings, CancellationToken cancellationToken) => apiClient.Update<ChatBot, ChatBot>(Routes.Chat, settings ?? throw new ArgumentNullException(nameof(settings)), instance.Id, cancellationToken);
45 
47  public Task<ChatBot> GetId(ChatBot settings, CancellationToken cancellationToken) => apiClient.Read<ChatBot>(Routes.SetID(Routes.Chat, (settings ?? throw new ArgumentNullException(nameof(settings))).Id), instance.Id, cancellationToken);
48  }
49 }
Task< ChatBot > Update(ChatBot settings, CancellationToken cancellationToken)
Updates a ChatBot's setttings
+
Task< IReadOnlyList< ChatBot > > List(CancellationToken cancellationToken)
List the ChatBots
+ +
Task< ChatBot > GetId(ChatBot settings, CancellationToken cancellationToken)
Get a ChatBot's setttings
+ +
Task< ChatBot > Create(ChatBot settings, CancellationToken cancellationToken)
Create a ChatBot
-
Routes to a server actions
Definition: Routes.cs:9
+
Routes to a server actions
Definition: Routes.cs:9
+ +
Task< ChatBot > ChatBot(Routes.Chat, settings ?? throw new ArgumentNullException(nameof(settings)), instance.Id, cancellationToken)
-
const string Chat
The Models.ChatBot controller
Definition: Routes.cs:69
+
const string Chat
The Models.ChatBot controller
Definition: Routes.cs:69
+
Task Delete(ChatBot settings, CancellationToken cancellationToken)
Delete a ChatBot
- -
Metadata about a server instance
Definition: Instance.cs:9
-
static string SetID(string route, long id)
Apply an id postfix to a route
-
static string List(string route)
Get the /List postfix for a route
- -
readonly Instance instance
The Instance for the ChatBotsClient
-
Web interface for the API
Definition: IApiClient.cs:11
-
readonly IApiClient apiClient
The IApiClient for the ChatBotsClient
-
ChatBotsClient(IApiClient apiClient, Instance instance)
Construct a ChatBotsClient
- +
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
+
Metadata about a server instance
Definition: Instance.cs:9
+
static string SetID(string route, long id)
Apply an id postfix to a route
+
Task Delete(string route, CancellationToken cancellationToken)
Run an HTTP DELETE request
+
static string List(string route)
Get the /List postfix for a route
+ +
readonly Instance instance
The Instance for the ChatBotsClient
+
Web interface for the API
Definition: IApiClient.cs:11
+
readonly IApiClient apiClient
The IApiClient for the ChatBotsClient
+
ChatBotsClient(IApiClient apiClient, Instance instance)
Construct a ChatBotsClient
+
diff --git a/_chat_command_8cs.html b/_chat_command_8cs.html index 758eab356b..c7e4f284ba 100644 --- a/_chat_command_8cs.html +++ b/_chat_command_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/ChatCommand.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Interop
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_chat_command_8cs_source.html b/_chat_command_8cs_source.html index 180296e819..1278424d91 100644 --- a/_chat_command_8cs_source.html +++ b/_chat_command_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/ChatCommand.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ChatCommand.cs
-Go to the documentation of this file.
2 
3 namespace Tgstation.Server.Host.Components.Interop
4 {
8  sealed class ChatCommand
9  {
13  public string Command { get; set; }
14 
18  public string Params { get; set; }
19 
23  public User User { get; set; }
24  }
25 }
-
Represents a chat command to be handled by DD
Definition: ChatCommand.cs:8
-
Represents a tgs_chat_user datum
Definition: User.cs:10
- - - - - +Go to the documentation of this file.
2 
4 {
8  sealed class ChatCommand
9  {
13  public string Command { get; set; }
14 
18  public string Params { get; set; }
19 
23  public User User { get; set; }
24  }
25 }
+
Represents a chat command to be handled by DD
Definition: ChatCommand.cs:8
+ + + +
Represents a tgs_chat_user datum
Definition: User.cs:10
+ + + +
diff --git a/_chat_connection_string_builder_8cs.html b/_chat_connection_string_builder_8cs.html index fd4075e329..22054fe1ee 100644 --- a/_chat_connection_string_builder_8cs.html +++ b/_chat_connection_string_builder_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/ChatConnectionStringBuilder.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Api.Models.Internal.ChatConnectionStringBuilder - Helper for building ChatBot.ConnectionStrings More...
+ Helper for building ChatBot.ConnectionStrings More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
namespace  Tgstation.Server.Api.Models.Internal
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_chat_connection_string_builder_8cs_source.html b/_chat_connection_string_builder_8cs_source.html index ca58c11477..665a63658f 100644 --- a/_chat_connection_string_builder_8cs_source.html +++ b/_chat_connection_string_builder_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/ChatConnectionStringBuilder.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ChatConnectionStringBuilder.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Api.Models.Internal
2 {
6  public abstract class ChatConnectionStringBuilder
7  {
11  public abstract bool Valid { get; }
12 
17  public abstract override string ToString();
18  }
19 }
- - +Go to the documentation of this file.
2 {
6  public abstract class ChatConnectionStringBuilder
7  {
11  public abstract bool Valid { get; }
12 
17  public abstract override string ToString();
18  }
19 }
abstract override string ToString()
Gets the ChatBot.ConnectionString associated with the ChatConnectionStringBuilder
+ + +
abstract bool Valid
If the ChatConnectionStringBuilder evaluates to a valid ChatBot.ConnectionString
diff --git a/_chat_controller_8cs.html b/_chat_controller_8cs.html index fa4fa30937..688d8e75b0 100644 --- a/_chat_controller_8cs.html +++ b/_chat_controller_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/ChatController.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Controllers.ChatControllerModelController<TModel> for managing Api.Models.ChatBots More...
ModelController<TModel> for managing Api.Models.ChatBots More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Controllers
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_chat_controller_8cs_source.html b/_chat_controller_8cs_source.html index 9cef6d405b..fb9811556f 100644 --- a/_chat_controller_8cs_source.html +++ b/_chat_controller_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/ChatController.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
20 namespace Tgstation.Server.Host.Controllers
21 {
25  [Route(Routes.Chat)]
26  public sealed class ChatController : ModelController<Api.Models.ChatBot>
27  {
32 
40  public ChatController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, ILogger<ChatController> logger) : base(databaseContext, authenticationContextFactory, logger, 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 
61  [TgsAuthorize(ChatBotRights.Create)]
62  public override async Task<IActionResult> Create([FromBody] Api.Models.ChatBot model, CancellationToken cancellationToken)
63  {
64  if (model == null)
65  throw new ArgumentNullException(nameof(model));
66 
67  if (String.IsNullOrWhiteSpace(model.Name))
68  return BadRequest(new ErrorMessage { Message = "name cannot be null or whitespace!" });
69 
70  if (String.IsNullOrWhiteSpace(model.ConnectionString))
71  return BadRequest(new ErrorMessage { Message = "connection_string cannot be null or whitespace!" });
72 
73  if (!model.Provider.HasValue)
74  return BadRequest(new ErrorMessage { Message = "provider cannot be null!" });
75 
76  switch (model.Provider)
77  {
78  case ChatProvider.Discord:
79  case ChatProvider.Irc:
80  break;
81  default:
82  return BadRequest(new ErrorMessage { Message = "Invalid provider!" });
83  }
84 
85  if (!model.ValidateProviderChannelTypes())
86  return BadRequest(new ErrorMessage { Message = "One or more of channels aren't formatted correctly for the given provider!" });
87 
88  model.Enabled = model.Enabled ?? false;
89 
90  // try to update das db first
91  var dbModel = new Models.ChatBot
92  {
93  Name = model.Name,
94  ConnectionString = model.ConnectionString,
95  Enabled = model.Enabled,
96  Channels = model.Channels?.Select(x => ConvertApiChatChannel(x)).ToList() ?? new List<Models.ChatChannel>(), // important that this isn't null
97  InstanceId = Instance.Id,
98  Provider = model.Provider,
99  };
100 
101  DatabaseContext.ChatBots.Add(dbModel);
102 
103  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
104 
105  try
106  {
107  try
108  {
109  // try to create it
110  var instance = instanceManager.GetInstance(Instance);
111  await instance.Chat.ChangeSettings(dbModel, cancellationToken).ConfigureAwait(false);
112 
113  if (dbModel.Channels.Count > 0)
114  await instance.Chat.ChangeChannels(dbModel.Id, dbModel.Channels, cancellationToken).ConfigureAwait(false);
115  }
116  catch
117  {
118  // undo the add
119  DatabaseContext.ChatBots.Remove(dbModel);
120  await DatabaseContext.Save(default).ConfigureAwait(false);
121  throw;
122  }
123  }
124  catch (InvalidOperationException e)
125  {
126  return BadRequest(new ErrorMessage { Message = e.Message });
127  }
128 
129  return StatusCode((int)HttpStatusCode.Created, dbModel.ToApi());
130  }
131 
133  [TgsAuthorize(ChatBotRights.Delete)]
134  public override async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
135  {
136  var instance = instanceManager.GetInstance(Instance);
137  await Task.WhenAll(instance.Chat.DeleteConnection(id, cancellationToken), DatabaseContext.ChatBots.Where(x => x.Id == id).DeleteAsync(cancellationToken)).ConfigureAwait(false);
138 
139  return Ok();
140  }
141 
143  [TgsAuthorize(ChatBotRights.Read)]
144  public override async Task<IActionResult> List(CancellationToken cancellationToken)
145  {
146  var query = DatabaseContext.ChatBots.Where(x => x.InstanceId == Instance.Id).Include(x => x.Channels);
147 
148  var results = await query.ToListAsync(cancellationToken).ConfigureAwait(false);
149 
150  var connectionStrings = (AuthenticationContext.GetRight(RightsType.ChatBots) & (ulong)ChatBotRights.ReadConnectionString) != 0;
151 
152  if (!connectionStrings)
153  foreach (var I in results)
154  I.ConnectionString = null;
155 
156  return Json(results.Select(x => x.ToApi()));
157  }
158 
160  [TgsAuthorize(ChatBotRights.Read)]
161  public override async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
162  {
163  var query = DatabaseContext.ChatBots.Where(x => x.Id == id).Include(x => x.Channels);
164 
165  var results = await query.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
166  if (results == default)
167  return StatusCode((int)HttpStatusCode.Gone);
168 
169  var connectionStrings = (AuthenticationContext.GetRight(RightsType.ChatBots) & (ulong)ChatBotRights.ReadConnectionString) != 0;
170 
171  if (!connectionStrings)
172  results.ConnectionString = null;
173 
174  return Json(results.ToApi());
175  }
176 
178  #pragma warning disable CA1506 // TODO: Decomplexify
179  [TgsAuthorize(ChatBotRights.WriteChannels | ChatBotRights.WriteConnectionString | ChatBotRights.WriteEnabled | ChatBotRights.WriteName | ChatBotRights.WriteProvider)]
180  public override async Task<IActionResult> Update([FromBody] Api.Models.ChatBot model, CancellationToken cancellationToken)
181  {
182  if (model == null)
183  throw new ArgumentNullException(nameof(model));
184 
185  if (model.Provider.HasValue && !model.ValidateProviderChannelTypes())
186  return BadRequest(new ErrorMessage { Message = "One or more of channels aren't formatted correctly for the given provider!" });
187 
188  var query = DatabaseContext.ChatBots.Where(x => x.InstanceId == Instance.Id && x.Id == model.Id).Include(x => x.Channels);
189 
190  var current = await query.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
191 
192  if (current == default)
193  return StatusCode((int)HttpStatusCode.Gone);
194 
195  var userRights = (ChatBotRights)AuthenticationContext.GetRight(RightsType.ChatBots);
196 
197  bool anySettingsModified = false;
198 
199  bool CheckModified<T>(Expression<Func<Api.Models.Internal.ChatBot, T>> expression, ChatBotRights requiredRight)
200  {
201  var memberSelectorExpression = (MemberExpression)expression.Body;
202  var property = (PropertyInfo)memberSelectorExpression.Member;
203 
204  var newVal = property.GetValue(model);
205  if (newVal == null)
206  return false;
207  if (!userRights.HasFlag(requiredRight) && property.GetValue(current) != newVal)
208  return true;
209 
210  property.SetValue(current, newVal);
211  anySettingsModified = true;
212  return false;
213  }
214 
215  var oldProvider = current.Provider;
216 
217  if (CheckModified(x => x.ConnectionString, ChatBotRights.WriteConnectionString)
218  || CheckModified(x => x.Enabled, ChatBotRights.WriteEnabled)
219  || CheckModified(x => x.Name, ChatBotRights.WriteName)
220  || CheckModified(x => x.Provider, ChatBotRights.WriteProvider)
221  || (model.Channels != null && !userRights.HasFlag(ChatBotRights.WriteChannels)))
222  return Forbid();
223 
224  var hasChannels = model.Channels != null;
225  if (hasChannels || (model.Provider.HasValue && model.Provider != oldProvider))
226  {
227  DatabaseContext.ChatChannels.RemoveRange(current.Channels);
228  if (hasChannels)
229  {
230  var dbChannels = model.Channels.Select(x => ConvertApiChatChannel(x)).ToList();
231  DatabaseContext.ChatChannels.AddRange(dbChannels);
232  current.Channels = dbChannels;
233  }
234  else
235  current.Channels.Clear();
236  }
237 
238  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
239 
240  var chat = instanceManager.GetInstance(Instance).Chat;
241 
242  if (anySettingsModified)
243  await chat.ChangeSettings(current, cancellationToken).ConfigureAwait(false); // have to rebuild the thing first
244 
245  if (model.Channels != null || anySettingsModified)
246  await chat.ChangeChannels(current.Id, current.Channels, cancellationToken).ConfigureAwait(false);
247 
248  if (userRights.HasFlag(ChatBotRights.Read))
249  {
250  if (!userRights.HasFlag(ChatBotRights.ReadConnectionString))
251  current.ConnectionString = null;
252  return Json(current.ToApi());
253  }
254 
255  return Ok();
256  }
257  #pragma warning restore CA1506
258  }
259 }
- - +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 : ModelController<Api.Models.ChatBot>
27  {
32 
40  public ChatController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, ILogger<ChatController> logger) : base(databaseContext, authenticationContextFactory, logger, 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 
61  [TgsAuthorize(ChatBotRights.Create)]
62  public override async Task<IActionResult> Create([FromBody] Api.Models.ChatBot model, CancellationToken cancellationToken)
63  {
64  if (model == null)
65  throw new ArgumentNullException(nameof(model));
66 
67  if (String.IsNullOrWhiteSpace(model.Name))
68  return BadRequest(new ErrorMessage { Message = "name cannot be null or whitespace!" });
69 
70  if (String.IsNullOrWhiteSpace(model.ConnectionString))
71  return BadRequest(new ErrorMessage { Message = "connection_string cannot be null or whitespace!" });
72 
73  if (!model.Provider.HasValue)
74  return BadRequest(new ErrorMessage { Message = "provider cannot be null!" });
75 
76  switch (model.Provider)
77  {
78  case ChatProvider.Discord:
79  case ChatProvider.Irc:
80  break;
81  default:
82  return BadRequest(new ErrorMessage { Message = "Invalid provider!" });
83  }
84 
85  if (!model.ValidateProviderChannelTypes())
86  return BadRequest(new ErrorMessage { Message = "One or more of channels aren't formatted correctly for the given provider!" });
87 
88  model.Enabled = model.Enabled ?? false;
89 
90  // try to update das db first
91  var dbModel = new Models.ChatBot
92  {
93  Name = model.Name,
94  ConnectionString = model.ConnectionString,
95  Enabled = model.Enabled,
96  Channels = model.Channels?.Select(x => ConvertApiChatChannel(x)).ToList() ?? new List<Models.ChatChannel>(), // important that this isn't null
97  InstanceId = Instance.Id,
98  Provider = model.Provider,
99  };
100 
101  DatabaseContext.ChatBots.Add(dbModel);
102 
103  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
104 
105  try
106  {
107  try
108  {
109  // try to create it
110  var instance = instanceManager.GetInstance(Instance);
111  await instance.Chat.ChangeSettings(dbModel, cancellationToken).ConfigureAwait(false);
112 
113  if (dbModel.Channels.Count > 0)
114  await instance.Chat.ChangeChannels(dbModel.Id, dbModel.Channels, cancellationToken).ConfigureAwait(false);
115  }
116  catch
117  {
118  // undo the add
119  DatabaseContext.ChatBots.Remove(dbModel);
120  await DatabaseContext.Save(default).ConfigureAwait(false);
121  throw;
122  }
123  }
124  catch (InvalidOperationException e)
125  {
126  return BadRequest(new ErrorMessage { Message = e.Message });
127  }
128 
129  return StatusCode((int)HttpStatusCode.Created, dbModel.ToApi());
130  }
131 
133  [TgsAuthorize(ChatBotRights.Delete)]
134  public override async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
135  {
136  var instance = instanceManager.GetInstance(Instance);
137  await Task.WhenAll(instance.Chat.DeleteConnection(id, cancellationToken), DatabaseContext.ChatBots.Where(x => x.Id == id).DeleteAsync(cancellationToken)).ConfigureAwait(false);
138 
139  return Ok();
140  }
141 
143  [TgsAuthorize(ChatBotRights.Read)]
144  public override async Task<IActionResult> List(CancellationToken cancellationToken)
145  {
146  var query = DatabaseContext.ChatBots.Where(x => x.InstanceId == Instance.Id).Include(x => x.Channels);
147 
148  var results = await query.ToListAsync(cancellationToken).ConfigureAwait(false);
149 
150  var connectionStrings = (AuthenticationContext.GetRight(RightsType.ChatBots) & (ulong)ChatBotRights.ReadConnectionString) != 0;
151 
152  if (!connectionStrings)
153  foreach (var I in results)
154  I.ConnectionString = null;
155 
156  return Json(results.Select(x => x.ToApi()));
157  }
158 
160  [TgsAuthorize(ChatBotRights.Read)]
161  public override async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
162  {
163  var query = DatabaseContext.ChatBots.Where(x => x.Id == id).Include(x => x.Channels);
164 
165  var results = await query.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
166  if (results == default)
167  return StatusCode((int)HttpStatusCode.Gone);
168 
169  var connectionStrings = (AuthenticationContext.GetRight(RightsType.ChatBots) & (ulong)ChatBotRights.ReadConnectionString) != 0;
170 
171  if (!connectionStrings)
172  results.ConnectionString = null;
173 
174  return Json(results.ToApi());
175  }
176 
178  #pragma warning disable CA1506 // TODO: Decomplexify
179  [TgsAuthorize(ChatBotRights.WriteChannels | ChatBotRights.WriteConnectionString | ChatBotRights.WriteEnabled | ChatBotRights.WriteName | ChatBotRights.WriteProvider)]
180  public override async Task<IActionResult> Update([FromBody] Api.Models.ChatBot model, CancellationToken cancellationToken)
181  {
182  if (model == null)
183  throw new ArgumentNullException(nameof(model));
184 
185  if (model.Provider.HasValue && !model.ValidateProviderChannelTypes())
186  return BadRequest(new ErrorMessage { Message = "One or more of channels aren't formatted correctly for the given provider!" });
187 
188  var query = DatabaseContext.ChatBots.Where(x => x.InstanceId == Instance.Id && x.Id == model.Id).Include(x => x.Channels);
189 
190  var current = await query.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
191 
192  if (current == default)
193  return StatusCode((int)HttpStatusCode.Gone);
194 
195  var userRights = (ChatBotRights)AuthenticationContext.GetRight(RightsType.ChatBots);
196 
197  bool anySettingsModified = false;
198 
199  bool CheckModified<T>(Expression<Func<Api.Models.Internal.ChatBot, T>> expression, ChatBotRights requiredRight)
200  {
201  var memberSelectorExpression = (MemberExpression)expression.Body;
202  var property = (PropertyInfo)memberSelectorExpression.Member;
203 
204  var newVal = property.GetValue(model);
205  if (newVal == null)
206  return false;
207  if (!userRights.HasFlag(requiredRight) && property.GetValue(current) != newVal)
208  return true;
209 
210  property.SetValue(current, newVal);
211  anySettingsModified = true;
212  return false;
213  }
214 
215  var oldProvider = current.Provider;
216 
217  if (CheckModified(x => x.ConnectionString, ChatBotRights.WriteConnectionString)
218  || CheckModified(x => x.Enabled, ChatBotRights.WriteEnabled)
219  || CheckModified(x => x.Name, ChatBotRights.WriteName)
220  || CheckModified(x => x.Provider, ChatBotRights.WriteProvider)
221  || (model.Channels != null && !userRights.HasFlag(ChatBotRights.WriteChannels)))
222  return Forbid();
223 
224  var hasChannels = model.Channels != null;
225  if (hasChannels || (model.Provider.HasValue && model.Provider != oldProvider))
226  {
227  DatabaseContext.ChatChannels.RemoveRange(current.Channels);
228  if (hasChannels)
229  {
230  var dbChannels = model.Channels.Select(x => ConvertApiChatChannel(x)).ToList();
231  DatabaseContext.ChatChannels.AddRange(dbChannels);
232  current.Channels = dbChannels;
233  }
234  else
235  current.Channels.Clear();
236  }
237 
238  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
239 
241 
242  if (anySettingsModified)
243  await chat.ChangeSettings(current, cancellationToken).ConfigureAwait(false); // have to rebuild the thing first
244 
245  if (model.Channels != null || anySettingsModified)
246  await chat.ChangeChannels(current.Id, current.Channels, cancellationToken).ConfigureAwait(false);
247 
248  if (userRights.HasFlag(ChatBotRights.Read))
249  {
250  if (!userRights.HasFlag(ChatBotRights.ReadConnectionString))
251  current.ConnectionString = null;
252  return Json(current.ToApi());
253  }
254 
255  return Ok();
256  }
257  #pragma warning restore CA1506
258  }
259 }
+ + + -
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
+
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
- +
IInstance GetInstance(Models.Instance metadata)
Get the IInstance associated with given metadata
- -
override async Task< IActionResult > Delete(long id, CancellationToken cancellationToken)
Attempt to delete a model with a particular id
- -
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
-
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
+
override async Task< IActionResult > Delete(long id, CancellationToken cancellationToken)
Attempt to delete a model with a particular id
+
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
-
ChatController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, ILogger< ChatController > logger)
Construct a ChatController
+
Routes to a server actions
Definition: Routes.cs:9
+
ChatController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, ILogger< ChatController > logger)
Construct a ChatController
+
IChat Chat
The IChat for the IInstance
Definition: IInstance.cs:37
override async Task< IActionResult > Update([FromBody] Api.Models.ChatBot model, CancellationToken cancellationToken)
-
string Message
A human readable description of the error
Definition: ErrorMessage.cs:13
-
const string Chat
The Models.ChatBot controller
Definition: Routes.cs:69
-
override async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Attempt to get a specific a TModel
+
string Message
A human readable description of the error
Definition: ErrorMessage.cs:13
+
const string Chat
The Models.ChatBot controller
Definition: Routes.cs:69
+
override async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Attempt to get a specific a TModel
-
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
+
ulong? DiscordChannelId
The Discord channel ID
Definition: ChatChannel.cs:18
+
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
override async Task< IActionResult > Create([FromBody] Api.Models.ChatBot model, CancellationToken cancellationToken)
-
An ApiController representing a TModel
+
An ApiController representing a TModel
- -
override async Task< IActionResult > List(CancellationToken cancellationToken)
Attempt to list entries of the TModel
-
Metadata about a server instance
Definition: Instance.cs:9
- -
ModelController<TModel> for managing Api.Models.ChatBots
-
readonly IInstanceManager instanceManager
The IInstanceManager for the ChatController
- -
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
- - + +
override async Task< IActionResult > List(CancellationToken cancellationToken)
Attempt to list entries of the TModel
+
Metadata about a server instance
Definition: Instance.cs:9
+ +
ModelController<TModel> 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
+ +
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
+ +
diff --git a/_chat_factory_8cs.html b/_chat_factory_8cs.html index ba258038de..4e80425acd 100644 --- a/_chat_factory_8cs.html +++ b/_chat_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/ChatFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_chat_factory_8cs_source.html b/_chat_factory_8cs_source.html index f095422d3d..453d221ab0 100644 --- a/_chat_factory_8cs_source.html +++ b/_chat_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/ChatFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ChatFactory.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using System;
3 using System.Collections.Generic;
6 using Tgstation.Server.Host.IO;
7 
8 namespace Tgstation.Server.Host.Components.Chat
9 {
11  sealed class ChatFactory : IChatFactory
12  {
16  readonly ILoggerFactory loggerFactory;
17 
22 
27 
32 
40  public ChatFactory(IProviderFactory providerFactory, IServerControl serverControl, IAsyncDelayer asyncDelayer, ILoggerFactory loggerFactory)
41  {
42  this.providerFactory = providerFactory ?? throw new ArgumentNullException(nameof(providerFactory));
43  this.serverControl = serverControl ?? throw new ArgumentNullException(nameof(serverControl));
44  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
45  this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
46  }
47 
49  public IChat CreateChat(IIOManager ioManager, ICommandFactory commandFactory, IEnumerable<Models.ChatBot> initialChatBots) => new Chat(providerFactory, ioManager, commandFactory, serverControl, asyncDelayer, loggerFactory, loggerFactory.CreateLogger<Chat>(), initialChatBots);
50  }
51 }
+Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using System;
3 using System.Collections.Generic;
6 using Tgstation.Server.Host.IO;
7 
9 {
11  sealed class ChatFactory : IChatFactory
12  {
16  readonly ILoggerFactory loggerFactory;
17 
22 
27 
32 
41  {
42  this.providerFactory = providerFactory ?? throw new ArgumentNullException(nameof(providerFactory));
43  this.serverControl = serverControl ?? throw new ArgumentNullException(nameof(serverControl));
44  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
45  this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
46  }
47 
49  public IChat CreateChat(IIOManager ioManager, ICommandFactory commandFactory, IEnumerable<Models.ChatBot> initialChatBots) => new Chat(providerFactory, ioManager, commandFactory, serverControl, asyncDelayer, loggerFactory, loggerFactory.CreateLogger<Chat>(), initialChatBots);
50  }
51 }
- - - - -
ChatFactory(IProviderFactory providerFactory, IServerControl serverControl, IAsyncDelayer asyncDelayer, ILoggerFactory loggerFactory)
Construct a ChatFactory
Definition: ChatFactory.cs:40
-
For managing connected chat services
Definition: IChat.cs:13
+ + +
ChatFactory(IProviderFactory providerFactory, IServerControl serverControl, IAsyncDelayer asyncDelayer, ILoggerFactory loggerFactory)
Construct a ChatFactory
Definition: ChatFactory.cs:40
+
For managing connected chat services
Definition: IChat.cs:13
- -
readonly IServerControl serverControl
The IServerControl for the ChatFactory
Definition: ChatFactory.cs:26
+ +
readonly IServerControl serverControl
The IServerControl for the ChatFactory
Definition: ChatFactory.cs:26
-
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the ChatFactory
Definition: ChatFactory.cs:31
-
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the ChatFactory
Definition: ChatFactory.cs:16
- +
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the ChatFactory
Definition: ChatFactory.cs:31
+
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the ChatFactory
Definition: ChatFactory.cs:16
+ - - -
Interface for using filesystems
Definition: IIOManager.cs:11
-
readonly IProviderFactory providerFactory
The IProviderFactory for the ChatFactory
Definition: ChatFactory.cs:21
- - + + +
Interface for using filesystems
Definition: IIOManager.cs:11
+
readonly IProviderFactory providerFactory
The IProviderFactory for the ChatFactory
Definition: ChatFactory.cs:21
+ + +
IChat CreateChat(IIOManager ioManager, ICommandFactory commandFactory, IEnumerable< Models.ChatBot > initialChatBots)
Create a IChat
Represents a service that may take an updated Host assembly and run it, stopping the current assembly...
@@ -121,7 +99,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_chat_provider_8cs.html b/_chat_provider_8cs.html index b3bd755d47..6cbcbd5f46 100644 --- a/_chat_provider_8cs.html +++ b/_chat_provider_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/ChatProvider.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Api +  namespace  Tgstation.Server.Api.Models   @@ -107,8 +92,8 @@ Namespaces Enumerations - + } +
enum  Tgstation.Server.Api.Models.ChatProvider { Tgstation.Server.Api.Models.ChatProvider.Irc, Tgstation.Server.Api.Models.ChatProvider.Discord - }
 Represents a chat service provider More...
 Represents a chat service provider More...
 
@@ -116,7 +101,7 @@ Enumerations diff --git a/_chat_provider_8cs_source.html b/_chat_provider_8cs_source.html index 6a2169454e..3bade4f02c 100644 --- a/_chat_provider_8cs_source.html +++ b/_chat_provider_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/ChatProvider.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
ChatProvider.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Api.Models
2 {
6  public enum ChatProvider
7  {
11  Irc,
12 
16  Discord
17  }
18 }
- -
ChatProvider
Represents a chat service provider
Definition: ChatProvider.cs:6
- - +Go to the documentation of this file.
2 {
6  public enum ChatProvider
7  {
11  Irc,
12 
16  Discord
17  }
18 }
+ + +
ChatProvider
Represents a chat service provider
Definition: ChatProvider.cs:6
diff --git a/_claims_injector_8cs.html b/_claims_injector_8cs.html index 07b1ed2674..1e94c5c7e8 100644 --- a/_claims_injector_8cs.html +++ b/_claims_injector_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/ClaimsInjector.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_claims_injector_8cs_source.html b/_claims_injector_8cs_source.html index dbb2646d02..f66b99a923 100644 --- a/_claims_injector_8cs_source.html +++ b/_claims_injector_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/ClaimsInjector.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
14 namespace Tgstation.Server.Host.Security
15 {
18  {
23 
28 
34  public ClaimsInjector(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory)
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 
75  var authenticationContext = authenticationContextFactory.CurrentAuthenticationContext;
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
+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
- - -
async Task InjectClaimsIntoContext(TokenValidatedContext tokenValidatedContext, CancellationToken cancellationToken)
Setup the System.Security.Claims.Claims for a given tokenValidatedContext
-
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
-
ClaimsInjector(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory)
Construct a ClaimsInjector
-
readonly IAuthenticationContextFactory authenticationContextFactory
The IAuthenticationContextFactory for the ClaimsInjector
+
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
+
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
+
ClaimsInjector(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory)
Construct a ClaimsInjector
+
readonly IAuthenticationContextFactory authenticationContextFactory
The IAuthenticationContextFactory for the ClaimsInjector
+ -
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 ...
-
readonly IDatabaseContext databaseContext
The IDatabaseContext for the ClaimsInjector
- -
long InstanceId
The Models.Instance.Id being accessed
Definition: ApiHeaders.cs:61
- +
long? InstanceId
The Models.Instance.Id being accessed
Definition: ApiHeaders.cs:61
+
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
+
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
- +
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/_client_exception_8cs.html b/_client_exception_8cs.html index 674b66a5ff..4870890731 100644 --- a/_client_exception_8cs.html +++ b/_client_exception_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ClientException.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Client.ClientException - Exceptions thrown by IServerClients More...
+ Exceptions thrown by IServerClients More...
  + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_client_exception_8cs_source.html b/_client_exception_8cs_source.html index d5a584bae6..0a81d3a2ca 100644 --- a/_client_exception_8cs_source.html +++ b/_client_exception_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ClientException.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ClientException.cs
-Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
5 namespace Tgstation.Server.Client
6 {
10  public abstract class ClientException : Exception
11  {
15  public HttpStatusCode StatusCode { get; }
16 
20  public Version ServerApiVersion { get; }
21 
27  protected ClientException(ErrorMessage errorMessage, HttpStatusCode statusCode) : base(errorMessage == null ? throw new ArgumentNullException(nameof(errorMessage)) : errorMessage.Message ?? "Unknown Error")
28  {
29  StatusCode = statusCode;
30  ServerApiVersion = errorMessage?.SeverApiVersion;
31  }
32 
36  protected ClientException() { }
37 
42  protected ClientException(string message) : base(message) { }
43 
49  protected ClientException(string message, Exception innerException) : base(message, innerException) { }
50  }
51 }
ClientException()
Construct a ClientException
-
ClientException(ErrorMessage errorMessage, HttpStatusCode statusCode)
Construct a ClientException using an errorMessage and statusCode
+Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
6 {
10  public abstract class ClientException : Exception
11  {
15  public HttpStatusCode StatusCode { get; }
16 
20  public Version ServerApiVersion { get; }
21 
27  protected ClientException(ErrorMessage errorMessage, HttpStatusCode statusCode) : base(errorMessage == null ? throw new ArgumentNullException(nameof(errorMessage)) : errorMessage.Message ?? "Unknown Error")
28  {
29  StatusCode = statusCode;
30  ServerApiVersion = errorMessage?.SeverApiVersion;
31  }
32 
36  protected ClientException() { }
37 
42  protected ClientException(string message) : base(message) { }
43 
49  protected ClientException(string message, Exception innerException) : base(message, innerException) { }
50  }
51 }
ClientException()
Construct a ClientException
- - -
ClientException(string message, Exception innerException)
Construct a ClientException with a message and innerException
+ +
ClientException(string message, Exception innerException)
Construct a ClientException with a message and innerException
+
HttpStatusCode StatusCode
The HttpStatusCode of the ClientException
-
ClientException(string message)
Construct a ClientException with a message
-
Version SeverApiVersion
The version of the API the server is using
Definition: ErrorMessage.cs:18
- -
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- -
Exceptions thrown by IServerClients
+
ClientException(string message)
Construct a ClientException with a message
+
Version ServerApiVersion
The Version of the server's API
+
Version SeverApiVersion
The version of the API the server is using
Definition: ErrorMessage.cs:18
+ +
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+ +
Exceptions thrown by IServerClients
diff --git a/_comm_command_8cs.html b/_comm_command_8cs.html index 0cbea4092c..06144b2a8a 100644 --- a/_comm_command_8cs.html +++ b/_comm_command_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/CommCommand.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Interop
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_comm_command_8cs_source.html b/_comm_command_8cs_source.html index b069272bb7..f59c249c8d 100644 --- a/_comm_command_8cs_source.html +++ b/_comm_command_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/CommCommand.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
CommCommand.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 
3 namespace Tgstation.Server.Host.Components.Interop
4 {
8  sealed class CommCommand
9  {
13  public IReadOnlyDictionary<string, object> Parameters { get; set; }
14 
18  public string RawJson { get; set; }
19  }
20 }
- - - +Go to the documentation of this file.
1 using System.Collections.Generic;
2 
4 {
8  sealed class CommCommand
9  {
13  public IReadOnlyDictionary<string, object> Parameters { get; set; }
14 
18  public string RawJson { get; set; }
19  }
20 }
IReadOnlyDictionary< string, object > Parameters
The dictionary of the CommCommand
Definition: CommCommand.cs:13
+
string RawJson
The raw JSON of the CommCommand
Definition: CommCommand.cs:18
+ +
diff --git a/_comm_context_8cs.html b/_comm_context_8cs.html index 4af6b68e43..c6a68a68e1 100644 --- a/_comm_context_8cs.html +++ b/_comm_context_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/CommContext.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Interop
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_comm_context_8cs_source.html b/_comm_context_8cs_source.html index cb9fb4c843..601c0d9fc0 100644 --- a/_comm_context_8cs_source.html +++ b/_comm_context_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/CommContext.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
11 namespace Tgstation.Server.Host.Components.Interop
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();
78  cancellationToken = cancellationTokenSource.Token;
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 
133  public void RegisterHandler(ICommHandler handler)
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
+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
+
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...
-
readonly ILogger< CommContext > logger
The ILogger for the CommContext
Definition: CommContext.cs:24
-
void RegisterHandler(ICommHandler handler)
Register a handler with the ICommContext
Definition: CommContext.cs:133
-
ICommHandler handler
The ICommHandler for the CommContext
Definition: CommContext.cs:44
- +
readonly ILogger< CommContext > logger
The ILogger for the CommContext
Definition: CommContext.cs:24
+
void RegisterHandler(ICommHandler handler)
Register a handler with the ICommContext
Definition: CommContext.cs:133
+
ICommHandler handler
The ICommHandler for the CommContext
Definition: CommContext.cs:44
+ -
CommContext(IIOManager ioManager, ILogger< CommContext > logger, string directory, string filter)
Construct an CommContext
Definition: CommContext.cs:58
-
readonly IIOManager ioManager
The IIOManager for the CommContext
Definition: CommContext.cs:19
-
bool disposed
If the CommContext has been disposed
Definition: CommContext.cs:49
-
readonly CancellationTokenSource cancellationTokenSource
The CancellationTokenSource for the CommContext
Definition: CommContext.cs:34
- -
async void HandleWrite(object sender, FileSystemEventArgs e)
Runs when the fileSystemWatcher triggers
Definition: CommContext.cs:98
-
Interface for using filesystems
Definition: IIOManager.cs:11
- - - + +
CommContext(IIOManager ioManager, ILogger< CommContext > logger, string directory, string filter)
Construct an CommContext
Definition: CommContext.cs:58
+
readonly IIOManager ioManager
The IIOManager for the CommContext
Definition: CommContext.cs:19
+
bool disposed
If the CommContext has been disposed
Definition: CommContext.cs:49
+
readonly CancellationTokenSource cancellationTokenSource
The CancellationTokenSource for the CommContext
Definition: CommContext.cs:34
+ +
async void HandleWrite(object sender, FileSystemEventArgs e)
Runs when the fileSystemWatcher triggers
Definition: CommContext.cs:98
+
Interface for using filesystems
Definition: IIOManager.cs:11
+
Task< byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
Returns all the contents of a file at path as a byte array
+ + +
diff --git a/_command_factory_8cs.html b/_command_factory_8cs.html index 1d333f815a..f1e4ce8f3a 100644 --- a/_command_factory_8cs.html +++ b/_command_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/CommandFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
namespace  Tgstation.Server.Host.Components.Chat.Commands
 
@@ -113,7 +102,7 @@ Namespaces diff --git a/_command_factory_8cs_source.html b/_command_factory_8cs_source.html index c23dad73ff..f8470d27bd 100644 --- a/_command_factory_8cs_source.html +++ b/_command_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/CommandFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
CommandFactory.cs
-Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
7 
8 namespace Tgstation.Server.Host.Components.Chat.Commands
9 {
12  {
17 
22 
27 
32 
36  readonly Models.Instance instance;
37 
42 
51  public CommandFactory(IApplication application, IByondManager byondManager, IRepositoryManager repositoryManager, IDatabaseContextFactory databaseContextFactory, Models.Instance instance)
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 
64  public void SetWatchdog(IWatchdog watchdog)
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  {
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  }
85  }
86 }
-
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
+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 }
+
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
- -
ICommand to return the IApplication.VersionString
+ +
ICommand to return the IApplication.VersionString
- -
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the CommandFactory
-
Command for reading the active Api.Models.TestMerges
-
For managing the BYOND installation
-
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
-
Factory for creating and loading IRepositorys
- -
void SetWatchdog(IWatchdog watchdog)
Set a watchdog 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
+
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
- - -
readonly IRepositoryManager repositoryManager
The IRepositoryManager for the CommandFactory
-
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
+
readonly IApplication application
The IApplication 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_8cs.html b/_components_2_watchdog_2_i_watchdog_8cs.html index 37d9ee8489..892fa936e2 100644 --- a/_components_2_watchdog_2_i_watchdog_8cs.html +++ b/_components_2_watchdog_2_i_watchdog_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/IWatchdog.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Watchdog
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_components_2_watchdog_2_i_watchdog_8cs_source.html b/_components_2_watchdog_2_i_watchdog_8cs_source.html index c36deddcfe..e2b34b2d2e 100644 --- a/_components_2_watchdog_2_i_watchdog_8cs_source.html +++ b/_components_2_watchdog_2_i_watchdog_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/IWatchdog.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IWatchdog.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 
7 namespace Tgstation.Server.Host.Components.Watchdog
8 {
13  {
17  bool Running { get; }
18 
22  bool AlphaIsActive { get; }
23 
27  Models.CompileJob ActiveCompileJob { get; }
28 
32  DreamDaemonLaunchParameters ActiveLaunchParameters { get; }
33 
37  DreamDaemonLaunchParameters LastLaunchParameters { get; }
38 
43 
49  Task Launch(CancellationToken cancellationToken);
50 
57  Task ChangeSettings(DreamDaemonLaunchParameters launchParameters, CancellationToken cancellationToken);
58 
65  Task Restart(bool graceful, CancellationToken cancellationToken);
66 
73  Task Terminate(bool graceful, CancellationToken cancellationToken);
74 
80  Task ResetRebootState(CancellationToken cancellationToken);
81  }
82 }
Consumes EventTypes and takes the appropriate actions
+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  {
17  bool Running { get; }
18 
22  bool AlphaIsActive { get; }
23 
27  Models.CompileJob ActiveCompileJob { get; }
28 
33 
38 
43 
49  Task Launch(CancellationToken cancellationToken);
50 
57  Task ChangeSettings(DreamDaemonLaunchParameters launchParameters, CancellationToken cancellationToken);
58 
65  Task Restart(bool graceful, CancellationToken cancellationToken);
66 
73  Task Terminate(bool graceful, CancellationToken cancellationToken);
74 
80  Task ResetRebootState(CancellationToken cancellationToken);
81  }
82 }
+
Consumes EventTypes and takes the appropriate actions
- - - + +
bool AlphaIsActive
If the alpha server is the active server
Definition: IWatchdog.cs:22
+
Task Launch(CancellationToken cancellationToken)
Start the IWatchdog
+
Models.CompileJob ActiveCompileJob
The CompileJob currently running on the server
Definition: IWatchdog.cs:27
- - +
DreamDaemonLaunchParameters ActiveLaunchParameters
The DreamDaemonLaunchParameters the active server is using
Definition: IWatchdog.cs:32
+
Task ChangeSettings(DreamDaemonLaunchParameters launchParameters, CancellationToken cancellationToken)
Changes the ActiveLaunchParameters. If currently Running triggers a graceful restart
+
Task Restart(bool graceful, CancellationToken cancellationToken)
Restarts the watchdog
+ +
Task ResetRebootState(CancellationToken cancellationToken)
Cancels pending graceful actions
+
DreamDaemonLaunchParameters LastLaunchParameters
The DreamDaemonLaunchParameters to be applied
Definition: IWatchdog.cs:37
+ +
bool Running
If the watchdog is running
Definition: IWatchdog.cs:17
-
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
- -
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
+
Task Terminate(bool graceful, CancellationToken cancellationToken)
Stops the watchdog
+
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
+ +
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
diff --git a/_components_2_watchdog_2_i_watchdog_factory_8cs.html b/_components_2_watchdog_2_i_watchdog_factory_8cs.html index e342c98571..d9cf8cd806 100644 --- a/_components_2_watchdog_2_i_watchdog_factory_8cs.html +++ b/_components_2_watchdog_2_i_watchdog_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/IWatchdogFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

interface  Tgstation.Server.Host.Components.Watchdog.IWatchdogFactory - For creating IWatchdogs More...
+ For creating IWatchdogs More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Watchdog
 
@@ -114,7 +101,7 @@ Namespaces 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 6039512a0a..5d9ffecb8b 100644 --- a/_components_2_watchdog_2_i_watchdog_factory_8cs_source.html +++ b/_components_2_watchdog_2_i_watchdog_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/IWatchdogFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IWatchdogFactory.cs
-Go to the documentation of this file.
4 
5 namespace Tgstation.Server.Host.Components.Watchdog
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 
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 }
-
Consumes EventTypes and takes the appropriate actions
+ +
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
+
For managing connected chat services
Definition: IChat.cs:13
- - - - - - - -
Handles saving and loading WatchdogReattachInformation
- - -
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
+ + + + + + + +
Handles saving and loading WatchdogReattachInformation
+ + +
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
diff --git a/_components_2_watchdog_2_reattach_information_8cs.html b/_components_2_watchdog_2_reattach_information_8cs.html index d4ab550b41..1b7d88ebf3 100644 --- a/_components_2_watchdog_2_reattach_information_8cs.html +++ b/_components_2_watchdog_2_reattach_information_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/ReattachInformation.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Components.Watchdog.ReattachInformation - Parameters necessary for duplicating a ISessionController session More...
+ Parameters necessary for duplicating a ISessionController session More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Watchdog
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_components_2_watchdog_2_reattach_information_8cs_source.html b/_components_2_watchdog_2_reattach_information_8cs_source.html index fad001dea8..ea777d7e19 100644 --- a/_components_2_watchdog_2_reattach_information_8cs_source.html +++ b/_components_2_watchdog_2_reattach_information_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/ReattachInformation.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ReattachInformation.cs
-Go to the documentation of this file.
1 using System;
3 
4 namespace Tgstation.Server.Host.Components.Watchdog
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;
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 }
- - -
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
- -
Parameters necessary for duplicating a ISessionController session
- - + +
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
+ +
Parameters necessary for duplicating a ISessionController session
+ +
diff --git a/_components_2_watchdog_2_watchdog_8cs.html b/_components_2_watchdog_2_watchdog_8cs.html index b3172a8289..5fbff60e48 100644 --- a/_components_2_watchdog_2_watchdog_8cs.html +++ b/_components_2_watchdog_2_watchdog_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/Watchdog.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Watchdog
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_components_2_watchdog_2_watchdog_8cs_source.html b/_components_2_watchdog_2_watchdog_8cs_source.html index 4a18102f7f..7f01e5626a 100644 --- a/_components_2_watchdog_2_watchdog_8cs_source.html +++ b/_components_2_watchdog_2_watchdog_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/Watchdog.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Watchdog.cs
-Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Microsoft.EntityFrameworkCore;
3 using Microsoft.Extensions.Logging;
4 using Newtonsoft.Json;
5 using Newtonsoft.Json.Serialization;
6 using System;
7 using System.Collections.Generic;
8 using System.Diagnostics;
9 using System.Globalization;
10 using System.Linq;
11 using System.Text;
12 using System.Threading;
13 using System.Threading.Tasks;
20 
21 namespace Tgstation.Server.Host.Components.Watchdog
22 {
24  #pragma warning disable CA1506 // TODO: Decomplexify
26  {
30  const int AlphaBravoStartupSeperationInterval = 10;
31 
33  public bool Running { get; private set; }
34 
36  public bool AlphaIsActive { get; private set; }
37 
39  public Models.CompileJob ActiveCompileJob => (AlphaIsActive ? alphaServer : bravoServer)?.Dmb.CompileJob;
40 
42  public DreamDaemonLaunchParameters ActiveLaunchParameters { get; private set; }
43 
45  public DreamDaemonLaunchParameters LastLaunchParameters { get; private set; }
46 
48  public RebootState? RebootState => Running ? (AlphaIsActive ? alphaServer?.RebootState : bravoServer?.RebootState) : null;
49 
53  readonly IChat chat;
54 
59 
64 
69 
74 
78  readonly IByondTopicSender byondTopicSender;
79 
84 
89 
94 
99 
103  readonly ILogger<Watchdog> logger;
104 
108  readonly SemaphoreSlim semaphore;
109 
113  readonly Api.Models.Instance instance;
114 
118  readonly bool autoStart;
119 
123  CancellationTokenSource monitorCts;
124 
129 
133  TaskCompletionSource<object> activeParametersUpdated;
134 
139 
144 
149 
167  public Watchdog(IChat chat, ISessionControllerFactory sessionControllerFactory, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IDatabaseContextFactory databaseContextFactory, IByondTopicSender byondTopicSender, IEventConsumer eventConsumer, IJobManager jobManager, IServerControl serverControl, IAsyncDelayer asyncDelayer, ILogger<Watchdog> logger, DreamDaemonLaunchParameters initialLaunchParameters, Api.Models.Instance instance, bool autoStart)
168  {
169  this.chat = chat ?? throw new ArgumentNullException(nameof(chat));
170  this.sessionControllerFactory = sessionControllerFactory ?? throw new ArgumentNullException(nameof(sessionControllerFactory));
171  this.dmbFactory = dmbFactory ?? throw new ArgumentNullException(nameof(dmbFactory));
172  this.reattachInfoHandler = reattachInfoHandler ?? throw new ArgumentNullException(nameof(reattachInfoHandler));
173  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
174  this.byondTopicSender = byondTopicSender ?? throw new ArgumentNullException(nameof(byondTopicSender));
175  this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
176  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
177  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
178  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
179  ActiveLaunchParameters = initialLaunchParameters ?? throw new ArgumentNullException(nameof(initialLaunchParameters));
180  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
181  this.autoStart = autoStart;
182 
183  if (serverControl == null)
184  throw new ArgumentNullException(nameof(serverControl));
185 
186  chat.RegisterCommandHandler(this);
187 
188  AlphaIsActive = true;
189  ActiveLaunchParameters = initialLaunchParameters;
190  releaseServers = false;
191  activeParametersUpdated = new TaskCompletionSource<object>();
192 
193  restartRegistration = serverControl.RegisterForRestart(this);
194  try
195  {
196  semaphore = new SemaphoreSlim(1);
197  }
198  catch
199  {
200  restartRegistration.Dispose();
201  throw;
202  }
203  }
204 
206  public void Dispose()
207  {
208  DisposeAndNullControllers();
209  semaphore.Dispose();
210  restartRegistration.Dispose();
211  }
212 
217  {
218  alphaServer?.Dispose();
219  alphaServer = null;
220  bravoServer?.Dispose();
221  bravoServer = null;
222  Running = false;
223  }
224 
231  async Task TerminateNoLock(bool graceful, bool announce, CancellationToken cancellationToken)
232  {
233  if (!Running)
234  return;
235  if (!graceful)
236  {
237  var chatTask = announce ? chat.SendWatchdogMessage("Terminating...", cancellationToken) : Task.CompletedTask;
238  await StopMonitor().ConfigureAwait(false);
239  DisposeAndNullControllers();
240  LastLaunchParameters = null;
241  await chatTask.ConfigureAwait(false);
242  return;
243  }
244 
245  // merely set the reboot state
246  var toKill = AlphaIsActive ? alphaServer : bravoServer;
247  var other = AlphaIsActive ? bravoServer : alphaServer;
248  if (toKill != null)
249  await toKill.SetRebootState(Components.Watchdog.RebootState.Shutdown, cancellationToken).ConfigureAwait(false);
250  }
251 
259  #pragma warning disable CA1502 // TODO: Decomplexify
260  async Task HandlerMonitorWakeup(MonitorActivationReason activationReason, MonitorState monitorState, CancellationToken cancellationToken)
261  {
262  logger.LogDebug("Monitor activation. Reason: {0}", activationReason);
263 
264  // this is where the bulk of the watchdog handling code lives and is fraught with lambdas, sorry not sorry
265  // I'll do my best to walk you through it
266 
267  // returns true if the inactive server can't be used immediately
268  // also sets monitor to restart if the above holds
269  bool FullRestartDeadInactive()
270  {
271  if (monitorState.RebootingInactiveServer || monitorState.InactiveServerCritFail)
272  {
273  logger.LogInformation("Inactive server is {0}! Restarting monitor...", monitorState.InactiveServerCritFail ? "critically failed" : "still rebooting");
274  monitorState.NextAction = MonitorAction.Restart; // will dispose server
275  return true;
276  }
277 
278  return false;
279  }
280 
281  // trys to set inactive server's port to the public game port
282  // doesn't handle closing active server's port
283  // returns true on success and swaps inactiveserver and activeserver also sets LastLaunchParameters to ActiveLaunchParameters
284  // on failure, sets monitor to restart
285  async Task<bool> MakeInactiveActive()
286  {
287  logger.LogDebug("Setting inactive server to port {0}...", ActiveLaunchParameters.PrimaryPort.Value);
288  var result = await monitorState.InactiveServer.SetPort(ActiveLaunchParameters.PrimaryPort.Value, cancellationToken).ConfigureAwait(false);
289 
290  if (!result)
291  {
292  logger.LogWarning("Failed to activate inactive server! Restarting monitor...");
293  monitorState.NextAction = MonitorAction.Restart; // will dispose server
294  return false;
295  }
296 
297  // inactive server should always be using active launch parameters
298  LastLaunchParameters = ActiveLaunchParameters;
299 
300  var tmp = monitorState.ActiveServer;
301  monitorState.ActiveServer = monitorState.InactiveServer;
302  monitorState.InactiveServer = tmp;
303  AlphaIsActive = !AlphaIsActive;
304  monitorState.ActiveServer.EnableCustomChatCommands();
305  return true;
306  }
307 
308  // Kills and tries to launch inactive server with the latest dmb
309  // falls back to current dmb on failure
310  // Sets critfail on inactive server failing that
311  // returns false if the backup dmb was used successfully, true otherwise
312  async Task UpdateAndRestartInactiveServer(bool breakAfter)
313  {
314  activeParametersUpdated = new TaskCompletionSource<object>();
315  monitorState.InactiveServer.Dispose(); // kill or recycle it
316  var desiredNextAction = breakAfter ? MonitorAction.Break : MonitorAction.Continue;
317  monitorState.NextAction = desiredNextAction;
318 
319  logger.LogInformation("Rebooting inactive server...");
320  var newDmb = dmbFactory.LockNextDmb(1);
321  try
322  {
323  monitorState.InactiveServer = await sessionControllerFactory.LaunchNew(ActiveLaunchParameters, newDmb, null, false, !monitorState.ActiveServer.IsPrimary, false, cancellationToken).ConfigureAwait(false);
324  monitorState.InactiveServer.SetHighPriority();
325  }
326  catch (OperationCanceledException)
327  {
328  throw;
329  }
330  catch (Exception e)
331  {
332  logger.LogError("Error occurred while recreating server! Attempting backup strategy of running DMB of running server! Exception: {0}", e.ToString());
333 
334  // ahh jeez, what do we do here?
335  // this is our fault, so it should never happen but
336  // idk maybe a database error while handling the newest dmb?
337  // either way try to start it using the active server's dmb as a backup
338  try
339  {
340  var dmbBackup = await dmbFactory.FromCompileJob(monitorState.ActiveServer.Dmb.CompileJob, cancellationToken).ConfigureAwait(false);
341 
342  if (dmbBackup == null) // NANI!?
343  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
344 
345  monitorState.InactiveServer = await sessionControllerFactory.LaunchNew(ActiveLaunchParameters, dmbBackup, null, false, !monitorState.ActiveServer.IsPrimary, false, cancellationToken).ConfigureAwait(false);
346  monitorState.InactiveServer.SetHighPriority();
347  await chat.SendWatchdogMessage("Staging newest DMB on inactive server failed: {0} Falling back to previous dmb...", cancellationToken).ConfigureAwait(false);
348  }
349  catch (OperationCanceledException)
350  {
351  throw;
352  }
353  catch (Exception e2)
354  {
355  // fuuuuucckkk
356  logger.LogError("Backup strategy failed! Monitor will restart when active server reboots! Exception: {0}", e2.ToString());
357  monitorState.InactiveServerCritFail = true;
358  await chat.SendWatchdogMessage("Attempted reboot of inactive server failed. Watchdog will reset when active server fails or exits", cancellationToken).ConfigureAwait(false);
359  return;
360  }
361  }
362 
363  logger.LogInformation("Successfully relaunched inactive server!");
364  monitorState.RebootingInactiveServer = true;
365  }
366 
367  string ExitWord(ISessionController controller) => controller.TerminationWasRequested ? "exited" : "crashed";
368 
369  // reason handling
370  switch (activationReason)
371  {
372  case MonitorActivationReason.ActiveServerCrashed:
373  if (monitorState.ActiveServer.RebootState == Components.Watchdog.RebootState.Shutdown)
374  {
375  // the time for graceful shutdown is now
376  await chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Active server {0}! Exiting due to graceful termination request...", ExitWord(monitorState.ActiveServer)), cancellationToken).ConfigureAwait(false);
377  DisposeAndNullControllers();
378  monitorState.NextAction = MonitorAction.Exit;
379  break;
380  }
381 
382  if (FullRestartDeadInactive())
383  {
384  // tell chat about it and go ahead
385  await chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Active server {0}! Inactive server unable to online!", ExitWord(monitorState.ActiveServer)), cancellationToken).ConfigureAwait(false);
386 
387  // we've already been set to restart
388  break;
389  }
390 
391  // tell chat about it
392  await chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Active server {0}! Onlining inactive server...", ExitWord(monitorState.ActiveServer)), cancellationToken).ConfigureAwait(false);
393 
394  // try to activate the inactive server
395  if (!await MakeInactiveActive().ConfigureAwait(false))
396  break; // failing that, we've already been set to restart
397 
398  // bring up another inactive server
399  await UpdateAndRestartInactiveServer(true).ConfigureAwait(false);
400  break;
401  case MonitorActivationReason.InactiveServerCrashed:
402  // just announce and try to bring it back
403  await chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Inactive server {0}! Rebooting...", ExitWord(monitorState.InactiveServer)), cancellationToken).ConfigureAwait(false);
404  await UpdateAndRestartInactiveServer(false).ConfigureAwait(false);
405  break;
406  case MonitorActivationReason.ActiveServerRebooted:
407  // ideal goal: active server just closed its port
408  // tell inactive server to open it's port and that's now the active server
409  var rebootState = monitorState.ActiveServer.RebootState;
410  monitorState.ActiveServer.ResetRebootState(); // the DMAPI has already done this internally
411 
412  if (FullRestartDeadInactive() && rebootState != Components.Watchdog.RebootState.Shutdown)
413  break; // full restart if the inactive server is being fucky
414 
415  // what matters here is the RebootState
416  var restartOnceSwapped = false;
417 
418  switch (rebootState)
419  {
420  case Components.Watchdog.RebootState.Normal:
421  // life as normal
422  break;
423  case Components.Watchdog.RebootState.Restart:
424  // reboot the current active server once the inactive one activates
425  restartOnceSwapped = true;
426  break;
427  case Components.Watchdog.RebootState.Shutdown:
428  // graceful shutdown time
429  await chat.SendWatchdogMessage("Active server rebooted! Exiting due to graceful termination request...", cancellationToken).ConfigureAwait(false);
430  DisposeAndNullControllers();
431  monitorState.NextAction = MonitorAction.Exit;
432  return;
433  default:
434  Trace.Assert(false, String.Format(CultureInfo.InvariantCulture, "Invalid RebootState: {0}!", rebootState));
435  break;
436  }
437 
438  // are both servers now running the same CompileJob?
439  var sameCompileJob = monitorState.InactiveServer.Dmb.CompileJob.Id == monitorState.ActiveServer.Dmb.CompileJob.Id;
440 
441  if (!sameCompileJob || ActiveLaunchParameters != LastLaunchParameters)
442  restartOnceSwapped = true; // need a new launch to update either settings or compile job
443 
444  if (restartOnceSwapped)
445  /*
446  * we need to manually restart active server
447  * just kill it here, easier that way
448  */
449  monitorState.ActiveServer.Dispose();
450 
451  var activeServerStillHasPortOpen = !restartOnceSwapped && !monitorState.ActiveServer.ClosePortOnReboot;
452 
453  if (activeServerStillHasPortOpen)
454  /* we didn't want active server to swap for some reason and it still has it's port open
455  * just continue as normal
456  */
457  break;
458 
459  if (!await MakeInactiveActive().ConfigureAwait(false))
460  break; // monitor will restart
461 
462  // servers now swapped
463  // enable this now if inactive server is not still valid
464  monitorState.ActiveServer.ClosePortOnReboot = restartOnceSwapped;
465 
466  if (!restartOnceSwapped)
467  /*
468  * now try to reopen it on the private port
469  * failing that, just reboot it
470  */
471  restartOnceSwapped = !await monitorState.InactiveServer.SetPort(ActiveLaunchParameters.SecondaryPort.Value, cancellationToken).ConfigureAwait(false);
472 
473  // break either way because any issues past this point would be solved by the reboot
474  if (restartOnceSwapped) // for one reason or another
475  await UpdateAndRestartInactiveServer(true).ConfigureAwait(false); // update and reboot
476  else
477  monitorState.NextAction = MonitorAction.Skip; // only skip checking inactive server rebooted, it's guaranteed InactiveServerStartup complete wouldn't fire this iteration
478  break;
479  case MonitorActivationReason.InactiveServerRebooted:
480  // just don't let the active server close it's port if the inactive server isn't ready
481  monitorState.RebootingInactiveServer = true;
482  monitorState.InactiveServer.ResetRebootState();
483  monitorState.ActiveServer.ClosePortOnReboot = false;
484  monitorState.NextAction = MonitorAction.Continue;
485  break;
486  case MonitorActivationReason.InactiveServerStartupComplete:
487  // opposite of above case
488  monitorState.RebootingInactiveServer = false;
489  monitorState.ActiveServer.ClosePortOnReboot = true;
490  monitorState.NextAction = MonitorAction.Continue;
491  break;
492  case MonitorActivationReason.NewDmbAvailable:
493  case MonitorActivationReason.ActiveLaunchParametersUpdated:
494  // just reload the inactive server and wait for a swap to apply the changes
495  await UpdateAndRestartInactiveServer(true).ConfigureAwait(false);
496  break;
497  default:
498  Trace.Assert(false, String.Format(CultureInfo.InvariantCulture, "Invalid monitor activation reason: {0}!", activationReason));
499  break;
500  }
501  }
502  #pragma warning restore CA1502
503 
509 #pragma warning disable CA1502 // TODO: Decomplexify
510  async Task MonitorLifetimes(CancellationToken cancellationToken)
511  {
512  logger.LogTrace("Entered MonitorLifetimes");
513 
514  // this function is responsible for calling HandlerMonitorWakeup when necessary and manitaining the MonitorState
515  var iteration = 1;
516  for (var monitorState = new MonitorState(); monitorState.NextAction != MonitorAction.Exit; ++iteration)
517  {
518  // always start out with continue
519  monitorState.NextAction = MonitorAction.Continue;
520 
521  // dump some info to the logs
522  logger.LogDebug("Iteration {0} of monitor loop", iteration);
523  try
524  {
525  if (AlphaIsActive)
526  logger.LogDebug("Alpha is the active server");
527  else
528  logger.LogDebug("Bravo is the active server");
529 
530  if (monitorState.RebootingInactiveServer)
531  logger.LogDebug("Inactive server is rebooting");
532 
533  // update the monitor state with the inactive/active servers
534  monitorState.ActiveServer = AlphaIsActive ? alphaServer : bravoServer;
535  monitorState.InactiveServer = AlphaIsActive ? bravoServer : alphaServer;
536 
537  if (monitorState.ActiveServer.ClosePortOnReboot)
538  logger.LogDebug("Active server will close port on reboot");
539  if (monitorState.InactiveServer.ClosePortOnReboot)
540  logger.LogDebug("Inactive server will close port on reboot");
541 
542  logger.LogDebug("Active server Compile Job ID: {0}", monitorState.ActiveServer.Dmb.CompileJob.Id);
543  logger.LogDebug("Inactive server Compile Job ID: {0}", monitorState.InactiveServer.Dmb.CompileJob.Id);
544 
545  // load the activation tasks into local variables
546  Task activeServerLifetime = monitorState.ActiveServer.Lifetime;
547  Task inactiveServerLifetime = monitorState.InactiveServer.Lifetime;
548  var activeServerReboot = monitorState.ActiveServer.OnReboot;
549  var inactiveServerReboot = monitorState.InactiveServer.OnReboot;
550  Task inactiveServerStartup = monitorState.RebootingInactiveServer ? monitorState.InactiveServer.LaunchResult : null;
551  Task activeLaunchParametersChanged = activeParametersUpdated.Task;
552  var newDmbAvailable = dmbFactory.OnNewerDmb;
553 
554  // cancel waiting if requested
555  var cancelTcs = new TaskCompletionSource<object>();
556  using (cancellationToken.Register(() => cancelTcs.SetCanceled()))
557  {
558  var toWaitOn = Task.WhenAny(activeServerLifetime, inactiveServerLifetime, activeServerReboot, inactiveServerReboot, newDmbAvailable, cancelTcs.Task, activeLaunchParametersChanged);
559  if (monitorState.RebootingInactiveServer)
560  toWaitOn = Task.WhenAny(toWaitOn, inactiveServerStartup);
561 
562  // wait for something to happen
563  await toWaitOn.ConfigureAwait(false);
564  cancellationToken.ThrowIfCancellationRequested();
565  }
566 
567  var chatTask = Task.CompletedTask;
568  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
569  {
570  // always run HandleMonitorWakeup from the context of the semaphore lock
571  // multiple things may have happened, handle them one at a time
572  for (var moreActivationsToProcess = true; moreActivationsToProcess && (monitorState.NextAction == MonitorAction.Continue || monitorState.NextAction == MonitorAction.Skip);)
573  {
574  MonitorActivationReason activationReason = default; // this will always be assigned before being used
575 
576  // process the tasks in this order and call HandlerMonitorWakup for each
577  bool CheckActivationReason(ref Task task, MonitorActivationReason testActivationReason)
578  {
579  var taskCompleted = task?.IsCompleted == true;
580  task = null;
581  if (monitorState.NextAction == MonitorAction.Skip)
582  monitorState.NextAction = MonitorAction.Continue;
583  else if (taskCompleted)
584  {
585  activationReason = testActivationReason;
586  return true;
587  }
588 
589  return false;
590  }
591 
592  if (CheckActivationReason(ref activeServerLifetime, MonitorActivationReason.ActiveServerCrashed)
593  || CheckActivationReason(ref inactiveServerLifetime, MonitorActivationReason.InactiveServerCrashed)
594  || CheckActivationReason(ref activeServerReboot, MonitorActivationReason.ActiveServerRebooted)
595  || CheckActivationReason(ref inactiveServerReboot, MonitorActivationReason.InactiveServerRebooted)
596  || CheckActivationReason(ref inactiveServerStartup, MonitorActivationReason.InactiveServerStartupComplete)
597  || CheckActivationReason(ref newDmbAvailable, MonitorActivationReason.NewDmbAvailable)
598  || CheckActivationReason(ref activeLaunchParametersChanged, MonitorActivationReason.ActiveLaunchParametersUpdated))
599  await HandlerMonitorWakeup(activationReason, monitorState, cancellationToken).ConfigureAwait(false);
600  else
601  moreActivationsToProcess = false;
602  }
603 
604  // writeback alphaServer and bravoServer from monitor state in case they changesd
605  alphaServer = AlphaIsActive ? monitorState.ActiveServer : monitorState.InactiveServer;
606  bravoServer = !AlphaIsActive ? monitorState.ActiveServer : monitorState.InactiveServer;
607  }
608 
609  // full reboot required
610  if (monitorState.NextAction == MonitorAction.Restart)
611  {
612  logger.LogDebug("Next state action is to restart");
613  DisposeAndNullControllers();
614  chatTask = chat.SendWatchdogMessage("Restarting entirely due to complications...", cancellationToken);
615 
616  for (var retryAttempts = 1; monitorState.NextAction == MonitorAction.Restart; ++retryAttempts)
617  {
618  Exception launchException = null;
619  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
620  try
621  {
622  // use LaunchImplNoLock without announcements or restarting the monitor
623  await LaunchImplNoLock(false, false, null, cancellationToken).ConfigureAwait(false);
624  if (Running)
625  {
626  logger.LogDebug("Relaunch successful, resetting monitor state...");
627  monitorState = new MonitorState(); // clean the slate and continue
628  }
629  }
630  catch (OperationCanceledException)
631  {
632  throw;
633  }
634  catch (Exception e)
635  {
636  launchException = e;
637  }
638 
639  await chatTask.ConfigureAwait(false);
640  if (!Running)
641  {
642  if (launchException == null)
643  logger.LogWarning("Failed to automatically restart the watchdog! Attempt: {0}", retryAttempts);
644  else
645  logger.LogWarning("Failed to automatically restart the watchdog! Attempt: {0}, Exception: {1}", retryAttempts, launchException);
646  var retryDelay = Math.Min(Math.Pow(2, retryAttempts), 3600); // max of one hour, increasing by a power of 2 each time
647  chatTask = chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Failed to restart watchdog (Attempt: {0}), retrying in {1} seconds...", retryAttempts, retryDelay), cancellationToken);
648  await Task.WhenAll(asyncDelayer.Delay(TimeSpan.FromSeconds(retryDelay), cancellationToken), chatTask).ConfigureAwait(false);
649  }
650  }
651  }
652  }
653  catch (OperationCanceledException)
654  {
655  logger.LogDebug("Monitor cancelled");
656  break;
657  }
658  catch (Exception e)
659  {
660  // really, this should NEVER happen
661  logger.LogError("Monitor crashed! Iteration: {0}, State: {1}, Exception: {2}", iteration, JsonConvert.SerializeObject(monitorState), e);
662  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);
663  }
664  }
665 
666  logger.LogTrace("Monitor exiting...");
667  }
668  #pragma warning restore CA1502
669 
674  async Task<bool> StopMonitor()
675  {
676  logger.LogTrace("StopMonitor");
677  if (monitorTask == null)
678  return false;
679  monitorCts.Cancel();
680  await monitorTask.ConfigureAwait(false);
681  monitorCts.Dispose();
682  monitorTask = null;
683  return true;
684  }
685 
687  public async Task ChangeSettings(DreamDaemonLaunchParameters launchParameters, CancellationToken cancellationToken)
688  {
689  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
690  {
691  if (launchParameters.Match(ActiveLaunchParameters))
692  return;
693  ActiveLaunchParameters = launchParameters;
694  if (Running)
695  activeParametersUpdated.TrySetResult(null); // queue an update
696  }
697  }
698 
707  #pragma warning disable CA1502 // TODO: Decomplexify
708  async Task LaunchImplNoLock(bool startMonitor, bool announce, WatchdogReattachInformation reattachInfo, CancellationToken cancellationToken)
709  {
710  logger.LogTrace("Begin LaunchNoLock");
711 
712  if (Running)
713  throw new JobException("Watchdog already running!");
714 
715  // this is necessary, the monitor could be in it's sleep loop trying to restart, if so cancel THAT monitor and start our own with blackjack and hookers
716  Task chatTask;
717  if (startMonitor && await StopMonitor().ConfigureAwait(false))
718  chatTask = chat.SendWatchdogMessage("Automatic retry sequence cancelled by manual launch. Restarting...", cancellationToken);
719  else if (announce)
720  chatTask = chat.SendWatchdogMessage(reattachInfo == null ? "Starting..." : "Reattaching...", cancellationToken); // simple announce
721  else
722  chatTask = Task.CompletedTask; // no announce
723 
724  // since neither server is running, this is safe to do
725  LastLaunchParameters = ActiveLaunchParameters;
726 
727  // for when we call ourself and want to not catch thrown exceptions
728  var ignoreNestedException = false;
729  try
730  {
731  // good ole sanity, should never fucking trigger but i don't trust myself even though I should
732  // TODO: Unit test this instead?
733  if (alphaServer != null || bravoServer != null)
734  throw new InvalidOperationException("Entered LaunchNoLock with one or more of the servers not being null!");
735 
736  // don't need a new dmb if reattaching
737  var doesntNeedNewDmb = reattachInfo?.Alpha != null && reattachInfo?.Bravo != null;
738  var dmbToUse = doesntNeedNewDmb ? null : dmbFactory.LockNextDmb(2);
739 
740  // if this try catches something, both servers are killed
741  try
742  {
743  // start the alpha server task, either by launch a new process or attaching to an existing one
744  // The tasks returned are mainly for writing interop files to the directories among other things and should generally never fail
745  // The tasks pertaining to server startup times are in the ISessionControllers
746  Task<ISessionController> alphaServerTask;
747  if (!doesntNeedNewDmb)
748  alphaServerTask = sessionControllerFactory.LaunchNew(ActiveLaunchParameters, dmbToUse, null, true, true, false, cancellationToken);
749  else
750  alphaServerTask = sessionControllerFactory.Reattach(reattachInfo.Alpha, cancellationToken);
751 
752  // retrieve the session controller
753  var startTime = DateTimeOffset.Now;
754  alphaServer = await alphaServerTask.ConfigureAwait(false);
755 
756  // failed reattaches will return null
757  alphaServer?.SetHighPriority();
758 
759  // extra delay for total ordering
760  var now = DateTimeOffset.Now;
761  var delay = now - startTime;
762 
763  // definitely not if reattaching though
764  if (reattachInfo == null && delay.TotalSeconds < AlphaBravoStartupSeperationInterval)
765  await asyncDelayer.Delay(startTime.AddSeconds(AlphaBravoStartupSeperationInterval) - now, cancellationToken).ConfigureAwait(false);
766 
767  // now bring bravo up
768  if (!doesntNeedNewDmb)
769  bravoServer = await sessionControllerFactory.LaunchNew(ActiveLaunchParameters, dmbToUse, null, false, false, false, cancellationToken).ConfigureAwait(false);
770  else
771  bravoServer = await sessionControllerFactory.Reattach(reattachInfo.Bravo, cancellationToken).ConfigureAwait(false);
772 
773  // failed reattaches will return null
774  bravoServer?.SetHighPriority();
775 
776  // possiblity of null servers due to failed reattaches
777  if (alphaServer == null || bravoServer == null)
778  {
779  await chatTask.ConfigureAwait(false);
780  var bothServersDead = alphaServer == null && bravoServer == null;
781  if (bothServersDead
782  || (alphaServer == null && reattachInfo.AlphaIsActive)
783  || (bravoServer == null && !reattachInfo.AlphaIsActive))
784  {
785  // we lost the active server, just restart entirely
786  DisposeAndNullControllers();
787  const string FailReattachMessage = "Unable to properly reattach to active server! Restarting...";
788  logger.LogWarning(FailReattachMessage);
789  logger.LogDebug(bothServersDead ? "Also could not reattach to inactive server!" : "Inactive server was reattached successfully!");
790  chatTask = chat.SendWatchdogMessage(FailReattachMessage, cancellationToken);
791  ignoreNestedException = true;
792  await LaunchImplNoLock(true, false, null, cancellationToken).ConfigureAwait(false);
793  return;
794  }
795 
796  // we still have the active server but the other one is dead to us, hand it off to the monitor to restart
797  const string InactiveReattachFailureMessage = "Unable to reattach to inactive server. Leaving for monitor to reboot...";
798  chatTask = chat.SendWatchdogMessage(InactiveReattachFailureMessage, cancellationToken);
799  logger.LogWarning(InactiveReattachFailureMessage);
800 
801  if (reattachInfo.AlphaIsActive)
802  bravoServer = sessionControllerFactory.CreateDeadSession(reattachInfo.Bravo.Dmb);
803  else
804  alphaServer = sessionControllerFactory.CreateDeadSession(reattachInfo.Alpha.Dmb);
805  }
806 
807  // throws a JobException if something went wrong with a launch
808  // Dead sessions won't trigger this
809  async Task<LaunchResult> CheckLaunch(ISessionController controller, string serverName)
810  {
811  var launch = await controller.LaunchResult.ConfigureAwait(false);
812  if (launch.ExitCode.HasValue) // you killed us ray...
813  throw new JobException(String.Format(CultureInfo.InvariantCulture, "{1} server failed to start: {0}", launch.ToString(), serverName));
814  if (!launch.StartupTime.HasValue)
815  throw new JobException(String.Format(CultureInfo.InvariantCulture, "{1} server timed out on startup: {0}s", launch.ToString(), ActiveLaunchParameters.StartupTimeout.Value));
816  return launch;
817  }
818 
819  var alphaLrt = CheckLaunch(alphaServer, "Alpha");
820  var bravoLrt = CheckLaunch(bravoServer, "Bravo");
821 
822  // this task completes when both serers have finished booting
823  var allTask = Task.WhenAll(alphaLrt, bravoLrt);
824 
825  // don't forget about the cancellationToken
826  var cancelTcs = new TaskCompletionSource<object>();
827  using (cancellationToken.Register(() => cancelTcs.SetCanceled()))
828  await Task.WhenAny(allTask, cancelTcs.Task).ConfigureAwait(false);
829  cancellationToken.ThrowIfCancellationRequested();
830 
831  await allTask.ConfigureAwait(false);
832 
833  // both servers are now running, alpha is the active server(unless reattach), huzzah
834  AlphaIsActive = reattachInfo?.AlphaIsActive ?? true;
835 
836  var activeServer = AlphaIsActive ? alphaServer : bravoServer;
837  activeServer.EnableCustomChatCommands();
838  activeServer.ClosePortOnReboot = true;
839 
840  logger.LogInformation("Launched servers successfully");
841  Running = true;
842 
843  if (startMonitor)
844  {
845  monitorCts = new CancellationTokenSource();
846  monitorTask = MonitorLifetimes(monitorCts.Token);
847  }
848  }
849  catch
850  {
851  if (dmbToUse != null)
852  {
853  // we locked 2 dmbs
854  if (bravoServer == null)
855  {
856  // bravo didn't get control of his
857  dmbToUse.Dispose();
858  if (alphaServer == null)
859  dmbToUse.Dispose(); // alpha didn't get control of his
860  }
861  }
862  else if (doesntNeedNewDmb) // we have reattachInfo
863  if (bravoServer == null)
864  {
865  // bravo didn't get control of his
866  reattachInfo.Bravo?.Dmb.Dispose();
867  if (alphaServer == null)
868  reattachInfo.Alpha?.Dmb.Dispose(); // alpha didn't get control of his
869  }
870 
871  // kill the controllers
872  DisposeAndNullControllers();
873  throw;
874  }
875  }
876  catch (Exception e)
877  {
878  // don't try to send chat tasks or warning logs if were suppressing exceptions or cancelled
879  if (!ignoreNestedException && !cancellationToken.IsCancellationRequested)
880  {
881  var originalChatTask = chatTask;
882  async Task ChainChatTaskWithErrorMessage()
883  {
884  await originalChatTask.ConfigureAwait(false);
885  await chat.SendWatchdogMessage("Startup failed!", cancellationToken).ConfigureAwait(false);
886  }
887 
888  chatTask = ChainChatTaskWithErrorMessage();
889  logger.LogWarning("Failed to start watchdog: {0}", e.ToString());
890  }
891 
892  throw;
893  }
894  finally
895  {
896  // finish the chat task that's in flight
897  try
898  {
899  await chatTask.ConfigureAwait(false);
900  }
901  catch (OperationCanceledException) { }
902  }
903  }
904  #pragma warning restore CA1502
905 
907  public async Task Launch(CancellationToken cancellationToken)
908  {
909  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
910  await LaunchImplNoLock(true, true, null, cancellationToken).ConfigureAwait(false);
911  }
912 
914  public async Task ResetRebootState(CancellationToken cancellationToken)
915  {
916  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
917  {
918  if (!Running)
919  return;
920  var toClear = AlphaIsActive ? alphaServer : bravoServer;
921  if (toClear != null)
922  toClear.ResetRebootState();
923  }
924  }
925 
927  public async Task Restart(bool graceful, CancellationToken cancellationToken)
928  {
929  logger.LogTrace("Begin Restart. Graceful: {0}", graceful);
930  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
931  {
932  if (!graceful || !Running)
933  {
934  Task chatTask;
935  if (Running)
936  {
937  chatTask = chat.SendWatchdogMessage("Manual restart triggered...", cancellationToken);
938  await TerminateNoLock(false, false, cancellationToken).ConfigureAwait(false);
939  }
940  else
941  chatTask = Task.CompletedTask;
942  await LaunchImplNoLock(true, !Running, null, cancellationToken).ConfigureAwait(false);
943  await chatTask.ConfigureAwait(false);
944  }
945 
946  var toReboot = AlphaIsActive ? alphaServer : bravoServer;
947  if (toReboot != null)
948  {
949  if (!await toReboot.SetRebootState(Components.Watchdog.RebootState.Restart, cancellationToken).ConfigureAwait(false))
950  logger.LogWarning("Unable to send reboot state change event!");
951  }
952  }
953  }
954 
956  public async Task Terminate(bool graceful, CancellationToken cancellationToken)
957  {
958  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
959  await TerminateNoLock(graceful, !releaseServers, cancellationToken).ConfigureAwait(false);
960  }
961 
963  public async Task StartAsync(CancellationToken cancellationToken)
964  {
965  var reattachInfo = await reattachInfoHandler.Load(cancellationToken).ConfigureAwait(false);
966  if (!autoStart && reattachInfo == null)
967  return;
968 
969  long? adminUserId = null;
970 
971  await databaseContextFactory.UseContext(async db => adminUserId = await db.Users
972  .Where(x => x.CanonicalName == Api.Models.User.AdminName.ToUpperInvariant())
973  .Select(x => x.Id)
974  .FirstAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false);
975  var job = new Models.Job
976  {
977  StartedBy = new Models.User
978  {
979  Id = adminUserId.Value
980  },
981  Instance = new Models.Instance
982  {
983  Id = instance.Id
984  },
985  Description = "Instance startup watchdog launch",
986  CancelRight = (ulong)DreamDaemonRights.Shutdown,
987  CancelRightsType = RightsType.DreamDaemon
988  };
989  await jobManager.RegisterOperation(job, async (j, databaseContext, progressFunction, ct) =>
990  {
991  using (await SemaphoreSlimContext.Lock(semaphore, ct).ConfigureAwait(false))
992  await LaunchImplNoLock(true, true, reattachInfo, ct).ConfigureAwait(false);
993  }, cancellationToken).ConfigureAwait(false);
994  }
995 
997  public async Task StopAsync(CancellationToken cancellationToken)
998  {
999  try
1000  {
1001  if (releaseServers && Running)
1002  {
1003  await StopMonitor().ConfigureAwait(false);
1004 
1005  var reattachInformation = new WatchdogReattachInformation
1006  {
1007  AlphaIsActive = AlphaIsActive
1008  };
1009  reattachInformation.Alpha = alphaServer?.Release();
1010  reattachInformation.Bravo = bravoServer?.Release();
1011  await reattachInfoHandler.Save(reattachInformation, cancellationToken).ConfigureAwait(false);
1012  }
1013 
1014  await Terminate(false, cancellationToken).ConfigureAwait(false);
1015  }
1016  catch
1017  {
1018  releaseServers = false;
1019  throw;
1020  }
1021  }
1022 
1024  public async Task<bool> HandleEvent(EventType eventType, IEnumerable<string> parameters, CancellationToken cancellationToken)
1025  {
1026  string results;
1027  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
1028  {
1029  if (!Running)
1030  return true;
1031 
1032  var builder = new StringBuilder(Constants.DMTopicEvent);
1033  builder.Append('&');
1034  var notification = new EventNotification
1035  {
1036  Type = eventType,
1037  Parameters = parameters
1038  };
1039  var json = JsonConvert.SerializeObject(notification);
1040  builder.Append(byondTopicSender.SanitizeString(Constants.DMParameterData));
1041  builder.Append('=');
1042  builder.Append(byondTopicSender.SanitizeString(json));
1043 
1044  var activeServer = AlphaIsActive ? alphaServer : bravoServer;
1045  results = await activeServer.SendCommand(builder.ToString(), cancellationToken).ConfigureAwait(false);
1046  }
1047 
1048  if (results == Constants.DMResponseSuccess)
1049  return true;
1050 
1051  List<Response> responses;
1052  try
1053  {
1054  responses = JsonConvert.DeserializeObject<List<Response>>(results);
1055  }
1056  catch
1057  {
1058  logger.LogInformation("Recieved invalid response from DD when parsing event {0}:{1}{2}", eventType, Environment.NewLine, results);
1059  return true;
1060  }
1061 
1062  await Task.WhenAll(responses.Select(x => chat.SendMessage(x.Message, x.ChannelIds, cancellationToken))).ConfigureAwait(false);
1063 
1064  return true;
1065  }
1066 
1068  public async Task<string> HandleChatCommand(string commandName, string arguments, Chat.User sender, CancellationToken cancellationToken)
1069  {
1070  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
1071  {
1072  if (!Running)
1073  return "ERROR: Server offline!";
1074 
1075  var commandObject = new ChatCommand
1076  {
1077  Command = commandName,
1078  Params = arguments,
1079  User = sender
1080  };
1081 
1082  var json = JsonConvert.SerializeObject(commandObject, new JsonSerializerSettings
1083  {
1084  ContractResolver = new CamelCasePropertyNamesContractResolver()
1085  });
1086 
1087  var command = String.Format(CultureInfo.InvariantCulture, "{0}&{1}={2}", byondTopicSender.SanitizeString(Constants.DMTopicChatCommand), byondTopicSender.SanitizeString(Constants.DMParameterData), byondTopicSender.SanitizeString(json));
1088 
1089  var activeServer = AlphaIsActive ? alphaServer : bravoServer;
1090  return await activeServer.SendCommand(command, cancellationToken).ConfigureAwait(false) ?? "ERROR: Bad topic exchange!";
1091  }
1092  }
1093 
1095  public async Task HandleRestart(Version updateVersion, CancellationToken cancellationToken)
1096  {
1097  releaseServers = true;
1098  if (Running)
1099  await chat.SendWatchdogMessage("Detaching...", cancellationToken).ConfigureAwait(false);
1100  }
1101  }
1102 }
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 IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the Watchdog
Definition: Watchdog.cs:73
-
async Task Launch(CancellationToken cancellationToken)
Start the IWatchdog
Definition: Watchdog.cs:907
+Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Microsoft.EntityFrameworkCore;
3 using Microsoft.Extensions.Logging;
4 using Newtonsoft.Json;
5 using Newtonsoft.Json.Serialization;
6 using System;
7 using System.Collections.Generic;
8 using System.Diagnostics;
9 using System.Globalization;
10 using System.Linq;
11 using System.Text;
12 using System.Threading;
13 using System.Threading.Tasks;
20 
22 {
24  #pragma warning disable CA1506 // TODO: Decomplexify
26  {
31 
33  public bool Running { get; private set; }
34 
36  public bool AlphaIsActive { get; private set; }
37 
39  public Models.CompileJob ActiveCompileJob => (AlphaIsActive ? alphaServer : bravoServer)?.Dmb.CompileJob;
40 
43 
45  public DreamDaemonLaunchParameters LastLaunchParameters { get; private set; }
46 
48  public RebootState? RebootState => Running ? (AlphaIsActive ? alphaServer?.RebootState : bravoServer?.RebootState) : null;
49 
53  readonly IChat chat;
54 
59 
64 
69 
74 
78  readonly IByondTopicSender byondTopicSender;
79 
84 
89 
94 
99 
103  readonly ILogger<Watchdog> logger;
104 
108  readonly SemaphoreSlim semaphore;
109 
113  readonly Api.Models.Instance instance;
114 
118  readonly bool autoStart;
119 
123  CancellationTokenSource monitorCts;
124 
129 
133  TaskCompletionSource<object> activeParametersUpdated;
134 
139 
144 
149 
167  public Watchdog(IChat chat, ISessionControllerFactory sessionControllerFactory, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IDatabaseContextFactory databaseContextFactory, IByondTopicSender byondTopicSender, IEventConsumer eventConsumer, IJobManager jobManager, IServerControl serverControl, IAsyncDelayer asyncDelayer, ILogger<Watchdog> logger, DreamDaemonLaunchParameters initialLaunchParameters, Api.Models.Instance instance, bool autoStart)
168  {
169  this.chat = chat ?? throw new ArgumentNullException(nameof(chat));
170  this.sessionControllerFactory = sessionControllerFactory ?? throw new ArgumentNullException(nameof(sessionControllerFactory));
171  this.dmbFactory = dmbFactory ?? throw new ArgumentNullException(nameof(dmbFactory));
172  this.reattachInfoHandler = reattachInfoHandler ?? throw new ArgumentNullException(nameof(reattachInfoHandler));
173  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
174  this.byondTopicSender = byondTopicSender ?? throw new ArgumentNullException(nameof(byondTopicSender));
175  this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
176  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
177  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
178  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
179  ActiveLaunchParameters = initialLaunchParameters ?? throw new ArgumentNullException(nameof(initialLaunchParameters));
180  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
181  this.autoStart = autoStart;
182 
183  if (serverControl == null)
184  throw new ArgumentNullException(nameof(serverControl));
185 
186  chat.RegisterCommandHandler(this);
187 
188  AlphaIsActive = true;
189  ActiveLaunchParameters = initialLaunchParameters;
190  releaseServers = false;
191  activeParametersUpdated = new TaskCompletionSource<object>();
192 
193  restartRegistration = serverControl.RegisterForRestart(this);
194  try
195  {
196  semaphore = new SemaphoreSlim(1);
197  }
198  catch
199  {
200  restartRegistration.Dispose();
201  throw;
202  }
203  }
204 
206  public void Dispose()
207  {
208  DisposeAndNullControllers();
209  semaphore.Dispose();
210  restartRegistration.Dispose();
211 
212  // mostly here to please fxcop, but it definitely should be disposed already
213  Debug.Assert(monitorCts == null, "We reached Disposes() an monitorCts is not null!");
214  monitorCts?.Dispose();
215  }
216 
221  {
222  alphaServer?.Dispose();
223  alphaServer = null;
224  bravoServer?.Dispose();
225  bravoServer = null;
226  Running = false;
227  }
228 
235  async Task TerminateNoLock(bool graceful, bool announce, CancellationToken cancellationToken)
236  {
237  if (!Running)
238  return;
239  if (!graceful)
240  {
241  var chatTask = announce ? chat.SendWatchdogMessage("Terminating...", cancellationToken) : Task.CompletedTask;
242  await StopMonitor().ConfigureAwait(false);
243  DisposeAndNullControllers();
244  LastLaunchParameters = null;
245  await chatTask.ConfigureAwait(false);
246  return;
247  }
248 
249  // merely set the reboot state
250  var toKill = AlphaIsActive ? alphaServer : bravoServer;
251  var other = AlphaIsActive ? bravoServer : alphaServer;
252  if (toKill != null)
253  await toKill.SetRebootState(Components.Watchdog.RebootState.Shutdown, cancellationToken).ConfigureAwait(false);
254  }
255 
263  #pragma warning disable CA1502 // TODO: Decomplexify
264  async Task HandlerMonitorWakeup(MonitorActivationReason activationReason, MonitorState monitorState, CancellationToken cancellationToken)
265  {
266  logger.LogDebug("Monitor activation. Reason: {0}", activationReason);
267 
268  // this is where the bulk of the watchdog handling code lives and is fraught with lambdas, sorry not sorry
269  // I'll do my best to walk you through it
270 
271  // returns true if the inactive server can't be used immediately
272  // also sets monitor to restart if the above holds
273  bool FullRestartDeadInactive()
274  {
275  if (monitorState.RebootingInactiveServer || monitorState.InactiveServerCritFail)
276  {
277  logger.LogInformation("Inactive server is {0}! Restarting monitor...", monitorState.InactiveServerCritFail ? "critically failed" : "still rebooting");
278  monitorState.NextAction = MonitorAction.Restart; // will dispose server
279  return true;
280  }
281 
282  return false;
283  }
284 
285  // trys to set inactive server's port to the public game port
286  // doesn't handle closing active server's port
287  // returns true on success and swaps inactiveserver and activeserver also sets LastLaunchParameters to ActiveLaunchParameters
288  // on failure, sets monitor to restart
289  async Task<bool> MakeInactiveActive()
290  {
291  logger.LogDebug("Setting inactive server to port {0}...", ActiveLaunchParameters.PrimaryPort.Value);
292  var result = await monitorState.InactiveServer.SetPort(ActiveLaunchParameters.PrimaryPort.Value, cancellationToken).ConfigureAwait(false);
293 
294  if (!result)
295  {
296  logger.LogWarning("Failed to activate inactive server! Restarting monitor...");
297  monitorState.NextAction = MonitorAction.Restart; // will dispose server
298  return false;
299  }
300 
301  // inactive server should always be using active launch parameters
302  LastLaunchParameters = ActiveLaunchParameters;
303 
304  var tmp = monitorState.ActiveServer;
305  monitorState.ActiveServer = monitorState.InactiveServer;
306  monitorState.InactiveServer = tmp;
307  AlphaIsActive = !AlphaIsActive;
308  monitorState.ActiveServer.EnableCustomChatCommands();
309  return true;
310  }
311 
312  // Kills and tries to launch inactive server with the latest dmb
313  // falls back to current dmb on failure
314  // Sets critfail on inactive server failing that
315  // returns false if the backup dmb was used successfully, true otherwise
316  async Task UpdateAndRestartInactiveServer(bool breakAfter)
317  {
318  activeParametersUpdated = new TaskCompletionSource<object>();
319  monitorState.InactiveServer.Dispose(); // kill or recycle it
320  var desiredNextAction = breakAfter ? MonitorAction.Break : MonitorAction.Continue;
321  monitorState.NextAction = desiredNextAction;
322 
323  logger.LogInformation("Rebooting inactive server...");
324  var newDmb = dmbFactory.LockNextDmb(1);
325  try
326  {
327  monitorState.InactiveServer = await sessionControllerFactory.LaunchNew(ActiveLaunchParameters, newDmb, null, false, !monitorState.ActiveServer.IsPrimary, false, cancellationToken).ConfigureAwait(false);
328  monitorState.InactiveServer.SetHighPriority();
329  }
330  catch (OperationCanceledException)
331  {
332  throw;
333  }
334  catch (Exception e)
335  {
336  logger.LogError("Error occurred while recreating server! Attempting backup strategy of running DMB of running server! Exception: {0}", e.ToString());
337 
338  // ahh jeez, what do we do here?
339  // this is our fault, so it should never happen but
340  // idk maybe a database error while handling the newest dmb?
341  // either way try to start it using the active server's dmb as a backup
342  try
343  {
344  var dmbBackup = await dmbFactory.FromCompileJob(monitorState.ActiveServer.Dmb.CompileJob, cancellationToken).ConfigureAwait(false);
345 
346  if (dmbBackup == null) // NANI!?
347  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
348 
349  monitorState.InactiveServer = await sessionControllerFactory.LaunchNew(ActiveLaunchParameters, dmbBackup, null, false, !monitorState.ActiveServer.IsPrimary, false, cancellationToken).ConfigureAwait(false);
350  monitorState.InactiveServer.SetHighPriority();
351  await chat.SendWatchdogMessage("Staging newest DMB on inactive server failed: {0} Falling back to previous dmb...", cancellationToken).ConfigureAwait(false);
352  }
353  catch (OperationCanceledException)
354  {
355  throw;
356  }
357  catch (Exception e2)
358  {
359  // fuuuuucckkk
360  logger.LogError("Backup strategy failed! Monitor will restart when active server reboots! Exception: {0}", e2.ToString());
361  monitorState.InactiveServerCritFail = true;
362  await chat.SendWatchdogMessage("Attempted reboot of inactive server failed. Watchdog will reset when active server fails or exits", cancellationToken).ConfigureAwait(false);
363  return;
364  }
365  }
366 
367  logger.LogInformation("Successfully relaunched inactive server!");
368  monitorState.RebootingInactiveServer = true;
369  }
370 
371  string ExitWord(ISessionController controller) => controller.TerminationWasRequested ? "exited" : "crashed";
372 
373  // reason handling
374  switch (activationReason)
375  {
376  case MonitorActivationReason.ActiveServerCrashed:
377  if (monitorState.ActiveServer.RebootState == Components.Watchdog.RebootState.Shutdown)
378  {
379  // the time for graceful shutdown is now
380  await chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Active server {0}! Exiting due to graceful termination request...", ExitWord(monitorState.ActiveServer)), cancellationToken).ConfigureAwait(false);
381  DisposeAndNullControllers();
382  monitorState.NextAction = MonitorAction.Exit;
383  break;
384  }
385 
386  if (FullRestartDeadInactive())
387  {
388  // tell chat about it and go ahead
389  await chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Active server {0}! Inactive server unable to online!", ExitWord(monitorState.ActiveServer)), cancellationToken).ConfigureAwait(false);
390 
391  // we've already been set to restart
392  break;
393  }
394 
395  // tell chat about it
396  await chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Active server {0}! Onlining inactive server...", ExitWord(monitorState.ActiveServer)), cancellationToken).ConfigureAwait(false);
397 
398  // try to activate the inactive server
399  if (!await MakeInactiveActive().ConfigureAwait(false))
400  break; // failing that, we've already been set to restart
401 
402  // bring up another inactive server
403  await UpdateAndRestartInactiveServer(true).ConfigureAwait(false);
404  break;
405  case MonitorActivationReason.InactiveServerCrashed:
406  // just announce and try to bring it back
407  await chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Inactive server {0}! Rebooting...", ExitWord(monitorState.InactiveServer)), cancellationToken).ConfigureAwait(false);
408  await UpdateAndRestartInactiveServer(false).ConfigureAwait(false);
409  break;
410  case MonitorActivationReason.ActiveServerRebooted:
411  // ideal goal: active server just closed its port
412  // tell inactive server to open it's port and that's now the active server
413  var rebootState = monitorState.ActiveServer.RebootState;
414  monitorState.ActiveServer.ResetRebootState(); // the DMAPI has already done this internally
415 
416  if (FullRestartDeadInactive() && rebootState != Components.Watchdog.RebootState.Shutdown)
417  break; // full restart if the inactive server is being fucky
418 
419  // what matters here is the RebootState
420  var restartOnceSwapped = false;
421 
422  switch (rebootState)
423  {
424  case Components.Watchdog.RebootState.Normal:
425  // life as normal
426  break;
427  case Components.Watchdog.RebootState.Restart:
428  // reboot the current active server once the inactive one activates
429  restartOnceSwapped = true;
430  break;
431  case Components.Watchdog.RebootState.Shutdown:
432  // graceful shutdown time
433  await chat.SendWatchdogMessage("Active server rebooted! Exiting due to graceful termination request...", cancellationToken).ConfigureAwait(false);
434  DisposeAndNullControllers();
435  monitorState.NextAction = MonitorAction.Exit;
436  return;
437  default:
438  Trace.Assert(false, String.Format(CultureInfo.InvariantCulture, "Invalid RebootState: {0}!", rebootState));
439  break;
440  }
441 
442  // are both servers now running the same CompileJob?
443  var sameCompileJob = monitorState.InactiveServer.Dmb.CompileJob.Id == monitorState.ActiveServer.Dmb.CompileJob.Id;
444 
445  if (!sameCompileJob || ActiveLaunchParameters != LastLaunchParameters)
446  restartOnceSwapped = true; // need a new launch to update either settings or compile job
447 
448  if (restartOnceSwapped)
449  /*
450  * we need to manually restart active server
451  * just kill it here, easier that way
452  */
453  monitorState.ActiveServer.Dispose();
454 
455  var activeServerStillHasPortOpen = !restartOnceSwapped && !monitorState.ActiveServer.ClosePortOnReboot;
456 
457  if (activeServerStillHasPortOpen)
458  /* we didn't want active server to swap for some reason and it still has it's port open
459  * just continue as normal
460  */
461  break;
462 
463  if (!await MakeInactiveActive().ConfigureAwait(false))
464  break; // monitor will restart
465 
466  // servers now swapped
467  // enable this now if inactive server is not still valid
468  monitorState.ActiveServer.ClosePortOnReboot = restartOnceSwapped;
469 
470  if (!restartOnceSwapped)
471  /*
472  * now try to reopen it on the private port
473  * failing that, just reboot it
474  */
475  restartOnceSwapped = !await monitorState.InactiveServer.SetPort(ActiveLaunchParameters.SecondaryPort.Value, cancellationToken).ConfigureAwait(false);
476 
477  // break either way because any issues past this point would be solved by the reboot
478  if (restartOnceSwapped) // for one reason or another
479  await UpdateAndRestartInactiveServer(true).ConfigureAwait(false); // update and reboot
480  else
481  monitorState.NextAction = MonitorAction.Skip; // only skip checking inactive server rebooted, it's guaranteed InactiveServerStartup complete wouldn't fire this iteration
482  break;
483  case MonitorActivationReason.InactiveServerRebooted:
484  // just don't let the active server close it's port if the inactive server isn't ready
485  monitorState.RebootingInactiveServer = true;
486  monitorState.InactiveServer.ResetRebootState();
487  monitorState.ActiveServer.ClosePortOnReboot = false;
488  monitorState.NextAction = MonitorAction.Continue;
489  break;
490  case MonitorActivationReason.InactiveServerStartupComplete:
491  // opposite of above case
492  monitorState.RebootingInactiveServer = false;
493  monitorState.ActiveServer.ClosePortOnReboot = true;
494  monitorState.NextAction = MonitorAction.Continue;
495  break;
496  case MonitorActivationReason.NewDmbAvailable:
497  case MonitorActivationReason.ActiveLaunchParametersUpdated:
498  // just reload the inactive server and wait for a swap to apply the changes
499  await UpdateAndRestartInactiveServer(true).ConfigureAwait(false);
500  break;
501  default:
502  Trace.Assert(false, String.Format(CultureInfo.InvariantCulture, "Invalid monitor activation reason: {0}!", activationReason));
503  break;
504  }
505  }
506  #pragma warning restore CA1502
507 
513 #pragma warning disable CA1502 // TODO: Decomplexify
514  async Task MonitorLifetimes(CancellationToken cancellationToken)
515  {
516  logger.LogTrace("Entered MonitorLifetimes");
517 
518  // this function is responsible for calling HandlerMonitorWakeup when necessary and manitaining the MonitorState
519  var iteration = 1;
520  for (var monitorState = new MonitorState(); monitorState.NextAction != MonitorAction.Exit; ++iteration)
521  {
522  // always start out with continue
523  monitorState.NextAction = MonitorAction.Continue;
524 
525  // dump some info to the logs
526  logger.LogDebug("Iteration {0} of monitor loop", iteration);
527  try
528  {
529  if (AlphaIsActive)
530  logger.LogDebug("Alpha is the active server");
531  else
532  logger.LogDebug("Bravo is the active server");
533 
534  if (monitorState.RebootingInactiveServer)
535  logger.LogDebug("Inactive server is rebooting");
536 
537  // update the monitor state with the inactive/active servers
538  monitorState.ActiveServer = AlphaIsActive ? alphaServer : bravoServer;
539  monitorState.InactiveServer = AlphaIsActive ? bravoServer : alphaServer;
540 
541  if (monitorState.ActiveServer.ClosePortOnReboot)
542  logger.LogDebug("Active server will close port on reboot");
543  if (monitorState.InactiveServer.ClosePortOnReboot)
544  logger.LogDebug("Inactive server will close port on reboot");
545 
546  logger.LogDebug("Active server Compile Job ID: {0}", monitorState.ActiveServer.Dmb.CompileJob.Id);
547  logger.LogDebug("Inactive server Compile Job ID: {0}", monitorState.InactiveServer.Dmb.CompileJob.Id);
548 
549  // load the activation tasks into local variables
550  Task activeServerLifetime = monitorState.ActiveServer.Lifetime;
551  Task inactiveServerLifetime = monitorState.InactiveServer.Lifetime;
552  var activeServerReboot = monitorState.ActiveServer.OnReboot;
553  var inactiveServerReboot = monitorState.InactiveServer.OnReboot;
554  Task inactiveServerStartup = monitorState.RebootingInactiveServer ? monitorState.InactiveServer.LaunchResult : null;
555  Task activeLaunchParametersChanged = activeParametersUpdated.Task;
556  var newDmbAvailable = dmbFactory.OnNewerDmb;
557 
558  // cancel waiting if requested
559  var cancelTcs = new TaskCompletionSource<object>();
560  using (cancellationToken.Register(() => cancelTcs.SetCanceled()))
561  {
562  var toWaitOn = Task.WhenAny(activeServerLifetime, inactiveServerLifetime, activeServerReboot, inactiveServerReboot, newDmbAvailable, cancelTcs.Task, activeLaunchParametersChanged);
563  if (monitorState.RebootingInactiveServer)
564  toWaitOn = Task.WhenAny(toWaitOn, inactiveServerStartup);
565 
566  // wait for something to happen
567  await toWaitOn.ConfigureAwait(false);
568  cancellationToken.ThrowIfCancellationRequested();
569  }
570 
571  var chatTask = Task.CompletedTask;
572  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
573  {
574  // always run HandleMonitorWakeup from the context of the semaphore lock
575  // multiple things may have happened, handle them one at a time
576  for (var moreActivationsToProcess = true; moreActivationsToProcess && (monitorState.NextAction == MonitorAction.Continue || monitorState.NextAction == MonitorAction.Skip);)
577  {
578  MonitorActivationReason activationReason = default; // this will always be assigned before being used
579 
580  // process the tasks in this order and call HandlerMonitorWakup for each
581  bool CheckActivationReason(ref Task task, MonitorActivationReason testActivationReason)
582  {
583  var taskCompleted = task?.IsCompleted == true;
584  task = null;
585  if (monitorState.NextAction == MonitorAction.Skip)
586  monitorState.NextAction = MonitorAction.Continue;
587  else if (taskCompleted)
588  {
589  activationReason = testActivationReason;
590  return true;
591  }
592 
593  return false;
594  }
595 
596  if (CheckActivationReason(ref activeServerLifetime, MonitorActivationReason.ActiveServerCrashed)
597  || CheckActivationReason(ref inactiveServerLifetime, MonitorActivationReason.InactiveServerCrashed)
598  || CheckActivationReason(ref activeServerReboot, MonitorActivationReason.ActiveServerRebooted)
599  || CheckActivationReason(ref inactiveServerReboot, MonitorActivationReason.InactiveServerRebooted)
600  || CheckActivationReason(ref inactiveServerStartup, MonitorActivationReason.InactiveServerStartupComplete)
601  || CheckActivationReason(ref newDmbAvailable, MonitorActivationReason.NewDmbAvailable)
602  || CheckActivationReason(ref activeLaunchParametersChanged, MonitorActivationReason.ActiveLaunchParametersUpdated))
603  await HandlerMonitorWakeup(activationReason, monitorState, cancellationToken).ConfigureAwait(false);
604  else
605  moreActivationsToProcess = false;
606  }
607 
608  // writeback alphaServer and bravoServer from monitor state in case they changesd
609  alphaServer = AlphaIsActive ? monitorState.ActiveServer : monitorState.InactiveServer;
610  bravoServer = !AlphaIsActive ? monitorState.ActiveServer : monitorState.InactiveServer;
611  }
612 
613  // full reboot required
614  if (monitorState.NextAction == MonitorAction.Restart)
615  {
616  logger.LogDebug("Next state action is to restart");
617  DisposeAndNullControllers();
618  chatTask = chat.SendWatchdogMessage("Restarting entirely due to complications...", cancellationToken);
619 
620  for (var retryAttempts = 1; monitorState.NextAction == MonitorAction.Restart; ++retryAttempts)
621  {
622  Exception launchException = null;
623  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
624  try
625  {
626  // use LaunchImplNoLock without announcements or restarting the monitor
627  await LaunchImplNoLock(false, false, null, cancellationToken).ConfigureAwait(false);
628  if (Running)
629  {
630  logger.LogDebug("Relaunch successful, resetting monitor state...");
631  monitorState = new MonitorState(); // clean the slate and continue
632  }
633  }
634  catch (OperationCanceledException)
635  {
636  throw;
637  }
638  catch (Exception e)
639  {
640  launchException = e;
641  }
642 
643  await chatTask.ConfigureAwait(false);
644  if (!Running)
645  {
646  if (launchException == null)
647  logger.LogWarning("Failed to automatically restart the watchdog! Attempt: {0}", retryAttempts);
648  else
649  logger.LogWarning("Failed to automatically restart the watchdog! Attempt: {0}, Exception: {1}", retryAttempts, launchException);
650  var retryDelay = Math.Min(Math.Pow(2, retryAttempts), 3600); // max of one hour, increasing by a power of 2 each time
651  chatTask = chat.SendWatchdogMessage(String.Format(CultureInfo.InvariantCulture, "Failed to restart watchdog (Attempt: {0}), retrying in {1} seconds...", retryAttempts, retryDelay), cancellationToken);
652  await Task.WhenAll(asyncDelayer.Delay(TimeSpan.FromSeconds(retryDelay), cancellationToken), chatTask).ConfigureAwait(false);
653  }
654  }
655  }
656  }
657  catch (OperationCanceledException)
658  {
659  logger.LogDebug("Monitor cancelled");
660  break;
661  }
662  catch (Exception e)
663  {
664  // really, this should NEVER happen
665  logger.LogError("Monitor crashed! Iteration: {0}, State: {1}, Exception: {2}", iteration, JsonConvert.SerializeObject(monitorState), e);
666  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);
667  }
668  }
669 
670  logger.LogTrace("Monitor exiting...");
671  }
672  #pragma warning restore CA1502
673 
678  async Task<bool> StopMonitor()
679  {
680  logger.LogTrace("StopMonitor");
681  if (monitorTask == null)
682  return false;
683  monitorCts.Cancel();
684  await monitorTask.ConfigureAwait(false);
685  monitorCts.Dispose();
686  monitorCts = null;
687  monitorTask = null;
688  return true;
689  }
690 
692  public async Task ChangeSettings(DreamDaemonLaunchParameters launchParameters, CancellationToken cancellationToken)
693  {
694  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
695  {
696  if (launchParameters.Match(ActiveLaunchParameters))
697  return;
698  ActiveLaunchParameters = launchParameters;
699  if (Running)
700  activeParametersUpdated.TrySetResult(null); // queue an update
701  }
702  }
703 
712  #pragma warning disable CA1502 // TODO: Decomplexify
713  async Task LaunchImplNoLock(bool startMonitor, bool announce, WatchdogReattachInformation reattachInfo, CancellationToken cancellationToken)
714  {
715  logger.LogTrace("Begin LaunchNoLock");
716 
717  if (Running)
718  throw new JobException("Watchdog already running!");
719 
720  // this is necessary, the monitor could be in it's sleep loop trying to restart, if so cancel THAT monitor and start our own with blackjack and hookers
721  Task chatTask;
722  if (startMonitor && await StopMonitor().ConfigureAwait(false))
723  chatTask = chat.SendWatchdogMessage("Automatic retry sequence cancelled by manual launch. Restarting...", cancellationToken);
724  else if (announce)
725  chatTask = chat.SendWatchdogMessage(reattachInfo == null ? "Starting..." : "Reattaching...", cancellationToken); // simple announce
726  else
727  chatTask = Task.CompletedTask; // no announce
728 
729  // since neither server is running, this is safe to do
730  LastLaunchParameters = ActiveLaunchParameters;
731 
732  // for when we call ourself and want to not catch thrown exceptions
733  var ignoreNestedException = false;
734  try
735  {
736  // good ole sanity, should never fucking trigger but i don't trust myself even though I should
737  // TODO: Unit test this instead?
738  if (alphaServer != null || bravoServer != null)
739  throw new InvalidOperationException("Entered LaunchNoLock with one or more of the servers not being null!");
740 
741  // don't need a new dmb if reattaching
742  var doesntNeedNewDmb = reattachInfo?.Alpha != null && reattachInfo?.Bravo != null;
743  var dmbToUse = doesntNeedNewDmb ? null : dmbFactory.LockNextDmb(2);
744 
745  // if this try catches something, both servers are killed
746  try
747  {
748  // start the alpha server task, either by launch a new process or attaching to an existing one
749  // The tasks returned are mainly for writing interop files to the directories among other things and should generally never fail
750  // The tasks pertaining to server startup times are in the ISessionControllers
751  Task<ISessionController> alphaServerTask;
752  if (!doesntNeedNewDmb)
753  alphaServerTask = sessionControllerFactory.LaunchNew(ActiveLaunchParameters, dmbToUse, null, true, true, false, cancellationToken);
754  else
755  alphaServerTask = sessionControllerFactory.Reattach(reattachInfo.Alpha, cancellationToken);
756 
757  // retrieve the session controller
758  var startTime = DateTimeOffset.Now;
759  alphaServer = await alphaServerTask.ConfigureAwait(false);
760 
761  // failed reattaches will return null
762  alphaServer?.SetHighPriority();
763 
764  // extra delay for total ordering
765  var now = DateTimeOffset.Now;
766  var delay = now - startTime;
767 
768  // definitely not if reattaching though
769  if (reattachInfo == null && delay.TotalSeconds < AlphaBravoStartupSeperationInterval)
770  await asyncDelayer.Delay(startTime.AddSeconds(AlphaBravoStartupSeperationInterval) - now, cancellationToken).ConfigureAwait(false);
771 
772  // now bring bravo up
773  if (!doesntNeedNewDmb)
774  bravoServer = await sessionControllerFactory.LaunchNew(ActiveLaunchParameters, dmbToUse, null, false, false, false, cancellationToken).ConfigureAwait(false);
775  else
776  bravoServer = await sessionControllerFactory.Reattach(reattachInfo.Bravo, cancellationToken).ConfigureAwait(false);
777 
778  // failed reattaches will return null
779  bravoServer?.SetHighPriority();
780 
781  // possiblity of null servers due to failed reattaches
782  if (alphaServer == null || bravoServer == null)
783  {
784  await chatTask.ConfigureAwait(false);
785  var bothServersDead = alphaServer == null && bravoServer == null;
786  if (bothServersDead
787  || (alphaServer == null && reattachInfo.AlphaIsActive)
788  || (bravoServer == null && !reattachInfo.AlphaIsActive))
789  {
790  // we lost the active server, just restart entirely
791  DisposeAndNullControllers();
792  const string FailReattachMessage = "Unable to properly reattach to active server! Restarting...";
793  logger.LogWarning(FailReattachMessage);
794  logger.LogDebug(bothServersDead ? "Also could not reattach to inactive server!" : "Inactive server was reattached successfully!");
795  chatTask = chat.SendWatchdogMessage(FailReattachMessage, cancellationToken);
796  ignoreNestedException = true;
797  await LaunchImplNoLock(true, false, null, cancellationToken).ConfigureAwait(false);
798  return;
799  }
800 
801  // we still have the active server but the other one is dead to us, hand it off to the monitor to restart
802  const string InactiveReattachFailureMessage = "Unable to reattach to inactive server. Leaving for monitor to reboot...";
803  chatTask = chat.SendWatchdogMessage(InactiveReattachFailureMessage, cancellationToken);
804  logger.LogWarning(InactiveReattachFailureMessage);
805 
806  if (reattachInfo.AlphaIsActive)
807  bravoServer = sessionControllerFactory.CreateDeadSession(reattachInfo.Bravo.Dmb);
808  else
809  alphaServer = sessionControllerFactory.CreateDeadSession(reattachInfo.Alpha.Dmb);
810  }
811 
812  // throws a JobException if something went wrong with a launch
813  // Dead sessions won't trigger this
814  async Task<LaunchResult> CheckLaunch(ISessionController controller, string serverName)
815  {
816  var launch = await controller.LaunchResult.ConfigureAwait(false);
817  if (launch.ExitCode.HasValue) // you killed us ray...
818  throw new JobException(String.Format(CultureInfo.InvariantCulture, "{1} server failed to start: {0}", launch.ToString(), serverName));
819  if (!launch.StartupTime.HasValue)
820  throw new JobException(String.Format(CultureInfo.InvariantCulture, "{1} server timed out on startup: {0}s", launch.ToString(), ActiveLaunchParameters.StartupTimeout.Value));
821  return launch;
822  }
823 
824  var alphaLrt = CheckLaunch(alphaServer, "Alpha");
825  var bravoLrt = CheckLaunch(bravoServer, "Bravo");
826 
827  // this task completes when both serers have finished booting
828  var allTask = Task.WhenAll(alphaLrt, bravoLrt);
829 
830  // don't forget about the cancellationToken
831  var cancelTcs = new TaskCompletionSource<object>();
832  using (cancellationToken.Register(() => cancelTcs.SetCanceled()))
833  await Task.WhenAny(allTask, cancelTcs.Task).ConfigureAwait(false);
834  cancellationToken.ThrowIfCancellationRequested();
835 
836  await allTask.ConfigureAwait(false);
837 
838  // both servers are now running, alpha is the active server(unless reattach), huzzah
839  AlphaIsActive = reattachInfo?.AlphaIsActive ?? true;
840 
841  var activeServer = AlphaIsActive ? alphaServer : bravoServer;
842  activeServer.EnableCustomChatCommands();
843  activeServer.ClosePortOnReboot = true;
844 
845  logger.LogInformation("Launched servers successfully");
846  Running = true;
847 
848  if (startMonitor)
849  {
850  monitorCts = new CancellationTokenSource();
851  monitorTask = MonitorLifetimes(monitorCts.Token);
852  }
853  }
854  catch
855  {
856  if (dmbToUse != null)
857  {
858  // we locked 2 dmbs
859  if (bravoServer == null)
860  {
861  // bravo didn't get control of his
862  dmbToUse.Dispose();
863  if (alphaServer == null)
864  dmbToUse.Dispose(); // alpha didn't get control of his
865  }
866  }
867  else if (doesntNeedNewDmb) // we have reattachInfo
868  if (bravoServer == null)
869  {
870  // bravo didn't get control of his
871  reattachInfo.Bravo?.Dmb.Dispose();
872  if (alphaServer == null)
873  reattachInfo.Alpha?.Dmb.Dispose(); // alpha didn't get control of his
874  }
875 
876  // kill the controllers
877  DisposeAndNullControllers();
878  throw;
879  }
880  }
881  catch (Exception e)
882  {
883  // don't try to send chat tasks or warning logs if were suppressing exceptions or cancelled
884  if (!ignoreNestedException && !cancellationToken.IsCancellationRequested)
885  {
886  var originalChatTask = chatTask;
887  async Task ChainChatTaskWithErrorMessage()
888  {
889  await originalChatTask.ConfigureAwait(false);
890  await chat.SendWatchdogMessage("Startup failed!", cancellationToken).ConfigureAwait(false);
891  }
892 
893  chatTask = ChainChatTaskWithErrorMessage();
894  logger.LogWarning("Failed to start watchdog: {0}", e.ToString());
895  }
896 
897  throw;
898  }
899  finally
900  {
901  // finish the chat task that's in flight
902  try
903  {
904  await chatTask.ConfigureAwait(false);
905  }
906  catch (OperationCanceledException) { }
907  }
908  }
909  #pragma warning restore CA1502
910 
912  public async Task Launch(CancellationToken cancellationToken)
913  {
914  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
915  await LaunchImplNoLock(true, true, null, cancellationToken).ConfigureAwait(false);
916  }
917 
919  public async Task ResetRebootState(CancellationToken cancellationToken)
920  {
921  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
922  {
923  if (!Running)
924  return;
925  var toClear = AlphaIsActive ? alphaServer : bravoServer;
926  if (toClear != null)
927  toClear.ResetRebootState();
928  }
929  }
930 
932  public async Task Restart(bool graceful, CancellationToken cancellationToken)
933  {
934  logger.LogTrace("Begin Restart. Graceful: {0}", graceful);
935  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
936  {
937  if (!graceful || !Running)
938  {
939  Task chatTask;
940  if (Running)
941  {
942  chatTask = chat.SendWatchdogMessage("Manual restart triggered...", cancellationToken);
943  await TerminateNoLock(false, false, cancellationToken).ConfigureAwait(false);
944  }
945  else
946  chatTask = Task.CompletedTask;
947  await LaunchImplNoLock(true, !Running, null, cancellationToken).ConfigureAwait(false);
948  await chatTask.ConfigureAwait(false);
949  }
950 
951  var toReboot = AlphaIsActive ? alphaServer : bravoServer;
952  if (toReboot != null)
953  {
954  if (!await toReboot.SetRebootState(Components.Watchdog.RebootState.Restart, cancellationToken).ConfigureAwait(false))
955  logger.LogWarning("Unable to send reboot state change event!");
956  }
957  }
958  }
959 
961  public async Task Terminate(bool graceful, CancellationToken cancellationToken)
962  {
963  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
964  await TerminateNoLock(graceful, !releaseServers, cancellationToken).ConfigureAwait(false);
965  }
966 
968  public async Task StartAsync(CancellationToken cancellationToken)
969  {
970  var reattachInfo = await reattachInfoHandler.Load(cancellationToken).ConfigureAwait(false);
971  if (!autoStart && reattachInfo == null)
972  return;
973 
974  long? adminUserId = null;
975 
976  await databaseContextFactory.UseContext(async db => adminUserId = await db.Users
977  .Where(x => x.CanonicalName == Api.Models.User.AdminName.ToUpperInvariant())
978  .Select(x => x.Id)
979  .FirstAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false);
980  var job = new Models.Job
981  {
982  StartedBy = new Models.User
983  {
984  Id = adminUserId.Value
985  },
986  Instance = new Models.Instance
987  {
988  Id = instance.Id
989  },
990  Description = "Instance startup watchdog launch",
991  CancelRight = (ulong)DreamDaemonRights.Shutdown,
992  CancelRightsType = RightsType.DreamDaemon
993  };
994  await jobManager.RegisterOperation(job, async (j, databaseContext, progressFunction, ct) =>
995  {
996  using (await SemaphoreSlimContext.Lock(semaphore, ct).ConfigureAwait(false))
997  await LaunchImplNoLock(true, true, reattachInfo, ct).ConfigureAwait(false);
998  }, cancellationToken).ConfigureAwait(false);
999  }
1000 
1002  public async Task StopAsync(CancellationToken cancellationToken)
1003  {
1004  try
1005  {
1006  if (releaseServers && Running)
1007  {
1008  await StopMonitor().ConfigureAwait(false);
1009 
1010  var reattachInformation = new WatchdogReattachInformation
1011  {
1012  AlphaIsActive = AlphaIsActive
1013  };
1014  reattachInformation.Alpha = alphaServer?.Release();
1015  reattachInformation.Bravo = bravoServer?.Release();
1016  await reattachInfoHandler.Save(reattachInformation, cancellationToken).ConfigureAwait(false);
1017  }
1018 
1019  await Terminate(false, cancellationToken).ConfigureAwait(false);
1020  }
1021  catch
1022  {
1023  releaseServers = false;
1024  throw;
1025  }
1026  }
1027 
1029  public async Task<bool> HandleEvent(EventType eventType, IEnumerable<string> parameters, CancellationToken cancellationToken)
1030  {
1031  string results;
1032  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
1033  {
1034  if (!Running)
1035  return true;
1036 
1037  var builder = new StringBuilder(Constants.DMTopicEvent);
1038  builder.Append('&');
1039  var notification = new EventNotification
1040  {
1041  Type = eventType,
1042  Parameters = parameters
1043  };
1044  var json = JsonConvert.SerializeObject(notification);
1045  builder.Append(byondTopicSender.SanitizeString(Constants.DMParameterData));
1046  builder.Append('=');
1047  builder.Append(byondTopicSender.SanitizeString(json));
1048 
1049  var activeServer = AlphaIsActive ? alphaServer : bravoServer;
1050  results = await activeServer.SendCommand(builder.ToString(), cancellationToken).ConfigureAwait(false);
1051  }
1052 
1053  if (results == Constants.DMResponseSuccess)
1054  return true;
1055 
1056  List<Response> responses;
1057  try
1058  {
1059  responses = JsonConvert.DeserializeObject<List<Response>>(results);
1060  }
1061  catch
1062  {
1063  logger.LogInformation("Recieved invalid response from DD when parsing event {0}:{1}{2}", eventType, Environment.NewLine, results);
1064  return true;
1065  }
1066 
1067  await Task.WhenAll(responses.Select(x => chat.SendMessage(x.Message, x.ChannelIds, cancellationToken))).ConfigureAwait(false);
1068 
1069  return true;
1070  }
1071 
1073  public async Task<string> HandleChatCommand(string commandName, string arguments, Chat.User sender, CancellationToken cancellationToken)
1074  {
1075  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
1076  {
1077  if (!Running)
1078  return "ERROR: Server offline!";
1079 
1080  var commandObject = new ChatCommand
1081  {
1082  Command = commandName,
1083  Params = arguments,
1084  User = sender
1085  };
1086 
1087  var json = JsonConvert.SerializeObject(commandObject, new JsonSerializerSettings
1088  {
1089  ContractResolver = new CamelCasePropertyNamesContractResolver()
1090  });
1091 
1092  var command = String.Format(CultureInfo.InvariantCulture, "{0}&{1}={2}", byondTopicSender.SanitizeString(Constants.DMTopicChatCommand), byondTopicSender.SanitizeString(Constants.DMParameterData), byondTopicSender.SanitizeString(json));
1093 
1094  var activeServer = AlphaIsActive ? alphaServer : bravoServer;
1095  return await activeServer.SendCommand(command, cancellationToken).ConfigureAwait(false) ?? "ERROR: Bad topic exchange!";
1096  }
1097  }
1098 
1100  public async Task HandleRestart(Version updateVersion, CancellationToken cancellationToken)
1101  {
1102  releaseServers = true;
1103  if (Running)
1104  await chat.SendWatchdogMessage("Detaching...", cancellationToken).ConfigureAwait(false);
1105  }
1106  }
1107 }
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 IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the Watchdog
Definition: Watchdog.cs:73
+ +
async Task Launch(CancellationToken cancellationToken)
Start the IWatchdog
Definition: Watchdog.cs:912
-
Represents a chat command to be handled by DD
Definition: ChatCommand.cs:8
-
readonly ILogger< Watchdog > logger
The ILogger<TCategoryName> for the Watchdog
Definition: Watchdog.cs:103
+
Represents a chat command to be handled by DD
Definition: ChatCommand.cs:8
+
readonly ILogger< Watchdog > logger
The ILogger<TCategoryName> for the Watchdog
Definition: Watchdog.cs:103
-
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
-
void RegisterCommandHandler(ICustomCommandHandler customCommandHandler)
Registers a customCommandHandler to use
+
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
+
void RegisterCommandHandler(ICustomCommandHandler customCommandHandler)
Registers a customCommandHandler to use
-
MonitorAction NextAction
The next MonitorAction to take in Watchdog.MonitorLifetimes(System.Threading.CancellationToken) ...
Definition: MonitorState.cs:23
-
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
-
async Task Terminate(bool graceful, CancellationToken cancellationToken)
Stops the watchdog
Definition: Watchdog.cs:956
- -
bool releaseServers
If the servers should be released instead of shutdown
Definition: Watchdog.cs:148
-
async Task Restart(bool graceful, CancellationToken cancellationToken)
Restarts the watchdog
Definition: Watchdog.cs:927
-
Consumes EventTypes and takes the appropriate actions
-
Task< LaunchResult > LaunchResult
A Task that completes when DreamDaemon starts pumping the windows message queue after loading a ...
+
MonitorAction NextAction
The next MonitorAction to take in Watchdog.MonitorLifetimes(System.Threading.CancellationToken)
Definition: MonitorState.cs:23
+ +
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
+
async Task Terminate(bool graceful, CancellationToken cancellationToken)
Stops the watchdog
Definition: Watchdog.cs:961
+ +
bool releaseServers
If the servers should be released instead of shutdown
Definition: Watchdog.cs:148
+
async Task Restart(bool graceful, CancellationToken cancellationToken)
Restarts the watchdog
Definition: Watchdog.cs:932
+
Consumes EventTypes and takes the appropriate actions
+
Task< LaunchResult > LaunchResult
A Task that completes when DreamDaemon starts pumping the windows message queue after loading a ....
- - -
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
-
const string DMTopicChatCommand
Chat command
Definition: Constants.cs:41
-
bool ClosePortOnReboot
If the port should be rotated off when the world reboots
-
Represents a server User
Definition: User.cs:10
- -
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
-
const string DMTopicEvent
Notify of an EventType
Definition: Constants.cs:46
- -
async Task LaunchImplNoLock(bool startMonitor, bool announce, WatchdogReattachInformation reattachInfo, CancellationToken cancellationToken)
Launches the Watchdog
Definition: Watchdog.cs:708
-
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
-
Task monitorTask
The Task running the monitor loop
Definition: Watchdog.cs:128
- - -
async Task ChangeSettings(DreamDaemonLaunchParameters launchParameters, CancellationToken cancellationToken)
Changes the ActiveLaunchParameters. If currently Running triggers a graceful restart ...
Definition: Watchdog.cs:687
-
async Task HandleRestart(Version updateVersion, CancellationToken cancellationToken)
Handle a restart of the server
Definition: Watchdog.cs:1095
-
For managing connected chat services
Definition: IChat.cs:13
-
readonly SemaphoreSlim semaphore
The SemaphoreSlim for the Watchdog
Definition: Watchdog.cs:108
+ +
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
+
Represents a server User
Definition: User.cs:10
+
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
+
const string DMTopicEvent
Notify of an EventType
Definition: Constants.cs:46
+ +
async Task LaunchImplNoLock(bool startMonitor, bool announce, WatchdogReattachInformation reattachInfo, CancellationToken cancellationToken)
Launches the Watchdog
Definition: Watchdog.cs:713
+
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
+
Task monitorTask
The Task running the monitor loop
Definition: Watchdog.cs:128
+ + +
async Task ChangeSettings(DreamDaemonLaunchParameters launchParameters, CancellationToken cancellationToken)
Changes the ActiveLaunchParameters. If currently Running triggers a graceful restart
Definition: Watchdog.cs:692
+
async Task HandleRestart(Version updateVersion, CancellationToken cancellationToken)
Handle a restart of the server
Definition: Watchdog.cs:1100
+
For managing connected chat services
Definition: IChat.cs:13
+
readonly SemaphoreSlim semaphore
The SemaphoreSlim for the Watchdog
Definition: Watchdog.cs:108
-
Handles communication with a DreamDaemon IProcess
-
bool IsPrimary
If the IDmbProvider.PrimaryDirectory of Dmb is being used
- -
readonly IEventConsumer eventConsumer
The IEventConsumer for the Watchdog
Definition: Watchdog.cs:83
-
void SetHighPriority()
Set&#39;s the owned System.Diagnostics.Process.PriorityClass to System.Diagnostics.ProcessPriorityClass.AboveNormal
-
bool TerminationWasRequested
If the DreamDaemon instance sent a
-
async Task< string > HandleChatCommand(string commandName, string arguments, Chat.User sender, CancellationToken cancellationToken)
Definition: Watchdog.cs:1068
+
Handles communication with a DreamDaemon IProcess
+
bool IsPrimary
If the IDmbProvider.PrimaryDirectory of Dmb is being used
+ +
readonly IEventConsumer eventConsumer
The IEventConsumer for the Watchdog
Definition: Watchdog.cs:83
+
void SetHighPriority()
Set's the owned System.Diagnostics.Process.PriorityClass to System.Diagnostics.ProcessPriorityClass....
+
bool TerminationWasRequested
If the DreamDaemon instance sent a
+
async Task< string > HandleChatCommand(string commandName, string arguments, Chat.User sender, CancellationToken cancellationToken)
Definition: Watchdog.cs:1073
-
void DisposeAndNullControllers()
Call IDisposable.Dispose on alphaServer and bravoServer and set them to
Definition: Watchdog.cs:216
- -
bool RebootingInactiveServer
If the inactive server is being rebooted
Definition: MonitorState.cs:13
-
readonly IJobManager jobManager
The IJobManager for the Watchdog
Definition: Watchdog.cs:88
-
DreamDaemonRights
Rights for Models.DreamDaemon
-
readonly Api.Models.Instance instance
The Api.Models.Instance for the Watchdog
Definition: Watchdog.cs:113
-
Instance(Api.Models.Instance metadata, IRepositoryManager repositoryManager, IByondManager byondManager, IDreamMaker dreamMaker, IWatchdog watchdog, IChat chat, StaticFiles.IConfiguration configuration, ICompileJobConsumer compileJobConsumer, IDatabaseContextFactory databaseContextFactory, IDmbFactory dmbFactory, IJobManager jobManager, IEventConsumer eventConsumer, IGitHubClientFactory gitHubClientFactory, ILogger< Instance > logger)
Construct an Instance
Definition: Instance.cs:112
- -
async Task< bool > StopMonitor()
Stops MonitorLifetimes(CancellationToken). Doesn&#39;t kill the servers
Definition: Watchdog.cs:674
- -
async Task ResetRebootState(CancellationToken cancellationToken)
Cancels pending graceful actions
Definition: Watchdog.cs:914
-
ReattachInformation Alpha
ReattachInformation for the Alpha session
-
async Task MonitorLifetimes(CancellationToken cancellationToken)
The loop that watches the watchdog
Definition: Watchdog.cs:510
- -
readonly ISessionControllerFactory sessionControllerFactory
The ISessionControllerFactory for the Watchdog
Definition: Watchdog.cs:58
+
void DisposeAndNullControllers()
Call IDisposable.Dispose on alphaServer and bravoServer and set them to null
Definition: Watchdog.cs:220
+ +
bool RebootingInactiveServer
If the inactive server is being rebooted
Definition: MonitorState.cs:13
+
readonly IJobManager jobManager
The IJobManager for the Watchdog
Definition: Watchdog.cs:88
+
DreamDaemonRights
Rights for Models.DreamDaemon
+
readonly Api.Models.Instance instance
The Api.Models.Instance for the Watchdog
Definition: Watchdog.cs:113
+
Instance(Api.Models.Instance metadata, IRepositoryManager repositoryManager, IByondManager byondManager, IDreamMaker dreamMaker, IWatchdog watchdog, IChat chat, StaticFiles.IConfiguration configuration, ICompileJobConsumer compileJobConsumer, IDatabaseContextFactory databaseContextFactory, IDmbFactory dmbFactory, IJobManager jobManager, IEventConsumer eventConsumer, IGitHubClientFactory gitHubClientFactory, ILogger< Instance > logger)
Construct an Instance
Definition: Instance.cs:112
+ +
async Task< bool > StopMonitor()
Stops MonitorLifetimes(CancellationToken). Doesn't kill the servers
Definition: Watchdog.cs:678
+ +
async Task ResetRebootState(CancellationToken cancellationToken)
Cancels pending graceful actions
Definition: Watchdog.cs:919
+
ReattachInformation Alpha
ReattachInformation for the Alpha session
+
async Task MonitorLifetimes(CancellationToken cancellationToken)
The loop that watches the watchdog
Definition: Watchdog.cs:514
+ +
readonly ISessionControllerFactory sessionControllerFactory
The ISessionControllerFactory for the Watchdog
Definition: Watchdog.cs:58
-
async Task StopAsync(CancellationToken cancellationToken)
Definition: Watchdog.cs:997
-
MonitorActivationReason
Reasons for the monitor to wake up
-
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 ...
- -
readonly IChat chat
The IChat for the Watchdog
Definition: Watchdog.cs:53
- - -
ISessionController ActiveServer
The active ISessionController
Definition: MonitorState.cs:29
-
Constants used for communication with the DMAPI
Definition: Constants.cs:6
- +
async Task StopAsync(CancellationToken cancellationToken)
Definition: Watchdog.cs:1002
+
MonitorActivationReason
Reasons for the monitor to wake up
+
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
+ +
readonly IChat chat
The IChat for the Watchdog
Definition: Watchdog.cs:53
+ + + +
ISessionController ActiveServer
The active ISessionController
Definition: MonitorState.cs:29
+
Constants used for communication with the DMAPI
Definition: Constants.cs:6
+
DreamDaemonLaunchParameters ActiveLaunchParameters
Definition: Watchdog.cs:42
+ -
ISessionController InactiveServer
The inactive ISessionController
Definition: MonitorState.cs:35
-
const string DMResponseSuccess
Generic OK response
Definition: Constants.cs:26
-
async Task< bool > HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
Handle a given eventType
Definition: Watchdog.cs:1024
-
Watchdog(IChat chat, ISessionControllerFactory sessionControllerFactory, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IDatabaseContextFactory databaseContextFactory, IByondTopicSender byondTopicSender, IEventConsumer eventConsumer, IJobManager jobManager, IServerControl serverControl, IAsyncDelayer asyncDelayer, ILogger< Watchdog > logger, DreamDaemonLaunchParameters initialLaunchParameters, Api.Models.Instance instance, bool autoStart)
Construct a IWatchdog
Definition: Watchdog.cs:167
- +
ISessionController InactiveServer
The inactive ISessionController
Definition: MonitorState.cs:35
+
const string DMResponseSuccess
Generic OK response
Definition: Constants.cs:26
+
async Task< bool > HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
Handle a given eventType
Definition: Watchdog.cs:1029
+
Watchdog(IChat chat, ISessionControllerFactory sessionControllerFactory, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IDatabaseContextFactory databaseContextFactory, IByondTopicSender byondTopicSender, IEventConsumer eventConsumer, IJobManager jobManager, IServerControl serverControl, IAsyncDelayer asyncDelayer, ILogger< Watchdog > logger, DreamDaemonLaunchParameters initialLaunchParameters, Api.Models.Instance instance, bool autoStart)
Construct a IWatchdog
Definition: Watchdog.cs:167
+
readonly bool autoStart
If the Watchdog should LaunchImplNoLock(bool, bool, WatchdogReattachInformation, CancellationToken) i...
Definition: Watchdog.cs:118
-
async Task StartAsync(CancellationToken cancellationToken)
Definition: Watchdog.cs:963
-
ISessionController alphaServer
Server designation alpha
Definition: Watchdog.cs:138
-
Handles Commands.ICommands that map to those defined in a IJsonTrackingContext
-
async Task HandlerMonitorWakeup(MonitorActivationReason activationReason, MonitorState monitorState, CancellationToken cancellationToken)
Handles the actions to take when the monitor has to "wake up"
Definition: Watchdog.cs:260
- -
readonly IReattachInfoHandler reattachInfoHandler
The IReattachInfoHandler for the Watchdog
Definition: Watchdog.cs:68
-
Task< string > SendCommand(string command, CancellationToken cancellationToken)
Sends a command to DreamDaemon through /world/Topic()
-
ReattachInformation Bravo
ReattachInformation for the Bravo session
-
async Task TerminateNoLock(bool graceful, bool announce, CancellationToken cancellationToken)
Implementation of Terminate(bool, CancellationToken). Does not lock semaphore
Definition: Watchdog.cs:231
-
readonly IDmbFactory dmbFactory
The IDmbFactory for the Watchdog
Definition: Watchdog.cs:63
-
bool Match(DreamDaemonLaunchParameters otherParameters)
Check if we match a given set of otherParameters
-
Represents the lifetime of a IRestartHandler registration
-
CancellationTokenSource monitorCts
The CancellationTokenSource for the monitor loop
Definition: Watchdog.cs:123
-
MonitorAction
The action for the monitor loop to take when control is returned to it
Definition: MonitorAction.cs:6
-
readonly IRestartRegistration restartRegistration
The IRestartRegistration for the Watchdog
Definition: Watchdog.cs:93
-
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the Watchdog
Definition: Watchdog.cs:98
+
async Task StartAsync(CancellationToken cancellationToken)
Definition: Watchdog.cs:968
+
ISessionController alphaServer
Server designation alpha
Definition: Watchdog.cs:138
+
Handles Commands.ICommands that map to those defined in a IJsonTrackingContext
+
async Task HandlerMonitorWakeup(MonitorActivationReason activationReason, MonitorState monitorState, CancellationToken cancellationToken)
Handles the actions to take when the monitor has to "wake up"
Definition: Watchdog.cs:264
+ +
readonly IReattachInfoHandler reattachInfoHandler
The IReattachInfoHandler for the Watchdog
Definition: Watchdog.cs:68
+
Task< string > SendCommand(string command, CancellationToken cancellationToken)
Sends a command to DreamDaemon through /world/Topic()
+
ReattachInformation Bravo
ReattachInformation for the Bravo session
+
async Task TerminateNoLock(bool graceful, bool announce, CancellationToken cancellationToken)
Implementation of Terminate(bool, CancellationToken). Does not lock semaphore
Definition: Watchdog.cs:235
+
readonly IDmbFactory dmbFactory
The IDmbFactory for the Watchdog
Definition: Watchdog.cs:63
+
bool Match(DreamDaemonLaunchParameters otherParameters)
Check if we match a given set of otherParameters
+
Represents the lifetime of a IRestartHandler registration
+
CancellationTokenSource monitorCts
The CancellationTokenSource for the monitor loop
Definition: Watchdog.cs:123
+
const int AlphaBravoStartupSeperationInterval
The time in seconds to wait from starting alphaServer to start bravoServer. Does not take responsiven...
Definition: Watchdog.cs:30
+
MonitorAction
The action for the monitor loop to take when control is returned to it
Definition: MonitorAction.cs:6
+
readonly IRestartRegistration restartRegistration
The IRestartRegistration for the Watchdog
Definition: Watchdog.cs:93
+
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the Watchdog
Definition: Watchdog.cs:98
-
IRestartRegistration RegisterForRestart(IRestartHandler handler)
Register a given handler to run before stopping the server for a restart
+
IRestartRegistration RegisterForRestart(IRestartHandler handler)
Register a given handler to run before stopping the server for a restart
TaskCompletionSource< object > activeParametersUpdated
TaskCompletionSource<TResult> that completes when ActiveLaunchParameters are changed and we are Runni...
Definition: Watchdog.cs:133
-
The (absolute) state of the Watchdog
Definition: MonitorState.cs:8
-
Handles saving and loading WatchdogReattachInformation
- -
static async Task< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore
-
ISessionController bravoServer
Server designation bravo
Definition: Watchdog.cs:143
-
void ResetRebootState()
Changes RebootState to Components.Watchdog.RebootState.Normal without telling the DMAPI ...
-
readonly IByondTopicSender byondTopicSender
The IByondTopicSender for the Watchdog
Definition: Watchdog.cs:78
-
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
- - -
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
+
The (absolute) state of the Watchdog
Definition: MonitorState.cs:8
+
Handles saving and loading WatchdogReattachInformation
+ +
static async Task< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore
+
ISessionController bravoServer
Server designation bravo
Definition: Watchdog.cs:143
+
void ResetRebootState()
Changes RebootState to Components.Watchdog.RebootState.Normal without telling the DMAPI
+
readonly IByondTopicSender byondTopicSender
The IByondTopicSender for the Watchdog
Definition: Watchdog.cs:78
+
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
+ + +
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...
diff --git a/_components_2_watchdog_2_watchdog_factory_8cs.html b/_components_2_watchdog_2_watchdog_factory_8cs.html index 2388323772..6476fdd52c 100644 --- a/_components_2_watchdog_2_watchdog_factory_8cs.html +++ b/_components_2_watchdog_2_watchdog_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/WatchdogFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Watchdog
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_components_2_watchdog_2_watchdog_factory_8cs_source.html b/_components_2_watchdog_2_watchdog_factory_8cs_source.html index 8ba096e733..ddde9cce78 100644 --- a/_components_2_watchdog_2_watchdog_factory_8cs_source.html +++ b/_components_2_watchdog_2_watchdog_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/WatchdogFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
WatchdogFactory.cs
-Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Microsoft.Extensions.Logging;
3 using System;
8 
9 namespace Tgstation.Server.Host.Components.Watchdog
10 {
13  {
18 
22  readonly ILoggerFactory loggerFactory;
23 
28 
32  readonly IByondTopicSender byondTopicSender;
33 
38 
43 
53  public WatchdogFactory(IServerControl serverControl, ILoggerFactory loggerFactory, IDatabaseContextFactory databaseContextFactory, IByondTopicSender byondTopicSender, IJobManager jobManager, IAsyncDelayer asyncDelayer)
54  {
55  this.serverControl = serverControl ?? throw new ArgumentNullException(nameof(serverControl));
56  this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
57  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
58  this.byondTopicSender = byondTopicSender ?? throw new ArgumentNullException(nameof(byondTopicSender));
59  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
60  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
61  }
62 
64  public IWatchdog CreateWatchdog(IChat chat, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IEventConsumer eventConsumer, ISessionControllerFactory sessionControllerFactory, Api.Models.Instance instance, DreamDaemonSettings settings) => new Watchdog(chat, sessionControllerFactory, dmbFactory, reattachInfoHandler, databaseContextFactory, byondTopicSender, eventConsumer, jobManager, serverControl, asyncDelayer, loggerFactory.CreateLogger<Watchdog>(), settings, instance, settings.AutoStart.Value);
65  }
66 }
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 System;
8 
10 {
13  {
18 
22  readonly ILoggerFactory loggerFactory;
23 
28 
32  readonly IByondTopicSender byondTopicSender;
33 
38 
43 
54  {
55  this.serverControl = serverControl ?? throw new ArgumentNullException(nameof(serverControl));
56  this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
57  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
58  this.byondTopicSender = byondTopicSender ?? throw new ArgumentNullException(nameof(byondTopicSender));
59  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
60  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
61  }
62 
64  public IWatchdog CreateWatchdog(IChat chat, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IEventConsumer eventConsumer, ISessionControllerFactory sessionControllerFactory, Api.Models.Instance instance, DreamDaemonSettings settings) => new Watchdog(chat, sessionControllerFactory, dmbFactory, reattachInfoHandler, databaseContextFactory, byondTopicSender, eventConsumer, jobManager, serverControl, asyncDelayer, loggerFactory.CreateLogger<Watchdog>(), settings, instance, settings.AutoStart.Value);
65  }
66 }
Manages the runtime of Jobs
Definition: IJobManager.cs:12
-
readonly IByondTopicSender byondTopicSender
The IByondTopicSender for the WatchdogFactory
+
readonly IByondTopicSender byondTopicSender
The IByondTopicSender for the WatchdogFactory
-
Consumes EventTypes and takes the appropriate actions
+ +
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
-
bool AutoStart
If DreamDaemon starts when it&#39;s Instance starts
- - -
For managing connected chat services
Definition: IChat.cs:13
+
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
+
readonly IJobManager jobManager
The IJobManager for the WatchdogFactory
+ +
IWatchdog CreateWatchdog(IChat chat, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IEventConsumer eventConsumer, ISessionControllerFactory sessionControllerFactory, Api.Models.Instance instance, DreamDaemonSettings settings)
Creates a IWatchdog
+ +
For managing connected chat services
Definition: IChat.cs:13
-
WatchdogFactory(IServerControl serverControl, ILoggerFactory loggerFactory, IDatabaseContextFactory databaseContextFactory, IByondTopicSender byondTopicSender, IJobManager jobManager, IAsyncDelayer asyncDelayer)
Construct a WatchdogFactory
-
readonly IServerControl serverControl
The IServerControl for the WatchdogFactory
+
WatchdogFactory(IServerControl serverControl, ILoggerFactory loggerFactory, IDatabaseContextFactory databaseContextFactory, IByondTopicSender byondTopicSender, IJobManager jobManager, IAsyncDelayer asyncDelayer)
Construct a WatchdogFactory
+
readonly IServerControl serverControl
The IServerControl for the WatchdogFactory
- - + + - - -
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the WatchdogFactory
+ + +
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the WatchdogFactory
- - -
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the WatchdogFactory
- -
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the WatchdogFactory
-
Handles saving and loading WatchdogReattachInformation
- - -
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
+ + +
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the WatchdogFactory
+ +
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer 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...
diff --git a/_components_2_watchdog_2_watchdog_reattach_information_8cs.html b/_components_2_watchdog_2_watchdog_reattach_information_8cs.html index 78a81c5eff..9fab51c99c 100644 --- a/_components_2_watchdog_2_watchdog_reattach_information_8cs.html +++ b/_components_2_watchdog_2_watchdog_reattach_information_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/WatchdogReattachInformation.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Components.Watchdog.WatchdogReattachInformation - Reattach information for a IWatchdog More...
+ Reattach information for a IWatchdog More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Watchdog
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_components_2_watchdog_2_watchdog_reattach_information_8cs_source.html b/_components_2_watchdog_2_watchdog_reattach_information_8cs_source.html index 2434028e56..0ab516cbb8 100644 --- a/_components_2_watchdog_2_watchdog_reattach_information_8cs_source.html +++ b/_components_2_watchdog_2_watchdog_reattach_information_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/WatchdogReattachInformation.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
WatchdogReattachInformation.cs
-Go to the documentation of this file.
1 using System;
2 using System.Globalization;
4 
5 namespace Tgstation.Server.Host.Components.Watchdog
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;
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 }
- - - - -
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
- -
Parameters necessary for duplicating a ISessionController 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
+ +
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
+
diff --git a/_configuration_8cs.html b/_configuration_8cs.html index dfa4b53fca..cb73fb94e2 100644 --- a/_configuration_8cs.html +++ b/_configuration_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.StaticFiles
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_configuration_8cs_source.html b/_configuration_8cs_source.html index 5b9d50f6bb..08f46a8e87 100644 --- a/_configuration_8cs_source.html +++ b/_configuration_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
16 namespace Tgstation.Server.Host.Components.StaticFiles
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 
90  public Configuration(IIOManager ioManager, ISynchronousIOManager synchronousIOManager, ISymlinkFactory symlinkFactory, IProcessExecutor processExecutor, IPostWriteHandler postWriteHandler, IPlatformIdentifier platformIdentifier, ILogger<Configuration> logger)
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 
110  string StaticIgnorePath() => ioManager.ConcatPath(GameStaticFilesSubdirectory, StaticIgnoreFile);
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);
139  var headFileExistsTask = ioManager.FileExists(ioManager.ConcatPath(CodeModificationsSubdirectory, CodeModificationsHeadFile), cancellationToken);
140  var tailFileExistsTask = ioManager.FileExists(ioManager.ConcatPath(CodeModificationsSubdirectory, CodeModificationsTailFile), 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 }
readonly ISynchronousIOManager synchronousIOManager
The ISynchronousIOManager for Configuration
+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
+
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
-
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< 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 > 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
+
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
-
Represents a user on the current System.Runtime.InteropServices.OSPlatform
- - -
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
- -
readonly IProcessExecutor processExecutor
The IProcessExecutor for Configuration
-
bool IsDirectory
If Path represents a directory
+
Represents a user on the current 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
+
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
+
static readonly IReadOnlyDictionary< EventType, string > EventTypeScriptFileNameMap
+ +
bool? IsDirectory
If Path represents a directory
+
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
-
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for Configuration
-
For accessing the disk in a synchronous manner
+
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
-
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 SemaphoreSlim semaphore
The SemaphoreSlim for Configuration
+
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
+
IEnumerable< string > GetDirectories(string path, CancellationToken cancellationToken)
Enumerate directories in a given path
+
readonly SemaphoreSlim semaphore
The SemaphoreSlim for Configuration
Represents a game configuration file. Create and delete actions uncerimonuously overwrite/delete file...
-
For managing the Configuration directory
+ -
readonly IPostWriteHandler postWriteHandler
The IPostWriteHandler for Configuration
-
bool AccessDenied
If access to the ConfigurationFile file was denied for the operation
- - - -
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
- -
static async Task< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore
- - +
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
+
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
+
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_client_8cs.html b/_configuration_client_8cs.html index b31542845d..8a1ad570ee 100644 --- a/_configuration_client_8cs.html +++ b/_configuration_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/ConfigurationClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_configuration_client_8cs_source.html b/_configuration_client_8cs_source.html index e7ed334084..2f38d6e7d5 100644 --- a/_configuration_client_8cs_source.html +++ b/_configuration_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/ConfigurationClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ConfigurationClient.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 using Tgstation.Server.Api;
7 
8 namespace Tgstation.Server.Client.Components
9 {
12  {
17 
21  readonly Instance instance;
22 
28  static string SanitizeGetPath(string path)
29  {
30  if (path == null)
31  path = String.Empty;
32  if (path.Length == 0 || path[0] != '/')
33  path = '/' + path;
34  return path;
35  }
36 
42  public ConfigurationClient(IApiClient apiClient, Instance instance)
43  {
44  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
45  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
46  }
47 
49  public Task DeleteEmptyDirectory(ConfigurationFile directory, CancellationToken cancellationToken) => apiClient.Delete(Routes.Configuration, directory, instance.Id, cancellationToken);
50 
52  public Task<ConfigurationFile> CreateDirectory(ConfigurationFile directory, CancellationToken cancellationToken) => apiClient.Create<ConfigurationFile, ConfigurationFile>(Routes.Configuration, directory, instance.Id, cancellationToken);
53 
55  public Task<IReadOnlyList<ConfigurationFile>> List(string directory, CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<ConfigurationFile>>(Routes.List(Routes.Configuration) + SanitizeGetPath(directory), instance.Id, cancellationToken);
56 
58  public Task<ConfigurationFile> Read(ConfigurationFile file, CancellationToken cancellationToken)
59  {
60  if (file == null)
61  throw new ArgumentNullException(nameof(file));
62  return apiClient.Read<ConfigurationFile>(Routes.ConfigurationFile + SanitizeGetPath(file.Path), instance.Id, cancellationToken);
63  }
64 
66  public Task<ConfigurationFile> Write(ConfigurationFile file, CancellationToken cancellationToken) => apiClient.Update<ConfigurationFile, ConfigurationFile>(Routes.Configuration, file ?? throw new ArgumentNullException(nameof(file)), instance.Id, cancellationToken);
67  }
68 }
const string Configuration
The Models.ConfigurationFile controller
Definition: Routes.cs:49
+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 using Tgstation.Server.Api;
7 
9 {
12  {
17 
21  readonly Instance instance;
22 
28  static string SanitizeGetPath(string path)
29  {
30  if (path == null)
31  path = String.Empty;
32  if (path.Length == 0 || path[0] != '/')
33  path = '/' + path;
34  return path;
35  }
36 
43  {
44  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
45  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
46  }
47 
49  public Task DeleteEmptyDirectory(ConfigurationFile directory, CancellationToken cancellationToken) => apiClient.Delete(Routes.Configuration, directory, instance.Id, cancellationToken);
50 
52  public Task<ConfigurationFile> CreateDirectory(ConfigurationFile directory, CancellationToken cancellationToken) => apiClient.Create<ConfigurationFile, ConfigurationFile>(Routes.Configuration, directory, instance.Id, cancellationToken);
53 
55  public Task<IReadOnlyList<ConfigurationFile>> List(string directory, CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<ConfigurationFile>>(Routes.List(Routes.Configuration) + SanitizeGetPath(directory), instance.Id, cancellationToken);
56 
58  public Task<ConfigurationFile> Read(ConfigurationFile file, CancellationToken cancellationToken)
59  {
60  if (file == null)
61  throw new ArgumentNullException(nameof(file));
62  return apiClient.Read<ConfigurationFile>(Routes.ConfigurationFile + SanitizeGetPath(file.Path), instance.Id, cancellationToken);
63  }
64 
66  public Task<ConfigurationFile> Write(ConfigurationFile file, CancellationToken cancellationToken) => apiClient.Update<ConfigurationFile, ConfigurationFile>(Routes.Configuration, file ?? throw new ArgumentNullException(nameof(file)), instance.Id, cancellationToken);
67  }
68 }
Task< ConfigurationFile > ConfigurationFile(Routes.Configuration, directory, instance.Id, cancellationToken)
+
const string Configuration
The Models.ConfigurationFile controller
Definition: Routes.cs:49
- - -
readonly IApiClient apiClient
The IApiClient for the ConfigurationClient
+
Task< ConfigurationFile > CreateDirectory(ConfigurationFile directory, CancellationToken cancellationToken)
Creates an empty directory
+
readonly IApiClient apiClient
The IApiClient for the ConfigurationClient
-
Task< ConfigurationFile > Read(ConfigurationFile file, CancellationToken cancellationToken)
Read a ConfigurationFile file
-
string Path
The path to the ConfigurationFile file
-
Routes to a server actions
Definition: Routes.cs:9
-
readonly Instance instance
The Instance for the ConfigurationClient
-
static string SanitizeGetPath(string path)
Sanitize a ConfigurationFile path for use in a GET Uri
+
Task< ConfigurationFile > Read(ConfigurationFile file, CancellationToken cancellationToken)
Read a ConfigurationFile file
+
string Path
The path to the ConfigurationFile file
+
Routes to a server actions
Definition: Routes.cs:9
+ +
readonly Instance instance
The Instance for the ConfigurationClient
+
static string SanitizeGetPath(string path)
Sanitize a ConfigurationFile path for use in a GET Uri
+
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
Represents a game configuration file. Create and delete actions uncerimonuously overwrite/delete file...
-
ConfigurationClient(IApiClient apiClient, Instance instance)
Construct a ConfigurationClient
-
Metadata about a server instance
Definition: Instance.cs:9
- +
Task< IReadOnlyList< ConfigurationFile > > List(string directory, CancellationToken cancellationToken)
List configuration files
+
Task< ConfigurationFile > Write(ConfigurationFile file, CancellationToken cancellationToken)
Overwrite a ConfigurationFile file
+
ConfigurationClient(IApiClient apiClient, Instance instance)
Construct a ConfigurationClient
+
Metadata about a server instance
Definition: Instance.cs:9
+ -
static string List(string route)
Get the /List postfix for a route
- -
Web interface for the API
Definition: IApiClient.cs:11
-
const string ConfigurationFile
Full combination of Configuration and File
Definition: Routes.cs:59
- +
Task Delete(string route, CancellationToken cancellationToken)
Run an HTTP DELETE request
+
static string List(string route)
Get the /List postfix for a route
+ +
Web interface for the API
Definition: IApiClient.cs:11
+
Task DeleteEmptyDirectory(ConfigurationFile directory, CancellationToken cancellationToken)
Delete an empty directory
+
const string ConfigurationFile
Full combination of Configuration and File
Definition: Routes.cs:59
+
diff --git a/_configuration_controller_8cs.html b/_configuration_controller_8cs.html index a658d38432..351f5614e7 100644 --- a/_configuration_controller_8cs.html +++ b/_configuration_controller_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/ConfigurationController.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Controllers.ConfigurationController - The ModelController<TModel> for ConfigurationFiles More...
+ The ModelController<TModel> for ConfigurationFiles More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Controllers
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_configuration_controller_8cs_source.html b/_configuration_controller_8cs_source.html index ac24d6fd22..0e99a5dacc 100644 --- a/_configuration_controller_8cs_source.html +++ b/_configuration_controller_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/ConfigurationController.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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.IO;
5 using System.Net;
6 using System.Threading;
7 using System.Threading.Tasks;
8 using Tgstation.Server.Api;
12 using Tgstation.Server.Host.IO;
15 
16 namespace Tgstation.Server.Host.Controllers
17 {
21  [Route(Routes.Configuration)]
22  public sealed class ConfigurationController : ModelController<ConfigurationFile>
23  {
28 
33 
42  public ConfigurationController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, IIOManager ioManager, ILogger<ConfigurationController> logger) : base(databaseContext, authenticationContextFactory, logger, true)
43  {
44  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
45  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
46  }
47 
54  bool ForbidDueToModeConflicts(string path, out ISystemIdentity systemIdentityToUse)
55  {
56  if (Instance.ConfigurationType == ConfigurationType.Disallowed || (Instance.ConfigurationType == ConfigurationType.SystemIdentityWrite && AuthenticationContext.SystemIdentity == null) || (path != null && ioManager.PathContainsParentAccess(path)))
57  {
58  systemIdentityToUse = null;
59  return true;
60  }
61 
62  systemIdentityToUse = Instance.ConfigurationType == ConfigurationType.SystemIdentityWrite ? AuthenticationContext.SystemIdentity : null;
63  return false;
64  }
65 
67  [TgsAuthorize(ConfigurationRights.Write)]
68  public override async Task<IActionResult> Update([FromBody] ConfigurationFile model, CancellationToken cancellationToken)
69  {
70  if (model == null)
71  throw new ArgumentNullException(nameof(model));
72  if (ForbidDueToModeConflicts(model.Path, out var systemIdentity))
73  return Forbid();
74 
75  var config = instanceManager.GetInstance(Instance).Configuration;
76  try
77  {
78  var newFile = await config.Write(model.Path, systemIdentity, model.Content, model.LastReadHash, cancellationToken).ConfigureAwait(false);
79  if (newFile == null)
80  return Conflict(new ErrorMessage
81  {
82  Message = "This file has been updated since you last viewed it!"
83  });
84 
85  newFile.Content = null;
86 
87  return model.LastReadHash == null ? (IActionResult)StatusCode((int)HttpStatusCode.Created, newFile) : Json(newFile);
88  }
89  catch(IOException e)
90  {
91  Logger.LogInformation("IOException while updating file {0}: {1}", model.Path, e);
92  return Conflict(new ErrorMessage
93  {
94  Message = e.Message
95  });
96  }
97  catch (NotImplementedException)
98  {
99  return StatusCode((int)HttpStatusCode.NotImplemented);
100  }
101  }
102 
109  [HttpGet(Routes.File + "/{*filePath}")]
110  [TgsAuthorize(ConfigurationRights.Read)]
111  public async Task<IActionResult> File(string filePath, CancellationToken cancellationToken)
112  {
113  if (ForbidDueToModeConflicts(filePath, out var systemIdentity))
114  return Forbid();
115 
116  try
117  {
118  var result = await instanceManager.GetInstance(Instance).Configuration.Read(filePath, systemIdentity, cancellationToken).ConfigureAwait(false);
119  if (result == null)
120  return StatusCode((int)HttpStatusCode.Gone);
121 
122  return Json(result);
123  }
124  catch (IOException e)
125  {
126  Logger.LogInformation("IOException while reading file {0}: {1}", filePath, e);
127  return Conflict(new ErrorMessage
128  {
129  Message = e.Message
130  });
131  }
132  catch (NotImplementedException)
133  {
134  return StatusCode((int)HttpStatusCode.NotImplemented);
135  }
136  }
137 
144  [HttpGet("List/{*directoryPath}")]
145  [TgsAuthorize(ConfigurationRights.List)]
146  public async Task<IActionResult> Directory(string directoryPath, CancellationToken cancellationToken)
147  {
148  if (ForbidDueToModeConflicts(directoryPath, out var systemIdentity))
149  return Forbid();
150 
151  try
152  {
153  var result = await instanceManager.GetInstance(Instance).Configuration.ListDirectory(directoryPath, systemIdentity, cancellationToken).ConfigureAwait(false);
154  if (result == null)
155  return StatusCode((int)HttpStatusCode.Gone);
156 
157  return Json(result);
158  }
159  catch (NotImplementedException)
160  {
161  return StatusCode((int)HttpStatusCode.NotImplemented);
162  }
163  catch (UnauthorizedAccessException)
164  {
165  return Forbid();
166  }
167  }
168 
170  [TgsAuthorize(ConfigurationRights.List)]
171  public override Task<IActionResult> List(CancellationToken cancellationToken) => Directory(null, cancellationToken);
172 
174  [TgsAuthorize(ConfigurationRights.Write)]
175  public override async Task<IActionResult> Create([FromBody] ConfigurationFile model, CancellationToken cancellationToken)
176  {
177  if (model == null)
178  throw new ArgumentNullException(nameof(model));
179 
180  if (ForbidDueToModeConflicts(model.Path, out var systemIdentity))
181  return Forbid();
182 
183  try
184  {
185  model.IsDirectory = true;
186  return await instanceManager.GetInstance(Instance).Configuration.CreateDirectory(model.Path, systemIdentity, cancellationToken).ConfigureAwait(false) ? (IActionResult)Json(model) : StatusCode((int)HttpStatusCode.Created, model);
187  }
188  catch (NotImplementedException)
189  {
190  return StatusCode((int)HttpStatusCode.NotImplemented);
191  }
192  catch (UnauthorizedAccessException)
193  {
194  return Forbid();
195  }
196  }
197 
204  [HttpDelete]
205  [TgsAuthorize(ConfigurationRights.Delete)]
206  public async Task<IActionResult> Delete([FromBody] ConfigurationFile directory, CancellationToken cancellationToken)
207  {
208  if (directory == null)
209  throw new ArgumentNullException(nameof(directory));
210 
211  if (ForbidDueToModeConflicts(directory.Path, out var systemIdentity))
212  return Forbid();
213 
214  try
215  {
216  return await instanceManager.GetInstance(Instance).Configuration.DeleteDirectory(directory.Path, systemIdentity, cancellationToken).ConfigureAwait(false) ? (IActionResult)Ok() : Conflict(new ErrorMessage
217  {
218  Message = "Directory not empty!"
219  });
220  }
221  catch (NotImplementedException)
222  {
223  return StatusCode((int)HttpStatusCode.NotImplemented);
224  }
225  catch (UnauthorizedAccessException)
226  {
227  return Forbid();
228  }
229  }
230  }
231 }
- -
ConfigurationRights
Rights for Models.ConfigurationFile
- -
const string Configuration
The Models.ConfigurationFile controller
Definition: Routes.cs:49
+Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.IO;
5 using System.Net;
6 using System.Threading;
7 using System.Threading.Tasks;
8 using Tgstation.Server.Api;
12 using Tgstation.Server.Host.IO;
15 
17 {
21  [Route(Routes.Configuration)]
22  public sealed class ConfigurationController : ModelController<ConfigurationFile>
23  {
28 
33 
42  public ConfigurationController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, IIOManager ioManager, ILogger<ConfigurationController> logger) : base(databaseContext, authenticationContextFactory, logger, true)
43  {
44  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
45  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
46  }
47 
54  bool ForbidDueToModeConflicts(string path, out ISystemIdentity systemIdentityToUse)
55  {
57  {
58  systemIdentityToUse = null;
59  return true;
60  }
61 
62  systemIdentityToUse = Instance.ConfigurationType == ConfigurationType.SystemIdentityWrite ? AuthenticationContext.SystemIdentity : null;
63  return false;
64  }
65 
67  [TgsAuthorize(ConfigurationRights.Write)]
68  public override async Task<IActionResult> Update([FromBody] ConfigurationFile model, CancellationToken cancellationToken)
69  {
70  if (model == null)
71  throw new ArgumentNullException(nameof(model));
72  if (ForbidDueToModeConflicts(model.Path, out var systemIdentity))
73  return Forbid();
74 
76  try
77  {
78  var newFile = await config.Write(model.Path, systemIdentity, model.Content, model.LastReadHash, cancellationToken).ConfigureAwait(false);
79  if (newFile == null)
80  return Conflict(new ErrorMessage
81  {
82  Message = "This file has been updated since you last viewed it!"
83  });
84 
85  newFile.Content = null;
86 
87  return model.LastReadHash == null ? (IActionResult)StatusCode((int)HttpStatusCode.Created, newFile) : Json(newFile);
88  }
89  catch(IOException e)
90  {
91  Logger.LogInformation("IOException while updating file {0}: {1}", model.Path, e);
92  return Conflict(new ErrorMessage
93  {
94  Message = e.Message
95  });
96  }
97  catch (NotImplementedException)
98  {
99  return StatusCode((int)HttpStatusCode.NotImplemented);
100  }
101  }
102 
109  [HttpGet(Routes.File + "/{*filePath}")]
110  [TgsAuthorize(ConfigurationRights.Read)]
111  public async Task<IActionResult> File(string filePath, CancellationToken cancellationToken)
112  {
113  if (ForbidDueToModeConflicts(filePath, out var systemIdentity))
114  return Forbid();
115 
116  try
117  {
118  var result = await instanceManager.GetInstance(Instance).Configuration.Read(filePath, systemIdentity, cancellationToken).ConfigureAwait(false);
119  if (result == null)
120  return StatusCode((int)HttpStatusCode.Gone);
121 
122  return Json(result);
123  }
124  catch (IOException e)
125  {
126  Logger.LogInformation("IOException while reading file {0}: {1}", filePath, e);
127  return Conflict(new ErrorMessage
128  {
129  Message = e.Message
130  });
131  }
132  catch (NotImplementedException)
133  {
134  return StatusCode((int)HttpStatusCode.NotImplemented);
135  }
136  }
137 
144  [HttpGet("List/{*directoryPath}")]
145  [TgsAuthorize(ConfigurationRights.List)]
146  public async Task<IActionResult> Directory(string directoryPath, CancellationToken cancellationToken)
147  {
148  if (ForbidDueToModeConflicts(directoryPath, out var systemIdentity))
149  return Forbid();
150 
151  try
152  {
153  var result = await instanceManager.GetInstance(Instance).Configuration.ListDirectory(directoryPath, systemIdentity, cancellationToken).ConfigureAwait(false);
154  if (result == null)
155  return StatusCode((int)HttpStatusCode.Gone);
156 
157  return Json(result);
158  }
159  catch (NotImplementedException)
160  {
161  return StatusCode((int)HttpStatusCode.NotImplemented);
162  }
163  catch (UnauthorizedAccessException)
164  {
165  return Forbid();
166  }
167  }
168 
170  [TgsAuthorize(ConfigurationRights.List)]
171  public override Task<IActionResult> List(CancellationToken cancellationToken) => Directory(null, cancellationToken);
172 
174  [TgsAuthorize(ConfigurationRights.Write)]
175  public override async Task<IActionResult> Create([FromBody] ConfigurationFile model, CancellationToken cancellationToken)
176  {
177  if (model == null)
178  throw new ArgumentNullException(nameof(model));
179 
180  if (ForbidDueToModeConflicts(model.Path, out var systemIdentity))
181  return Forbid();
182 
183  try
184  {
185  model.IsDirectory = true;
186  return await instanceManager.GetInstance(Instance).Configuration.CreateDirectory(model.Path, systemIdentity, cancellationToken).ConfigureAwait(false) ? (IActionResult)Json(model) : StatusCode((int)HttpStatusCode.Created, model);
187  }
188  catch (NotImplementedException)
189  {
190  return StatusCode((int)HttpStatusCode.NotImplemented);
191  }
192  catch (UnauthorizedAccessException)
193  {
194  return Forbid();
195  }
196  }
197 
204  [HttpDelete]
205  [TgsAuthorize(ConfigurationRights.Delete)]
206  public async Task<IActionResult> Delete([FromBody] ConfigurationFile directory, CancellationToken cancellationToken)
207  {
208  if (directory == null)
209  throw new ArgumentNullException(nameof(directory));
210 
211  if (ForbidDueToModeConflicts(directory.Path, out var systemIdentity))
212  return Forbid();
213 
214  try
215  {
216  return await instanceManager.GetInstance(Instance).Configuration.DeleteDirectory(directory.Path, systemIdentity, cancellationToken).ConfigureAwait(false) ? (IActionResult)Ok() : Conflict(new ErrorMessage
217  {
218  Message = "Directory not empty!"
219  });
220  }
221  catch (NotImplementedException)
222  {
223  return StatusCode((int)HttpStatusCode.NotImplemented);
224  }
225  catch (UnauthorizedAccessException)
226  {
227  return Forbid();
228  }
229  }
230  }
231 }
+ +
ConfigurationRights
Rights for Models.ConfigurationFile
+ + +
const string Configuration
The Models.ConfigurationFile controller
Definition: Routes.cs:49
- -
Represents a user on the current System.Runtime.InteropServices.OSPlatform
+
IInstance GetInstance(Models.Instance metadata)
Get the IInstance associated with given metadata
+
Represents a user on the current System.Runtime.InteropServices.OSPlatform
- -
override async Task< IActionResult > Create([FromBody] ConfigurationFile model, CancellationToken cancellationToken)
-
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
-
ConfigurationType
The type of configuration allowed on an Instance
-
ConfigurationController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, IIOManager ioManager, ILogger< ConfigurationController > logger)
Construct a UserController
+
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
+
ConfigurationType
The type of configuration allowed on an Instance
+
ConfigurationController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, IIOManager ioManager, ILogger< ConfigurationController > logger)
Construct a UserController
-
The ModelController<TModel> for ConfigurationFiles
-
Routes to a server actions
Definition: Routes.cs:9
-
readonly IIOManager ioManager
The IIOManager for the ConfigurationController
-
string Message
A human readable description of the error
Definition: ErrorMessage.cs:13
+
The ModelController<TModel> for ConfigurationFiles
+
Routes to a server actions
Definition: Routes.cs:9
+
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
Represents a game configuration file. Create and delete actions uncerimonuously overwrite/delete file...
-
An ApiController representing a TModel
+
An ApiController representing a TModel
-
async Task< IActionResult > File(string filePath, CancellationToken cancellationToken)
Get the contents of a file at a filePath
- -
Metadata about a server instance
Definition: Instance.cs:9
- - -
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
-
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- +
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
+
Metadata about a server instance
Definition: Instance.cs:9
+ +
bool PathContainsParentAccess(string path)
Check if a path contains the '..' parent directory accessor
+
override Task< IActionResult > List(CancellationToken cancellationToken)
Attempt to list entries of the TModel
+ +
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
+
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+
override async Task< IActionResult > Update([FromBody] ConfigurationFile model, CancellationToken cancellationToken)
- + -
ConfigurationType ConfigurationType
If ConfigurationFile can be used on the Instance
Definition: Instance.cs:38
diff --git a/_configuration_file_8cs.html b/_configuration_file_8cs.html index cd2db9fa77..dfbafd623b 100644 --- a/_configuration_file_8cs.html +++ b/_configuration_file_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/ConfigurationFile.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_configuration_file_8cs_source.html b/_configuration_file_8cs_source.html index 5e2bd2a11f..1178bc0a3f 100644 --- a/_configuration_file_8cs_source.html +++ b/_configuration_file_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/ConfigurationFile.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ConfigurationFile.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Api.Models
2 {
6  public sealed class ConfigurationFile
7  {
11  public string Path { get; set; }
12 
16  public bool? AccessDenied { get; set; }
17 
21  public bool? IsDirectory { get; set; }
22 
26  public string LastReadHash { get; set; }
27 
31 #pragma warning disable CA1819 // Properties should not return arrays
32  public byte[] Content { get; set; }
33 #pragma warning restore CA1819 // Properties should not return arrays
34  }
35 }
+Go to the documentation of this file.
2 {
6  public sealed class ConfigurationFile
7  {
11  public string Path { get; set; }
12 
16  public bool? AccessDenied { get; set; }
17 
21  public bool? IsDirectory { get; set; }
22 
26  public string LastReadHash { get; set; }
27 
31 #pragma warning disable CA1819 // Properties should not return arrays
32  public byte[] Content { get; set; }
33 #pragma warning restore CA1819 // Properties should not return arrays
34  }
35 }
string LastReadHash
The MD5 hash of the file when last read by the user. If this doesn't match during update actions,...
+
bool? IsDirectory
If Path represents a directory
+ +
string Path
The path to the ConfigurationFile file
Represents a game configuration file. Create and delete actions uncerimonuously overwrite/delete file...
- +
byte [] Content
The content of the ConfigurationFile. Will be null if AccessDenied is true or during listing and writ...
+
bool? AccessDenied
If access to the ConfigurationFile file was denied for the operation
diff --git a/_configuration_rights_8cs.html b/_configuration_rights_8cs.html index 8717c40ce4..e34380959a 100644 --- a/_configuration_rights_8cs.html +++ b/_configuration_rights_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/ConfigurationRights.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Api +  namespace  Tgstation.Server.Api.Rights   @@ -113,8 +98,8 @@ Enumerations
  Tgstation.Server.Api.Rights.ConfigurationRights.Delete = 8
- } - + } +
 Rights for Models.ConfigurationFile More...
 Rights for Models.ConfigurationFile More...
 
@@ -122,7 +107,7 @@ Enumerations diff --git a/_configuration_rights_8cs_source.html b/_configuration_rights_8cs_source.html index 7f32539b8c..2f796f2de3 100644 --- a/_configuration_rights_8cs_source.html +++ b/_configuration_rights_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/ConfigurationRights.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
ConfigurationRights.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Api.Rights
4 {
8  [Flags]
9  public enum ConfigurationRights : ulong
10  {
14  None = 0,
15 
19  Read = 1,
20 
24  Write = 2,
25 
29  List = 4,
30 
34  Delete = 8
35  }
36 }
ConfigurationRights
Rights for Models.ConfigurationFile
- - - - - -
User can read all chat settings except Models.Internal.ChatBot.ConnectionString
- - +Go to the documentation of this file.
1 using System;
2 
4 {
8  [Flags]
9  public enum ConfigurationRights : ulong
10  {
14  None = 0,
15 
19  Read = 1,
20 
24  Write = 2,
25 
29  List = 4,
30 
34  Delete = 8
35  }
36 }
ConfigurationRights
Rights for Models.ConfigurationFile
+ + + + +
User can read all chat settings except Models.Internal.ChatBot.ConnectionString
+
diff --git a/_configuration_test_8cs.html b/_configuration_test_8cs.html index 369ed5024a..6a3dd86256 100644 --- a/_configuration_test_8cs.html +++ b/_configuration_test_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Tests/Instance/ConfigurationTest.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Tests
 
namespace  Tgstation.Server.Tests.Instance
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_configuration_test_8cs_source.html b/_configuration_test_8cs_source.html index c4e78e34cc..5e680a4991 100644 --- a/_configuration_test_8cs_source.html +++ b/_configuration_test_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Tests/Instance/ConfigurationTest.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ConfigurationTest.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.IO;
4 using System.Text;
5 using System.Threading;
6 using System.Threading.Tasks;
10 
11 namespace Tgstation.Server.Tests.Instance
12 {
13  sealed class ConfigurationTest
14  {
16  readonly Api.Models.Instance instance;
17 
18  public ConfigurationTest(IConfigurationClient configurationClient, Api.Models.Instance instance)
19  {
20  this.configurationClient = configurationClient ?? throw new ArgumentNullException(nameof(configurationClient));
21  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
22  }
23 
25  {
26  var tmp = (file.Path?.StartsWith('/') ?? false) ? '.' + file.Path : file.Path;
27  var path = Path.Combine(instance.Path, "Configuration", tmp);
28  return File.Exists(path);
29  }
30 
31  async Task TestDeleteDirectory(CancellationToken cancellationToken)
32  {
33  //try to delete non-existent
34  var TestDir = new ConfigurationFile
35  {
36  Path = "/TestDeleteDir"
37  };
38 
39  await configurationClient.DeleteEmptyDirectory(TestDir, cancellationToken).ConfigureAwait(false);
40 
41  //try to delete non-empty
42  var file = await configurationClient.Write(new ConfigurationFile
43  {
44  Content = Encoding.UTF8.GetBytes("Hello world!"),
45  Path = TestDir.Path + "/test.txt"
46  }, cancellationToken).ConfigureAwait(false);
47 
48  Assert.IsTrue(FileExists(file));
49 
50  await Assert.ThrowsExceptionAsync<ConflictException>(() => configurationClient.DeleteEmptyDirectory(TestDir, cancellationToken)).ConfigureAwait(false);
51 
52  file.Content = null;
53  await configurationClient.Write(file, cancellationToken).ConfigureAwait(false);
54 
55  await configurationClient.DeleteEmptyDirectory(TestDir, cancellationToken).ConfigureAwait(false);
56  }
57 
58  public async Task Run(CancellationToken cancellationToken)
59  {
60  await TestDeleteDirectory(cancellationToken).ConfigureAwait(false);
61  }
62  }
63 }
- +Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.IO;
4 using System.Text;
5 using System.Threading;
6 using System.Threading.Tasks;
10 
12 {
13  sealed class ConfigurationTest
14  {
16  readonly Api.Models.Instance instance;
17 
19  {
20  this.configurationClient = configurationClient ?? throw new ArgumentNullException(nameof(configurationClient));
21  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
22  }
23 
25  {
26  var tmp = (file.Path?.StartsWith('/') ?? false) ? '.' + file.Path : file.Path;
27  var path = Path.Combine(instance.Path, "Configuration", tmp);
28  return File.Exists(path);
29  }
30 
31  async Task TestDeleteDirectory(CancellationToken cancellationToken)
32  {
33  //try to delete non-existent
34  var TestDir = new ConfigurationFile
35  {
36  Path = "/TestDeleteDir"
37  };
38 
39  await configurationClient.DeleteEmptyDirectory(TestDir, cancellationToken).ConfigureAwait(false);
40 
41  //try to delete non-empty
42  var file = await configurationClient.Write(new ConfigurationFile
43  {
44  Content = Encoding.UTF8.GetBytes("Hello world!"),
45  Path = TestDir.Path + "/test.txt"
46  }, cancellationToken).ConfigureAwait(false);
47 
48  Assert.IsTrue(FileExists(file));
49 
50  await Assert.ThrowsExceptionAsync<ConflictException>(() => configurationClient.DeleteEmptyDirectory(TestDir, cancellationToken)).ConfigureAwait(false);
51 
52  file.Content = null;
53  await configurationClient.Write(file, cancellationToken).ConfigureAwait(false);
54 
55  await configurationClient.DeleteEmptyDirectory(TestDir, cancellationToken).ConfigureAwait(false);
56  }
57 
58  public async Task Run(CancellationToken cancellationToken)
59  {
60  await TestDeleteDirectory(cancellationToken).ConfigureAwait(false);
61  }
62  }
63 }
Task< ConfigurationFile > Write(ConfigurationFile file, CancellationToken cancellationToken)
Overwrite a ConfigurationFile file
+ - -
string Path
The path to the ConfigurationFile file
+
string Path
The path to where the Instance is located. Can only be changed while the Instance is offline....
Definition: Instance.cs:26
+
string Path
The path to the ConfigurationFile file
async Task TestDeleteDirectory(CancellationToken cancellationToken)
+ +
Task DeleteEmptyDirectory(ConfigurationFile directory, CancellationToken cancellationToken)
Delete an empty directory
Represents a game configuration file. Create and delete actions uncerimonuously overwrite/delete file...
-
Occurs when the client performs an action that would result in data conflict
-
Metadata about a server instance
Definition: Instance.cs:9
- - +
Occurs when the client performs an action that would result in data conflict
+ +
ConfigurationTest(IConfigurationClient configurationClient, Api.Models.Instance instance)
async Task Run(CancellationToken cancellationToken)
- +
diff --git a/_configuration_type_8cs.html b/_configuration_type_8cs.html index efda222835..ea48b9330f 100644 --- a/_configuration_type_8cs.html +++ b/_configuration_type_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/ConfigurationType.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Api +  namespace  Tgstation.Server.Api.Models   @@ -108,8 +93,8 @@ Enumerations - + } +
enum  Tgstation.Server.Api.Models.ConfigurationType { Tgstation.Server.Api.Models.ConfigurationType.Disallowed, Tgstation.Server.Api.Models.ConfigurationType.HostWrite, Tgstation.Server.Api.Models.ConfigurationType.SystemIdentityWrite - }
 The type of configuration allowed on an Instance More...
 The type of configuration allowed on an Instance More...
 
@@ -117,7 +102,7 @@ Enumerations diff --git a/_configuration_type_8cs_source.html b/_configuration_type_8cs_source.html index c8d7809734..20da482701 100644 --- a/_configuration_type_8cs_source.html +++ b/_configuration_type_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/ConfigurationType.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
ConfigurationType.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Api.Models
2 {
6  public enum ConfigurationType
7  {
11  Disallowed,
12 
16  HostWrite,
17 
22  }
23 }
-
ConfigurationType
The type of configuration allowed on an Instance
- - -
Configuration editing is allowed by all users on all files
- +Go to the documentation of this file.
2 {
6  public enum ConfigurationType
7  {
11  Disallowed,
12 
16  HostWrite,
17 
22  }
23 }
ConfigurationType
The type of configuration allowed on an Instance
+ + + +
Configuration editing is allowed by all users on all files
diff --git a/_conflict_exception_8cs.html b/_conflict_exception_8cs.html index a5f44ec4f4..28925ffa7e 100644 --- a/_conflict_exception_8cs.html +++ b/_conflict_exception_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ConflictException.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_conflict_exception_8cs_source.html b/_conflict_exception_8cs_source.html index 40dd9210c0..f4b7476487 100644 --- a/_conflict_exception_8cs_source.html +++ b/_conflict_exception_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ConflictException.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ConflictException.cs
-Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
5 namespace Tgstation.Server.Client
6 {
10  public sealed class ConflictException : ClientException
11  {
17  public ConflictException(ErrorMessage errorMessage, HttpStatusCode statusCode) : base(errorMessage, statusCode)
18  { }
19 
23  public ConflictException() { }
24 
29  public ConflictException(string message) : base(message) { }
30 
36  public ConflictException(string message, Exception innerException) : base(message, innerException) { }
37  }
38 }
ConflictException()
Construct a ConflictException
-
ConflictException(string message, Exception innerException)
Construct an ConflictException with a message and innerException
+Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
6 {
10  public sealed class ConflictException : ClientException
11  {
17  public ConflictException(ErrorMessage errorMessage, HttpStatusCode statusCode) : base(errorMessage, statusCode)
18  { }
19 
23  public ConflictException() { }
24 
29  public ConflictException(string message) : base(message) { }
30 
36  public ConflictException(string message, Exception innerException) : base(message, innerException) { }
37  }
38 }
ConflictException()
Construct a ConflictException
+
ConflictException(string message, Exception innerException)
Construct an ConflictException with a message and innerException
-
ConflictException(string message)
Construct an ConflictException with a message
- - -
ConflictException(ErrorMessage errorMessage, HttpStatusCode statusCode)
Construct an ConflictException with a errorMessage and statusCode
+
ConflictException(string message)
Construct an ConflictException with a message
+ +
ConflictException(ErrorMessage errorMessage, HttpStatusCode statusCode)
Construct an ConflictException with a errorMessage and statusCode
-
Occurs when the client performs an action that would result in data conflict
- -
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- -
Exceptions thrown by IServerClients
+
Occurs when the client performs an action that would result in data conflict
+ +
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+ +
Exceptions thrown by IServerClients
diff --git a/_console_8cs.html b/_console_8cs.html index d0f341d5c6..f065598f73 100644 --- a/_console_8cs.html +++ b/_console_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/Console.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.IO
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_console_8cs_source.html b/_console_8cs_source.html index 210153ec50..726154c060 100644 --- a/_console_8cs_source.html +++ b/_console_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/Console.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
6 namespace Tgstation.Server.Host.IO
7 {
9  sealed class Console : IConsole
10  {
12  public bool Available => Environment.UserInteractive;
13 
15  {
16  if (!Available)
17  throw new InvalidOperationException("Console unavailable");
18  }
19 
21  public Task PressAnyKeyAsync(CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
22  {
23  CheckAvailable();
24  System.Console.Read();
25  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
26 
28  public Task<string> ReadLineAsync(bool usePasswordChar, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
29  {
30  // TODO: Make this better: https://stackoverflow.com/questions/9479573/how-to-interrupt-console-readline
31  CheckAvailable();
32  if (!usePasswordChar)
33  return System.Console.ReadLine();
34 
35  var passwordBuilder = new StringBuilder();
36  do
37  {
38  var keyDescription = System.Console.ReadKey(true);
39  if (keyDescription.Key == ConsoleKey.Enter)
40  break;
41  else if (keyDescription.Key == ConsoleKey.Backspace)
42  {
43  if (passwordBuilder.Length > 0)
44  {
45  --passwordBuilder.Length;
46  System.Console.Write("\b \b");
47  }
48  }
49  else if (keyDescription.KeyChar != '\u0000')
50  {
51  // KeyChar == '\u0000' if the key pressed does not correspond to a printable character, e.g. F1, Pause-Break, etc
52  passwordBuilder.Append(keyDescription.KeyChar);
53  System.Console.Write('*');
54  }
55  }
56  while (!cancellationToken.IsCancellationRequested);
57 
58  cancellationToken.ThrowIfCancellationRequested();
59  System.Console.WriteLine();
60  return passwordBuilder.ToString();
61  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
62 
64  public Task WriteAsync(string text, bool newLine, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
65  {
66  CheckAvailable();
67  if (text == null)
68  {
69  if (!newLine)
70  throw new InvalidOperationException("Cannot write null text without a new line!");
71  System.Console.WriteLine();
72  }
73  else if (newLine)
74  System.Console.WriteLine(text);
75  else
76  System.Console.Write(text);
77  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
78  }
79 }
+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
10  {
12  public bool Available => Environment.UserInteractive;
13 
15  {
16  if (!Available)
17  throw new InvalidOperationException("Console unavailable");
18  }
19 
21  public Task PressAnyKeyAsync(CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
22  {
24  System.Console.Read();
25  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
26 
28  public Task<string> ReadLineAsync(bool usePasswordChar, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
29  {
30  // TODO: Make this better: https://stackoverflow.com/questions/9479573/how-to-interrupt-console-readline
32  if (!usePasswordChar)
33  return System.Console.ReadLine();
34 
35  var passwordBuilder = new StringBuilder();
36  do
37  {
38  var keyDescription = System.Console.ReadKey(true);
39  if (keyDescription.Key == ConsoleKey.Enter)
40  break;
41  else if (keyDescription.Key == ConsoleKey.Backspace)
42  {
43  if (passwordBuilder.Length > 0)
44  {
45  --passwordBuilder.Length;
46  System.Console.Write("\b \b");
47  }
48  }
49  else if (keyDescription.KeyChar != '\u0000')
50  {
51  // KeyChar == '\u0000' if the key pressed does not correspond to a printable character, e.g. F1, Pause-Break, etc
52  passwordBuilder.Append(keyDescription.KeyChar);
53  System.Console.Write('*');
54  }
55  }
56  while (!cancellationToken.IsCancellationRequested);
57 
58  cancellationToken.ThrowIfCancellationRequested();
59  System.Console.WriteLine();
60  return passwordBuilder.ToString();
61  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
62 
64  public Task WriteAsync(string text, bool newLine, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
65  {
67  if (text == null)
68  {
69  if (!newLine)
70  throw new InvalidOperationException("Cannot write null text without a new line!");
71  System.Console.WriteLine();
72  }
73  else if (newLine)
74  System.Console.WriteLine(text);
75  else
76  System.Console.Write(text);
77  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
78  }
79 }
+ -
Abstraction for System.Console
Definition: IConsole.cs:9
- - - +
Abstraction for System.Console
Definition: IConsole.cs:9
+
Task PressAnyKeyAsync(CancellationToken cancellationToken)
Wait for a key press on the IConsole
+
Task< string > ReadLineAsync(bool usePasswordChar, CancellationToken cancellationToken)
Read a line from the IConsole
+
Task WriteAsync(string text, bool newLine, CancellationToken cancellationToken)
Write some text to the IConsole
+
diff --git a/_constants_8cs.html b/_constants_8cs.html index 23194ed624..d3507a8630 100644 --- a/_constants_8cs.html +++ b/_constants_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/Constants.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Components.Interop.ConstantsConstants used for communication with the DMAPI More...
Constants used for communication with the DMAPI More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Interop
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_constants_8cs_source.html b/_constants_8cs_source.html index 3fe3d1028f..c07b1ab609 100644 --- a/_constants_8cs_source.html +++ b/_constants_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/Constants.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Constants.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Host.Components.Interop
2 {
6  static class Constants
7  {
11  public const string DMParamHostVersion = "server_service_version";
12 
16  public const string DMParamInfoJson = "tgs_json";
17 
21  public const string DMInteropAccessIdentifier = "tgs_tok";
22 
26  public const string DMResponseSuccess = "tgs_succ";
27 
31  public const string DMTopicChangePort = "tgs_port";
32 
36  public const string DMTopicChangeReboot = "tgs_rmode";
37 
41  public const string DMTopicChatCommand = "tgs_chat_comm";
42 
46  public const string DMTopicEvent = "tgs_event";
47 
51  public const string DMTopicInteropResponse = "tgs_interop";
52 
56  public const string DMCommandNewPort = "tgs_new_port";
57 
61  public const string DMCommandApiValidate = "tgs_validate";
62 
66  public const string DMCommandServerPrimed = "tgs_prime";
67 
71  public const string DMCommandWorldReboot = "tgs_reboot";
72 
76  public const string DMCommandEndProcess = "tgs_kill";
77 
81  public const string DMCommandChat = "tgs_chat_send";
82 
86  public const string DMParameterCommand = "tgs_com";
87 
91  public const string DMParameterData = "tgs_data";
92  }
93 }
-
Constants used for communication with the DMAPI
Definition: Constants.cs:6
- +Go to the documentation of this file.
2 {
6  static class Constants
7  {
11  public const string DMParamHostVersion = "server_service_version";
12 
16  public const string DMParamInfoJson = "tgs_json";
17 
21  public const string DMInteropAccessIdentifier = "tgs_tok";
22 
26  public const string DMResponseSuccess = "tgs_succ";
27 
31  public const string DMTopicChangePort = "tgs_port";
32 
36  public const string DMTopicChangeReboot = "tgs_rmode";
37 
41  public const string DMTopicChatCommand = "tgs_chat_comm";
42 
46  public const string DMTopicEvent = "tgs_event";
47 
51  public const string DMTopicInteropResponse = "tgs_interop";
52 
56  public const string DMCommandNewPort = "tgs_new_port";
57 
61  public const string DMCommandApiValidate = "tgs_validate";
62 
66  public const string DMCommandServerPrimed = "tgs_prime";
67 
71  public const string DMCommandWorldReboot = "tgs_reboot";
72 
76  public const string DMCommandEndProcess = "tgs_kill";
77 
81  public const string DMCommandChat = "tgs_chat_send";
82 
86  public const string DMParameterCommand = "tgs_com";
87 
91  public const string DMParameterData = "tgs_data";
92  }
93 }
const string DMCommandWorldReboot
World reboot command
Definition: Constants.cs:71
+
const string DMParamInfoJson
Path to the JsonFile
Definition: Constants.cs:16
+ +
const string DMTopicEvent
Notify of an EventType
Definition: Constants.cs:46
+
const string DMCommandEndProcess
Terminate process command
Definition: Constants.cs:76
+
const string DMCommandApiValidate
API validation command
Definition: Constants.cs:61
+ +
const string DMTopicInteropResponse
Response to an interop export from DM
Definition: Constants.cs:51
+
const string DMCommandServerPrimed
Server primed command
Definition: Constants.cs:66
+ +
const string DMParamHostVersion
Identifies a TGS execution. The server version
Definition: Constants.cs:11
+
Constants used for communication with the DMAPI
Definition: Constants.cs:6
+ +
const string DMResponseSuccess
Generic OK response
Definition: Constants.cs:26
+
const string DMParameterCommand
Topic command parameter
Definition: Constants.cs:86
+
const string DMCommandNewPort
Set port command
Definition: Constants.cs:56
+
const string DMInteropAccessIdentifier
The JsonFile.AccessIdentifier
Definition: Constants.cs:21
+
const string DMTopicChangeReboot
Change reboot mode
Definition: Constants.cs:36
+
const string DMCommandChat
Chat send command
Definition: Constants.cs:81
diff --git a/_control_panel_configuration_8cs.html b/_control_panel_configuration_8cs.html index 14abbff295..5c53db7384 100644 --- a/_control_panel_configuration_8cs.html +++ b/_control_panel_configuration_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Configuration/ControlPanelConfiguration.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Configuration
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_control_panel_configuration_8cs_source.html b/_control_panel_configuration_8cs_source.html index 33291a8721..00db0cd026 100644 --- a/_control_panel_configuration_8cs_source.html +++ b/_control_panel_configuration_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Configuration/ControlPanelConfiguration.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ControlPanelConfiguration.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 
3 namespace Tgstation.Server.Host.Configuration
4 {
8  public sealed class ControlPanelConfiguration
9  {
13  public const string Section = "ControlPanel";
14 
18  public bool Enable { get; set; }
19 
23  public bool AllowAnyOrigin { get; set; }
24 
28  public List<string> AllowedOrigins { get; set; }
29  }
30 }
- - - +Go to the documentation of this file.
1 using System.Collections.Generic;
2 
4 {
8  public sealed class ControlPanelConfiguration
9  {
13  public const string Section = "ControlPanel";
14 
18  public bool Enable { get; set; }
19 
23  public bool AllowAnyOrigin { get; set; }
24 
28  public List<string> AllowedOrigins { get; set; }
29  }
30 }
List< string > AllowedOrigins
Origins allowed for CORS requests
+ +
bool AllowAnyOrigin
If any origin is allowed for CORS requests. This overrides AllowedOrigins
+
const string Section
The key for the Microsoft.Extensions.Configuration.IConfigurationSection the ControlPanelConfiguratio...
+ +
diff --git a/_credentials_provider_8cs.html b/_credentials_provider_8cs.html index fc7f9b1bf7..b9a19da021 100644 --- a/_credentials_provider_8cs.html +++ b/_credentials_provider_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Repository/CredentialsProvider.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Repository
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_credentials_provider_8cs_source.html b/_credentials_provider_8cs_source.html index 1688c419dc..976d507c29 100644 --- a/_credentials_provider_8cs_source.html +++ b/_credentials_provider_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Repository/CredentialsProvider.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
7 namespace Tgstation.Server.Host.Components.Repository
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 }
- -
CredentialsProvider(ILogger< CredentialsProvider > logger)
Construct a CredentialsProvider
+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
- - - - -
readonly ILogger< CredentialsProvider > logger
The ILogger for the CredentialsProvider
+ + + +
readonly ILogger< CredentialsProvider > logger
The ILogger for the CredentialsProvider
- -
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
- + +
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
+
diff --git a/_cryptography_suite_8cs.html b/_cryptography_suite_8cs.html index 72a52d6b8b..0ae1c5d2a0 100644 --- a/_cryptography_suite_8cs.html +++ b/_cryptography_suite_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/CryptographySuite.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_cryptography_suite_8cs_source.html b/_cryptography_suite_8cs_source.html index fe526757a7..665754f9fb 100644 --- a/_cryptography_suite_8cs_source.html +++ b/_cryptography_suite_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/CryptographySuite.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
CryptographySuite.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Identity;
2 using System;
3 using System.Globalization;
4 using System.Security.Cryptography;
6 
7 namespace Tgstation.Server.Host.Security
8 {
11  {
15  const uint SecureStringLength = 30;
16 
20  readonly IPasswordHasher<User> passwordHasher;
21 
26  public CryptographySuite(IPasswordHasher<User> passwordHasher)
27  {
28  this.passwordHasher = passwordHasher ?? throw new ArgumentNullException(nameof(passwordHasher));
29  }
30 
32  public byte[] GetSecureBytes(uint amount)
33  {
34  using (var rng = new RNGCryptoServiceProvider())
35  {
36  var byt = new byte[amount];
37  rng.GetBytes(byt);
38  return byt;
39  }
40  }
41 
43  public void SetUserPassword(User user, string newPassword, bool newUser)
44  {
45  if (user == null)
46  throw new ArgumentNullException(nameof(user));
47  if (newPassword == null)
48  throw new ArgumentNullException(nameof(newPassword));
49  user.PasswordHash = passwordHasher.HashPassword(user, newPassword);
50  if (!newUser)
51  user.LastPasswordUpdate = DateTimeOffset.Now;
52  }
53 
55  public bool CheckUserPassword(User user, string password)
56  {
57  var result = passwordHasher.VerifyHashedPassword(user, user.PasswordHash, password);
58  switch (result)
59  {
60  case PasswordVerificationResult.Failed:
61  return false;
62  case PasswordVerificationResult.SuccessRehashNeeded:
63  SetUserPassword(user, password, false);
64  break;
65  case PasswordVerificationResult.Success:
66  break;
67  default:
68  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Password hasher return unknown PasswordVerificationResult: {0}", result));
69  }
70 
71  return true;
72  }
73 
75  public string GetSecureString() => Convert.ToBase64String(GetSecureBytes(SecureStringLength));
76  }
77 }
string PasswordHash
The hash of the user&#39;s password
Definition: User.cs:13
- -
readonly IPasswordHasher< User > passwordHasher
The IPasswordHasher<TUser> for the CryptographySuite
+Go to the documentation of this file.
1 using Microsoft.AspNetCore.Identity;
2 using System;
3 using System.Globalization;
4 using System.Security.Cryptography;
6 
8 {
11  {
15  const uint SecureStringLength = 30;
16 
20  readonly IPasswordHasher<User> passwordHasher;
21 
26  public CryptographySuite(IPasswordHasher<User> passwordHasher)
27  {
28  this.passwordHasher = passwordHasher ?? throw new ArgumentNullException(nameof(passwordHasher));
29  }
30 
32  public byte[] GetSecureBytes(uint amount)
33  {
34  using (var rng = new RNGCryptoServiceProvider())
35  {
36  var byt = new byte[amount];
37  rng.GetBytes(byt);
38  return byt;
39  }
40  }
41 
43  public void SetUserPassword(User user, string newPassword, bool newUser)
44  {
45  if (user == null)
46  throw new ArgumentNullException(nameof(user));
47  if (newPassword == null)
48  throw new ArgumentNullException(nameof(newPassword));
49  user.PasswordHash = passwordHasher.HashPassword(user, newPassword);
50  if (!newUser)
51  user.LastPasswordUpdate = DateTimeOffset.Now;
52  }
53 
55  public bool CheckUserPassword(User user, string password)
56  {
57  var result = passwordHasher.VerifyHashedPassword(user, user.PasswordHash, password);
58  switch (result)
59  {
60  case PasswordVerificationResult.Failed:
61  return false;
62  case PasswordVerificationResult.SuccessRehashNeeded:
63  SetUserPassword(user, password, false);
64  break;
65  case PasswordVerificationResult.Success:
66  break;
67  default:
68  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Password hasher return unknown PasswordVerificationResult: {0}", result));
69  }
70 
71  return true;
72  }
73 
75  public string GetSecureString() => Convert.ToBase64String(GetSecureBytes(SecureStringLength));
76  }
77 }
string PasswordHash
The hash of the user's password
Definition: User.cs:13
+
string GetSecureString()
Generates a 40-length secure ascii string
+
readonly IPasswordHasher< User > passwordHasher
The IPasswordHasher<TUser> for the CryptographySuite
- -
DateTimeOffset LastPasswordUpdate
When PasswordHash was last changed
Definition: User.cs:29
-
void SetUserPassword(User user, string newPassword, bool newUser)
Sets a User.PasswordHash for a given user
-
Contains various cryptographic functions
+
void SetUserPassword(User user, string newPassword, bool newUser)
Sets a User.PasswordHash for a given user
+
Contains various cryptographic functions
-
bool CheckUserPassword(User user, string password)
Checks a given password matches a given user &#39;s User.PasswordHash. This may result in User...
- - -
byte[] GetSecureBytes(uint amount)
Generates a secure set of bytes
-
CryptographySuite(IPasswordHasher< User > passwordHasher)
Construct a CryptographySuite
- +
const uint SecureStringLength
Length in bytes of generated base64 secure string
+
DateTimeOffset? LastPasswordUpdate
When PasswordHash was last changed
Definition: User.cs:29
+ +
bool CheckUserPassword(User user, string password)
Checks a given password matches a given user 's User.PasswordHash. This may result in User....
+ + +
byte [] GetSecureBytes(uint amount)
Generates a secure set of bytes
+
CryptographySuite(IPasswordHasher< User > passwordHasher)
Construct a CryptographySuite
+
diff --git a/_custom_command_8cs.html b/_custom_command_8cs.html index 1f9a722e1e..5476910da7 100644 --- a/_custom_command_8cs.html +++ b/_custom_command_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/CustomCommand.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
namespace  Tgstation.Server.Host.Components.Chat.Commands
 
@@ -114,7 +103,7 @@ Namespaces diff --git a/_custom_command_8cs_source.html b/_custom_command_8cs_source.html index 409fa25217..0f44923aaf 100644 --- a/_custom_command_8cs_source.html +++ b/_custom_command_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/CustomCommand.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
CustomCommand.cs
-Go to the documentation of this file.
1 using Newtonsoft.Json;
2 using System;
3 using System.Threading;
4 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Host.Components.Chat.Commands
7 {
11  public sealed class CustomCommand : ICommand
12  {
14  public string Name { get; set; }
15 
17  public string HelpText { get; set; }
18 
20  [JsonConverter(typeof(BoolConverter))]
21  public bool AdminOnly { get; set; }
22 
27 
32  public void SetHandler(ICustomCommandHandler handler)
33  {
34  if (this.handler != null)
35  throw new InvalidOperationException("SetHandler() already called!");
36  this.handler = handler ?? throw new ArgumentNullException(nameof(handler));
37  }
38 
40  public Task<string> Invoke(string arguments, User user, CancellationToken cancellationToken)
41  {
42  if (handler == null)
43  throw new InvalidOperationException("SetHandler() has not been called!");
44  return handler.HandleChatCommand(Name, arguments, user, cancellationToken);
45  }
46  }
47 }
void SetHandler(ICustomCommandHandler handler)
Set a new handler
- - -
Task< string > Invoke(string arguments, User user, CancellationToken cancellationToken)
Invoke the ICommand
-
JsonConverter for decoding bools returned by BYOND
Definition: BoolConverter.cs:9
+Go to the documentation of this file.
1 using Newtonsoft.Json;
2 using System;
3 using System.Threading;
4 using System.Threading.Tasks;
5 
7 {
11  public sealed class CustomCommand : ICommand
12  {
14  public string Name { get; set; }
15 
17  public string HelpText { get; set; }
18 
20  [JsonConverter(typeof(BoolConverter))]
21  public bool AdminOnly { get; set; }
22 
27 
33  {
34  if (this.handler != null)
35  throw new InvalidOperationException("SetHandler() already called!");
36  this.handler = handler ?? throw new ArgumentNullException(nameof(handler));
37  }
38 
40  public Task<string> Invoke(string arguments, User user, CancellationToken cancellationToken)
41  {
42  if (handler == null)
43  throw new InvalidOperationException("SetHandler() has not been called!");
44  return handler.HandleChatCommand(Name, arguments, user, cancellationToken);
45  }
46  }
47 }
void SetHandler(ICustomCommandHandler handler)
Set a new handler
+ + +
Task< string > Invoke(string arguments, User user, CancellationToken cancellationToken)
Invoke the ICommand
+
JsonConverter for decoding bools returned by BYOND
Definition: BoolConverter.cs:9
- -
ICustomCommandHandler handler
The ICustomCommandHandler for the CustomCommand
-
Represents a tgs_chat_user datum
Definition: User.cs:10
-
Handles Commands.ICommands that map to those defined in a IJsonTrackingContext
-
Task< string > HandleChatCommand(string commandName, string arguments, User sender, CancellationToken cancellationToken)
Handle a chat command
-
Represents a command that can be invoked by talking to chat bots
Definition: ICommand.cs:9
- + + +
ICustomCommandHandler handler
The ICustomCommandHandler for the CustomCommand
+ +
Represents a tgs_chat_user datum
Definition: User.cs:10
+
Handles Commands.ICommands that map to those defined in a IJsonTrackingContext
+
Task< string > HandleChatCommand(string commandName, string arguments, User sender, CancellationToken cancellationToken)
Handle a chat command
+
Represents a command that can be invoked by talking to chat bots
Definition: ICommand.cs:9
diff --git a/_d_b_connection_factory_8cs.html b/_d_b_connection_factory_8cs.html index 708af11087..53f838f42d 100644 --- a/_d_b_connection_factory_8cs.html +++ b/_d_b_connection_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/DBConnectionFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_d_b_connection_factory_8cs_source.html b/_d_b_connection_factory_8cs_source.html index ff8f0539d1..4f1012e891 100644 --- a/_d_b_connection_factory_8cs_source.html +++ b/_d_b_connection_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/DBConnectionFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
8 namespace Tgstation.Server.Host.Core
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 }
- - +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
+ +
DbConnection CreateConnection(string connectionString, DatabaseType databaseType)
Create a DbConnection
-
DatabaseType
Type of database to user
Definition: DatabaseType.cs:6
- - - +
DatabaseType
Type of database to user
Definition: DatabaseType.cs:6
+ + +
diff --git a/_database_configuration_8cs.html b/_database_configuration_8cs.html index 3c0ea6e2bd..3973d1f548 100644 --- a/_database_configuration_8cs.html +++ b/_database_configuration_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Configuration/DatabaseConfiguration.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Configuration
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_database_configuration_8cs_source.html b/_database_configuration_8cs_source.html index 994bf50b8c..44b243e696 100644 --- a/_database_configuration_8cs_source.html +++ b/_database_configuration_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Configuration/DatabaseConfiguration.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
DatabaseConfiguration.cs
-Go to the documentation of this file.
1 using Newtonsoft.Json;
2 using Newtonsoft.Json.Converters;
3 
4 namespace Tgstation.Server.Host.Configuration
5 {
9  sealed class DatabaseConfiguration
10  {
14  public const string Section = "Database";
15 
19  [JsonConverter(typeof(StringEnumConverter))]
20  public DatabaseType DatabaseType { get; set; }
21 
25  public bool ResetAdminPassword { get; set; }
26 
30  public string ConnectionString { get; set; }
31 
35  public bool DropDatabase { get; set; }
36 
40  public string MySqlServerVersion { get; set; }
41  }
42 }
+Go to the documentation of this file.
1 using Newtonsoft.Json;
2 using Newtonsoft.Json.Converters;
3 
5 {
9  sealed class DatabaseConfiguration
10  {
14  public const string Section = "Database";
15 
19  [JsonConverter(typeof(StringEnumConverter))]
20  public DatabaseType DatabaseType { get; set; }
21 
25  public bool ResetAdminPassword { get; set; }
26 
30  public string ConnectionString { get; set; }
31 
35  public bool DropDatabase { get; set; }
36 
40  public string MySqlServerVersion { get; set; }
41  }
42 }
string ConnectionString
The connection string for the database
+
const string Section
The key for the Microsoft.Extensions.Configuration.IConfigurationSection the DatabaseConfiguration re...
- -
Configuration options for the Models.DatabaseContext<TParentContext>
-
DatabaseType
Type of database to user
Definition: DatabaseType.cs:6
- + +
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>
+
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/_database_context_8cs.html b/_database_context_8cs.html index c6ab7e33b6..38bc1cda8e 100644 --- a/_database_context_8cs.html +++ b/_database_context_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/DatabaseContext.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_database_context_8cs_source.html b/_database_context_8cs_source.html index e23a41d68c..8ff14299bd 100644 --- a/_database_context_8cs_source.html +++ b/_database_context_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/DatabaseContext.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
15 namespace Tgstation.Server.Host.Models
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 }
+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>
- + +
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
+
For initially seeding a database
+ +
DbSet< RevisionInformation > RevisionInformations
+
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
-
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&#39;s password reset
+
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 ...
-
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
+
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
-
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>
+ +
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>
- -
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>
+
Configuration options for the Models.DatabaseContext<TParentContext>
+
DbSet< RevInfoTestMerge > RevInfoTestMerges
The RevInfoTestMerges om the 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>
- - + + +
Task SeedDatabase(IDatabaseContext databaseContext, CancellationToken cancellationToken)
Initially seed a given databaseContext
+ @@ -130,7 +124,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_database_context_factory_8cs.html b/_database_context_factory_8cs.html index f62a6b31d3..695e55f26f 100644 --- a/_database_context_factory_8cs.html +++ b/_database_context_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/DatabaseContextFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_database_context_factory_8cs_source.html b/_database_context_factory_8cs_source.html index cd109556f1..e4113ae7f8 100644 --- a/_database_context_factory_8cs_source.html +++ b/_database_context_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/DatabaseContextFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
DatabaseContextFactory.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.DependencyInjection;
2 using System;
3 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Host.Core
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 }
- +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
- - +
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
+ +
diff --git a/_database_seeder_8cs.html b/_database_seeder_8cs.html index b5c1ed5fe5..502b140e4f 100644 --- a/_database_seeder_8cs.html +++ b/_database_seeder_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/DatabaseSeeder.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_database_seeder_8cs_source.html b/_database_seeder_8cs_source.html index a9694cc313..92091faef5 100644 --- a/_database_seeder_8cs_source.html +++ b/_database_seeder_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/DatabaseSeeder.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
9 namespace Tgstation.Server.Host.Models
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&#39;s default and enables the account ...
+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>
- -
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
- -
For initially seeding a database
-
DbSet< User > Users
The Users in the IDatabaseContext
-
AdministrationRights
Rights for Models.Administration
-
async Task SeedDatabase(IDatabaseContext databaseContext, CancellationToken cancellationToken)
Initially seed a given databaseContext
-
Contains various cryptographic functions
+
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
+
AdministrationRights
Rights for Models.Administration
+
async Task SeedDatabase(IDatabaseContext databaseContext, CancellationToken cancellationToken)
Initially seed a given databaseContext
+
Contains various cryptographic functions
-
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
+
InstanceManagerRights
Rights for managing Models.Instances
+
void SeedAdminUser(IDatabaseContext databaseContext)
Add a default admin User to a given databaseContext
+
void SetUserPassword(User user, string newPassword, bool newUser)
Sets a User.PasswordHash for a given user
- - - + + +
diff --git a/_database_type_8cs.html b/_database_type_8cs.html index 9c421a7fbf..60de80e18b 100644 --- a/_database_type_8cs.html +++ b/_database_type_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Configuration/DatabaseType.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Host +  namespace  Tgstation.Server.Host.Configuration   @@ -108,8 +93,8 @@ Enumerations - + } +
enum  Tgstation.Server.Host.Configuration.DatabaseType { Tgstation.Server.Host.Configuration.DatabaseType.SqlServer, Tgstation.Server.Host.Configuration.DatabaseType.MySql, Tgstation.Server.Host.Configuration.DatabaseType.MariaDB - }
 Type of database to user More...
 Type of database to user More...
 
@@ -117,7 +102,7 @@ Enumerations diff --git a/_database_type_8cs_source.html b/_database_type_8cs_source.html index c1cec12924..6ecc38f08f 100644 --- a/_database_type_8cs_source.html +++ b/_database_type_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Configuration/DatabaseType.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
DatabaseType.cs
-Go to the documentation of this file. diff --git a/_dead_session_controller_8cs.html b/_dead_session_controller_8cs.html index 30fb0716d3..3b745cf670 100644 --- a/_dead_session_controller_8cs.html +++ b/_dead_session_controller_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/DeadSessionController.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Components.Watchdog.DeadSessionController - Implements a fake "dead" ISessionController More...
+ Implements a fake "dead" ISessionController More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Watchdog
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_dead_session_controller_8cs_source.html b/_dead_session_controller_8cs_source.html index 74712de446..684de69c70 100644 --- a/_dead_session_controller_8cs_source.html +++ b/_dead_session_controller_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/DeadSessionController.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
DeadSessionController.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
5 namespace Tgstation.Server.Host.Components.Watchdog
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 }
Represents the result of trying to start a DD process
Definition: LaunchResult.cs:9
- - -
Handles communication with a DreamDaemon IProcess
- +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 }
+ + +
Represents the result of trying to start a DD process
Definition: LaunchResult.cs:9
+ +
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
+
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
+ +
Task< bool > SetRebootState(RebootState newRebootState, CancellationToken cancellationToken)
Attempts to change the current RebootState to newRebootState
+ -
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
- -
ApiValidationStatus
Status of DMAPI validation
+
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
+
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
+
Parameters necessary for duplicating a ISessionController session
+
ApiValidationStatus
Status of DMAPI validation
diff --git a/_default_i_o_manager_8cs.html b/_default_i_o_manager_8cs.html index 62586b1c0b..6fe39afd63 100644 --- a/_default_i_o_manager_8cs.html +++ b/_default_i_o_manager_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/DefaultIOManager.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.IO.DefaultIOManagerIIOManager that resolves paths to Environment.CurrentDirectory More...
IIOManager that resolves paths to Environment.CurrentDirectory More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.IO
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_default_i_o_manager_8cs_source.html b/_default_i_o_manager_8cs_source.html index e1630b9f80..035aa9edf1 100644 --- a/_default_i_o_manager_8cs_source.html +++ b/_default_i_o_manager_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/DefaultIOManager.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
11 namespace Tgstation.Server.Host.IO
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
- -
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
- -
static async Task NormalizeAndDelete(DirectoryInfo dir, CancellationToken cancellationToken)
Recursively empty a directory
-
async Task CopyDirectory(string src, string dest, IEnumerable< string > ignore, CancellationToken cancellationToken)
Copies a directory from src to dest
-
async Task< byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
Returns all the contents of a file at path as a byte array
-
IEnumerable< Task > CopyDirectoryImpl(string src, string dest, IEnumerable< string > ignore, CancellationToken cancellationToken)
Copies a directory from src to dest
-
async Task< byte[]> DownloadFile(Uri url, CancellationToken cancellationToken)
Downloads a file from url
-
IIOManager that resolves paths to Environment.CurrentDirectory
-
Interface for using filesystems
Definition: IIOManager.cs:11
- +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
+
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
+
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
+
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
+
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
+
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
+
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
+
static FileStream OpenWriteStream(string path)
Opens a FileStream for async writing at a given path
+
Task< IReadOnlyList< string > > GetDirectories(string path, CancellationToken cancellationToken)
Returns directory names in a given path
+
Task DeleteFile(string path, CancellationToken cancellationToken)
Deletes a file at path
+
virtual string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
+
Interface for using filesystems
Definition: IIOManager.cs:11
+
const int DefaultBufferSize
Default FileStream buffer size used by .NET
+
bool PathContainsParentAccess(string path)
Check if a path contains the '..' parent directory accessor
+
Task CreateDirectory(string path, CancellationToken cancellationToken)
Create a directory at path
+
string GetFileName(string path)
Gets the file name portion of a path
+
diff --git a/_design_time_db_context_factory_helpers_8cs.html b/_design_time_db_context_factory_helpers_8cs.html index 3bb322f2fc..b0e9596729 100644 --- a/_design_time_db_context_factory_helpers_8cs.html +++ b/_design_time_db_context_factory_helpers_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/DesignTimeDbContextFactoryHelpers.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

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

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_design_time_db_context_factory_helpers_8cs_source.html b/_design_time_db_context_factory_helpers_8cs_source.html index 583948d304..d6266e9900 100644 --- a/_design_time_db_context_factory_helpers_8cs_source.html +++ b/_design_time_db_context_factory_helpers_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/DesignTimeDbContextFactoryHelpers.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
DesignTimeDbContextFactoryHelpers.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Configuration;
2 using Microsoft.Extensions.Options;
3 using System.IO;
4 using System.Reflection;
6 
7 namespace Tgstation.Server.Host.Models.Migrations
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  builder.SetBasePath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
32  builder.AddJsonFile(RootJson);
33  builder.AddJsonFile(DevJson);
34  var configuration = builder.Build();
35  return Options.Create(configuration.GetSection(DatabaseConfiguration.Section).Get<DatabaseConfiguration>());
36  }
37  }
38 }
static IOptions< DatabaseConfiguration > GetDbContextOptions()
Get the IOptions<TOptions> for the DatabaseConfiguration
- - -
Contains helpers for creating design time Models.DatabaseContext<TParentContext>s ...
+Go to the documentation of this file.
1 using Microsoft.Extensions.Configuration;
2 using Microsoft.Extensions.Options;
3 using System.IO;
4 using System.Reflection;
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  builder.SetBasePath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
32  builder.AddJsonFile(RootJson);
33  builder.AddJsonFile(DevJson);
34  var configuration = builder.Build();
35  return Options.Create(configuration.GetSection(DatabaseConfiguration.Section).Get<DatabaseConfiguration>());
36  }
37  }
38 }
static IOptions< DatabaseConfiguration > GetDbContextOptions()
Get the IOptions<TOptions> for the DatabaseConfiguration
+ +
Contains helpers for creating design time DatabaseContext<TParentContext>s
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 Models.DatabaseContext<TParentContext>
+ +
const string RootJson
Path to the json file to use for migrations configuration
+ +
diff --git a/_discord_connection_string_builder_8cs.html b/_discord_connection_string_builder_8cs.html index 2a40612ebd..aad75c6773 100644 --- a/_discord_connection_string_builder_8cs.html +++ b/_discord_connection_string_builder_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/DiscordConnectionStringBuilder.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Api.Models.DiscordConnectionStringBuilder - ChatConnectionStringBuilder for ChatProvider.Discord More...
+ ChatConnectionStringBuilder for ChatProvider.Discord More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_discord_connection_string_builder_8cs_source.html b/_discord_connection_string_builder_8cs_source.html index 7816f62480..401a2803ff 100644 --- a/_discord_connection_string_builder_8cs_source.html +++ b/_discord_connection_string_builder_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/DiscordConnectionStringBuilder.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
DiscordConnectionStringBuilder.cs
-Go to the documentation of this file.
1 using System;
3 
4 namespace Tgstation.Server.Api.Models
5 {
10  {
12  public override bool Valid => !String.IsNullOrEmpty(BotToken);
13 
18  public string BotToken { get; set; }
19 
24 
29  public DiscordConnectionStringBuilder(string connectionString)
30  {
31  BotToken = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
32  }
33 
35  public override string ToString() => BotToken;
36  }
37 }
- - -
ChatConnectionStringBuilder for ChatProvider.Discord
+Go to the documentation of this file.
1 using System;
3 
5 {
10  {
12  public override bool Valid => !String.IsNullOrEmpty(BotToken);
13 
18  public string BotToken { get; set; }
19 
24 
29  public DiscordConnectionStringBuilder(string connectionString)
30  {
31  BotToken = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
32  }
33 
35  public override string ToString() => BotToken;
36  }
37 }
+
ChatConnectionStringBuilder for ChatProvider.Discord
- -
DiscordConnectionStringBuilder(string connectionString)
Construct a DiscordConnectionStringBuilder from a connectionString
- -
DiscordConnectionStringBuilder()
Construct a DiscordConnectionStringBuilder
- - +
override string ToString()
Gets the ChatBot.ConnectionString associated with the ChatConnectionStringBuilder
+ +
DiscordConnectionStringBuilder(string connectionString)
Construct a DiscordConnectionStringBuilder from a connectionString
+ +
DiscordConnectionStringBuilder()
Construct a DiscordConnectionStringBuilder
+ + + +
diff --git a/_discord_provider_8cs.html b/_discord_provider_8cs.html index d72ad4a6d7..8bd00063ac 100644 --- a/_discord_provider_8cs.html +++ b/_discord_provider_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Components.Chat.Providers.DiscordProviderIProvider for the Discord app More...
IProvider for the Discord app More...
  + + + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
namespace  Tgstation.Server.Host.Components.Chat.Providers
 
@@ -114,7 +103,7 @@ Namespaces diff --git a/_discord_provider_8cs_source.html b/_discord_provider_8cs_source.html index 3c12c381f3..afcffe85f8 100644 --- a/_discord_provider_8cs_source.html +++ b/_discord_provider_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Providers/DiscordProvider.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
DiscordProvider.cs
-Go to the documentation of this file.
1 using Discord;
2 using Discord.WebSocket;
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 
11 namespace Tgstation.Server.Host.Components.Chat.Providers
12 {
16  sealed class DiscordProvider : Provider
17  {
19  public override bool Connected => client.ConnectionState == ConnectionState.Connected;
20 
22  public override string BotMention
23  {
24  get
25  {
26  if (!Connected)
27  throw new InvalidOperationException("Provider not connected");
28  return NormalizeMention(client.CurrentUser.Mention);
29  }
30  }
31 
35  readonly ILogger<DiscordProvider> logger;
36 
40  readonly DiscordSocketClient client;
41 
45  readonly string botToken;
46 
50  readonly List<ulong> mappedChannels;
51 
57  static string NormalizeMention(string fromDiscord) => fromDiscord.Replace("!", String.Empty, StringComparison.Ordinal);
58 
64  public DiscordProvider(ILogger<DiscordProvider> logger, string botToken)
65  {
66  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
67  this.botToken = botToken ?? throw new ArgumentNullException(nameof(botToken));
68  client = new DiscordSocketClient();
69  client.MessageReceived += Client_MessageReceived;
70  mappedChannels = new List<ulong>();
71  logger.LogTrace("Created.");
72  }
73 
75  public override void Dispose()
76  {
77  logger.LogTrace("Disposed.");
78  client.Dispose();
79  }
80 
86  async Task Client_MessageReceived(SocketMessage e)
87  {
88  if (e.Author.Id == client.CurrentUser.Id)
89  return;
90 
91  var pm = e.Channel is IPrivateChannel;
92 
93  if (!pm && !mappedChannels.Contains(e.Channel.Id))
94  {
95  var mentionedUs = e.MentionedUsers.Any(x => x.Id == client.CurrentUser.Id);
96  if (mentionedUs)
97  {
98  logger.LogTrace("Ignoring mention from {0} ({1}) by {2} ({3}). Channel not mapped!", e.Channel.Id, e.Channel.Name, e.Author.Id, e.Author.Username);
99  await SendMessage(e.Channel.Id, "I do not respond to this channel!", default).ConfigureAwait(false);
100  }
101 
102  return;
103  }
104 
105  var result = new Message
106  {
107  Content = e.Content,
108  User = new User
109  {
110  RealId = e.Author.Id,
111  Channel = new Channel
112  {
113  RealId = e.Channel.Id,
114  IsPrivateChannel = pm,
115  ConnectionName = pm ? e.Author.Username : (e.Channel as ITextChannel)?.Guild.Name ?? "UNKNOWN",
116  FriendlyName = e.Channel.Name
117 
118  // isAdmin and Tag populated by manager
119  },
120  FriendlyName = e.Author.Username,
121  Mention = NormalizeMention(e.Author.Mention)
122  }
123  };
124  EnqueueMessage(result);
125  }
126 
128  public override async Task<bool> Connect(CancellationToken cancellationToken)
129  {
130  logger.LogTrace("Connecting...");
131  if (Connected)
132  {
133  logger.LogTrace("Already connected not doing connection attempt!");
134  return true;
135  }
136 
137  try
138  {
139  await client.LoginAsync(TokenType.Bot, botToken, true).ConfigureAwait(false);
140 
141  logger.LogTrace("Logged in.");
142  cancellationToken.ThrowIfCancellationRequested();
143 
144  await client.StartAsync().ConfigureAwait(false);
145 
146  logger.LogTrace("Started.");
147 
148  var channelsAvailable = new TaskCompletionSource<object>();
149  client.Ready += () =>
150  {
151  channelsAvailable.TrySetResult(null);
152  return Task.CompletedTask;
153  };
154  using (cancellationToken.Register(() => channelsAvailable.SetCanceled()))
155  await channelsAvailable.Task.ConfigureAwait(false);
156  logger.LogDebug("Connection established!");
157  }
158  catch (OperationCanceledException)
159  {
160  throw;
161  }
162  catch (Exception e)
163  {
164  logger.LogWarning("Error connecting to Discord: {0}", e);
165  return false;
166  }
167 
168  return true;
169  }
170 
172  public override async Task Disconnect(CancellationToken cancellationToken)
173  {
174  logger.LogTrace("Disconnecting...");
175  if (!Connected)
176  {
177  logger.LogTrace("Already disconnected not doing disconnection attempt!");
178  return;
179  }
180 
181  try
182  {
183  await client.StopAsync().ConfigureAwait(false);
184  logger.LogTrace("Stopped.");
185  cancellationToken.ThrowIfCancellationRequested();
186  await client.LogoutAsync().ConfigureAwait(false);
187  logger.LogDebug("Disconnected!");
188  }
189  catch (OperationCanceledException)
190  {
191  throw;
192  }
193  catch (Exception e)
194  {
195  logger.LogWarning("Error disconnecting from discord: {0}", e);
196  }
197  }
198 
200  public override Task<IReadOnlyList<Channel>> MapChannels(IEnumerable<ChatChannel> channels, CancellationToken cancellationToken)
201  {
202  if (channels == null)
203  throw new ArgumentNullException(nameof(channels));
204 
205  if (!Connected)
206  throw new InvalidOperationException("Provider not connected!");
207 
208  Channel GetModelChannelFromDBChannel(ChatChannel channelFromDB)
209  {
210  if (!channelFromDB.DiscordChannelId.HasValue)
211  throw new InvalidOperationException("ChatChannel missing DiscordChannelId!");
212 
213  var channelId = channelFromDB.DiscordChannelId.Value;
214  var discordChannel = client.GetChannel(channelId);
215  if (discordChannel is ITextChannel textChannel)
216  {
217  var channelModel = new Channel
218  {
219  RealId = discordChannel.Id,
220  IsAdminChannel = channelFromDB.IsAdminChannel == true,
221  ConnectionName = textChannel.Guild.Name,
222  FriendlyName = textChannel.Name,
223  IsPrivateChannel = false,
224  Tag = channelFromDB.Tag
225  };
226  logger.LogTrace("Mapped channel {0}: {1}", channelModel.RealId, channelModel.FriendlyName);
227  return channelModel;
228  }
229 
230  logger.LogWarning("Cound not map channel {0}! Incorrect type: {1}", channelId, discordChannel.GetType());
231  return null;
232  }
233 
234  var enumerator = channels.Select(x => GetModelChannelFromDBChannel(x)).Where(x => x != null).ToList();
235 
236  lock (this)
237  {
238  mappedChannels.Clear();
239  mappedChannels.AddRange(enumerator.Select(x => x.RealId));
240  }
241 
242  return Task.FromResult<IReadOnlyList<Channel>>(enumerator);
243  }
244 
246  public override async Task SendMessage(ulong channelId, string message, CancellationToken cancellationToken)
247  {
248  try
249  {
250  var channel = client.GetChannel(channelId) as IMessageChannel;
251  await (channel?.SendMessageAsync(message, false, null, new RequestOptions
252  {
253  CancelToken = cancellationToken
254  }) ?? Task.CompletedTask).ConfigureAwait(false);
255  }
256  catch (OperationCanceledException)
257  {
258  throw;
259  }
260  catch (Exception e)
261  {
262  logger.LogWarning("Error sending discord message: {0}", e);
263  }
264  }
265  }
266 }
async Task Client_MessageReceived(SocketMessage e)
Handle a message recieved from Discord
+Go to the documentation of this file.
1 using Discord;
2 using Discord.WebSocket;
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 
12 {
16  sealed class DiscordProvider : Provider
17  {
19  public override bool Connected => client.ConnectionState == ConnectionState.Connected;
20 
22  public override string BotMention
23  {
24  get
25  {
26  if (!Connected)
27  throw new InvalidOperationException("Provider not connected");
28  return NormalizeMention(client.CurrentUser.Mention);
29  }
30  }
31 
35  readonly ILogger<DiscordProvider> logger;
36 
40  readonly DiscordSocketClient client;
41 
45  readonly string botToken;
46 
50  readonly List<ulong> mappedChannels;
51 
57  static string NormalizeMention(string fromDiscord) => fromDiscord.Replace("!", String.Empty, StringComparison.Ordinal);
58 
64  public DiscordProvider(ILogger<DiscordProvider> logger, string botToken)
65  {
66  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
67  this.botToken = botToken ?? throw new ArgumentNullException(nameof(botToken));
68  client = new DiscordSocketClient();
69  client.MessageReceived += Client_MessageReceived;
70  mappedChannels = new List<ulong>();
71  logger.LogTrace("Created.");
72  }
73 
75  public override void Dispose()
76  {
77  logger.LogTrace("Disposed.");
78  client.Dispose();
79  }
80 
86  async Task Client_MessageReceived(SocketMessage e)
87  {
88  if (e.Author.Id == client.CurrentUser.Id)
89  return;
90 
91  var pm = e.Channel is IPrivateChannel;
92 
93  if (!pm && !mappedChannels.Contains(e.Channel.Id))
94  {
95  var mentionedUs = e.MentionedUsers.Any(x => x.Id == client.CurrentUser.Id);
96  if (mentionedUs)
97  {
98  logger.LogTrace("Ignoring mention from {0} ({1}) by {2} ({3}). Channel not mapped!", e.Channel.Id, e.Channel.Name, e.Author.Id, e.Author.Username);
99  await SendMessage(e.Channel.Id, "I do not respond to this channel!", default).ConfigureAwait(false);
100  }
101 
102  return;
103  }
104 
105  var result = new Message
106  {
107  Content = e.Content,
108  User = new User
109  {
110  RealId = e.Author.Id,
111  Channel = new Channel
112  {
113  RealId = e.Channel.Id,
114  IsPrivateChannel = pm,
115  ConnectionName = pm ? e.Author.Username : (e.Channel as ITextChannel)?.Guild.Name ?? "UNKNOWN",
116  FriendlyName = e.Channel.Name
117 
118  // isAdmin and Tag populated by manager
119  },
120  FriendlyName = e.Author.Username,
121  Mention = NormalizeMention(e.Author.Mention)
122  }
123  };
124  EnqueueMessage(result);
125  }
126 
128  public override async Task<bool> Connect(CancellationToken cancellationToken)
129  {
130  logger.LogTrace("Connecting...");
131  if (Connected)
132  {
133  logger.LogTrace("Already connected not doing connection attempt!");
134  return true;
135  }
136 
137  try
138  {
139  await client.LoginAsync(TokenType.Bot, botToken, true).ConfigureAwait(false);
140 
141  logger.LogTrace("Logged in.");
142  cancellationToken.ThrowIfCancellationRequested();
143 
144  await client.StartAsync().ConfigureAwait(false);
145 
146  logger.LogTrace("Started.");
147 
148  var channelsAvailable = new TaskCompletionSource<object>();
149  client.Ready += () =>
150  {
151  channelsAvailable.TrySetResult(null);
152  return Task.CompletedTask;
153  };
154  using (cancellationToken.Register(() => channelsAvailable.SetCanceled()))
155  await channelsAvailable.Task.ConfigureAwait(false);
156  logger.LogDebug("Connection established!");
157  }
158  catch (OperationCanceledException)
159  {
160  throw;
161  }
162  catch (Exception e)
163  {
164  logger.LogWarning("Error connecting to Discord: {0}", e);
165  return false;
166  }
167 
168  return true;
169  }
170 
172  public override async Task Disconnect(CancellationToken cancellationToken)
173  {
174  logger.LogTrace("Disconnecting...");
175  if (!Connected)
176  {
177  logger.LogTrace("Already disconnected not doing disconnection attempt!");
178  return;
179  }
180 
181  try
182  {
183  await client.StopAsync().ConfigureAwait(false);
184  logger.LogTrace("Stopped.");
185  cancellationToken.ThrowIfCancellationRequested();
186  await client.LogoutAsync().ConfigureAwait(false);
187  logger.LogDebug("Disconnected!");
188  }
189  catch (OperationCanceledException)
190  {
191  throw;
192  }
193  catch (Exception e)
194  {
195  logger.LogWarning("Error disconnecting from discord: {0}", e);
196  }
197  }
198 
200  public override Task<IReadOnlyList<Channel>> MapChannels(IEnumerable<ChatChannel> channels, CancellationToken cancellationToken)
201  {
202  if (channels == null)
203  throw new ArgumentNullException(nameof(channels));
204 
205  if (!Connected)
206  throw new InvalidOperationException("Provider not connected!");
207 
208  Channel GetModelChannelFromDBChannel(ChatChannel channelFromDB)
209  {
210  if (!channelFromDB.DiscordChannelId.HasValue)
211  throw new InvalidOperationException("ChatChannel missing DiscordChannelId!");
212 
213  var channelId = channelFromDB.DiscordChannelId.Value;
214  var discordChannel = client.GetChannel(channelId);
215  if (discordChannel is ITextChannel textChannel)
216  {
217  var channelModel = new Channel
218  {
219  RealId = discordChannel.Id,
220  IsAdminChannel = channelFromDB.IsAdminChannel == true,
221  ConnectionName = textChannel.Guild.Name,
222  FriendlyName = textChannel.Name,
223  IsPrivateChannel = false,
224  Tag = channelFromDB.Tag
225  };
226  logger.LogTrace("Mapped channel {0}: {1}", channelModel.RealId, channelModel.FriendlyName);
227  return channelModel;
228  }
229 
230  logger.LogWarning("Cound not map channel {0}! Incorrect type: {1}", channelId, discordChannel.GetType());
231  return null;
232  }
233 
234  var enumerator = channels.Select(x => GetModelChannelFromDBChannel(x)).Where(x => x != null).ToList();
235 
236  lock (this)
237  {
238  mappedChannels.Clear();
239  mappedChannels.AddRange(enumerator.Select(x => x.RealId));
240  }
241 
242  return Task.FromResult<IReadOnlyList<Channel>>(enumerator);
243  }
244 
246  public override async Task SendMessage(ulong channelId, string message, CancellationToken cancellationToken)
247  {
248  try
249  {
250  var channel = client.GetChannel(channelId) as IMessageChannel;
251  await (channel?.SendMessageAsync(message, false, null, new RequestOptions
252  {
253  CancelToken = cancellationToken
254  }) ?? Task.CompletedTask).ConfigureAwait(false);
255  }
256  catch (OperationCanceledException)
257  {
258  throw;
259  }
260  catch (Exception e)
261  {
262  logger.LogWarning("Error sending discord message: {0}", e);
263  }
264  }
265  }
266 }
+
async Task Client_MessageReceived(SocketMessage e)
Handle a message recieved from Discord
-
Indicates a chat channel
Definition: ChatChannel.cs:8
+ - - -
override async Task SendMessage(ulong channelId, string message, CancellationToken cancellationToken)
Send a message to the IProvider
- + +
override async Task SendMessage(ulong channelId, string message, CancellationToken cancellationToken)
Send a message to the IProvider
override Task< IReadOnlyList< Channel > > MapChannels(IEnumerable< ChatChannel > channels, CancellationToken cancellationToken)
-
Represents a message recieved by a IProvider
Definition: Message.cs:6
-
override async Task Disconnect(CancellationToken cancellationToken)
Gracefully disconnects the provider. Implies a call to IDisposable.Dispose
- -
override async Task< bool > Connect(CancellationToken cancellationToken)
Attempt to connect the IProvider
-
readonly ILogger< DiscordProvider > logger
The ILogger for the DiscordProvider
+
Represents a message recieved by a IProvider
Definition: Message.cs:6
+ +
override async Task Disconnect(CancellationToken cancellationToken)
Gracefully disconnects the provider. Implies a call to IDisposable.Dispose
+ + +
override async Task< bool > Connect(CancellationToken cancellationToken)
Attempt to connect the IProvider
+
readonly ILogger< DiscordProvider > logger
The ILogger for the DiscordProvider
-
readonly string botToken
The token used for connecting to discord
-
readonly DiscordSocketClient client
The DiscordSocketClient for the DiscordProvider
-
string Tag
A custom tag users can define to group channels together
Definition: ChatChannel.cs:41
-
DiscordProvider(ILogger< DiscordProvider > logger, string botToken)
Construct a DiscordProvider
-
Represents a Providers.IProvider channel
Definition: Channel.cs:10
-
string Id
Backing field for RealId. Represented as a string to avoid BYOND percision loss
Definition: Channel.cs:15
-
readonly List< ulong > mappedChannels
List<T> of mapped ITextChannel IEntity<TId>.Ids
- -
Represents a tgs_chat_user datum
Definition: User.cs:10
-
ulong DiscordChannelId
The Discord channel ID
Definition: ChatChannel.cs:18
- -
string Id
Backing field for RealId. Represented as a string to avoid BYOND percision loss
Definition: User.cs:15
-
bool IsAdminChannel
If the ChatChannel is an admin channel
Definition: ChatChannel.cs:24
- - +
readonly string botToken
The token used for connecting to discord
+
static string NormalizeMention(string fromDiscord)
Normalize a discord mention string
+
readonly DiscordSocketClient client
The DiscordSocketClient for the DiscordProvider
+
string Tag
A custom tag users can define to group channels together
Definition: ChatChannel.cs:41
+
bool? IsAdminChannel
If the ChatChannel is an admin channel
Definition: ChatChannel.cs:24
+
ulong? DiscordChannelId
The Discord channel ID
Definition: ChatChannel.cs:18
+
DiscordProvider(ILogger< DiscordProvider > logger, string botToken)
Construct a DiscordProvider
+
Represents a Providers.IProvider channel
Definition: Channel.cs:10
+
string Id
Backing field for RealId. Represented as a string to avoid BYOND percision loss
Definition: Channel.cs:15
+
readonly List< ulong > mappedChannels
List<T> of mapped ITextChannel IEntity<TId>.Ids
+
Represents a tgs_chat_user datum
Definition: User.cs:10
+ + +
string Id
Backing field for RealId. Represented as a string to avoid BYOND percision loss
Definition: User.cs:15
+
void EnqueueMessage(Message message)
Queues a message for NextMessage(CancellationToken)
Definition: Provider.cs:40
+
diff --git a/_dmb_factory_8cs.html b/_dmb_factory_8cs.html index e282bb6b7f..fa127f4c53 100644 --- a/_dmb_factory_8cs.html +++ b/_dmb_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Compiler/DmbFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

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

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Compiler
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_dmb_factory_8cs_source.html b/_dmb_factory_8cs_source.html index 82850af684..69442c79bf 100644 --- a/_dmb_factory_8cs_source.html +++ b/_dmb_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Compiler/DmbFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
12 namespace Tgstation.Server.Host.Components.Compiler
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 
61 
65  TaskCompletionSource<object> newerDmbTcs;
66 
71 
72  Dictionary<long, int> jobLockCounts;
73 
81  public DmbFactory(IDatabaseContextFactory databaseContextFactory, IIOManager ioManager, ILogger<DmbFactory> logger, Api.Models.Instance instance)
82  {
83  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
84  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
85  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
86  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
87 
88  cleanupTask = Task.CompletedTask;
89  newerDmbTcs = new TaskCompletionSource<object>();
90  cleanupCts = new CancellationTokenSource();
91  jobLockCounts = new Dictionary<long, int>();
92  }
93 
95  public void Dispose() => cleanupCts.Dispose(); // we don't dispose nextDmbProvider here, since it might be the only thing we have
96 
102  {
103  async Task HandleCleanup()
104  {
105  var deleteJob = ioManager.DeleteDirectory(job.DirectoryName.ToString(), cleanupCts.Token);
106  Task otherTask;
107 
108  // lock (this) //already locked below
109  otherTask = cleanupTask;
110  await Task.WhenAll(otherTask, deleteJob).ConfigureAwait(false);
111  }
112 
113  lock (this)
114  if (!jobLockCounts.TryGetValue(job.Id, out var currentVal) || currentVal == 1)
115  {
116  jobLockCounts.Remove(job.Id);
117  logger.LogDebug("Cleaning compile job {0} => {1}", job.Id, job.DirectoryName);
118  cleanupTask = HandleCleanup();
119  }
120  else
121  {
122  var decremented = --jobLockCounts[job.Id];
123  logger.LogTrace("Compile job {0} lock count now: {1}", job.Id, decremented);
124  }
125  }
126 
128  public async Task LoadCompileJob(CompileJob job, CancellationToken cancellationToken)
129  {
130  if (job == null)
131  throw new ArgumentNullException(nameof(job));
132 
133  var newProvider = await FromCompileJob(job, cancellationToken).ConfigureAwait(false);
134  if (newProvider == null)
135  return;
136  lock (this)
137  {
138  nextDmbProvider?.Dispose();
139  nextDmbProvider = newProvider;
140  newerDmbTcs.SetResult(nextDmbProvider);
141  newerDmbTcs = new TaskCompletionSource<object>();
142  }
143  }
144 
146  public IDmbProvider LockNextDmb(int lockCount)
147  {
148  if (!DmbAvailable)
149  throw new InvalidOperationException("No .dmb available!");
150  if (lockCount < 0)
151  throw new ArgumentOutOfRangeException(nameof(lockCount), lockCount, "lockCount must be greater than or equal to 0!");
152  lock (this)
153  {
154  var jobId = nextDmbProvider.CompileJob.Id;
155  var incremented = jobLockCounts[jobId] += lockCount;
156  logger.LogTrace("Compile job {0} lock count now: {1}", jobId, incremented);
157  return nextDmbProvider;
158  }
159  }
160 
162  public Task StartAsync(CancellationToken cancellationToken) => databaseContextFactory.UseContext(async (db) =>
163  {
164  // where complete clause not necessary, only successful COMPILEjobs get in the db
165  var cj = await db.CompileJobs.Where(x => x.Job.Instance.Id == instance.Id)
166  .OrderByDescending(x => x.Job.StoppedAt).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
167  if (cj == default(CompileJob))
168  return;
169  await LoadCompileJob(cj, cancellationToken).ConfigureAwait(false);
170 
171  // we dont do CleanUnusedCompileJobs here because the watchdog may have plans for them yet
172  });
173 
175  public async Task StopAsync(CancellationToken cancellationToken)
176  {
177  using (cancellationToken.Register(() => cleanupCts.Cancel()))
178  await cleanupTask.ConfigureAwait(false);
179  }
180 
182  #pragma warning disable CA1506 // TODO: Decomplexify
183  public async Task<IDmbProvider> FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken)
184  {
185  if (compileJob == null)
186  throw new ArgumentNullException(nameof(compileJob));
187 
188  // ensure we have the entire compile job tree
189  await databaseContextFactory.UseContext(async db => compileJob = await db.CompileJobs.Where(x => x.Id == compileJob.Id)
190  .Include(x => x.Job).ThenInclude(x => x.StartedBy)
191  .Include(x => x.RevisionInformation).ThenInclude(x => x.PrimaryTestMerge).ThenInclude(x => x.MergedBy)
192  .Include(x => x.RevisionInformation).ThenInclude(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).ThenInclude(x => x.MergedBy)
193  .FirstAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false); // can't wait to see that query
194 
195  logger.LogTrace("Loading compile job {0}...", compileJob.Id);
196  var providerSubmitted = false;
197  var newProvider = new DmbProvider(compileJob, ioManager, () =>
198  {
199  if (providerSubmitted)
200  CleanJob(compileJob);
201  });
202 
203  try
204  {
205  var primaryCheckTask = ioManager.FileExists(ioManager.ConcatPath(newProvider.PrimaryDirectory, newProvider.DmbName), cancellationToken);
206  var secondaryCheckTask = ioManager.FileExists(ioManager.ConcatPath(newProvider.PrimaryDirectory, newProvider.DmbName), cancellationToken);
207 
208  if (!(await primaryCheckTask.ConfigureAwait(false) && await secondaryCheckTask.ConfigureAwait(false)))
209  {
210  logger.LogWarning("Error loading compile job, .dmb missing!");
211  return null; // omae wa mou shinderu
212  }
213 
214  lock (this)
215  {
216  if (!jobLockCounts.TryGetValue(compileJob.Id, out int value))
217  {
218  value = 1;
219  jobLockCounts.Add(compileJob.Id, 1);
220  }
221  else
222  jobLockCounts[compileJob.Id] = ++value;
223 
224  logger.LogTrace("Compile job {0} lock count now: {1}", compileJob.Id, value);
225 
226  providerSubmitted = true;
227  return newProvider;
228  }
229  }
230  finally
231  {
232  if (!providerSubmitted)
233  newProvider.Dispose();
234  }
235  }
236  #pragma warning restore CA1506
237 
239  #pragma warning disable CA1506 // TODO: Decomplexify
240  public async Task CleanUnusedCompileJobs(CompileJob exceptThisOne, CancellationToken cancellationToken)
241  {
242  List<long> jobIdsToSkip;
243 
244  // don't clean locked directories
245  lock (this)
246  jobIdsToSkip = jobLockCounts.Select(x => x.Key).ToList();
247 
248  List<string> jobUidsToNotErase = null;
249 
250  // find the uids of locked directories
251  await databaseContextFactory.UseContext(async db =>
252  {
253  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);
254  }).ConfigureAwait(false);
255 
256  // add the other exemption
257  if (exceptThisOne != null)
258  jobUidsToNotErase.Add(exceptThisOne.DirectoryName.Value.ToString().ToUpperInvariant());
259 
260  // cleanup
261  await ioManager.CreateDirectory(".", cancellationToken).ConfigureAwait(false);
262  var directories = await ioManager.GetDirectories(".", cancellationToken).ConfigureAwait(false);
263  int deleting = 0;
264  var tasks = directories.Select(async x =>
265  {
266  var nameOnly = ioManager.GetFileName(x);
267  if (jobUidsToNotErase.Contains(nameOnly.ToUpperInvariant()))
268  return;
269  try
270  {
271  ++deleting;
272  await ioManager.DeleteDirectory(x, cancellationToken).ConfigureAwait(false);
273  }
274  catch (OperationCanceledException)
275  {
276  throw;
277  }
278  catch (Exception e)
279  {
280  logger.LogWarning("Error deleting directory {0}! Exception: {1}", x, e);
281  }
282  }).ToList();
283  if (deleting > 0)
284  {
285  logger.LogDebug("Cleaning {0} unused game folders...", deleting);
286  await Task.WhenAll().ConfigureAwait(false);
287  }
288  }
289  #pragma warning restore CA1506
290  }
291 }
-
IDmbProvider nextDmbProvider
The latest DmbProvider
Definition: DmbFactory.cs:70
-
Task cleanupTask
Task representing calls to CleanJob(CompileJob)
Definition: DmbFactory.cs:60
-
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 }
+
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
+ + +
Task StartAsync(CancellationToken cancellationToken)
+ - -
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
-
async Task StopAsync(CancellationToken cancellationToken)
Definition: DmbFactory.cs:175
- -
readonly IIOManager ioManager
The IIOManager for the DmbFactory
Definition: DmbFactory.cs:40
+
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:32
+
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:183
-
DmbFactory(IDatabaseContextFactory databaseContextFactory, IIOManager ioManager, ILogger< DmbFactory > logger, Api.Models.Instance instance)
Construct a DmbFactory
Definition: DmbFactory.cs:81
-
async Task CleanUnusedCompileJobs(CompileJob exceptThisOne, CancellationToken cancellationToken)
Deletes all compile jobs that are inactive in the Game folder exceptThisOne
Definition: DmbFactory.cs:240
-
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
-
void CleanJob(CompileJob job)
Delete the Api.Models.Internal.CompileJob.DirectoryName of job
Definition: DmbFactory.cs:101
-
IDmbProvider LockNextDmb(int lockCount)
Gets the next IDmbProvider
Definition: DmbFactory.cs:146
-
Guid DirectoryName
The Game folder the results were compiled into
Definition: CompileJob.cs:32
-
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:65
-
async Task LoadCompileJob(CompileJob job, CancellationToken cancellationToken)
Load a new job into the ICompileJobConsumer
Definition: DmbFactory.cs:128
-
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
- -
Interface for using filesystems
Definition: IIOManager.cs:11
- - + + +
async Task< IDmbProvider > FromCompileJob(CompileJob compileJob, CancellationToken cancellationToken)
Gets a IDmbProvider for a given CompileJob
Definition: DmbFactory.cs:186
+
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
+
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
+ +
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
+
Interface for using filesystems
Definition: IIOManager.cs:11
+ + +
string ConcatPath(params string[] paths)
Combines an array of strings into a path
+
@@ -133,7 +121,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_dmb_provider_8cs.html b/_dmb_provider_8cs.html index 09c73b5e73..fc314c0a1c 100644 --- a/_dmb_provider_8cs.html +++ b/_dmb_provider_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Compiler/DmbProvider.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Compiler
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_dmb_provider_8cs_source.html b/_dmb_provider_8cs_source.html index d1f650ec5e..85afc93c16 100644 --- a/_dmb_provider_8cs_source.html +++ b/_dmb_provider_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Compiler/DmbProvider.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
DmbProvider.cs
-Go to the documentation of this file.
1 using System;
2 using Tgstation.Server.Host.IO;
4 
5 namespace Tgstation.Server.Host.Components.Compiler
6 {
8  sealed class DmbProvider : IDmbProvider
9  {
11  public string DmbName => String.Concat(CompileJob.DmeName, DreamMaker.DmbExtension);
12 
14  public string PrimaryDirectory => ioManager.ResolvePath(ioManager.ConcatPath(CompileJob.DirectoryName.ToString(), DreamMaker.ADirectoryName));
15 
17  public string SecondaryDirectory => ioManager.ResolvePath(ioManager.ConcatPath(CompileJob.DirectoryName.ToString(), DreamMaker.BDirectoryName));
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:20
- +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:20
- -
const string BDirectoryName
Name of the secondary directory used for compilation
Definition: DreamMaker.cs:31
-
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
-
Guid DirectoryName
The Game folder the results were compiled into
Definition: CompileJob.cs:32
- -
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
-
Interface for using filesystems
Definition: IIOManager.cs:11
- - +
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:32
+
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
+
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
+
@@ -117,7 +102,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_dream_daemon_8cs.html b/_dream_daemon_8cs.html index 3bcda161b8..6187bb8d96 100644 --- a/_dream_daemon_8cs.html +++ b/_dream_daemon_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/DreamDaemon.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Api.Models.DreamDaemon - Represents an instance of BYOND's DreamDaemon game server. Create action starts the server. Delete action shuts down the server More...
+ Represents an instance of BYOND's DreamDaemon game server. Create action starts the server. Delete action shuts down the server More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_dream_daemon_8cs_source.html b/_dream_daemon_8cs_source.html index 166eb7e593..62ebc13107 100644 --- a/_dream_daemon_8cs_source.html +++ b/_dream_daemon_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/DreamDaemon.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
DreamDaemon.cs
-Go to the documentation of this file.
2 
3 namespace Tgstation.Server.Api.Models
4 {
8  public sealed class DreamDaemon : DreamDaemonSettings
9  {
13  public CompileJob ActiveCompileJob { get; set; }
14 
18  public CompileJob StagedCompileJob { get; set; }
19 
23  public bool? Running { get; set; }
24 
28  public DreamDaemonSecurity? CurrentSecurity { get; set; }
29 
33  public ushort? CurrentPort { get; set; }
34 
38  public bool? CurrentAllowWebclient { get; set; }
39  }
40 }
+Go to the documentation of this file.
2 
4 {
8  public sealed class DreamDaemon : DreamDaemonSettings
9  {
13  public CompileJob ActiveCompileJob { get; set; }
14 
18  public CompileJob StagedCompileJob { get; set; }
19 
23  public bool? Running { get; set; }
24 
28  public DreamDaemonSecurity? CurrentSecurity { get; set; }
29 
33  public ushort? CurrentPort { get; set; }
34 
38  public bool? CurrentAllowWebclient { get; set; }
39  }
40 }
- - - - -
DreamDaemonSecurity
DreamDaemon&#39;s security level
-
Represents an instance of BYOND&#39;s DreamDaemon game server. Create action starts the server...
Definition: DreamDaemon.cs:8
- + +
DreamDaemonSecurity? CurrentSecurity
The current DreamDaemonSecurity of DreamDaemon. May be downgraded due to requirements of ActiveCompil...
Definition: DreamDaemon.cs:28
+ +
CompileJob StagedCompileJob
The next revision to go live
Definition: DreamDaemon.cs:18
+
CompileJob ActiveCompileJob
The live revision
Definition: DreamDaemon.cs:13
+
ushort? CurrentPort
The port the running DreamDaemon instance is set to
Definition: DreamDaemon.cs:33
+ +
DreamDaemonSecurity
DreamDaemon's security level
+
bool? Running
The current status of DreamDaemon
Definition: DreamDaemon.cs:23
+
Represents an instance of BYOND's DreamDaemon game server. Create action starts the server....
Definition: DreamDaemon.cs:8
+
bool? CurrentAllowWebclient
The webclient status the running DreamDaemon instance is set to
Definition: DreamDaemon.cs:38
+
diff --git a/_dream_daemon_client_8cs.html b/_dream_daemon_client_8cs.html index 68f18e6719..4f5f91d2fb 100644 --- a/_dream_daemon_client_8cs.html +++ b/_dream_daemon_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/DreamDaemonClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_dream_daemon_client_8cs_source.html b/_dream_daemon_client_8cs_source.html index 928b4730ed..a8e17a18c6 100644 --- a/_dream_daemon_client_8cs_source.html +++ b/_dream_daemon_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/DreamDaemonClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
DreamDaemonClient.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 using Tgstation.Server.Api;
6 
7 namespace Tgstation.Server.Client.Components
8 {
11  {
16 
20  readonly Instance instance;
21 
27  public DreamDaemonClient(IApiClient apiClient, Instance instance)
28  {
29  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
30  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
31  }
32 
34  public Task Shutdown(CancellationToken cancellationToken) => apiClient.Delete(Routes.DreamDaemon, instance.Id, cancellationToken);
35 
37  public Task<Job> Start(CancellationToken cancellationToken) => apiClient.Create<Job>(Routes.DreamDaemon, instance.Id, cancellationToken);
38 
40  public Task<Job> Restart(CancellationToken cancellationToken) => apiClient.Patch<Job>(Routes.DreamDaemon, instance.Id, cancellationToken);
41 
43  public Task<DreamDaemon> Read(CancellationToken cancellationToken) => apiClient.Read<DreamDaemon>(Routes.DreamDaemon, instance.Id, cancellationToken);
44 
46  public Task<DreamDaemon> Update(DreamDaemon dreamDaemon, CancellationToken cancellationToken) => apiClient.Update<DreamDaemon, DreamDaemon>(Routes.DreamDaemon, dreamDaemon ?? throw new ArgumentNullException(nameof(dreamDaemon)), instance.Id, cancellationToken);
47  }
48 }
DreamDaemonClient(IApiClient apiClient, Instance instance)
Construct a DreamDaemonClient
+Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 using Tgstation.Server.Api;
6 
8 {
11  {
16 
20  readonly Instance instance;
21 
28  {
29  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
30  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
31  }
32 
34  public Task Shutdown(CancellationToken cancellationToken) => apiClient.Delete(Routes.DreamDaemon, instance.Id, cancellationToken);
35 
37  public Task<Job> Start(CancellationToken cancellationToken) => apiClient.Create<Job>(Routes.DreamDaemon, instance.Id, cancellationToken);
38 
40  public Task<Job> Restart(CancellationToken cancellationToken) => apiClient.Patch<Job>(Routes.DreamDaemon, instance.Id, cancellationToken);
41 
43  public Task<DreamDaemon> Read(CancellationToken cancellationToken) => apiClient.Read<DreamDaemon>(Routes.DreamDaemon, instance.Id, cancellationToken);
44 
46  public Task<DreamDaemon> Update(DreamDaemon dreamDaemon, CancellationToken cancellationToken) => apiClient.Update<DreamDaemon, DreamDaemon>(Routes.DreamDaemon, dreamDaemon ?? throw new ArgumentNullException(nameof(dreamDaemon)), instance.Id, cancellationToken);
47  }
48 }
Task< Job > Start(CancellationToken cancellationToken)
Start DreamDaemon
+
DreamDaemonClient(IApiClient apiClient, Instance instance)
Construct a DreamDaemonClient
- - +
Task Shutdown(CancellationToken cancellationToken)
Shutdown DreamDaemon
+
Task< DreamDaemon > Update(DreamDaemon dreamDaemon, CancellationToken cancellationToken)
Update DreamDaemon. This may trigger Api.Models.Internal.DreamDaemonSettings.SoftRestart
-
Routes to a server actions
Definition: Routes.cs:9
+
Routes to a server actions
Definition: Routes.cs:9
+ +
Task< Job > Restart(CancellationToken cancellationToken)
Restart DreamDaemon
+
Task< DreamDaemon > Read(CancellationToken cancellationToken)
Get the DreamDaemon represented by the IDreamDaemonClient
-
const string DreamDaemon
The Models.DreamDaemon controller
Definition: Routes.cs:44
-
readonly Instance instance
The Instance for the DreamDaemonClient
- -
Metadata about a server instance
Definition: Instance.cs:9
- -
Web interface for the API
Definition: IApiClient.cs:11
-
Represents an instance of BYOND&#39;s DreamDaemon game server. Create action starts the server...
Definition: DreamDaemon.cs:8
-
readonly IApiClient apiClient
The IApiClient for the DreamDaemonClient
- -
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job ...
Definition: Job.cs:6
+
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 Instance instance
The Instance for the DreamDaemonClient
+ +
Metadata about a server instance
Definition: Instance.cs:9
+
Task Delete(string route, CancellationToken cancellationToken)
Run an HTTP DELETE request
+ +
Web interface for the API
Definition: IApiClient.cs:11
+
Represents an instance of BYOND's DreamDaemon game server. Create action starts the server....
Definition: DreamDaemon.cs:8
+
readonly IApiClient apiClient
The IApiClient for the DreamDaemonClient
+
Task< DreamDaemon > DreamDaemon(Routes.DreamDaemon, dreamDaemon ?? throw new ArgumentNullException(nameof(dreamDaemon)), instance.Id, cancellationToken)
+ +
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job
Definition: Job.cs:6
diff --git a/_dream_daemon_controller_8cs.html b/_dream_daemon_controller_8cs.html index 15ff7260fa..0397fd92f2 100644 --- a/_dream_daemon_controller_8cs.html +++ b/_dream_daemon_controller_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/DreamDaemonController.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Controllers.DreamDaemonControllerModelController<TModel> for managing the DreamDaemon More...
ModelController<TModel> for managing the DreamDaemon More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Controllers
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_dream_daemon_controller_8cs_source.html b/_dream_daemon_controller_8cs_source.html index 2ed91d345a..c3929460fd 100644 --- a/_dream_daemon_controller_8cs_source.html +++ b/_dream_daemon_controller_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/DreamDaemonController.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
20 namespace Tgstation.Server.Host.Controllers
21 {
25  [Route(Routes.DreamDaemon)]
26  public sealed class DreamDaemonController : ModelController<DreamDaemon>
27  {
32 
37 
46  public DreamDaemonController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, IInstanceManager instanceManager, ILogger<DreamDaemonController> logger) : base(databaseContext, authenticationContextFactory, logger, true)
47  {
48  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
49  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
50  }
51 
53  [TgsAuthorize(DreamDaemonRights.Start)]
54  public override async Task<IActionResult> Create([FromBody] DreamDaemon model, CancellationToken cancellationToken)
55  {
56  // alias for launching DD
57  var instance = instanceManager.GetInstance(Instance);
58 
59  if (instance.Watchdog.Running)
60  return StatusCode((int)HttpStatusCode.Gone);
61 
62  var job = new Models.Job
63  {
64  Description = "Launch DreamDaemon",
65  CancelRight = (ulong)DreamDaemonRights.Shutdown,
66  CancelRightsType = RightsType.DreamDaemon,
68  StartedBy = AuthenticationContext.User
69  };
70  await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressHandler, innerCt) => instance.Watchdog.Launch(innerCt), cancellationToken).ConfigureAwait(false);
71  return Accepted(job.ToApi());
72  }
73 
75  [TgsAuthorize(DreamDaemonRights.ReadMetadata | DreamDaemonRights.ReadRevision)]
76  public override Task<IActionResult> Read(CancellationToken cancellationToken) => ReadImpl(null, cancellationToken);
77 
84  async Task<IActionResult> ReadImpl(DreamDaemonSettings settings, CancellationToken cancellationToken)
85  {
86  var instance = instanceManager.GetInstance(Instance);
87  var dd = instance.Watchdog;
88 
89  var metadata = (AuthenticationContext.GetRight(RightsType.DreamDaemon) & (ulong)DreamDaemonRights.ReadMetadata) != 0;
90  var revision = (AuthenticationContext.GetRight(RightsType.DreamDaemon) & (ulong)DreamDaemonRights.ReadRevision) != 0;
91 
92  if (settings == null)
93  {
94  settings = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).Select(x => x.DreamDaemonSettings).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
95  if (settings == default)
96  return StatusCode((int)HttpStatusCode.Gone);
97  }
98 
99  var result = new DreamDaemon();
100  if (metadata)
101  {
102  var alphaActive = dd.AlphaIsActive;
103  var llp = dd.LastLaunchParameters;
104  var rstate = dd.RebootState;
105  result.AutoStart = settings.AutoStart;
106  result.CurrentPort = alphaActive ? llp?.PrimaryPort : llp?.SecondaryPort;
107  result.CurrentSecurity = llp?.SecurityLevel;
108  result.CurrentAllowWebclient = llp?.AllowWebClient;
109  result.PrimaryPort = settings.PrimaryPort;
110  result.AllowWebClient = settings.AllowWebClient;
111  result.Running = dd.Running;
112  result.SecondaryPort = settings.SecondaryPort;
113  result.SecurityLevel = settings.SecurityLevel;
114  result.SoftRestart = rstate == RebootState.Restart;
115  result.SoftShutdown = rstate == RebootState.Shutdown;
116  result.StartupTimeout = settings.StartupTimeout;
117  }
118 
119  if (revision)
120  {
121  var latestCompileJob = instance.LatestCompileJob();
122  result.ActiveCompileJob = (dd.ActiveCompileJob ?? latestCompileJob)?.ToApi();
123  if (latestCompileJob?.Id != result.ActiveCompileJob?.Id)
124  result.StagedCompileJob = latestCompileJob?.ToApi();
125  }
126 
127  return Json(result);
128  }
129 
135  [HttpDelete]
136  [TgsAuthorize(DreamDaemonRights.Shutdown)]
137  public async Task<IActionResult> Delete(CancellationToken cancellationToken)
138  {
139  var instance = instanceManager.GetInstance(Instance);
140  await instance.Watchdog.Terminate(false, cancellationToken).ConfigureAwait(false);
141  return Ok();
142  }
143 
145  #pragma warning disable CA1506 // TODO: Decomplexify
146  [TgsAuthorize(DreamDaemonRights.SetAutoStart | DreamDaemonRights.SetPorts | DreamDaemonRights.SetSecurity | DreamDaemonRights.SetWebClient | DreamDaemonRights.SoftRestart | DreamDaemonRights.SoftShutdown | DreamDaemonRights.Start | DreamDaemonRights.SetStartupTimeout)]
147  public override async Task<IActionResult> Update([FromBody] DreamDaemon model, CancellationToken cancellationToken)
148  {
149  if (model == null)
150  throw new ArgumentNullException(nameof(model));
151 
152  if (model.PrimaryPort == 0)
153  return BadRequest(new ErrorMessage { Message = "Primary port cannot be 0!" });
154 
155  if (model.SecurityLevel == DreamDaemonSecurity.Ultrasafe)
156  return BadRequest(new ErrorMessage { Message = "This version of TGS does not support the ultrasafe DreamDaemon configuration!" });
157 
158  // alias for changing DD settings
159  var current = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).Select(x => x.DreamDaemonSettings).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
160 
161  if (current == default)
162  return StatusCode((int)HttpStatusCode.Gone);
163 
164  var userRights = (DreamDaemonRights)AuthenticationContext.GetRight(RightsType.DreamDaemon);
165 
166  bool CheckModified<T>(Expression<Func<Api.Models.Internal.DreamDaemonSettings, T>> expression, DreamDaemonRights requiredRight)
167  {
168  var memberSelectorExpression = (MemberExpression)expression.Body;
169  var property = (PropertyInfo)memberSelectorExpression.Member;
170 
171  var newVal = property.GetValue(model);
172  if (newVal == null)
173  return false;
174  if (!userRights.HasFlag(requiredRight) && property.GetValue(current) != newVal)
175  return true;
176 
177  property.SetValue(current, newVal);
178  return false;
179  }
180 
181  var oldSoftRestart = current.SoftRestart;
182  var oldSoftShutdown = current.SoftShutdown;
183 
184  if (CheckModified(x => x.AllowWebClient, DreamDaemonRights.SetWebClient)
185  || CheckModified(x => x.AutoStart, DreamDaemonRights.SetAutoStart)
186  || CheckModified(x => x.PrimaryPort, DreamDaemonRights.SetPorts)
187  || CheckModified(x => x.SecondaryPort, DreamDaemonRights.SetPorts)
188  || CheckModified(x => x.SecurityLevel, DreamDaemonRights.SetSecurity)
189  || CheckModified(x => x.SoftRestart, DreamDaemonRights.SoftRestart)
190  || CheckModified(x => x.SoftShutdown, DreamDaemonRights.SoftShutdown)
191  || CheckModified(x => x.StartupTimeout, DreamDaemonRights.SetStartupTimeout))
192  return Forbid();
193 
194  if (current.PrimaryPort == current.SecondaryPort)
195  return BadRequest(new ErrorMessage { Message = "Primary port and secondary port cannot be the same!" });
196 
197  var wd = instanceManager.GetInstance(Instance).Watchdog;
198 
199  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
200 
201  // run this second because current may be modified by it
202  await wd.ChangeSettings(current, cancellationToken).ConfigureAwait(false);
203 
204  if (!oldSoftRestart.Value && current.SoftRestart.Value)
205  await wd.Restart(true, cancellationToken).ConfigureAwait(false);
206  else if (!oldSoftShutdown.Value && current.SoftShutdown.Value)
207  await wd.Terminate(true, cancellationToken).ConfigureAwait(false);
208  else if ((oldSoftRestart.Value && !current.SoftRestart.Value) || (oldSoftShutdown.Value && !current.SoftShutdown.Value))
209  await wd.ResetRebootState(cancellationToken).ConfigureAwait(false);
210 
211  return await ReadImpl(current, cancellationToken).ConfigureAwait(false);
212  }
213  #pragma warning restore CA1506
214 
220  [HttpPatch]
221  [TgsAuthorize(DreamDaemonRights.Restart)]
222  public async Task<IActionResult> Restart(CancellationToken cancellationToken)
223  {
224  var job = new Models.Job
225  {
226  Instance = Instance,
227  CancelRightsType = RightsType.DreamDaemon,
228  CancelRight = (ulong)DreamDaemonRights.Shutdown,
229  StartedBy = AuthenticationContext.User,
230  Description = "Restart Watchdog"
231  };
232 
233  var watchdog = instanceManager.GetInstance(Instance).Watchdog;
234 
235  await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressReporter, ct) => watchdog.Restart(false, ct), cancellationToken).ConfigureAwait(false);
236  return Accepted(job.ToApi());
237  }
238  }
239 }
async Task< IActionResult > Delete(CancellationToken cancellationToken)
Stops DreamDaemon if it&#39;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;
19 
21 {
25  [Route(Routes.DreamDaemon)]
26  public sealed class DreamDaemonController : ModelController<DreamDaemon>
27  {
32 
37 
46  public DreamDaemonController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, IInstanceManager instanceManager, ILogger<DreamDaemonController> logger) : base(databaseContext, authenticationContextFactory, logger, true)
47  {
48  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
49  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
50  }
51 
53  [TgsAuthorize(DreamDaemonRights.Start)]
54  public override async Task<IActionResult> Create([FromBody] DreamDaemon model, CancellationToken cancellationToken)
55  {
56  // alias for launching DD
57  var instance = instanceManager.GetInstance(Instance);
58 
59  if (instance.Watchdog.Running)
60  return StatusCode((int)HttpStatusCode.Gone);
61 
62  var job = new Models.Job
63  {
64  Description = "Launch DreamDaemon",
65  CancelRight = (ulong)DreamDaemonRights.Shutdown,
66  CancelRightsType = RightsType.DreamDaemon,
68  StartedBy = AuthenticationContext.User
69  };
70  await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressHandler, innerCt) => instance.Watchdog.Launch(innerCt), cancellationToken).ConfigureAwait(false);
71  return Accepted(job.ToApi());
72  }
73 
75  [TgsAuthorize(DreamDaemonRights.ReadMetadata | DreamDaemonRights.ReadRevision)]
76  public override Task<IActionResult> Read(CancellationToken cancellationToken) => ReadImpl(null, cancellationToken);
77 
84  async Task<IActionResult> ReadImpl(DreamDaemonSettings settings, CancellationToken cancellationToken)
85  {
86  var instance = instanceManager.GetInstance(Instance);
87  var dd = instance.Watchdog;
88 
89  var metadata = (AuthenticationContext.GetRight(RightsType.DreamDaemon) & (ulong)DreamDaemonRights.ReadMetadata) != 0;
90  var revision = (AuthenticationContext.GetRight(RightsType.DreamDaemon) & (ulong)DreamDaemonRights.ReadRevision) != 0;
91 
92  if (settings == null)
93  {
94  settings = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).Select(x => x.DreamDaemonSettings).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
95  if (settings == default)
96  return StatusCode((int)HttpStatusCode.Gone);
97  }
98 
99  var result = new DreamDaemon();
100  if (metadata)
101  {
102  var alphaActive = dd.AlphaIsActive;
103  var llp = dd.LastLaunchParameters;
104  var rstate = dd.RebootState;
105  result.AutoStart = settings.AutoStart;
106  result.CurrentPort = alphaActive ? llp?.PrimaryPort : llp?.SecondaryPort;
107  result.CurrentSecurity = llp?.SecurityLevel;
108  result.CurrentAllowWebclient = llp?.AllowWebClient;
109  result.PrimaryPort = settings.PrimaryPort;
110  result.AllowWebClient = settings.AllowWebClient;
111  result.Running = dd.Running;
112  result.SecondaryPort = settings.SecondaryPort;
113  result.SecurityLevel = settings.SecurityLevel;
114  result.SoftRestart = rstate == RebootState.Restart;
115  result.SoftShutdown = rstate == RebootState.Shutdown;
116  result.StartupTimeout = settings.StartupTimeout;
117  }
118 
119  if (revision)
120  {
121  var latestCompileJob = instance.LatestCompileJob();
122  result.ActiveCompileJob = (dd.ActiveCompileJob ?? latestCompileJob)?.ToApi();
123  if (latestCompileJob?.Id != result.ActiveCompileJob?.Id)
124  result.StagedCompileJob = latestCompileJob?.ToApi();
125  }
126 
127  return Json(result);
128  }
129 
135  [HttpDelete]
136  [TgsAuthorize(DreamDaemonRights.Shutdown)]
137  public async Task<IActionResult> Delete(CancellationToken cancellationToken)
138  {
139  var instance = instanceManager.GetInstance(Instance);
140  await instance.Watchdog.Terminate(false, cancellationToken).ConfigureAwait(false);
141  return Ok();
142  }
143 
145  #pragma warning disable CA1506 // TODO: Decomplexify
146  [TgsAuthorize(DreamDaemonRights.SetAutoStart | DreamDaemonRights.SetPorts | DreamDaemonRights.SetSecurity | DreamDaemonRights.SetWebClient | DreamDaemonRights.SoftRestart | DreamDaemonRights.SoftShutdown | DreamDaemonRights.Start | DreamDaemonRights.SetStartupTimeout)]
147  public override async Task<IActionResult> Update([FromBody] DreamDaemon model, CancellationToken cancellationToken)
148  {
149  if (model == null)
150  throw new ArgumentNullException(nameof(model));
151 
152  if (model.PrimaryPort == 0)
153  return BadRequest(new ErrorMessage { Message = "Primary port cannot be 0!" });
154 
155  if (model.SecurityLevel == DreamDaemonSecurity.Ultrasafe)
156  return BadRequest(new ErrorMessage { Message = "This version of TGS does not support the ultrasafe DreamDaemon configuration!" });
157 
158  // alias for changing DD settings
159  var current = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).Select(x => x.DreamDaemonSettings).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
160 
161  if (current == default)
162  return StatusCode((int)HttpStatusCode.Gone);
163 
164  var userRights = (DreamDaemonRights)AuthenticationContext.GetRight(RightsType.DreamDaemon);
165 
166  bool CheckModified<T>(Expression<Func<Api.Models.Internal.DreamDaemonSettings, T>> expression, DreamDaemonRights requiredRight)
167  {
168  var memberSelectorExpression = (MemberExpression)expression.Body;
169  var property = (PropertyInfo)memberSelectorExpression.Member;
170 
171  var newVal = property.GetValue(model);
172  if (newVal == null)
173  return false;
174  if (!userRights.HasFlag(requiredRight) && property.GetValue(current) != newVal)
175  return true;
176 
177  property.SetValue(current, newVal);
178  return false;
179  }
180 
181  var oldSoftRestart = current.SoftRestart;
182  var oldSoftShutdown = current.SoftShutdown;
183 
184  if (CheckModified(x => x.AllowWebClient, DreamDaemonRights.SetWebClient)
185  || CheckModified(x => x.AutoStart, DreamDaemonRights.SetAutoStart)
186  || CheckModified(x => x.PrimaryPort, DreamDaemonRights.SetPorts)
187  || CheckModified(x => x.SecondaryPort, DreamDaemonRights.SetPorts)
188  || CheckModified(x => x.SecurityLevel, DreamDaemonRights.SetSecurity)
189  || CheckModified(x => x.SoftRestart, DreamDaemonRights.SoftRestart)
190  || CheckModified(x => x.SoftShutdown, DreamDaemonRights.SoftShutdown)
191  || CheckModified(x => x.StartupTimeout, DreamDaemonRights.SetStartupTimeout))
192  return Forbid();
193 
194  if (current.PrimaryPort == current.SecondaryPort)
195  return BadRequest(new ErrorMessage { Message = "Primary port and secondary port cannot be the same!" });
196 
198 
199  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
200 
201  // run this second because current may be modified by it
202  await wd.ChangeSettings(current, cancellationToken).ConfigureAwait(false);
203 
204  if (!oldSoftRestart.Value && current.SoftRestart.Value)
205  await wd.Restart(true, cancellationToken).ConfigureAwait(false);
206  else if (!oldSoftShutdown.Value && current.SoftShutdown.Value)
207  await wd.Terminate(true, cancellationToken).ConfigureAwait(false);
208  else if ((oldSoftRestart.Value && !current.SoftRestart.Value) || (oldSoftShutdown.Value && !current.SoftShutdown.Value))
209  await wd.ResetRebootState(cancellationToken).ConfigureAwait(false);
210 
211  return await ReadImpl(current, cancellationToken).ConfigureAwait(false);
212  }
213  #pragma warning restore CA1506
214 
220  [HttpPatch]
221  [TgsAuthorize(DreamDaemonRights.Restart)]
222  public async Task<IActionResult> Restart(CancellationToken cancellationToken)
223  {
224  var job = new Models.Job
225  {
226  Instance = Instance,
227  CancelRightsType = RightsType.DreamDaemon,
228  CancelRight = (ulong)DreamDaemonRights.Shutdown,
229  StartedBy = AuthenticationContext.User,
230  Description = "Restart Watchdog"
231  };
232 
234 
235  await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressReporter, ct) => watchdog.Restart(false, ct), cancellationToken).ConfigureAwait(false);
236  return Accepted(job.ToApi());
237  }
238  }
239 }
async Task< IActionResult > Delete(CancellationToken cancellationToken)
Stops DreamDaemon if it's running
+ +
Manages the runtime of Jobs
Definition: IJobManager.cs:12
+ + + +
ushort? PrimaryPort
The first port DreamDaemon uses. This should be the publically advertised port
+
override Task< IActionResult > Read(CancellationToken cancellationToken)
Attempt to read a TModel
-
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
+
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
- +
IInstance GetInstance(Models.Instance metadata)
Get the IInstance associated with given metadata
- -
DreamDaemonSecurity SecurityLevel
The DreamDaemonSecurity level of DreamDaemon
-
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
-
bool AutoStart
If DreamDaemon starts when it&#39;s Instance starts
-
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
+
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
+
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)
Handle a HTTP PATCH to the DreamDaemonController
-
Routes to a server actions
Definition: Routes.cs:9
-
DreamDaemonRights
Rights for Models.DreamDaemon
- +
async Task< IActionResult > ReadImpl(DreamDaemonSettings settings, CancellationToken cancellationToken)
Implementation of Read(CancellationToken)
+
async Task< IActionResult > Restart(CancellationToken cancellationToken)
Handle a HTTP PATCH to the DreamDaemonController
+
Routes to a server actions
Definition: Routes.cs:9
+
DreamDaemonRights
Rights for Models.DreamDaemon
override async Task< IActionResult > Update([FromBody] DreamDaemon model, CancellationToken cancellationToken)
-
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
-
ModelController<TModel> for managing the DreamDaemon
-
const string DreamDaemon
The Models.DreamDaemon controller
Definition: Routes.cs:44
-
readonly IInstanceManager instanceManager
The IInstanceManager for the DreamMakerController
-
An ApiController representing a TModel
+
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
+
ModelController<TModel> for managing the DreamDaemon
+
const string DreamDaemon
The Models.DreamDaemon controller
Definition: Routes.cs:44
+
readonly IInstanceManager instanceManager
The IInstanceManager for the DreamMakerController
+
An ApiController representing a TModel
-
readonly IJobManager jobManager
The IJobManager for the DreamMakerController
- -
Metadata about a server instance
Definition: Instance.cs:9
+
readonly IJobManager jobManager
The IJobManager for the DreamMakerController
+ +
IWatchdog Watchdog
The IWatchdog for the IInstance
Definition: IInstance.cs:32
+
Metadata about a server instance
Definition: Instance.cs:9
override async Task< IActionResult > Create([FromBody] DreamDaemon model, CancellationToken cancellationToken)
- - -
DreamDaemonSecurity
DreamDaemon&#39;s security level
-
Represents an instance of BYOND&#39;s DreamDaemon game server. Create action starts the server...
Definition: DreamDaemon.cs:8
-
User can read all chat settings except Models.Internal.ChatBot.ConnectionString
-
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+ + +
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
+
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- -
ushort PrimaryPort
The first port DreamDaemon uses. This should be the publically advertised port
-
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
- - -
bool AllowWebClient
If the BYOND web client can be used to connect to the game server
+ +
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
+ +
DreamDaemonSecurity? SecurityLevel
The DreamDaemonSecurity level of DreamDaemon
diff --git a/_dream_daemon_launch_parameters_8cs.html b/_dream_daemon_launch_parameters_8cs.html index 651380350e..1947711fcc 100644 --- a/_dream_daemon_launch_parameters_8cs.html +++ b/_dream_daemon_launch_parameters_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/DreamDaemonLaunchParameters.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters - Launch settings for DreamDaemon More...
+ Launch settings for DreamDaemon More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
namespace  Tgstation.Server.Api.Models.Internal
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_dream_daemon_launch_parameters_8cs_source.html b/_dream_daemon_launch_parameters_8cs_source.html index c27e2efdb2..df9e324ccd 100644 --- a/_dream_daemon_launch_parameters_8cs_source.html +++ b/_dream_daemon_launch_parameters_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/DreamDaemonLaunchParameters.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
DreamDaemonLaunchParameters.cs
-Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
3 namespace Tgstation.Server.Api.Models.Internal
4 {
9  {
13  [Required]
14  public bool? AllowWebClient { get; set; }
15 
19  [Required]
20  public DreamDaemonSecurity? SecurityLevel { get; set; }
21 
25  [Required]
26  public ushort? PrimaryPort { get; set; }
27 
31  [Required]
32  public ushort? SecondaryPort { get; set; }
33 
37  [Required]
38  public uint? StartupTimeout { get; set; }
39 
45  public bool Match(DreamDaemonLaunchParameters otherParameters) =>
46  AllowWebClient == otherParameters.AllowWebClient
47  && SecurityLevel == otherParameters.SecurityLevel
48  && PrimaryPort == otherParameters.PrimaryPort
49  && SecondaryPort == otherParameters.SecondaryPort
50  && StartupTimeout == otherParameters.StartupTimeout;
51  }
52 }
- - -
DreamDaemonSecurity SecurityLevel
The DreamDaemonSecurity level of DreamDaemon
- -
DreamDaemonSecurity
DreamDaemon&#39;s security level
-
ushort PrimaryPort
The first port DreamDaemon uses. This should be the publically advertised port
- - -
bool AllowWebClient
If the BYOND web client can be used to connect to the game server
+Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
3 
5 {
10  {
14  [Required]
15  public bool? AllowWebClient { get; set; }
16 
20  [Required]
21  public DreamDaemonSecurity? SecurityLevel { get; set; }
22 
26  [Required]
27  public ushort? PrimaryPort { get; set; }
28 
32  [Required]
33  public ushort? SecondaryPort { get; set; }
34 
38  [Required]
39  public uint? StartupTimeout { get; set; }
40 
46  public bool Match(DreamDaemonLaunchParameters otherParameters) =>
47  AllowWebClient == (otherParameters?.AllowWebClient ?? throw new ArgumentNullException(nameof(otherParameters)))
48  && SecurityLevel == otherParameters.SecurityLevel
49  && PrimaryPort == otherParameters.PrimaryPort
50  && SecondaryPort == otherParameters.SecondaryPort
51  && StartupTimeout == otherParameters.StartupTimeout;
52  }
53 }
ushort? PrimaryPort
The first port DreamDaemon uses. This should be the publically advertised port
+ + + + +
DreamDaemonSecurity
DreamDaemon's security level
+
bool? AllowWebClient
If the BYOND web client can be used to connect to the game server
+
bool Match(DreamDaemonLaunchParameters otherParameters)
Check if we match a given set of otherParameters
+
DreamDaemonSecurity? SecurityLevel
The DreamDaemonSecurity level of DreamDaemon
diff --git a/_dream_daemon_rights_8cs.html b/_dream_daemon_rights_8cs.html index 15f9c1c227..dc90684a60 100644 --- a/_dream_daemon_rights_8cs.html +++ b/_dream_daemon_rights_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/DreamDaemonRights.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Api +  namespace  Tgstation.Server.Api.Rights   @@ -123,8 +108,8 @@ Enumerations
  Tgstation.Server.Api.Rights.DreamDaemonRights.SetStartupTimeout = 2048
- } - + } +
 Rights for Models.DreamDaemon More...
 Rights for Models.DreamDaemon More...
 
@@ -132,7 +117,7 @@ Enumerations diff --git a/_dream_daemon_rights_8cs_source.html b/_dream_daemon_rights_8cs_source.html index 95cd532e80..0c4b665abc 100644 --- a/_dream_daemon_rights_8cs_source.html +++ b/_dream_daemon_rights_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/DreamDaemonRights.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
DreamDaemonRights.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Api.Rights
4 {
8  [Flags]
9  public enum DreamDaemonRights : ulong
10  {
14  None = 0,
15 
19  ReadRevision = 1,
20 
24  SetPorts = 2,
25 
29  SetAutoStart = 4,
30 
34  SetSecurity = 8,
35 
39  ReadMetadata = 16,
40 
44  SetWebClient = 32,
45 
49  SoftRestart = 64,
50 
54  SoftShutdown = 128,
55 
59  Restart = 256,
60 
64  Shutdown = 512,
65 
69  Start = 1024,
70 
74  SetStartupTimeout = 2048
75  }
76 }
User can enable Models.Internal.DreamDaemonSettings.SoftRestart
- - -
User can change Models.Internal.DreamDaemonLaunchParameters.AllowWebClient
-
User can change both primary and secondary ports
- -
User can change Models.Internal.DreamDaemonLaunchParameters.StartupTimeout
-
DreamDaemonRights
Rights for Models.DreamDaemon
-
User can read all ports, Models.Internal.DreamDaemonSettings.SoftRestart, Models.Internal.DreamDaemonSettings.SoftShutdown, Models.DreamDaemon.Running, Models.Internal.DreamDaemonLaunchParameters.AllowWebClient, and Models.Internal.DreamDaemonSettings.AutoStart
-
User can immediately restart Models.DreamDaemon
-
User can read Models.DreamDaemon.ActiveCompileJob and Models.DreamDaemon.StagedCompileJob ...
-
User can start Models.DreamDaemon and disable Models.Internal.DreamDaemonSettings.SoftRestart and Models.Internal.DreamDaemonSettings.SoftShutdown
-
User set Models.Internal.DreamDaemonLaunchParameters.SecurityLevel
-
User can enable Models.Internal.DreamDaemonSettings.SoftShutdown
-
User can change Models.Internal.DreamDaemonSettings.AutoStart
- -
User can immediately shutdown Models.DreamDaemon
+Go to the documentation of this file.
1 using System;
2 
4 {
8  [Flags]
9  public enum DreamDaemonRights : ulong
10  {
14  None = 0,
15 
19  ReadRevision = 1,
20 
24  SetPorts = 2,
25 
29  SetAutoStart = 4,
30 
34  SetSecurity = 8,
35 
39  ReadMetadata = 16,
40 
44  SetWebClient = 32,
45 
49  SoftRestart = 64,
50 
54  SoftShutdown = 128,
55 
59  Restart = 256,
60 
64  Shutdown = 512,
65 
69  Start = 1024,
70 
74  SetStartupTimeout = 2048
75  }
76 }
User can enable Models.Internal.DreamDaemonSettings.SoftRestart
+
User can change Models.Internal.DreamDaemonLaunchParameters.AllowWebClient
+
User can change both primary and secondary ports
+ +
User can change Models.Internal.DreamDaemonLaunchParameters.StartupTimeout
+
DreamDaemonRights
Rights for Models.DreamDaemon
+
User can read all ports, Models.Internal.DreamDaemonSettings.SoftRestart, Models.Internal....
+ +
User can immediately restart Models.DreamDaemon
+
User can read Models.DreamDaemon.ActiveCompileJob and Models.DreamDaemon.StagedCompileJob
+
User can start Models.DreamDaemon and disable Models.Internal.DreamDaemonSettings....
+
User set Models.Internal.DreamDaemonLaunchParameters.SecurityLevel
+
User can enable Models.Internal.DreamDaemonSettings.SoftShutdown
+
User can change Models.Internal.DreamDaemonSettings.AutoStart
+
User can immediately shutdown Models.DreamDaemon
diff --git a/_dream_daemon_security_8cs.html b/_dream_daemon_security_8cs.html index f92e7da8af..67af585b0e 100644 --- a/_dream_daemon_security_8cs.html +++ b/_dream_daemon_security_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/DreamDaemonSecurity.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Api +  namespace  Tgstation.Server.Api.Models   @@ -108,8 +93,8 @@ Enumerations - + } +
enum  Tgstation.Server.Api.Models.DreamDaemonSecurity { Tgstation.Server.Api.Models.DreamDaemonSecurity.Trusted, Tgstation.Server.Api.Models.DreamDaemonSecurity.Safe, Tgstation.Server.Api.Models.DreamDaemonSecurity.Ultrasafe - }
 DreamDaemon's security level More...
 DreamDaemon's security level More...
 
@@ -117,7 +102,7 @@ Enumerations diff --git a/_dream_daemon_security_8cs_source.html b/_dream_daemon_security_8cs_source.html index 2eeb96faa8..7b4f74ca85 100644 --- a/_dream_daemon_security_8cs_source.html +++ b/_dream_daemon_security_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/DreamDaemonSecurity.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
DreamDaemonSecurity.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Api.Models
2 {
6  public enum DreamDaemonSecurity
7  {
11  Trusted,
12 
16  Safe,
17 
21  Ultrasafe
22  }
23 }
-
Server will not be able to run shell commands or access files outside it&#39;s working directory ...
-
Server will not be able to run shell commands or access anything but temporary files. Currently unsupported!
-
Server is unrestricted in terms of file access and shell commands
-
DreamDaemonSecurity
DreamDaemon&#39;s security level
- +Go to the documentation of this file.
2 {
6  public enum DreamDaemonSecurity
7  {
11  Trusted,
12 
16  Safe,
17 
21  Ultrasafe
22  }
23 }
+
Server will not be able to run shell commands or access files outside it's working directory
+
Server will not be able to run shell commands or access anything but temporary files....
+
Server is unrestricted in terms of file access and shell commands
+
DreamDaemonSecurity
DreamDaemon's security level
diff --git a/_dream_daemon_status_8cs.html b/_dream_daemon_status_8cs.html index 05b7c6831a..0201674866 100644 --- a/_dream_daemon_status_8cs.html +++ b/_dream_daemon_status_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/DreamDaemonStatus.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Api +  namespace  Tgstation.Server.Api.Models   @@ -108,8 +93,8 @@ Enumerations - + } +
enum  Tgstation.Server.Api.Models.DreamDaemonStatus { Tgstation.Server.Api.Models.DreamDaemonStatus.Offline, Tgstation.Server.Api.Models.DreamDaemonStatus.HardRebooting, Tgstation.Server.Api.Models.DreamDaemonStatus.Online - }
 The status of DreamDaemon More...
 The status of DreamDaemon More...
 
@@ -117,7 +102,7 @@ Enumerations diff --git a/_dream_daemon_status_8cs_source.html b/_dream_daemon_status_8cs_source.html index c6d429248e..665f08711b 100644 --- a/_dream_daemon_status_8cs_source.html +++ b/_dream_daemon_status_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/DreamDaemonStatus.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
DreamDaemonStatus.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Api.Models
2 {
6 #pragma warning disable CA1717 // Only FlagsAttribute enums should have plural names
7  public enum DreamDaemonStatus
8 #pragma warning restore CA1717 // Only FlagsAttribute enums should have plural names
9  {
13  Offline,
14 
19 
23  Online,
24  }
25 }
-
DreamDaemonStatus
The status of DreamDaemon
- - - - +Go to the documentation of this file.
2 {
6 #pragma warning disable CA1717 // Only FlagsAttribute enums should have plural names
7  public enum DreamDaemonStatus
8 #pragma warning restore CA1717 // Only FlagsAttribute enums should have plural names
9  {
13  Offline,
14 
19 
23  Online,
24  }
25 }
DreamDaemonStatus
The status of DreamDaemon
+ + + +
diff --git a/_dream_maker_client_8cs.html b/_dream_maker_client_8cs.html index fc10a61a6e..a45374f918 100644 --- a/_dream_maker_client_8cs.html +++ b/_dream_maker_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/DreamMakerClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_dream_maker_client_8cs_source.html b/_dream_maker_client_8cs_source.html index 02db12676e..4245fca33d 100644 --- a/_dream_maker_client_8cs_source.html +++ b/_dream_maker_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/DreamMakerClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
DreamMakerClient.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 using Tgstation.Server.Api;
7 
8 namespace Tgstation.Server.Client.Components
9 {
12  {
17 
21  readonly Instance instance;
22 
28  public DreamMakerClient(IApiClient apiClient, Instance instance)
29  {
30  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
31  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
32  }
33 
35  public Task<Job> Compile(CancellationToken cancellationToken) => apiClient.Create<Job>(Routes.DreamMaker, instance.Id, cancellationToken);
36 
38  public Task<CompileJob> GetCompileJob(CompileJob compileJob, CancellationToken cancellationToken) => apiClient.Read<CompileJob>(Routes.SetID(Routes.DreamMaker, compileJob?.Id ?? throw new ArgumentNullException(nameof(compileJob))), instance.Id, cancellationToken);
39 
41  public Task<IReadOnlyList<CompileJob>> GetJobIds(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<CompileJob>>(Routes.List(Routes.DreamMaker), instance.Id, cancellationToken);
42 
44  public Task<DreamMaker> Read(CancellationToken cancellationToken) => apiClient.Read<DreamMaker>(Routes.DreamMaker, instance.Id, cancellationToken);
45 
47  public Task<DreamMaker> Update(DreamMaker dreamMaker, CancellationToken cancellationToken) => apiClient.Update<DreamMaker, DreamMaker>(Routes.DreamMaker, dreamMaker ?? throw new ArgumentNullException(nameof(dreamMaker)), instance.Id, cancellationToken);
48  }
49 }
Represents the state of the DreamMaker compiler. Create action starts a new compile. Delete action cancels the current compile
Definition: DreamMaker.cs:8
- +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 using Tgstation.Server.Api;
7 
9 {
12  {
17 
21  readonly Instance instance;
22 
29  {
30  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
31  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
32  }
33 
35  public Task<Job> Compile(CancellationToken cancellationToken) => apiClient.Create<Job>(Routes.DreamMaker, instance.Id, cancellationToken);
36 
38  public Task<CompileJob> GetCompileJob(CompileJob compileJob, CancellationToken cancellationToken) => apiClient.Read<CompileJob>(Routes.SetID(Routes.DreamMaker, compileJob?.Id ?? throw new ArgumentNullException(nameof(compileJob))), instance.Id, cancellationToken);
39 
41  public Task<IReadOnlyList<CompileJob>> GetJobIds(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<CompileJob>>(Routes.List(Routes.DreamMaker), instance.Id, cancellationToken);
42 
44  public Task<DreamMaker> Read(CancellationToken cancellationToken) => apiClient.Read<DreamMaker>(Routes.DreamMaker, instance.Id, cancellationToken);
45 
47  public Task<DreamMaker> Update(DreamMaker dreamMaker, CancellationToken cancellationToken) => apiClient.Update<DreamMaker, DreamMaker>(Routes.DreamMaker, dreamMaker ?? throw new ArgumentNullException(nameof(dreamMaker)), instance.Id, cancellationToken);
48  }
49 }
Represents the state of the DreamMaker compiler. Create action starts a new compile....
Definition: DreamMaker.cs:8
+ +
Task< DreamMaker > Read(CancellationToken cancellationToken)
Get the DreamMaker information
- - - -
DreamMakerClient(IApiClient apiClient, Instance instance)
Construct a DreamMakerClient
+
Task< Job > Compile(CancellationToken cancellationToken)
Compile the current repository revision
+
DreamMakerClient(IApiClient apiClient, Instance instance)
Construct a DreamMakerClient
-
readonly IApiClient apiClient
The IApiClient for the DreamMakerClient
-
Routes to a server actions
Definition: Routes.cs:9
-
readonly Instance instance
The Instance for the DreamMakerClient
-
const string DreamMaker
The Models.DreamMaker controller
Definition: Routes.cs:74
-
Metadata about a server instance
Definition: Instance.cs:9
-
static string SetID(string route, long id)
Apply an id postfix to a route
-
static string List(string route)
Get the /List postfix for a route
- -
Web interface for the API
Definition: IApiClient.cs:11
+
readonly IApiClient apiClient
The IApiClient for the DreamMakerClient
+
Routes to a server actions
Definition: Routes.cs:9
+ +
Task< DreamMaker > DreamMaker(Routes.DreamMaker, dreamMaker ?? throw new ArgumentNullException(nameof(dreamMaker)), instance.Id, cancellationToken)
+
Task< IReadOnlyList< CompileJob > > GetJobIds(CancellationToken cancellationToken)
Gets the Api.Models.Internal.CompileJob.Ids of all CompileJobs for the instance
+
readonly Instance instance
The Instance for the DreamMakerClient
+
const string DreamMaker
The Models.DreamMaker controller
Definition: Routes.cs:74
+
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
+
Task< CompileJob > GetCompileJob(CompileJob compileJob, CancellationToken cancellationToken)
Get a compileJob
+
Metadata about a server instance
Definition: Instance.cs:9
+
static string SetID(string route, long id)
Apply an id postfix to a route
+
static string List(string route)
Get the /List postfix for a route
+ +
Web interface for the API
Definition: IApiClient.cs:11
+
Task< DreamMaker > Update(DreamMaker dreamMaker, CancellationToken cancellationToken)
Updates the DreamMaker setttings
- -
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job ...
Definition: Job.cs:6
+ +
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job
Definition: Job.cs:6
diff --git a/_dream_maker_controller_8cs.html b/_dream_maker_controller_8cs.html index 3a500e3fbc..5522e218ea 100644 --- a/_dream_maker_controller_8cs.html +++ b/_dream_maker_controller_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/DreamMakerController.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Controllers
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_dream_maker_controller_8cs_source.html b/_dream_maker_controller_8cs_source.html index 791c4ab97e..ae0fd08838 100644 --- a/_dream_maker_controller_8cs_source.html +++ b/_dream_maker_controller_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/DreamMakerController.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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.Linq;
6 using System.Net;
7 using System.Threading;
8 using System.Threading.Tasks;
9 using Tgstation.Server.Api;
16 
17 namespace Tgstation.Server.Host.Controllers
18 {
22  [Route(Routes.DreamMaker)]
23  #pragma warning disable CA1506 // TODO: Decomplexify
24  public sealed class DreamMakerController : ModelController<DreamMaker>
25  {
30 
35 
44  public DreamMakerController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, IInstanceManager instanceManager, ILogger<DreamMakerController> logger) : base(databaseContext, authenticationContextFactory, logger, true)
45  {
46  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
47  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
48  }
49 
51  [TgsAuthorize(DreamMakerRights.Read)]
52  public override async Task<IActionResult> Read(CancellationToken cancellationToken)
53  {
54  var instance = instanceManager.GetInstance(Instance);
55  var dreamMakerSettings = await DatabaseContext.DreamMakerSettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
56  return Json(dreamMakerSettings.ToApi());
57  }
58 
60  [TgsAuthorize(DreamMakerRights.CompileJobs)]
61  public override async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
62  {
63  var compileJob = await DatabaseContext.CompileJobs
64  .Where(x => x.Id == id && x.Job.Instance.Id == Instance.Id)
65  .Include(x => x.Job).ThenInclude(x => x.StartedBy)
66  .Include(x => x.RevisionInformation).ThenInclude(x => x.PrimaryTestMerge).ThenInclude(x => x.MergedBy)
67  .Include(x => x.RevisionInformation).ThenInclude(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).ThenInclude(x => x.MergedBy)
68  .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
69  if (compileJob == default)
70  return NotFound();
71  return Json(compileJob.ToApi());
72  }
73 
75  [TgsAuthorize(DreamMakerRights.CompileJobs)]
76  public override async Task<IActionResult> List(CancellationToken cancellationToken)
77  {
78  var compileJobs = await DatabaseContext.CompileJobs.Where(x => x.Job.Instance.Id == Instance.Id).OrderByDescending(x => x.Job.StoppedAt).Select(x => new Api.Models.CompileJob
79  {
80  Id = x.Id
81  }).ToListAsync(cancellationToken).ConfigureAwait(false);
82  return Json(compileJobs);
83  }
84 
86  [TgsAuthorize(DreamMakerRights.Compile)]
87  public override async Task<IActionResult> Create([FromBody] DreamMaker model, CancellationToken cancellationToken)
88  {
89  var job = new Models.Job
90  {
91  Description = "Compile active repository code",
92  StartedBy = AuthenticationContext.User,
93  CancelRightsType = RightsType.DreamMaker,
94  CancelRight = (ulong)DreamMakerRights.CancelCompile,
96  };
97  await jobManager.RegisterOperation(job, instanceManager.GetInstance(Instance).CompileProcess, cancellationToken).ConfigureAwait(false);
98  return Accepted(job.ToApi());
99  }
100 
102  [TgsAuthorize(DreamMakerRights.SetDme | DreamMakerRights.SetApiValidationPort | DreamMakerRights.SetApiValidationPort)]
103  public override async Task<IActionResult> Update([FromBody] DreamMaker model, CancellationToken cancellationToken)
104  {
105  if (model.ApiValidationPort == 0)
106  return BadRequest(new ErrorMessage { Message = "API Validation port cannot be 0!" });
107 
108  if (model.ApiValidationSecurityLevel == DreamDaemonSecurity.Ultrasafe)
109  return BadRequest(new ErrorMessage { Message = "This version of TGS does not support the ultrasafe DreamDaemon configuration!" });
110 
111  var hostModel = await DatabaseContext.DreamMakerSettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
112  if (hostModel == null)
113  return StatusCode((int)HttpStatusCode.Gone);
114 
115  if (model.ProjectName != null)
116  {
118  return Forbid();
119  if (model.ProjectName.Length == 0)
120  hostModel.ProjectName = null;
121  else
122  hostModel.ProjectName = model.ProjectName;
123  }
124 
125  if (model.ApiValidationPort.HasValue)
126  {
127  if (!AuthenticationContext.InstanceUser.DreamMakerRights.Value.HasFlag(DreamMakerRights.SetApiValidationPort))
128  return Forbid();
129  hostModel.ApiValidationPort = model.ApiValidationPort;
130  }
131 
132  if (model.ApiValidationSecurityLevel.HasValue)
133  {
134  if (!AuthenticationContext.InstanceUser.DreamMakerRights.Value.HasFlag(DreamMakerRights.SetSecurityLevel))
135  return Forbid();
136  hostModel.ApiValidationSecurityLevel = model.ApiValidationSecurityLevel;
137  }
138 
139  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
140 
141  if ((AuthenticationContext.GetRight(RightsType.DreamMaker) & (ulong)DreamMakerRights.Read) == 0)
142  return Ok();
143 
144  return await Read(cancellationToken).ConfigureAwait(false);
145  }
146  }
147 }
-
Manages the runtime of Jobs
Definition: IJobManager.cs:12
- -
readonly IInstanceManager instanceManager
The IInstanceManager for the DreamMakerController
- -
Represents the state of the DreamMaker compiler. Create action starts a new compile. Delete action cancels the current compile
Definition: DreamMaker.cs:8
-
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
- +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.Net;
7 using System.Threading;
8 using System.Threading.Tasks;
9 using Tgstation.Server.Api;
16 
18 {
22  [Route(Routes.DreamMaker)]
23  #pragma warning disable CA1506 // TODO: Decomplexify
24  public sealed class DreamMakerController : ModelController<DreamMaker>
25  {
30 
35 
44  public DreamMakerController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, IInstanceManager instanceManager, ILogger<DreamMakerController> logger) : base(databaseContext, authenticationContextFactory, logger, true)
45  {
46  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
47  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
48  }
49 
51  [TgsAuthorize(DreamMakerRights.Read)]
52  public override async Task<IActionResult> Read(CancellationToken cancellationToken)
53  {
54  var instance = instanceManager.GetInstance(Instance);
55  var dreamMakerSettings = await DatabaseContext.DreamMakerSettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
56  return Json(dreamMakerSettings.ToApi());
57  }
58 
60  [TgsAuthorize(DreamMakerRights.CompileJobs)]
61  public override async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
62  {
63  var compileJob = await DatabaseContext.CompileJobs
64  .Where(x => x.Id == id && x.Job.Instance.Id == Instance.Id)
65  .Include(x => x.Job).ThenInclude(x => x.StartedBy)
66  .Include(x => x.RevisionInformation).ThenInclude(x => x.PrimaryTestMerge).ThenInclude(x => x.MergedBy)
67  .Include(x => x.RevisionInformation).ThenInclude(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).ThenInclude(x => x.MergedBy)
68  .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
69  if (compileJob == default)
70  return NotFound();
71  return Json(compileJob.ToApi());
72  }
73 
75  [TgsAuthorize(DreamMakerRights.CompileJobs)]
76  public override async Task<IActionResult> List(CancellationToken cancellationToken)
77  {
78  var compileJobs = await DatabaseContext.CompileJobs.Where(x => x.Job.Instance.Id == Instance.Id).OrderByDescending(x => x.Job.StoppedAt).Select(x => new Api.Models.CompileJob
79  {
80  Id = x.Id
81  }).ToListAsync(cancellationToken).ConfigureAwait(false);
82  return Json(compileJobs);
83  }
84 
86  [TgsAuthorize(DreamMakerRights.Compile)]
87  public override async Task<IActionResult> Create([FromBody] DreamMaker model, CancellationToken cancellationToken)
88  {
89  var job = new Models.Job
90  {
91  Description = "Compile active repository code",
92  StartedBy = AuthenticationContext.User,
93  CancelRightsType = RightsType.DreamMaker,
94  CancelRight = (ulong)DreamMakerRights.CancelCompile,
96  };
97  await jobManager.RegisterOperation(job, instanceManager.GetInstance(Instance).CompileProcess, cancellationToken).ConfigureAwait(false);
98  return Accepted(job.ToApi());
99  }
100 
102  [TgsAuthorize(DreamMakerRights.SetDme | DreamMakerRights.SetApiValidationPort | DreamMakerRights.SetApiValidationPort)]
103  public override async Task<IActionResult> Update([FromBody] DreamMaker model, CancellationToken cancellationToken)
104  {
105  if (model.ApiValidationPort == 0)
106  return BadRequest(new ErrorMessage { Message = "API Validation port cannot be 0!" });
107 
108  if (model.ApiValidationSecurityLevel == DreamDaemonSecurity.Ultrasafe)
109  return BadRequest(new ErrorMessage { Message = "This version of TGS does not support the ultrasafe DreamDaemon configuration!" });
110 
111  var hostModel = await DatabaseContext.DreamMakerSettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
112  if (hostModel == null)
113  return StatusCode((int)HttpStatusCode.Gone);
114 
115  if (model.ProjectName != null)
116  {
118  return Forbid();
119  if (model.ProjectName.Length == 0)
120  hostModel.ProjectName = null;
121  else
122  hostModel.ProjectName = model.ProjectName;
123  }
124 
125  if (model.ApiValidationPort.HasValue)
126  {
127  if (!AuthenticationContext.InstanceUser.DreamMakerRights.Value.HasFlag(DreamMakerRights.SetApiValidationPort))
128  return Forbid();
129  hostModel.ApiValidationPort = model.ApiValidationPort;
130  }
131 
132  if (model.ApiValidationSecurityLevel.HasValue)
133  {
134  if (!AuthenticationContext.InstanceUser.DreamMakerRights.Value.HasFlag(DreamMakerRights.SetSecurityLevel))
135  return Forbid();
136  hostModel.ApiValidationSecurityLevel = model.ApiValidationSecurityLevel;
137  }
138 
139  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
140 
141  if ((AuthenticationContext.GetRight(RightsType.DreamMaker) & (ulong)DreamMakerRights.Read) == 0)
142  return Ok();
143 
144  return await Read(cancellationToken).ConfigureAwait(false);
145  }
146  }
147 }
+
Manages the runtime of Jobs
Definition: IJobManager.cs:12
+ +
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
+
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
+
DbSet< DreamMakerSettings > DreamMakerSettings
- -
override async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Attempt to get a specific a TModel
+
override async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Attempt to get a specific a TModel
+
IInstance GetInstance(Models.Instance metadata)
Get the IInstance associated with given metadata
-
override async Task< IActionResult > Update([FromBody] DreamMaker model, CancellationToken cancellationToken)
-
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
-
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
+
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....
+
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
-
Routes to a server actions
Definition: Routes.cs:9
-
const string DreamMaker
The Models.DreamMaker controller
Definition: Routes.cs:74
-
DreamMakerRights
Rights for Models.DreamMaker
+
Routes to a server actions
Definition: Routes.cs:9
+
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
-
override async Task< IActionResult > List(CancellationToken cancellationToken)
Attempt to list entries of the TModel
-
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
-
An ApiController representing a TModel
+
override async Task< IActionResult > List(CancellationToken cancellationToken)
Attempt to list entries of the TModel
+
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
+
An ApiController representing a TModel
-
DreamMakerRights DreamMakerRights
The Rights.DreamMakerRights of the InstanceUser
Definition: InstanceUser.cs:39
- +
override async Task< IActionResult > Create([FromBody] DreamMaker model, CancellationToken cancellationToken)
-
override async Task< IActionResult > Read(CancellationToken cancellationToken)
Attempt to read a TModel
-
Metadata about a server instance
Definition: Instance.cs:9
- - -
DreamDaemonSecurity
DreamDaemon&#39;s security level
-
User can read all chat settings except Models.Internal.ChatBot.ConnectionString
-
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+
override async Task< IActionResult > Read(CancellationToken cancellationToken)
Attempt to read a TModel
+
Metadata about a server instance
Definition: Instance.cs:9
+ + +
DreamDaemonSecurity
DreamDaemon's security level
+
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- + - +
diff --git a/_dream_maker_rights_8cs.html b/_dream_maker_rights_8cs.html index 48fcce24e0..93f5786291 100644 --- a/_dream_maker_rights_8cs.html +++ b/_dream_maker_rights_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/DreamMakerRights.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Api +  namespace  Tgstation.Server.Api.Rights   @@ -116,8 +101,8 @@ EnumerationsTgstation.Server.Api.Rights.DreamMakerRights.CompileJobs = 32, Tgstation.Server.Api.Rights.DreamMakerRights.SetSecurityLevel = 64
- } - + } +
 Rights for Models.DreamMaker More...
 Rights for Models.DreamMaker More...
 
@@ -125,7 +110,7 @@ Enumerations diff --git a/_dream_maker_rights_8cs_source.html b/_dream_maker_rights_8cs_source.html index 38c72b2d86..becbc446d7 100644 --- a/_dream_maker_rights_8cs_source.html +++ b/_dream_maker_rights_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/DreamMakerRights.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
DreamMakerRights.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Api.Rights
4 {
8  [Flags]
9  public enum DreamMakerRights : ulong
10  {
14  None = 0,
15 
19  Read = 1,
20 
24  Compile = 2,
25 
29  CancelCompile = 4,
30 
34  SetDme = 8,
35 
40 
44  CompileJobs = 32,
45 
49  SetSecurityLevel = 64
50  }
51 }
- -
User may modify Models.DreamMaker.ApiValidationPort
- - -
User may modify Models.DreamMaker.ApiValidationSecurityLevel
-
User may list and read all Models.CompileJobs
-
DreamMakerRights
Rights for Models.DreamMaker
-
User may modify Models.DreamMaker.ProjectName
-
User can read all chat settings except Models.Internal.ChatBot.ConnectionString
- - +Go to the documentation of this file.
1 using System;
2 
4 {
8  [Flags]
9  public enum DreamMakerRights : ulong
10  {
14  None = 0,
15 
19  Read = 1,
20 
24  Compile = 2,
25 
29  CancelCompile = 4,
30 
34  SetDme = 8,
35 
40 
44  CompileJobs = 32,
45 
49  SetSecurityLevel = 64
50  }
51 }
User may modify Models.DreamMaker.ApiValidationPort
+ + +
User may modify Models.DreamMaker.ApiValidationSecurityLevel
+
User may list and read all Models.CompileJobs
+
DreamMakerRights
Rights for Models.DreamMaker
+ +
User may modify Models.DreamMaker.ProjectName
+
User can read all chat settings except Models.Internal.ChatBot.ConnectionString
+
diff --git a/_dream_maker_settings_8cs.html b/_dream_maker_settings_8cs.html index 2a5899ef63..1cd91fb9c0 100644 --- a/_dream_maker_settings_8cs.html +++ b/_dream_maker_settings_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/DreamMakerSettings.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_dream_maker_settings_8cs_source.html b/_dream_maker_settings_8cs_source.html index 16adae2631..1d766994da 100644 --- a/_dream_maker_settings_8cs_source.html +++ b/_dream_maker_settings_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/DreamMakerSettings.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
DreamMakerSettings.cs
-Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
3 namespace Tgstation.Server.Host.Models
4 {
6  public sealed class DreamMakerSettings : Api.Models.DreamMaker
7  {
11  public long Id { get; set; }
12 
16  public long InstanceId { get; set; }
17 
21  [Required]
22  public Instance Instance { get; set; }
23 
28  public Api.Models.DreamMaker ToApi() => new Api.Models.DreamMaker
29  {
30  ProjectName = ProjectName,
31  ApiValidationPort = ApiValidationPort,
32  ApiValidationSecurityLevel = ApiValidationSecurityLevel
33  };
34  }
35 }
- - -
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
- +Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
4 {
6  public sealed class DreamMakerSettings : Api.Models.DreamMaker
7  {
11  public long Id { get; set; }
12 
16  public long InstanceId { get; set; }
17 
21  [Required]
22  public Instance Instance { get; set; }
23 
28  public Api.Models.DreamMaker ToApi() => new Api.Models.DreamMaker
29  {
33  };
34  }
35 }
+ +
ushort? ApiValidationPort
The port used during compilation to validate the DMAPI
Definition: DreamMaker.cs:19
+
string ProjectName
The .dme file DreamMaker tries to compile with without the extension
Definition: DreamMaker.cs:13
+
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
+
DreamDaemonSecurity? ApiValidationSecurityLevel
The DreamDaemonSecurity level used to validate the DMAPI
Definition: DreamMaker.cs:25
+ + +
Api.Models.DreamMaker ToApi()
Convert the DreamDaemonSettings to it's API form
diff --git a/_error_message_8cs.html b/_error_message_8cs.html index 31d51cf256..5c3aeeb67e 100644 --- a/_error_message_8cs.html +++ b/_error_message_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/ErrorMessage.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_error_message_8cs_source.html b/_error_message_8cs_source.html index a38cc590bd..10a63b1d59 100644 --- a/_error_message_8cs_source.html +++ b/_error_message_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/ErrorMessage.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ErrorMessage.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Api.Models
4 {
8  public sealed class ErrorMessage
9  {
13  public string Message { get; set; }
14 
18  public Version SeverApiVersion { get; set; } = ApiHeaders.Version;
19  }
20 }
- -
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
-
static Version Version
Get the version of the Api the caller is using
Definition: ApiHeaders.cs:56
-
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- +Go to the documentation of this file.
1 using System;
2 
4 {
8  public sealed class ErrorMessage
9  {
13  public string Message { get; set; }
14 
18  public Version SeverApiVersion { get; set; } = ApiHeaders.Version;
19  }
20 }
+
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
+
string Message
A human readable description of the error
Definition: ErrorMessage.cs:13
+
Version SeverApiVersion
The version of the API the server is using
Definition: ErrorMessage.cs:18
+
static Version Version
Get the version of the Api the caller is using
Definition: ApiHeaders.cs:56
+
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
diff --git a/_event_consumer_8cs.html b/_event_consumer_8cs.html index b4cc075aaa..42982f2018 100644 --- a/_event_consumer_8cs.html +++ b/_event_consumer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/EventConsumer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_event_consumer_8cs_source.html b/_event_consumer_8cs_source.html index fda9d4fb7b..d2746ec60c 100644 --- a/_event_consumer_8cs_source.html +++ b/_event_consumer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/EventConsumer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
EventConsumer.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;
7 
8 namespace Tgstation.Server.Host.Components
9 {
12  {
17 
22 
27  public EventConsumer(IConfiguration configuration)
28  {
29  this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
30  }
31 
33  public async Task<bool> HandleEvent(EventType eventType, IEnumerable<string> parameters, CancellationToken cancellationToken)
34  {
35  if (watchdog == null)
36  throw new InvalidOperationException("EventConsumer used without watchdog set!");
37 
38  if (!await configuration.HandleEvent(eventType, parameters, cancellationToken).ConfigureAwait(false))
39  return false;
40  return await watchdog.HandleEvent(eventType, parameters, cancellationToken).ConfigureAwait(false);
41  }
42 
47  public void SetWatchdog(IWatchdog watchdog)
48  {
49 #pragma warning disable IDE0016 // Use 'throw' expression
50  if (watchdog == null)
51  throw new ArgumentNullException(nameof(watchdog));
52 #pragma warning restore IDE0016 // Use 'throw' expression
53  if (this.watchdog != null)
54  throw new InvalidOperationException("watchdog already set!");
55  this.watchdog = watchdog;
56  }
57  }
58 }
async Task< bool > HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
Handle a given eventType
+Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Threading;
4 using System.Threading.Tasks;
7 
9 {
12  {
17 
22 
28  {
29  this.configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
30  }
31 
33  public async Task<bool> HandleEvent(EventType eventType, IEnumerable<string> parameters, CancellationToken cancellationToken)
34  {
35  if (watchdog == null)
36  throw new InvalidOperationException("EventConsumer used without watchdog set!");
37 
38  if (!await configuration.HandleEvent(eventType, parameters, cancellationToken).ConfigureAwait(false))
39  return false;
40  return await watchdog.HandleEvent(eventType, parameters, cancellationToken).ConfigureAwait(false);
41  }
42 
48  {
49 #pragma warning disable IDE0016 // Use 'throw' expression
50  if (watchdog == null)
51  throw new ArgumentNullException(nameof(watchdog));
52 #pragma warning restore IDE0016 // Use 'throw' expression
53  if (this.watchdog != null)
54  throw new InvalidOperationException("watchdog already set!");
55  this.watchdog = watchdog;
56  }
57  }
58 }
async Task< bool > HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
Handle a given eventType
-
Consumes EventTypes and takes the appropriate actions
- - -
IWatchdog watchdog
The IWatchdog for the EventConsumer
-
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
+
Consumes EventTypes and takes the appropriate actions
+
IWatchdog watchdog
The IWatchdog for the EventConsumer
+
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
-
readonly IConfiguration configuration
The IConfiguration for the EventConsumer
-
EventConsumer(IConfiguration configuration)
Construct an IEventConsumer
-
For managing the Configuration directory
- - +
readonly IConfiguration configuration
The IConfiguration for the EventConsumer
+
EventConsumer(IConfiguration configuration)
Construct an IEventConsumer
+ + + -
Task< bool > HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
Handle a given eventType
- -
void SetWatchdog(IWatchdog watchdog)
Set the watchdog for the EventConsumer
- -
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
+
Task< bool > HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
Handle a given eventType
+ +
void SetWatchdog(IWatchdog watchdog)
Set the watchdog for the EventConsumer
+ +
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
diff --git a/_event_notification_8cs.html b/_event_notification_8cs.html index 95bcb5825a..9331009969 100644 --- a/_event_notification_8cs.html +++ b/_event_notification_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/EventNotification.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Components.Interop.EventNotification - For notifying DD of EventTypes More...
+ For notifying DD of EventTypes More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Interop
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_event_notification_8cs_source.html b/_event_notification_8cs_source.html index d41c0f91d2..d9091e75bd 100644 --- a/_event_notification_8cs_source.html +++ b/_event_notification_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/EventNotification.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
EventNotification.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 
3 namespace Tgstation.Server.Host.Components.Interop
4 {
8  sealed class EventNotification
9  {
13  public EventType Type { get; set; }
14 
18  public IEnumerable<string> Parameters { get; set; }
19  }
20 }
- -
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
- - +Go to the documentation of this file.
1 using System.Collections.Generic;
2 
4 {
8  sealed class EventNotification
9  {
13  public EventType Type { get; set; }
14 
18  public IEnumerable<string> Parameters { get; set; }
19  }
20 }
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
+ + +
IEnumerable< string > Parameters
The event parameters
+
diff --git a/_event_type_8cs.html b/_event_type_8cs.html index c5e0175e54..27628b5b84 100644 --- a/_event_type_8cs.html +++ b/_event_type_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/EventType.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Host +  namespace  Tgstation.Server.Host.Components   @@ -124,8 +109,8 @@ Enumerations   Tgstation.Server.Host.Components.EventType.InstanceAutoUpdateStart = 12, Tgstation.Server.Host.Components.EventType.RepoMergeConflict = 13
- } - + } +
 Types of events. Mirror in tgs.dm More...
 Types of events. Mirror in tgs.dm More...
 
@@ -133,7 +118,7 @@ Enumerations diff --git a/_event_type_8cs_source.html b/_event_type_8cs_source.html index b425e8b5ce..caa6bbdf4b 100644 --- a/_event_type_8cs_source.html +++ b/_event_type_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/EventType.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
EventType.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Host.Components
2 {
6  public enum EventType
7  {
11  RepoResetOrigin = 0,
12 
16  RepoCheckout = 1,
17 
21  RepoFetch = 2,
22 
27 
32 
37 
41  ByondInstallFail = 6,
42 
47 
51  CompileStart = 8,
52 
56  CompileCancelled = 9,
57 
61  CompileFailure = 10,
62 
66  CompileComplete = 11,
67 
72 
76  RepoMergeConflict = 13,
77  }
78 }
- - -
Parameters: Base sha, target sha, base reference, target reference
-
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
-
Parameters: Pull request number, pull request sha, merger message
- -
Parameters: Absolute path to repository root
- -
Parameters: Reference name, commit sha
-
Parameters: Game directory path, origin commit sha
-
Parameters: Game directory path, "1" if compile succeeded and api validation failed, "0" otherwise
-
Parameters: Old active version, new active version
- - - - +Go to the documentation of this file.
2 {
6  public enum EventType
7  {
11  RepoResetOrigin = 0,
12 
16  RepoCheckout = 1,
17 
21  RepoFetch = 2,
22 
27 
32 
37 
41  ByondInstallFail = 6,
42 
47 
51  CompileStart = 8,
52 
56  CompileCancelled = 9,
57 
61  CompileFailure = 10,
62 
66  CompileComplete = 11,
67 
72 
76  RepoMergeConflict = 13,
77  }
78 }
+ +
Parameters: Base sha, target sha, base reference, target reference
+
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
+
Parameters: Pull request number, pull request sha, merger message
+ +
Parameters: Absolute path to repository root
+ + +
Parameters: Game directory path, origin commit sha
+
Parameters: Game directory path, "1" if compile succeeded and api validation failed,...
+
Parameters: Old active version, new active version
+ + + +
diff --git a/_file_logging_configuration_8cs.html b/_file_logging_configuration_8cs.html index 4492e9def8..0c13518107 100644 --- a/_file_logging_configuration_8cs.html +++ b/_file_logging_configuration_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Configuration/FileLoggingConfiguration.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Configuration
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_file_logging_configuration_8cs_source.html b/_file_logging_configuration_8cs_source.html index 15d9249331..14a2c30c8e 100644 --- a/_file_logging_configuration_8cs_source.html +++ b/_file_logging_configuration_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Configuration/FileLoggingConfiguration.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
FileLoggingConfiguration.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Newtonsoft.Json;
3 using Newtonsoft.Json.Converters;
4 
5 namespace Tgstation.Server.Host.Configuration
6 {
11  {
15  public const string Section = "FileLogging";
16 
20  const LogLevel DefaultLogLevel = LogLevel.Debug;
21 
25  const LogLevel DefaultMicrosoftLogLevel = LogLevel.Warning;
26 
30  public string Directory { get; set; }
31 
35  public bool Disable { get; set; }
36 
40  [JsonConverter(typeof(StringEnumConverter))]
41  public LogLevel LogLevel { get; set; } = DefaultLogLevel;
42 
46  [JsonConverter(typeof(StringEnumConverter))]
47  public LogLevel MicrosoftLogLevel { get; set; } = DefaultMicrosoftLogLevel;
48  }
49 }
+Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Newtonsoft.Json;
3 using Newtonsoft.Json.Converters;
4 
6 {
11  {
15  public const string Section = "FileLogging";
16 
21 
26 
30  public string Directory { get; set; }
31 
35  public bool Disable { get; set; }
36 
40  [JsonConverter(typeof(StringEnumConverter))]
41  public LogLevel LogLevel { get; set; } = DefaultLogLevel;
42 
46  [JsonConverter(typeof(StringEnumConverter))]
48  }
49 }
LogLevel MicrosoftLogLevel
The minimum Microsoft.Extensions.Logging.LogLevel to display in logs for Microsoft library sources
+ +
LogLevel LogLevel
The minimum Microsoft.Extensions.Logging.LogLevel to display in logs
+ + - - - + + +
const LogLevel DefaultMicrosoftLogLevel
Default value for MicrosoftLogLevel
+
const string Section
The key for the Microsoft.Extensions.Configuration.IConfigurationSection the FileLoggingConfiguration...
diff --git a/_general_configuration_8cs.html b/_general_configuration_8cs.html index 043a9b49fd..1b9cc46ec5 100644 --- a/_general_configuration_8cs.html +++ b/_general_configuration_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Configuration/GeneralConfiguration.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Configuration
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_general_configuration_8cs_source.html b/_general_configuration_8cs_source.html index 48659a92a4..571df33ce9 100644 --- a/_general_configuration_8cs_source.html +++ b/_general_configuration_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Configuration/GeneralConfiguration.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
GeneralConfiguration.cs
-Go to the documentation of this file.
1 using Newtonsoft.Json;
2 using Newtonsoft.Json.Converters;
3 
4 namespace Tgstation.Server.Host.Configuration
5 {
9  public sealed class GeneralConfiguration
10  {
14  public const string Section = "General";
15 
19  const uint DefaultMinimumPasswordLength = 15;
20 
24  const int DefaultByondTopicTimeout = 5000;
25 
29  const int DefaultRestartTimeout = 10000;
30 
34  public uint MinimumPasswordLength { get; set; } = DefaultMinimumPasswordLength;
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  }
57 }
-
SetupWizardMode
Determines if the Core.ISetupWizard will run
+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  }
57 }
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
+
const uint DefaultMinimumPasswordLength
The default value for MinimumPasswordLength
- - - +
int RestartTimeout
The timeout milliseconds for restarting the server
+ + +
int ByondTopicTimeout
The timeout in milliseconds for sending and receiving topics to/from DreamDaemon. Note that a single ...
+
const int DefaultRestartTimeout
The default value for RestartTimeout
+
uint MinimumPasswordLength
Minimum length of database user passwords
diff --git a/_git_hub_client_factory_8cs.html b/_git_hub_client_factory_8cs.html index a03ab24765..b4589a5366 100644 --- a/_git_hub_client_factory_8cs.html +++ b/_git_hub_client_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/GitHubClientFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_git_hub_client_factory_8cs_source.html b/_git_hub_client_factory_8cs_source.html index e83a76be4b..cdf23266dc 100644 --- a/_git_hub_client_factory_8cs_source.html +++ b/_git_hub_client_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/GitHubClientFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
GitHubClientFactory.cs
-Go to the documentation of this file.
1 using System;
2 using Octokit;
3 
4 namespace Tgstation.Server.Host.Core
5 {
8  {
13 
18  public GitHubClientFactory(IApplication application)
19  {
20  this.application = application ?? throw new ArgumentNullException(nameof(application));
21  }
22 
27  GitHubClient CreateBaseClient() => new GitHubClient(new ProductHeaderValue(application.VersionPrefix, application.Version.ToString()));
28 
30  public IGitHubClient CreateClient() => CreateBaseClient();
31 
33  public IGitHubClient CreateClient(string accessToken)
34  {
35  if (accessToken == null)
36  throw new ArgumentNullException(nameof(accessToken));
37  var result = CreateBaseClient();
38  result.Credentials = new Credentials(accessToken);
39  return result;
40  }
41  }
42 }
IGitHubClient CreateClient(string accessToken)
Create a client with authentication using a personal access token
- -
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
- - -
GitHubClientFactory(IApplication application)
Construct a GitHubClientFactory
- -
readonly IApplication application
The IApplication for the GitHubClientFactory
+Go to the documentation of this file.
1 using System;
2 using Octokit;
3 
5 {
8  {
13 
19  {
20  this.application = application ?? throw new ArgumentNullException(nameof(application));
21  }
22 
27  GitHubClient CreateBaseClient() => new GitHubClient(new ProductHeaderValue(application.VersionPrefix, application.Version.ToString()));
28 
30  public IGitHubClient CreateClient() => CreateBaseClient();
31 
33  public IGitHubClient CreateClient(string accessToken)
34  {
35  if (accessToken == null)
36  throw new ArgumentNullException(nameof(accessToken));
37  var result = CreateBaseClient();
38  result.Credentials = new Credentials(accessToken);
39  return result;
40  }
41  }
42 }
IGitHubClient CreateClient(string accessToken)
Create a client with authentication using a personal access token
+
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
+
string VersionPrefix
Prefix to VersionString
Definition: IApplication.cs:13
+
GitHubClientFactory(IApplication application)
Construct a GitHubClientFactory
+ +
GitHubClient CreateBaseClient()
Create a GitHubClient
+ +
readonly IApplication application
The IApplication for the GitHubClientFactory
- +
IGitHubClient CreateClient()
Create a client with anonymous authentication. Low rate limit
+
Version Version
The version of the Application
Definition: IApplication.cs:23
diff --git a/_global_suppressions_8cs.html b/_global_suppressions_8cs.html index 7889e1a0eb..9c1b1e52e3 100644 --- a/_global_suppressions_8cs.html +++ b/_global_suppressions_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Service/GlobalSuppressions.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + + - + - - + + + +
GlobalSuppressions.cs
-Go to the documentation of this file.
1 [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2232:MarkWindowsFormsEntryPointsWithStaThread", Justification = "No don't")]
2 
3 // This file is used by Code Analysis to maintain SuppressMessage
4 // attributes that are applied to this project.
5 // Project-level suppressions either have no target or are given
6 // a specific target and scoped to a namespace, type, member, etc.
7 //
8 // To add a suppression to this file, right-click the message in the
9 // Code Analysis results, point to "Suppress Message", and click
10 // "In Suppression File".
11 // You do not need to add suppressions to this file manually.
-
+Go to the documentation of this file.
1 [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2232:MarkWindowsFormsEntryPointsWithStaThread", Justification = "No don't, it breaks shit")]
2 
3 // This file is used by Code Analysis to maintain SuppressMessage
4 // attributes that are applied to this project.
5 // Project-level suppressions either have no target or are given
6 // a specific target and scoped to a namespace, type, member, etc.
7 //
8 // To add a suppression to this file, right-click the message in the
9 // Code Analysis results, point to "Suppress Message", and click
10 // "In Suppression File".
11 // You do not need to add suppressions to this file manually.
diff --git a/_home_controller_8cs.html b/_home_controller_8cs.html index ba5cc3a01c..566d3a4eed 100644 --- a/_home_controller_8cs.html +++ b/_home_controller_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/HomeController.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +

Classes

class  Tgstation.Server.Host.Controllers.HomeController - Main ApiController for the Application More...
+ Main ApiController for the Application More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Controllers
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_home_controller_8cs_source.html b/_home_controller_8cs_source.html index 52f96f7cf9..37f7595bad 100644 --- a/_home_controller_8cs_source.html +++ b/_home_controller_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/HomeController.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
HomeController.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Authorization;
2 using Microsoft.AspNetCore.Mvc;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.Extensions.Logging;
5 using Microsoft.Extensions.Options;
6 using System;
7 using System.Linq;
8 using System.Net.Mime;
9 using System.Threading;
10 using System.Threading.Tasks;
11 using Tgstation.Server.Api;
16 using Wangkanai.Detection;
17 
18 namespace Tgstation.Server.Host.Controllers
19 {
23  [Route(Routes.Root)]
24  public sealed class HomeController : ApiController
25  {
30 
35 
40 
45 
50 
54  readonly IBrowserResolver browserResolver;
55 
60 
74  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)
75  {
76  this.tokenFactory = tokenFactory ?? throw new ArgumentNullException(nameof(tokenFactory));
77  this.systemIdentityFactory = systemIdentityFactory ?? throw new ArgumentNullException(nameof(systemIdentityFactory));
78  this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite));
79  this.application = application ?? throw new ArgumentNullException(nameof(application));
80  this.identityCache = identityCache ?? throw new ArgumentNullException(nameof(identityCache));
81  this.browserResolver = browserResolver ?? throw new ArgumentNullException(nameof(browserResolver));
82  controlPanelConfiguration = controlPanelConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(controlPanelConfigurationOptions));
83  }
84 
89  [TgsAuthorize]
90  [AllowAnonymous]
91  [HttpGet]
92  public IActionResult Home()
93  {
94  if (AuthenticationContext != null)
95  return Json(new Api.Models.ServerInformation
96  {
97  Version = application.Version,
98  ApiVersion = ApiHeaders.Version
99  });
100 
101  // if we are using a browser and the control panel, soft redirect to the app page
102  if (controlPanelConfiguration.Enable && browserResolver.Browser.Type != BrowserType.Generic)
103  {
104  Logger.LogDebug("Unauthorized browser request (User-Agent: \"{0}\"), loading control panel...", browserResolver.UserAgent);
105  return File("~/index.html", MediaTypeNames.Text.Html);
106  }
107 
108  return Unauthorized();
109  }
110 
116  [HttpPost]
117  #pragma warning disable CA1506 // TODO: Decomplexify
118  public async Task<IActionResult> CreateToken(CancellationToken cancellationToken)
119  {
120  if (ApiHeaders == null)
121  return BadRequest(new Api.Models.ErrorMessage { Message = "Missing API headers!" });
122 
124  return BadRequest(new Api.Models.ErrorMessage { Message = "Cannot create a token using another token!" });
125 
126  ISystemIdentity identity;
127  try
128  {
129  // trust the system over the database because a user's name can change while still having the same SID
130  identity = await systemIdentityFactory.CreateSystemIdentity(ApiHeaders.Username, ApiHeaders.Password, cancellationToken).ConfigureAwait(false);
131  }
132  catch (NotImplementedException)
133  {
134  identity = null;
135  }
136 
137  using (identity)
138  {
139  IQueryable<User> query;
140  if (identity == null)
141  query = DatabaseContext.Users.Where(x => x.CanonicalName == ApiHeaders.Username.ToUpperInvariant());
142  else
143  query = DatabaseContext.Users.Where(x => x.SystemIdentifier == identity.Uid);
144  var user = await query.Select(x => new User
145  {
146  Id = x.Id,
147  PasswordHash = x.PasswordHash,
148  Enabled = x.Enabled,
149  Name = x.Name
150  }).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
151 
152  if (user == null)
153  return Unauthorized();
154 
155  if (identity == null)
156  {
157  var originalHash = user.PasswordHash;
158  if (!cryptographySuite.CheckUserPassword(user, ApiHeaders.Password))
159  return Unauthorized();
160  if (user.PasswordHash != originalHash)
161  {
162  var updatedUser = new User
163  {
164  Id = user.Id
165  };
166  DatabaseContext.Users.Attach(updatedUser);
167  updatedUser.PasswordHash = user.PasswordHash;
168  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
169  }
170  }
171 
172  // check if the name changed and updoot accordingly
173  else if (identity.Username != user.Name)
174  {
175  DatabaseContext.Users.Attach(user);
176  user.Name = identity.Username;
177  user.CanonicalName = user.Name.ToUpperInvariant();
178  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
179  }
180 
181  if (!user.Enabled.Value)
182  return Forbid();
183 
184  var token = await tokenFactory.CreateToken(user, cancellationToken).ConfigureAwait(false);
185  if (identity != null)
186  {
187  // expire the identity slightly after the auth token in case of lag
188  var identExpiry = token.ExpiresAt.Value;
189  identExpiry += tokenFactory.ValidationParameters.ClockSkew;
190  identExpiry += TimeSpan.FromSeconds(15);
191  identityCache.CacheSystemIdentity(user, identity, identExpiry);
192  }
193 
194  Logger.LogDebug("Successfully logged in user {0}!", user.Id);
195 
196  return Json(token);
197  }
198  }
199  #pragma warning restore CA1506
200  }
201 }
- - -
async Task< IActionResult > CreateToken(CancellationToken cancellationToken)
Attempt to authenticate a User using ApiController.ApiHeaders
+Go to the documentation of this file.
1 using Microsoft.AspNetCore.Authorization;
2 using Microsoft.AspNetCore.Mvc;
3 using Microsoft.EntityFrameworkCore;
4 using Microsoft.Extensions.Logging;
5 using Microsoft.Extensions.Options;
6 using System;
7 using System.Linq;
8 using System.Net.Mime;
9 using System.Threading;
10 using System.Threading.Tasks;
11 using Tgstation.Server.Api;
16 using Wangkanai.Detection;
17 
19 {
23  [Route(Routes.Root)]
24  public sealed class HomeController : ApiController
25  {
30 
35 
40 
45 
50 
54  readonly IBrowserResolver browserResolver;
55 
60 
74  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)
75  {
76  this.tokenFactory = tokenFactory ?? throw new ArgumentNullException(nameof(tokenFactory));
77  this.systemIdentityFactory = systemIdentityFactory ?? throw new ArgumentNullException(nameof(systemIdentityFactory));
78  this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite));
79  this.application = application ?? throw new ArgumentNullException(nameof(application));
80  this.identityCache = identityCache ?? throw new ArgumentNullException(nameof(identityCache));
81  this.browserResolver = browserResolver ?? throw new ArgumentNullException(nameof(browserResolver));
82  controlPanelConfiguration = controlPanelConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(controlPanelConfigurationOptions));
83  }
84 
89  [TgsAuthorize]
90  [AllowAnonymous]
91  [HttpGet]
92  public IActionResult Home()
93  {
94  if (AuthenticationContext != null)
95  return Json(new Api.Models.ServerInformation
96  {
97  Version = application.Version,
98  ApiVersion = ApiHeaders.Version
99  });
100 
101  // if we are using a browser and the control panel, soft redirect to the app page
102  if (controlPanelConfiguration.Enable && browserResolver.Browser.Type != BrowserType.Generic)
103  {
104  Logger.LogDebug("Unauthorized browser request (User-Agent: \"{0}\"), loading control panel...", browserResolver.UserAgent);
105  return File("~/index.html", MediaTypeNames.Text.Html);
106  }
107 
108  return Unauthorized();
109  }
110 
116  [HttpPost]
117  #pragma warning disable CA1506 // TODO: Decomplexify
118  public async Task<IActionResult> CreateToken(CancellationToken cancellationToken)
119  {
120  if (ApiHeaders == null)
121  return BadRequest(new Api.Models.ErrorMessage { Message = "Missing API headers!" });
122 
124  return BadRequest(new Api.Models.ErrorMessage { Message = "Cannot create a token using another token!" });
125 
126  ISystemIdentity systemIdentity;
127  try
128  {
129  // trust the system over the database because a user's name can change while still having the same SID
130  systemIdentity = await systemIdentityFactory.CreateSystemIdentity(ApiHeaders.Username, ApiHeaders.Password, cancellationToken).ConfigureAwait(false);
131  }
132  catch (NotImplementedException)
133  {
134  systemIdentity = null;
135  }
136 
137  using (systemIdentity)
138  {
139  IQueryable<User> query;
140  if (systemIdentity == null)
141  query = DatabaseContext.Users.Where(x => x.CanonicalName == ApiHeaders.Username.ToUpperInvariant());
142  else
143  query = DatabaseContext.Users.Where(x => x.SystemIdentifier == systemIdentity.Uid);
144  var user = await query.Select(x => new User
145  {
146  Id = x.Id,
147  PasswordHash = x.PasswordHash,
148  Enabled = x.Enabled,
149  Name = x.Name
150  }).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
151 
152  if (user == null)
153  return Unauthorized();
154 
155  if (systemIdentity == null)
156  {
157  var originalHash = user.PasswordHash;
159  return Unauthorized();
160  if (user.PasswordHash != originalHash)
161  {
162  Logger.LogDebug("User ID {0}'s password hash needs a refresh, updating database.", user.Id);
163  var updatedUser = new User
164  {
165  Id = user.Id
166  };
167  DatabaseContext.Users.Attach(updatedUser);
168  updatedUser.PasswordHash = user.PasswordHash;
169  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
170  }
171  }
172 
173  // check if the name changed and updoot accordingly
174  else if (systemIdentity.Username != user.Name)
175  {
176  Logger.LogDebug("User ID {0}'s system identity needs a refresh, updating database.", user.Id);
177  DatabaseContext.Users.Attach(user);
178  user.Name = systemIdentity.Username;
179  user.CanonicalName = user.Name.ToUpperInvariant();
180  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
181  }
182 
183  // Now that the bookeeping is done, tell them to fuck off if necessary
184  if (!user.Enabled.Value)
185  return Forbid();
186 
187  var token = await tokenFactory.CreateToken(user, cancellationToken).ConfigureAwait(false);
188  if (systemIdentity != null)
189  {
190  // expire the identity slightly after the auth token in case of lag
191  var identExpiry = token.ExpiresAt.Value;
192  identExpiry += tokenFactory.ValidationParameters.ClockSkew;
193  identExpiry += TimeSpan.FromSeconds(15);
194  identityCache.CacheSystemIdentity(user, systemIdentity, identExpiry);
195  }
196 
197  Logger.LogDebug("Successfully logged in user {0}!", user.Id);
198 
199  return Json(token);
200  }
201  }
202  #pragma warning restore CA1506
203  }
204 }
+ + +
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....
-
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
- +
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 System.Runtime.InteropServices.OSPlatform
- -
IActionResult Home()
Main page of the Application
-
string Username
The client&#39;s username
Definition: ApiHeaders.cs:86
-
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
-
Contains various cryptographic functions
-
readonly ICryptographySuite cryptographySuite
The ICryptographySuite for the HomeController
-
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
-
readonly ControlPanelConfiguration controlPanelConfiguration
The ControlPanelConfiguration for the HomeController
+ +
IActionResult Home()
Main page of the Application
+
string Username
The client's username
Definition: ApiHeaders.cs:86
+
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
+
Contains various cryptographic functions
+
readonly ICryptographySuite cryptographySuite
The ICryptographySuite for the HomeController
+
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
+
readonly ControlPanelConfiguration controlPanelConfiguration
The ControlPanelConfiguration for the HomeController
-
string Password
The client&#39;s password
Definition: ApiHeaders.cs:91
-
readonly IApplication application
The IApplication for the HomeController
+
string Password
The client's password
Definition: ApiHeaders.cs:91
+
readonly IApplication application
The IApplication for the HomeController
-
Routes to a server actions
Definition: Routes.cs:9
-
Main ApiController for the Application
+
Routes to a server actions
Definition: Routes.cs:9
+
Main ApiController for the Application
- -
readonly IIdentityCache identityCache
The IIdentityCache for the HomeController
- - -
bool IsTokenAuthentication
If the header uses password or JWT authentication
Definition: ApiHeaders.cs:96
+ +
readonly IIdentityCache identityCache
The IIdentityCache for the HomeController
+ + +
bool IsTokenAuthentication
If the header uses password or JWT authentication
Definition: ApiHeaders.cs:96
-
const string Root
The root controller
Definition: Routes.cs:14
+
const string Root
The root controller
Definition: Routes.cs:14
- -
long Id
The ID of the User
Definition: User.cs:15
- - -
readonly IBrowserResolver browserResolver
The IBrowserResolver 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
- - + +
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
+
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 ITokenFactory tokenFactory
The ITokenFactory for the HomeController
+
string Uid
A unique identifier for the user
+ +
diff --git a/_http_client_8cs.html b/_http_client_8cs.html index 1c273151ad..20b5343bff 100644 --- a/_http_client_8cs.html +++ b/_http_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/HttpClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -113,7 +96,7 @@ Namespaces diff --git a/_http_client_8cs_source.html b/_http_client_8cs_source.html index 11a6b85194..cf08b2136c 100644 --- a/_http_client_8cs_source.html +++ b/_http_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/HttpClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
HttpClient.cs
-Go to the documentation of this file.
1 using System;
2 using System.Net.Http;
3 using System.Threading;
4 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Client
7 {
9  sealed class HttpClient : IHttpClient
10  {
12  public TimeSpan Timeout
13  {
14  get => httpClient.Timeout;
15  set => httpClient.Timeout = value;
16  }
17 
21  readonly System.Net.Http.HttpClient httpClient;
22 
26  public HttpClient()
27  {
28  httpClient = new System.Net.Http.HttpClient();
29  }
30 
32  public void Dispose() => httpClient.Dispose();
33 
35  public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) => httpClient.SendAsync(request, cancellationToken);
36  }
37 }
TimeSpan Timeout
The request timeout
Definition: IHttpClient.cs:16
- - -
readonly System.Net.Http.HttpClient httpClient
The real System.Net.Http.HttpClient
Definition: HttpClient.cs:21
-
For sending HTTP requests
Definition: IHttpClient.cs:11
-
HttpClient()
Construct an HttpClient
Definition: HttpClient.cs:26
+Go to the documentation of this file.
1 using System;
2 using System.Net.Http;
3 using System.Threading;
4 using System.Threading.Tasks;
5 
7 {
9  sealed class HttpClient : IHttpClient
10  {
12  public TimeSpan Timeout
13  {
14  get => httpClient.Timeout;
15  set => httpClient.Timeout = value;
16  }
17 
21  readonly System.Net.Http.HttpClient httpClient;
22 
26  public HttpClient()
27  {
28  httpClient = new System.Net.Http.HttpClient();
29  }
30 
32  public void Dispose() => httpClient.Dispose();
33 
35  public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) => httpClient.SendAsync(request, cancellationToken);
36  }
37 }
+ +
readonly System.Net.Http.HttpClient httpClient
The real System.Net.Http.HttpClient
Definition: HttpClient.cs:21
+
For sending HTTP requests
Definition: IHttpClient.cs:11
+ +
HttpClient()
Construct an HttpClient
Definition: HttpClient.cs:26
- +
Task< HttpResponseMessage > SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
Send an HTTP request
diff --git a/_i_administration_client_8cs.html b/_i_administration_client_8cs.html index 61999414a7..847bfa835d 100644 --- a/_i_administration_client_8cs.html +++ b/_i_administration_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/IAdministrationClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_i_administration_client_8cs_source.html b/_i_administration_client_8cs_source.html index fe16f8f993..ac1a32ceda 100644 --- a/_i_administration_client_8cs_source.html +++ b/_i_administration_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/IAdministrationClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IAdministrationClient.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
4 
5 namespace Tgstation.Server.Client
6 {
10  public interface IAdministrationClient
11  {
17  Task<Administration> Read(CancellationToken cancellationToken);
18 
25  Task Update(Administration administration, CancellationToken cancellationToken);
26 
32  Task Restart(CancellationToken cancellationToken);
33  }
34 }
+Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
4 
6 {
10  public interface IAdministrationClient
11  {
17  Task<Administration> Read(CancellationToken cancellationToken);
18 
25  Task Update(Administration administration, CancellationToken cancellationToken);
26 
32  Task Restart(CancellationToken cancellationToken);
33  }
34 }
Task Restart(CancellationToken cancellationToken)
Restarts the TGS server
+ - - + -
Represents administrative server information
- - +
Represents administrative server information
+
Task< Administration > Read(CancellationToken cancellationToken)
Get the Administration represented by the IAdministrationClient
+ +
Task Update(Administration administration, CancellationToken cancellationToken)
Updates the Administration setttings
+
diff --git a/_i_api_client_8cs.html b/_i_api_client_8cs.html index 1c947358a9..cb9037ce0e 100644 --- a/_i_api_client_8cs.html +++ b/_i_api_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/IApiClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_i_api_client_8cs_source.html b/_i_api_client_8cs_source.html index 198b5344c7..fc150f8646 100644 --- a/_i_api_client_8cs_source.html +++ b/_i_api_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/IApiClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IApiClient.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 using Tgstation.Server.Api;
5 
6 namespace Tgstation.Server.Client
7 {
11  interface IApiClient : IDisposable
12  {
16  ApiHeaders Headers { get; set; }
17 
21  Uri Url { get; }
22 
26  TimeSpan Timeout { get; set; }
27 
32  void AddRequestLogger(IRequestLogger requestLogger);
33 
43  Task<TResult> Create<TBody, TResult>(string route, TBody body, CancellationToken cancellationToken);
44 
52  Task<TResult> Create<TResult>(string route, CancellationToken cancellationToken);
53 
61  Task<TResult> Read<TResult>(string route, CancellationToken cancellationToken);
62 
72  Task<TResult> Update<TBody, TResult>(string route, TBody body, CancellationToken cancellationToken);
73 
81  Task<TResult> Update<TResult>(string route, CancellationToken cancellationToken);
82 
91  Task Update<TBody>(string route, TBody body, CancellationToken cancellationToken);
92 
99  Task Delete(string route, CancellationToken cancellationToken);
100 
111  Task<TResult> Create<TBody, TResult>(string route, TBody body, long instanceId, CancellationToken cancellationToken);
112 
121  Task<TResult> Create<TResult>(string route, long instanceId, CancellationToken cancellationToken);
122 
131  Task<TResult> Patch<TResult>(string route, long instanceId, CancellationToken cancellationToken);
132 
141  Task<TResult> Read<TResult>(string route, long instanceId, CancellationToken cancellationToken);
142 
153  Task<TResult> Update<TBody, TResult>(string route, TBody body, long instanceId, CancellationToken cancellationToken);
154 
162  Task Delete(string route, long instanceId, CancellationToken cancellationToken);
163 
173  Task Delete<TBody>(string route, TBody body, long instanceId, CancellationToken cancellationToken);
174 
183  Task<TResult> Delete<TResult>(string route, long instanceId, CancellationToken cancellationToken);
184  }
185 }
- - -
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
-
For logging HTTP requests and responses
- +Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 using Tgstation.Server.Api;
5 
7 {
11  interface IApiClient : IDisposable
12  {
16  ApiHeaders Headers { get; set; }
17 
21  Uri Url { get; }
22 
26  TimeSpan Timeout { get; set; }
27 
32  void AddRequestLogger(IRequestLogger requestLogger);
33 
43  Task<TResult> Create<TBody, TResult>(string route, TBody body, CancellationToken cancellationToken);
44 
52  Task<TResult> Create<TResult>(string route, CancellationToken cancellationToken);
53 
61  Task<TResult> Read<TResult>(string route, CancellationToken cancellationToken);
62 
72  Task<TResult> Update<TBody, TResult>(string route, TBody body, CancellationToken cancellationToken);
73 
81  Task<TResult> Update<TResult>(string route, CancellationToken cancellationToken);
82 
91  Task Update<TBody>(string route, TBody body, CancellationToken cancellationToken);
92 
99  Task Delete(string route, CancellationToken cancellationToken);
100 
111  Task<TResult> Create<TBody, TResult>(string route, TBody body, long instanceId, CancellationToken cancellationToken);
112 
121  Task<TResult> Create<TResult>(string route, long instanceId, CancellationToken cancellationToken);
122 
131  Task<TResult> Patch<TResult>(string route, long instanceId, CancellationToken cancellationToken);
132 
141  Task<TResult> Read<TResult>(string route, long instanceId, CancellationToken cancellationToken);
142 
153  Task<TResult> Update<TBody, TResult>(string route, TBody body, long instanceId, CancellationToken cancellationToken);
154 
162  Task Delete(string route, long instanceId, CancellationToken cancellationToken);
163 
173  Task Delete<TBody>(string route, TBody body, long instanceId, CancellationToken cancellationToken);
174 
183  Task<TResult> Delete<TResult>(string route, long instanceId, CancellationToken cancellationToken);
184  }
185 }
ApiHeaders Headers
The ApiHeaders the IApiClient uses
Definition: IApiClient.cs:16
+ + +
TimeSpan Timeout
The request timeout
Definition: IApiClient.cs:26
+
Task Delete< TBody >(string route, TBody body, long instanceId, CancellationToken cancellationToken)
Run an HTTP DELETE request
+
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
+
Task< TResult > Patch< TResult >(string route, long instanceId, CancellationToken cancellationToken)
Run an HTTP PATCH request
+
Task< TResult > Create< TResult >(string route, CancellationToken cancellationToken)
Run an HTTP PUT request
+
Task Update< TBody >(string route, TBody body, CancellationToken cancellationToken)
Run an HTTP POST request
+
Task< TResult > Delete< TResult >(string route, long instanceId, CancellationToken cancellationToken)
Run an HTTP DELETE request
+
Task< TResult > Read< TResult >(string route, CancellationToken cancellationToken)
Run an HTTP GET request
+
Task< TResult > Create< TBody, TResult >(string route, TBody body, CancellationToken cancellationToken)
Run an HTTP PUT request
+
For logging HTTP requests and responses
+
Task Delete(string route, CancellationToken cancellationToken)
Run an HTTP DELETE request
+
Task< TResult > Update< TBody, TResult >(string route, TBody body, CancellationToken cancellationToken)
Run an HTTP POST request
+
Uri Url
The Uri pointing the tgstation-server
Definition: IApiClient.cs:21
+
void AddRequestLogger(IRequestLogger requestLogger)
Adds a requestLogger to the request pipeline
+ +
Task< TResult > Update< TResult >(string route, CancellationToken cancellationToken)
Run an HTTP POST request
-
Web interface for the API
Definition: IApiClient.cs:11
- +
Web interface for the API
Definition: IApiClient.cs:11
+
diff --git a/_i_api_client_factory_8cs.html b/_i_api_client_factory_8cs.html index 88084f7735..a91e8e5696 100644 --- a/_i_api_client_factory_8cs.html +++ b/_i_api_client_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/IApiClientFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

interface  Tgstation.Server.Client.IApiClientFactory - For creating IApiClients More...
+ For creating IApiClients More...
  + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_i_api_client_factory_8cs_source.html b/_i_api_client_factory_8cs_source.html index 6316ae978e..7b0a00e287 100644 --- a/_i_api_client_factory_8cs_source.html +++ b/_i_api_client_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/IApiClientFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IApiClientFactory.cs
-Go to the documentation of this file.
1 using System;
2 using Tgstation.Server.Api;
3 
4 namespace Tgstation.Server.Client
5 {
9  interface IApiClientFactory
10  {
17  IApiClient CreateApiClient(Uri url, ApiHeaders apiHeaders);
18  }
19 }
- - -
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
- -
Web interface for the API
Definition: IApiClient.cs:11
- - +Go to the documentation of this file.
1 using System;
2 using Tgstation.Server.Api;
3 
5 {
9  interface IApiClientFactory
10  {
17  IApiClient CreateApiClient(Uri url, ApiHeaders apiHeaders);
18  }
19 }
+ +
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
+
IApiClient CreateApiClient(Uri url, ApiHeaders apiHeaders)
Create an IApiClient
+ +
Web interface for the API
Definition: IApiClient.cs:11
+ +
diff --git a/_i_application_8cs.html b/_i_application_8cs.html index 2ec0bfafc3..51ce4cdef9 100644 --- a/_i_application_8cs.html +++ b/_i_application_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IApplication.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_application_8cs_source.html b/_i_application_8cs_source.html index 46912ac3fe..c9ccab6d79 100644 --- a/_i_application_8cs_source.html +++ b/_i_application_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IApplication.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IApplication.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Host.Core
4 {
8  public interface IApplication
9  {
13  string VersionPrefix { get; }
14 
18  string VersionString { get; }
19 
23  Version Version { get; }
24 
29  void Ready(Exception initializationError);
30  }
31 }
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
- - - +Go to the documentation of this file.
1 using System;
2 
4 {
8  public interface IApplication
9  {
13  string VersionPrefix { get; }
14 
18  string VersionString { get; }
19 
23  Version Version { get; }
24 
29  void Ready(Exception initializationError);
30  }
31 }
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
+
string VersionPrefix
Prefix to VersionString
Definition: IApplication.cs:13
+ +
void Ready(Exception initializationError)
Mark the IApplication as ready to run
+
string VersionString
A more verbose version of Version
Definition: IApplication.cs:18
+
Version Version
The version of the Application
Definition: IApplication.cs:23
diff --git a/_i_async_delayer_8cs.html b/_i_async_delayer_8cs.html index 40b2959ed9..6769b7d56d 100644 --- a/_i_async_delayer_8cs.html +++ b/_i_async_delayer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IAsyncDelayer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_async_delayer_8cs_source.html b/_i_async_delayer_8cs_source.html index 6eb3e71cd5..2bcc3c5791 100644 --- a/_i_async_delayer_8cs_source.html +++ b/_i_async_delayer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IAsyncDelayer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IAsyncDelayer.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
5 namespace Tgstation.Server.Host.Core
6 {
10  interface IAsyncDelayer
11  {
18  Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken);
19  }
20 }
- - - +Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
6 {
10  interface IAsyncDelayer
11  {
18  Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken);
19  }
20 }
+ +
Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan
diff --git a/_i_authentication_context_8cs.html b/_i_authentication_context_8cs.html index f3c9ec68c4..cdc4f363e5 100644 --- a/_i_authentication_context_8cs.html +++ b/_i_authentication_context_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/IAuthenticationContext.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_authentication_context_8cs_source.html b/_i_authentication_context_8cs_source.html index 9edfa9a5c5..d1bf62dd1f 100644 --- a/_i_authentication_context_8cs_source.html +++ b/_i_authentication_context_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/IAuthenticationContext.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IAuthenticationContext.cs
-Go to the documentation of this file.
1 using System;
4 
5 namespace Tgstation.Server.Host.Security
6 {
11  {
15  User User { get; }
16 
21 
27  ulong GetRight(RightsType rightsType);
28 
32  ISystemIdentity SystemIdentity { get; }
33  }
34 }
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
+Go to the documentation of this file.
1 using System;
4 
6 {
11  {
15  User User { get; }
16 
21 
27  ulong GetRight(RightsType rightsType);
28 
33  }
34 }
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
+
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
- -
Represents a user on the current System.Runtime.InteropServices.OSPlatform
+
Represents a user on the current System.Runtime.InteropServices.OSPlatform
- -
Represents the currently authenticated Api.Models.User
+
Represents the currently authenticated Api.Models.User
+
ISystemIdentity SystemIdentity
The ISystemIdentity of User if applicable
+ - + - - + +
diff --git a/_i_authentication_context_factory_8cs.html b/_i_authentication_context_factory_8cs.html index f15a13a7fb..a5b8c76bcf 100644 --- a/_i_authentication_context_factory_8cs.html +++ b/_i_authentication_context_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/IAuthenticationContextFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_authentication_context_factory_8cs_source.html b/_i_authentication_context_factory_8cs_source.html index 61e8c686e9..0ba456cda9 100644 --- a/_i_authentication_context_factory_8cs_source.html +++ b/_i_authentication_context_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/IAuthenticationContextFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IAuthenticationContextFactory.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
5 namespace Tgstation.Server.Host.Security
6 {
11  {
15  IAuthenticationContext CurrentAuthenticationContext { get; }
16 
25  Task CreateAuthenticationContext(long userId, long? instanceId, DateTimeOffset validAfter, CancellationToken cancellationToken);
26  }
27 }
- - -
Represents the currently authenticated Api.Models.User
- +Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
6 {
11  {
16 
25  Task CreateAuthenticationContext(long userId, long? instanceId, DateTimeOffset validAfter, CancellationToken cancellationToken);
26  }
27 }
+
Task CreateAuthenticationContext(long userId, long? instanceId, DateTimeOffset validAfter, CancellationToken cancellationToken)
Create an IAuthenticationContext to populate CurrentAuthenticationContext
+
Represents the currently authenticated Api.Models.User
+ +
IAuthenticationContext CurrentAuthenticationContext
The IAuthenticationContext the IAuthenticationContextFactory created
diff --git a/_i_byond_client_8cs.html b/_i_byond_client_8cs.html index d538fe8166..41e85e5d83 100644 --- a/_i_byond_client_8cs.html +++ b/_i_byond_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/IByondClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_byond_client_8cs_source.html b/_i_byond_client_8cs_source.html index 60b69d9fe3..6ad789c69f 100644 --- a/_i_byond_client_8cs_source.html +++ b/_i_byond_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/IByondClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IByondClient.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Client.Components
7 {
11  public interface IByondClient
12  {
18  Task<Byond> ActiveVersion(CancellationToken cancellationToken);
19 
25  Task<IReadOnlyList<Byond>> InstalledVersions(CancellationToken cancellationToken);
26 
33  Task<Byond> SetActiveVersion(Byond byond, CancellationToken cancellationToken);
34  }
35 }
- -
For managing the Byond installation
Definition: IByondClient.cs:11
- +Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
11  public interface IByondClient
12  {
18  Task<Byond> ActiveVersion(CancellationToken cancellationToken);
19 
25  Task<IReadOnlyList<Byond>> InstalledVersions(CancellationToken cancellationToken);
26 
33  Task<Byond> SetActiveVersion(Byond byond, CancellationToken cancellationToken);
34  }
35 }
+
For managing the Byond installation
Definition: IByondClient.cs:11
+
Task< IReadOnlyList< Byond > > InstalledVersions(CancellationToken cancellationToken)
Get all installed Byond System.Versions
-
Represents a BYOND installation
Definition: Byond.cs:8
- - + +
Task< Byond > ActiveVersion(CancellationToken cancellationToken)
Get the Byond active System.Version information
+
Task< Byond > SetActiveVersion(Byond byond, CancellationToken cancellationToken)
Updates the Byond information
+
Represents a BYOND installation
Definition: Byond.cs:8
+ +
diff --git a/_i_byond_executable_lock_8cs.html b/_i_byond_executable_lock_8cs.html index 58f05936e3..8aaf1983cb 100644 --- a/_i_byond_executable_lock_8cs.html +++ b/_i_byond_executable_lock_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Byond/IByondExecutableLock.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Byond
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_byond_executable_lock_8cs_source.html b/_i_byond_executable_lock_8cs_source.html index 1fdb8f08f5..99087f77b3 100644 --- a/_i_byond_executable_lock_8cs_source.html +++ b/_i_byond_executable_lock_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Byond/IByondExecutableLock.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IByondExecutableLock.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Host.Components.Byond
4 {
8  public interface IByondExecutableLock : IDisposable
9  {
13  Version Version { get; }
14 
18  string DreamDaemonPath { get; }
19 
23  string DreamMakerPath { get; }
24 
28  void DoNotDeleteThisSession();
29  }
30 }
- - -
Represents usage of the two primary BYOND server executables
+Go to the documentation of this file.
1 using System;
2 
4 {
8  public interface IByondExecutableLock : IDisposable
9  {
13  Version Version { get; }
14 
18  string DreamDaemonPath { get; }
19 
23  string DreamMakerPath { get; }
24 
29  }
30 }
+
string DreamMakerPath
The path to the dm/DreamMaker executable
+
Represents usage of the two primary BYOND server executables
+
string DreamDaemonPath
The path to the DreamDaemon executable
+
void DoNotDeleteThisSession()
Call if, during a detach, this version should not be deleted
- +
Version Version
The System.Version of the locked executables
diff --git a/_i_byond_installer_8cs.html b/_i_byond_installer_8cs.html index 4836432c02..1891e5203a 100644 --- a/_i_byond_installer_8cs.html +++ b/_i_byond_installer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Byond/IByondInstaller.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Byond
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_byond_installer_8cs_source.html b/_i_byond_installer_8cs_source.html index a3be4730c0..edb4a1facb 100644 --- a/_i_byond_installer_8cs_source.html +++ b/_i_byond_installer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Byond/IByondInstaller.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IByondInstaller.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
5 namespace Tgstation.Server.Host.Components.Byond
6 {
10  interface IByondInstaller
11  {
15  string DreamDaemonName { get; }
16 
20  string DreamMakerName { get; }
21 
28  Task<byte[]> DownloadVersion(Version version, CancellationToken cancellationToken);
29 
37  Task InstallByond(string path, Version version, CancellationToken cancellationToken);
38 
44  Task CleanCache(CancellationToken cancellationToken);
45  }
46 }
- - -
For downloading and installing BYOND extractions for a given system
- +Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
6 {
10  interface IByondInstaller
11  {
15  string DreamDaemonName { get; }
16 
20  string DreamMakerName { get; }
21 
28  Task<byte[]> DownloadVersion(Version version, CancellationToken cancellationToken);
29 
37  Task InstallByond(string path, Version version, CancellationToken cancellationToken);
38 
44  Task CleanCache(CancellationToken cancellationToken);
45  }
46 }
string DreamMakerName
Get the file name of the DreamMaker executable
+
Task< byte[]> DownloadVersion(Version version, CancellationToken cancellationToken)
Download a given BYOND version
+ +
Task InstallByond(string path, Version version, CancellationToken cancellationToken)
Does actions necessary to get an extracted BYOND installation working
+
For downloading and installing BYOND extractions for a given system
+
Task CleanCache(CancellationToken cancellationToken)
Attempts to cleans the BYOND cache folder for the system
+
string DreamDaemonName
Get the file name of the DreamDaemon executable
diff --git a/_i_byond_manager_8cs.html b/_i_byond_manager_8cs.html index ee36a1257c..ac51ae2c2e 100644 --- a/_i_byond_manager_8cs.html +++ b/_i_byond_manager_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Byond/IByondManager.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Byond
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_byond_manager_8cs_source.html b/_i_byond_manager_8cs_source.html index 3fb9826ae8..4b3dd6a0f4 100644 --- a/_i_byond_manager_8cs_source.html +++ b/_i_byond_manager_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Byond/IByondManager.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IByondManager.cs
-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;
6 
7 namespace Tgstation.Server.Host.Components.Byond
8 {
13  {
17  Version ActiveVersion { get; }
18 
22  IReadOnlyList<Version> InstalledVersions { get; }
23 
30  Task ChangeVersion(Version version, CancellationToken cancellationToken);
31 
38  Task<IByondExecutableLock> UseExecutables(Version requiredVersion, CancellationToken cancellationToken);
39  }
40 }
- - -
For managing the BYOND installation
+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;
6 
8 {
13  {
17  Version ActiveVersion { get; }
18 
22  IReadOnlyList<Version> InstalledVersions { get; }
23 
30  Task ChangeVersion(Version version, CancellationToken cancellationToken);
31 
38  Task<IByondExecutableLock> UseExecutables(Version requiredVersion, CancellationToken cancellationToken);
39  }
40 }
+
Version ActiveVersion
The currently active BYOND version
+
Task ChangeVersion(Version version, CancellationToken cancellationToken)
Change the active BYOND version
+ +
IReadOnlyList< Version > InstalledVersions
The installed BYOND versions
+
Task< IByondExecutableLock > UseExecutables(Version requiredVersion, CancellationToken cancellationToken)
Lock the current installation's location and return a IByondExecutableLock
-
diff --git a/_i_chat_8cs.html b/_i_chat_8cs.html index 2d1e9f1180..9f1102f41b 100644 --- a/_i_chat_8cs.html +++ b/_i_chat_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/IChat.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_chat_8cs_source.html b/_i_chat_8cs_source.html index fdc5419025..7f3bd1f57f 100644 --- a/_i_chat_8cs_source.html +++ b/_i_chat_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/IChat.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IChat.cs
-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;
7 
8 namespace Tgstation.Server.Host.Components.Chat
9 {
13  public interface IChat : IHostedService, IDisposable
14  {
20  bool Connected(long connectionId);
21 
26  void RegisterCommandHandler(ICustomCommandHandler customCommandHandler);
27 
34  Task ChangeSettings(ChatBot newSettings, CancellationToken cancellationToken);
35 
42  Task DeleteConnection(long connectionId, CancellationToken cancellationToken);
43 
51  Task ChangeChannels(long connectionId, IEnumerable<Api.Models.ChatChannel> newChannels, CancellationToken cancellationToken);
52 
60  Task SendMessage(string message, IEnumerable<ulong> channelIds, CancellationToken cancellationToken);
61 
68  Task SendWatchdogMessage(string message, CancellationToken cancellationToken);
69 
76  Task SendUpdateMessage(string message, CancellationToken cancellationToken);
77 
86  Task<IJsonTrackingContext> TrackJsons(string basePath, string channelsJsonName, string commandsJsonName, CancellationToken cancellationToken);
87  }
88 }
- - -
Manage the server chat bots
Definition: ChatBot.cs:10
-
For managing connected chat services
Definition: IChat.cs:13
+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;
7 
9 {
13  public interface IChat : IHostedService, IDisposable
14  {
20  bool Connected(long connectionId);
21 
26  void RegisterCommandHandler(ICustomCommandHandler customCommandHandler);
27 
34  Task ChangeSettings(ChatBot newSettings, CancellationToken cancellationToken);
35 
42  Task DeleteConnection(long connectionId, CancellationToken cancellationToken);
43 
51  Task ChangeChannels(long connectionId, IEnumerable<Api.Models.ChatChannel> newChannels, CancellationToken cancellationToken);
52 
60  Task SendMessage(string message, IEnumerable<ulong> channelIds, CancellationToken cancellationToken);
61 
68  Task SendWatchdogMessage(string message, CancellationToken cancellationToken);
69 
76  Task SendUpdateMessage(string message, CancellationToken cancellationToken);
77 
86  Task<IJsonTrackingContext> TrackJsons(string basePath, string channelsJsonName, string commandsJsonName, CancellationToken cancellationToken);
87  }
88 }
+
void RegisterCommandHandler(ICustomCommandHandler customCommandHandler)
Registers a customCommandHandler to use
+ +
Task SendUpdateMessage(string message, CancellationToken cancellationToken)
Send a chat message to configured update channels
+
Task SendWatchdogMessage(string message, CancellationToken cancellationToken)
Send a chat message to configured watchdog channels
+
Task ChangeSettings(ChatBot newSettings, CancellationToken cancellationToken)
Change chat settings. If the ChatBot.Id is not currently in use, a new connection will be made instea...
+
Manage the server chat bots
Definition: ChatBot.cs:9
+
For managing connected chat services
Definition: IChat.cs:13
- -
Handles Commands.ICommands that map to those defined in a IJsonTrackingContext
- +
Task< IJsonTrackingContext > TrackJsons(string basePath, string channelsJsonName, string commandsJsonName, CancellationToken cancellationToken)
Start tracking json files for commands and channels
+ +
Task ChangeChannels(long connectionId, IEnumerable< Api.Models.ChatChannel > newChannels, CancellationToken cancellationToken)
Change chat channels
+
bool Connected(long connectionId)
If a given set of ChatBot is connected
+
Task DeleteConnection(long connectionId, CancellationToken cancellationToken)
Disconnects and deletes a given connection
+
Task SendMessage(string message, IEnumerable< ulong > channelIds, CancellationToken cancellationToken)
Send a chat message to a given set of channelIds
+
Handles Commands.ICommands that map to those defined in a IJsonTrackingContext
+ - +
diff --git a/_i_chat_bots_client_8cs.html b/_i_chat_bots_client_8cs.html index c8b51ca6a4..ba2b25170b 100644 --- a/_i_chat_bots_client_8cs.html +++ b/_i_chat_bots_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/IChatBotsClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_chat_bots_client_8cs_source.html b/_i_chat_bots_client_8cs_source.html index 8e25f71807..a6a599631a 100644 --- a/_i_chat_bots_client_8cs_source.html +++ b/_i_chat_bots_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/IChatBotsClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IChatBotsClient.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Client.Components
7 {
11  public interface IChatBotsClient
12  {
18  Task<IReadOnlyList<ChatBot>> List(CancellationToken cancellationToken);
19 
26  Task<ChatBot> Create(ChatBot settings, CancellationToken cancellationToken);
27 
34  Task<ChatBot> Update(ChatBot settings, CancellationToken cancellationToken);
35 
42  Task<ChatBot> GetId(ChatBot settings, CancellationToken cancellationToken);
43 
50  Task Delete(ChatBot settings, CancellationToken cancellationToken);
51  }
52 }
- - - +Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
11  public interface IChatBotsClient
12  {
18  Task<IReadOnlyList<ChatBot>> List(CancellationToken cancellationToken);
19 
26  Task<ChatBot> Create(ChatBot settings, CancellationToken cancellationToken);
27 
34  Task<ChatBot> Update(ChatBot settings, CancellationToken cancellationToken);
35 
42  Task<ChatBot> GetId(ChatBot settings, CancellationToken cancellationToken);
43 
50  Task Delete(ChatBot settings, CancellationToken cancellationToken);
51  }
52 }
+ +
Task< ChatBot > Update(ChatBot settings, CancellationToken cancellationToken)
Updates a ChatBot's setttings
+ - - +
Task Delete(ChatBot settings, CancellationToken cancellationToken)
Delete a ChatBot
+
Task< ChatBot > Create(ChatBot settings, CancellationToken cancellationToken)
Create a ChatBot
+ +
Task< IReadOnlyList< ChatBot > > List(CancellationToken cancellationToken)
List the ChatBots
+
Task< ChatBot > GetId(ChatBot settings, CancellationToken cancellationToken)
Get a ChatBot's setttings
+
diff --git a/_i_chat_factory_8cs.html b/_i_chat_factory_8cs.html index c184a25ef8..db6f304939 100644 --- a/_i_chat_factory_8cs.html +++ b/_i_chat_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/IChatFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

interface  Tgstation.Server.Host.Components.Chat.IChatFactory - For creating IChats More...
+ For creating IChats More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_chat_factory_8cs_source.html b/_i_chat_factory_8cs_source.html index 1ff7743f84..e16fed2c9b 100644 --- a/_i_chat_factory_8cs_source.html +++ b/_i_chat_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/IChatFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IChatFactory.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
3 using Tgstation.Server.Host.IO;
4 
5 namespace Tgstation.Server.Host.Components.Chat
6 {
10  interface IChatFactory
11  {
19  IChat CreateChat(IIOManager ioManager, ICommandFactory commandFactory, IEnumerable<Models.ChatBot> initialChatBots);
20  }
21 }
- - - -
For managing connected chat services
Definition: IChat.cs:13
- +Go to the documentation of this file.
1 using System.Collections.Generic;
3 using Tgstation.Server.Host.IO;
4 
6 {
10  interface IChatFactory
11  {
19  IChat CreateChat(IIOManager ioManager, ICommandFactory commandFactory, IEnumerable<Models.ChatBot> initialChatBots);
20  }
21 }
+
IChat CreateChat(IIOManager ioManager, ICommandFactory commandFactory, IEnumerable< Models.ChatBot > initialChatBots)
Create a IChat
+ +
For managing connected chat services
Definition: IChat.cs:13
+ - - -
Interface for using filesystems
Definition: IIOManager.cs:11
- - + + +
Interface for using filesystems
Definition: IIOManager.cs:11
+ +
diff --git a/_i_claims_injector_8cs.html b/_i_claims_injector_8cs.html index 134a1f49c7..3705a7ef95 100644 --- a/_i_claims_injector_8cs.html +++ b/_i_claims_injector_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/IClaimsInjector.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

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

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_claims_injector_8cs_source.html b/_i_claims_injector_8cs_source.html index 141dacf5c3..40bbf40a83 100644 --- a/_i_claims_injector_8cs_source.html +++ b/_i_claims_injector_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/IClaimsInjector.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
5 namespace Tgstation.Server.Host.Security
6 {
10  interface IClaimsInjector
11  {
18  Task InjectClaimsIntoContext(TokenValidatedContext tokenValidatedContext, CancellationToken cancellationToken);
19  }
20 }
- -
For injecting System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look for ...
- +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
+ +
For injecting System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look for
diff --git a/_i_comm_context_8cs.html b/_i_comm_context_8cs.html index fbb14ffd30..45f928c6e6 100644 --- a/_i_comm_context_8cs.html +++ b/_i_comm_context_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/ICommContext.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Interop
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_comm_context_8cs_source.html b/_i_comm_context_8cs_source.html index c0d0e2fb82..f058970ec5 100644 --- a/_i_comm_context_8cs_source.html +++ b/_i_comm_context_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/ICommContext.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ICommContext.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Host.Components.Interop
4 {
9  {
14  void RegisterHandler(ICommHandler handler);
15  }
16 }
- -
Represents a registration of an interop session
Definition: ICommContext.cs:8
+Go to the documentation of this file.
1 using System;
2 
4 {
9  {
14  void RegisterHandler(ICommHandler handler);
15  }
16 }
Represents a registration of an interop session
Definition: ICommContext.cs:8
+
void RegisterHandler(ICommHandler handler)
Register a handler with the ICommContext
+ - - +
diff --git a/_i_comm_handler_8cs.html b/_i_comm_handler_8cs.html index 74c8592ac8..bd7e4c827e 100644 --- a/_i_comm_handler_8cs.html +++ b/_i_comm_handler_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/ICommHandler.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

interface  Tgstation.Server.Host.Components.Interop.ICommHandler - Handles CommCommands More...
+ Handles CommCommands More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Interop
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_comm_handler_8cs_source.html b/_i_comm_handler_8cs_source.html index 179d2f9998..eccca6e1f9 100644 --- a/_i_comm_handler_8cs_source.html +++ b/_i_comm_handler_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/ICommHandler.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ICommHandler.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
4 namespace Tgstation.Server.Host.Components.Interop
5 {
9  interface ICommHandler
10  {
17  Task HandleInterop(CommCommand command, CancellationToken cancellationToken);
18  }
19 }
- - - - +Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
5 {
9  interface ICommHandler
10  {
17  Task HandleInterop(CommCommand command, CancellationToken cancellationToken);
18  }
19 }
Task HandleInterop(CommCommand command, CancellationToken cancellationToken)
Handle a command
+ + +
diff --git a/_i_command_8cs.html b/_i_command_8cs.html index 24f447ae76..680171a083 100644 --- a/_i_command_8cs.html +++ b/_i_command_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/ICommand.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
namespace  Tgstation.Server.Host.Components.Chat.Commands
 
@@ -114,7 +103,7 @@ Namespaces diff --git a/_i_command_8cs_source.html b/_i_command_8cs_source.html index 63701aef1b..798187232b 100644 --- a/_i_command_8cs_source.html +++ b/_i_command_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/ICommand.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ICommand.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
4 namespace Tgstation.Server.Host.Components.Chat.Commands
5 {
9  public interface ICommand
10  {
14  string Name { get; }
15 
19  string HelpText { get; }
20 
24  bool AdminOnly { get; }
25 
33  Task<string> Invoke(string arguments, User user, CancellationToken cancellationToken);
34  }
35 }
- -
Represents a tgs_chat_user datum
Definition: User.cs:10
-
Represents a command that can be invoked by talking to chat bots
Definition: ICommand.cs:9
- +Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
5 {
9  public interface ICommand
10  {
14  string Name { get; }
15 
19  string HelpText { get; }
20 
24  bool AdminOnly { get; }
25 
33  Task<string> Invoke(string arguments, User user, CancellationToken cancellationToken);
34  }
35 }
Task< string > Invoke(string arguments, User user, CancellationToken cancellationToken)
Invoke the ICommand
+
bool AdminOnly
If the command should only be available to Users who's User.Channel has Channel.IsAdminChannel set
Definition: ICommand.cs:24
+ +
Represents a tgs_chat_user datum
Definition: User.cs:10
+
string Name
The text to invoke the command. May not be "?" or "help" (case-insensitive)
Definition: ICommand.cs:14
+
Represents a command that can be invoked by talking to chat bots
Definition: ICommand.cs:9
+
string HelpText
The help text to display when queires are made about the command
Definition: ICommand.cs:19
diff --git a/_i_command_factory_8cs.html b/_i_command_factory_8cs.html index 55d2b1bcc8..e01d5cfe3d 100644 --- a/_i_command_factory_8cs.html +++ b/_i_command_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/ICommandFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

interface  Tgstation.Server.Host.Components.Chat.Commands.ICommandFactory - Factory for built in ICommands More...
+ Factory for built in ICommands More...
  + + + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
namespace  Tgstation.Server.Host.Components.Chat.Commands
 
@@ -114,7 +103,7 @@ Namespaces diff --git a/_i_command_factory_8cs_source.html b/_i_command_factory_8cs_source.html index fe7d4fd8a0..808df8769d 100644 --- a/_i_command_factory_8cs_source.html +++ b/_i_command_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/ICommandFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ICommandFactory.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 
3 namespace Tgstation.Server.Host.Components.Chat.Commands
4 {
8  interface ICommandFactory
9  {
14  IReadOnlyList<ICommand> GenerateCommands();
15  }
16 }
- - - +Go to the documentation of this file.
1 using System.Collections.Generic;
2 
4 {
8  interface ICommandFactory
9  {
14  IReadOnlyList<ICommand> GenerateCommands();
15  }
16 }
+
IReadOnlyList< ICommand > GenerateCommands()
Generate builtin ICommands
+
diff --git a/_i_compile_job_consumer_8cs.html b/_i_compile_job_consumer_8cs.html index 99c59ac8c7..7b05f13190 100644 --- a/_i_compile_job_consumer_8cs.html +++ b/_i_compile_job_consumer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Compiler/ICompileJobConsumer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Compiler
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_compile_job_consumer_8cs_source.html b/_i_compile_job_consumer_8cs_source.html index 231008f8ed..a45da3cbfd 100644 --- a/_i_compile_job_consumer_8cs_source.html +++ b/_i_compile_job_consumer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Compiler/ICompileJobConsumer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
7 namespace Tgstation.Server.Host.Components.Compiler
8 {
13  {
20  Task LoadCompileJob(CompileJob job, CancellationToken cancellationToken);
21  }
22 }
- +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.html b/_i_configuration_8cs.html index 209c3146b6..4bef0bfc76 100644 --- a/_i_configuration_8cs.html +++ b/_i_configuration_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/StaticFiles/IConfiguration.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.StaticFiles
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_configuration_8cs_source.html b/_i_configuration_8cs_source.html index 7d478de963..270b73e490 100644 --- a/_i_configuration_8cs_source.html +++ b/_i_configuration_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/StaticFiles/IConfiguration.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IConfiguration.cs
-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 
9 namespace Tgstation.Server.Host.Components.StaticFiles
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
+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 System.Runtime.InteropServices.OSPlatform
-
For managing the Configuration directory
+
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
+
Task< bool > CreateDirectory(string configurationRelativePath, ISystemIdentity systemIdentity, CancellationToken cancellationToken)
Create an empty directory at configurationRelativePath
+ - +
Task< ServerSideModifications > CopyDMFilesTo(string dmeFile, string destination, CancellationToken cancellationToken)
Copies all files in the CodeModifications directory to destination
+ +
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_configuration_client_8cs.html b/_i_configuration_client_8cs.html index fa7cfbe181..9f4aa455fc 100644 --- a/_i_configuration_client_8cs.html +++ b/_i_configuration_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/IConfigurationClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_configuration_client_8cs_source.html b/_i_configuration_client_8cs_source.html index 7a04e53d4f..2c3b23d7fd 100644 --- a/_i_configuration_client_8cs_source.html +++ b/_i_configuration_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/IConfigurationClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IConfigurationClient.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Client.Components
7 {
11  public interface IConfigurationClient
12  {
19  Task<IReadOnlyList<ConfigurationFile>> List(string directory, CancellationToken cancellationToken);
20 
27  Task<ConfigurationFile> Read(ConfigurationFile file, CancellationToken cancellationToken);
28 
35  Task<ConfigurationFile> Write(ConfigurationFile file, CancellationToken cancellationToken);
36 
43  Task DeleteEmptyDirectory(ConfigurationFile directory, CancellationToken cancellationToken);
44 
51  Task<ConfigurationFile> CreateDirectory(ConfigurationFile directory, CancellationToken cancellationToken);
52  }
53 }
- - +Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
11  public interface IConfigurationClient
12  {
19  Task<IReadOnlyList<ConfigurationFile>> List(string directory, CancellationToken cancellationToken);
20 
27  Task<ConfigurationFile> Read(ConfigurationFile file, CancellationToken cancellationToken);
28 
35  Task<ConfigurationFile> Write(ConfigurationFile file, CancellationToken cancellationToken);
36 
43  Task DeleteEmptyDirectory(ConfigurationFile directory, CancellationToken cancellationToken);
44 
51  Task<ConfigurationFile> CreateDirectory(ConfigurationFile directory, CancellationToken cancellationToken);
52  }
53 }
Task< ConfigurationFile > Write(ConfigurationFile file, CancellationToken cancellationToken)
Overwrite a ConfigurationFile file
+ +
Task< ConfigurationFile > CreateDirectory(ConfigurationFile directory, CancellationToken cancellationToken)
Creates an empty directory
+
Task< IReadOnlyList< ConfigurationFile > > List(string directory, CancellationToken cancellationToken)
List configuration files
+ +
Task DeleteEmptyDirectory(ConfigurationFile directory, CancellationToken cancellationToken)
Delete an empty directory
Represents a game configuration file. Create and delete actions uncerimonuously overwrite/delete file...
- - - + + +
Task< ConfigurationFile > Read(ConfigurationFile file, CancellationToken cancellationToken)
Read a ConfigurationFile file
+
diff --git a/_i_console_8cs.html b/_i_console_8cs.html index 3abb3e0778..5497d3c8f7 100644 --- a/_i_console_8cs.html +++ b/_i_console_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/IConsole.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.IO
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_console_8cs_source.html b/_i_console_8cs_source.html index 15e1707b6c..86bb465bb9 100644 --- a/_i_console_8cs_source.html +++ b/_i_console_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/IConsole.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IConsole.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
4 namespace Tgstation.Server.Host.IO
5 {
9  interface IConsole
10  {
14  bool Available { get; }
15 
23  Task WriteAsync(string text, bool newLine, CancellationToken cancellationToken);
24 
30  Task PressAnyKeyAsync(CancellationToken cancellationToken);
31 
38  Task<string> ReadLineAsync(bool usePasswordChar, CancellationToken cancellationToken);
39  }
40 }
-
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 
23  Task WriteAsync(string text, bool newLine, CancellationToken cancellationToken);
24 
30  Task PressAnyKeyAsync(CancellationToken cancellationToken);
31 
38  Task<string> ReadLineAsync(bool usePasswordChar, CancellationToken cancellationToken);
39  }
40 }
Abstraction for System.Console
Definition: IConsole.cs:9
+
bool Available
If the IConsole is visible to the user
Definition: IConsole.cs:14
+
Task< string > ReadLineAsync(bool usePasswordChar, CancellationToken cancellationToken)
Read a line from the IConsole
+
Task WriteAsync(string text, bool newLine, CancellationToken cancellationToken)
Write some text to the IConsole
+
Task PressAnyKeyAsync(CancellationToken cancellationToken)
Wait for a key press on the IConsole
+
diff --git a/_i_credentials_provider_8cs.html b/_i_credentials_provider_8cs.html index 7da6219fb8..71bbe2ee2f 100644 --- a/_i_credentials_provider_8cs.html +++ b/_i_credentials_provider_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Repository/ICredentialsProvider.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Repository
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_credentials_provider_8cs_source.html b/_i_credentials_provider_8cs_source.html index 03737fd776..072f1905f8 100644 --- a/_i_credentials_provider_8cs_source.html +++ b/_i_credentials_provider_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Repository/ICredentialsProvider.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ICredentialsProvider.cs
-Go to the documentation of this file.
1 using LibGit2Sharp.Handlers;
2 
3 namespace Tgstation.Server.Host.Components.Repository
4 {
9  {
16  CredentialsHandler GenerateHandler(string username, string password);
17  }
18 }
- - - - +Go to the documentation of this file.
1 using LibGit2Sharp.Handlers;
2 
4 {
9  {
16  CredentialsHandler GenerateHandler(string username, string password);
17  }
18 }
+
CredentialsHandler GenerateHandler(string username, string password)
Generate a CredentialsHandler from a given username and password
+
diff --git a/_i_cryptography_suite_8cs.html b/_i_cryptography_suite_8cs.html index 75b9bb63a6..9972c5d8ed 100644 --- a/_i_cryptography_suite_8cs.html +++ b/_i_cryptography_suite_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/ICryptographySuite.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_cryptography_suite_8cs_source.html b/_i_cryptography_suite_8cs_source.html index b7986d9db2..f67de7a822 100644 --- a/_i_cryptography_suite_8cs_source.html +++ b/_i_cryptography_suite_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/ICryptographySuite.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ICryptographySuite.cs
-Go to the documentation of this file.
2 
3 namespace Tgstation.Server.Host.Security
4 {
8  public interface ICryptographySuite
9  {
15  byte[] GetSecureBytes(uint amount);
16 
23  void SetUserPassword(User user, string newPassword, bool newUser);
24 
31  bool CheckUserPassword(User user, string password);
32 
37  string GetSecureString();
38  }
39 }
+Go to the documentation of this file.
2 
4 {
8  public interface ICryptographySuite
9  {
15  byte[] GetSecureBytes(uint amount);
16 
23  void SetUserPassword(User user, string newPassword, bool newUser);
24 
31  bool CheckUserPassword(User user, string password);
32 
37  string GetSecureString();
38  }
39 }
bool CheckUserPassword(User user, string password)
Checks a given password matches a given user 's User.PasswordHash. This may result in User....
-
Contains various cryptographic functions
+
byte [] GetSecureBytes(uint amount)
Generates a secure set of bytes
+
Contains various cryptographic functions
- - - + +
void SetUserPassword(User user, string newPassword, bool newUser)
Sets a User.PasswordHash for a given user
+
string GetSecureString()
Generates a 40-length secure ascii string
+ + +
diff --git a/_i_custom_command_handler_8cs.html b/_i_custom_command_handler_8cs.html index d67046ec99..c2f8fb7d47 100644 --- a/_i_custom_command_handler_8cs.html +++ b/_i_custom_command_handler_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/ICustomCommandHandler.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

interface  Tgstation.Server.Host.Components.Chat.ICustomCommandHandler - Handles Commands.ICommands that map to those defined in a IJsonTrackingContext More...
+ Handles Commands.ICommands that map to those defined in a IJsonTrackingContext More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_custom_command_handler_8cs_source.html b/_i_custom_command_handler_8cs_source.html index d6575bf2c6..f6c508a297 100644 --- a/_i_custom_command_handler_8cs_source.html +++ b/_i_custom_command_handler_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/ICustomCommandHandler.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ICustomCommandHandler.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
4 namespace Tgstation.Server.Host.Components.Chat
5 {
9  public interface ICustomCommandHandler
10  {
19  Task<string> HandleChatCommand(string commandName, string arguments, User sender, CancellationToken cancellationToken);
20  }
21 }
- -
Represents a tgs_chat_user datum
Definition: User.cs:10
-
Handles Commands.ICommands that map to those defined in a IJsonTrackingContext
- +Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
5 {
9  public interface ICustomCommandHandler
10  {
19  Task<string> HandleChatCommand(string commandName, string arguments, User sender, CancellationToken cancellationToken);
20  }
21 }
+
Represents a tgs_chat_user datum
Definition: User.cs:10
+
Handles Commands.ICommands that map to those defined in a IJsonTrackingContext
+
Task< string > HandleChatCommand(string commandName, string arguments, User sender, CancellationToken cancellationToken)
Handle a chat command
diff --git a/_i_d_b_connection_factory_8cs.html b/_i_d_b_connection_factory_8cs.html index 70589a5570..154d781989 100644 --- a/_i_d_b_connection_factory_8cs.html +++ b/_i_d_b_connection_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IDBConnectionFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_d_b_connection_factory_8cs_source.html b/_i_d_b_connection_factory_8cs_source.html index 86ea4a81ff..5f73fd0f0e 100644 --- a/_i_d_b_connection_factory_8cs_source.html +++ b/_i_d_b_connection_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IDBConnectionFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IDBConnectionFactory.cs
-Go to the documentation of this file.
1 using System.Data.Common;
3 
4 namespace Tgstation.Server.Host.Core
5 {
10  {
17  DbConnection CreateConnection(string connectionString, DatabaseType databaseType);
18  }
19 }
- - +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
- - - +
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 068b97ccfe..d9e4a8d19f 100644 --- a/_i_database_context_8cs.html +++ b/_i_database_context_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/IDatabaseContext.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_database_context_8cs_source.html b/_i_database_context_8cs_source.html index 4cd144979a..334e7122b5 100644 --- a/_i_database_context_8cs_source.html +++ b/_i_database_context_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/IDatabaseContext.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
6 namespace Tgstation.Server.Host.Models
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 }
+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
- - +
DbSet< WatchdogReattachInformation > WatchdogReattachInformations
The DbSet<TEntity> for Models.WatchdogReattachInformations
+
DbSet< ReattachInformation > ReattachInformations
The DbSet<TEntity> for Models.ReattachInformations
+ +
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
diff --git a/_i_database_context_factory_8cs.html b/_i_database_context_factory_8cs.html index 4ca7937d55..25e36111c0 100644 --- a/_i_database_context_factory_8cs.html +++ b/_i_database_context_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IDatabaseContextFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_database_context_factory_8cs_source.html b/_i_database_context_factory_8cs_source.html index b8cb1c51dc..22fd333f40 100644 --- a/_i_database_context_factory_8cs_source.html +++ b/_i_database_context_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IDatabaseContextFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IDatabaseContextFactory.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading.Tasks;
4 
5 namespace Tgstation.Server.Host.Core
6 {
11  {
17  Task UseContext(Func<IDatabaseContext, Task> operation);
18  }
19 }
- - -
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
- - - +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
+ +
diff --git a/_i_database_seeder_8cs.html b/_i_database_seeder_8cs.html index 6d1b145cb8..7c8d78457a 100644 --- a/_i_database_seeder_8cs.html +++ b/_i_database_seeder_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/IDatabaseSeeder.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_database_seeder_8cs_source.html b/_i_database_seeder_8cs_source.html index 76df6b208e..a8a7eb1319 100644 --- a/_i_database_seeder_8cs_source.html +++ b/_i_database_seeder_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/IDatabaseSeeder.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IDatabaseSeeder.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
4 namespace Tgstation.Server.Host.Models
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
- +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
diff --git a/_i_dmb_factory_8cs.html b/_i_dmb_factory_8cs.html index 144d4da88c..49e6e2ed75 100644 --- a/_i_dmb_factory_8cs.html +++ b/_i_dmb_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Compiler/IDmbFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

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

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Compiler
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_dmb_factory_8cs_source.html b/_i_dmb_factory_8cs_source.html index f22edce58d..2797120e44 100644 --- a/_i_dmb_factory_8cs_source.html +++ b/_i_dmb_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Compiler/IDmbFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IDmbFactory.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Host.Components.Compiler
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 }
- - - -
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
- - + +
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
+ +
diff --git a/_i_dmb_provider_8cs.html b/_i_dmb_provider_8cs.html index fa3d05543b..5e0df9d4ca 100644 --- a/_i_dmb_provider_8cs.html +++ b/_i_dmb_provider_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/IDmbProvider.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_dmb_provider_8cs_source.html b/_i_dmb_provider_8cs_source.html index 78d35e4389..60e522d8da 100644 --- a/_i_dmb_provider_8cs_source.html +++ b/_i_dmb_provider_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/IDmbProvider.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IDmbProvider.cs
-Go to the documentation of this file.
1 using System;
3 
4 namespace Tgstation.Server.Host.Components
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 }
+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
- - -
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
+
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
+ + +
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
- - + +
diff --git a/_i_dream_daemon_client_8cs.html b/_i_dream_daemon_client_8cs.html index c78382f3b9..84af78ce74 100644 --- a/_i_dream_daemon_client_8cs.html +++ b/_i_dream_daemon_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/IDreamDaemonClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_dream_daemon_client_8cs_source.html b/_i_dream_daemon_client_8cs_source.html index 08d10f3007..0b33836f84 100644 --- a/_i_dream_daemon_client_8cs_source.html +++ b/_i_dream_daemon_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/IDreamDaemonClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IDreamDaemonClient.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
4 
5 namespace Tgstation.Server.Client.Components
6 {
10  public interface IDreamDaemonClient
11  {
17  Task<DreamDaemon> Read(CancellationToken cancellationToken);
18 
24  Task<Job> Start(CancellationToken cancellationToken);
25 
31  Task<Job> Restart(CancellationToken cancellationToken);
32 
38  Task Shutdown(CancellationToken cancellationToken);
39 
46  Task<DreamDaemon> Update(DreamDaemon dreamDaemon, CancellationToken cancellationToken);
47  }
48 }
- - +Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
4 
6 {
10  public interface IDreamDaemonClient
11  {
17  Task<DreamDaemon> Read(CancellationToken cancellationToken);
18 
24  Task<Job> Start(CancellationToken cancellationToken);
25 
31  Task<Job> Restart(CancellationToken cancellationToken);
32 
38  Task Shutdown(CancellationToken cancellationToken);
39 
46  Task<DreamDaemon> Update(DreamDaemon dreamDaemon, CancellationToken cancellationToken);
47  }
48 }
- - -
Represents an instance of BYOND&#39;s DreamDaemon game server. Create action starts the server...
Definition: DreamDaemon.cs:8
- + +
Task< Job > Start(CancellationToken cancellationToken)
Start DreamDaemon
+
Task Shutdown(CancellationToken cancellationToken)
Shutdown DreamDaemon
+
Task< DreamDaemon > Read(CancellationToken cancellationToken)
Get the DreamDaemon represented by the IDreamDaemonClient
+ +
Task< DreamDaemon > Update(DreamDaemon dreamDaemon, CancellationToken cancellationToken)
Update DreamDaemon. This may trigger Api.Models.Internal.DreamDaemonSettings.SoftRestart
+ +
Task< Job > Restart(CancellationToken cancellationToken)
Restart DreamDaemon
+
Represents an instance of BYOND's DreamDaemon game server. Create action starts the server....
Definition: DreamDaemon.cs:8
+
diff --git a/_i_dream_maker_8cs.html b/_i_dream_maker_8cs.html index b83c5c4929..8ef3812aa9 100644 --- a/_i_dream_maker_8cs.html +++ b/_i_dream_maker_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Compiler/IDreamMaker.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Compiler
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_dream_maker_8cs_source.html b/_i_dream_maker_8cs_source.html index 3c570d78f9..f0ed6ebfa4 100644 --- a/_i_dream_maker_8cs_source.html +++ b/_i_dream_maker_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Compiler/IDreamMaker.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IDreamMaker.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Host.Components.Compiler
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
+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
+ + + +
diff --git a/_i_dream_maker_client_8cs.html b/_i_dream_maker_client_8cs.html index d877cb9f35..8182b7e7bf 100644 --- a/_i_dream_maker_client_8cs.html +++ b/_i_dream_maker_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/IDreamMakerClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_dream_maker_client_8cs_source.html b/_i_dream_maker_client_8cs_source.html index e8ef97ea53..75dbc4e45c 100644 --- a/_i_dream_maker_client_8cs_source.html +++ b/_i_dream_maker_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/IDreamMakerClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IDreamMakerClient.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Client.Components
7 {
11  public interface IDreamMakerClient
12  {
18  Task<DreamMaker> Read(CancellationToken cancellationToken);
19 
26  Task<DreamMaker> Update(DreamMaker dreamMaker, CancellationToken cancellationToken);
27 
33  Task<Job> Compile(CancellationToken cancellationToken);
34 
40  Task<IReadOnlyList<CompileJob>> GetJobIds(CancellationToken cancellationToken);
41 
48  Task<CompileJob> GetCompileJob(CompileJob compileJob, CancellationToken cancellationToken);
49  }
50 }
Represents the state of the DreamMaker compiler. Create action starts a new compile. Delete action cancels the current compile
Definition: DreamMaker.cs:8
- +Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
11  public interface IDreamMakerClient
12  {
18  Task<DreamMaker> Read(CancellationToken cancellationToken);
19 
26  Task<DreamMaker> Update(DreamMaker dreamMaker, CancellationToken cancellationToken);
27 
33  Task<Job> Compile(CancellationToken cancellationToken);
34 
40  Task<IReadOnlyList<CompileJob>> GetJobIds(CancellationToken cancellationToken);
41 
48  Task<CompileJob> GetCompileJob(CompileJob compileJob, CancellationToken cancellationToken);
49  }
50 }
Represents the state of the DreamMaker compiler. Create action starts a new compile....
Definition: DreamMaker.cs:8
+ - - +
Task< DreamMaker > Read(CancellationToken cancellationToken)
Get the DreamMaker information
+
Task< Job > Compile(CancellationToken cancellationToken)
Compile the current repository revision
- - + +
Task< CompileJob > GetCompileJob(CompileJob compileJob, CancellationToken cancellationToken)
Get a compileJob
+
Task< DreamMaker > Update(DreamMaker dreamMaker, CancellationToken cancellationToken)
Updates the DreamMaker setttings
+ +
Task< IReadOnlyList< CompileJob > > GetJobIds(CancellationToken cancellationToken)
Gets the Api.Models.Internal.CompileJob.Ids of all CompileJobs for the instance
+
diff --git a/_i_event_consumer_8cs.html b/_i_event_consumer_8cs.html index 68d6c2d46f..8723664cd9 100644 --- a/_i_event_consumer_8cs.html +++ b/_i_event_consumer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/IEventConsumer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

interface  Tgstation.Server.Host.Components.IEventConsumer - Consumes EventTypes and takes the appropriate actions More...
+ Consumes EventTypes and takes the appropriate actions More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_event_consumer_8cs_source.html b/_i_event_consumer_8cs_source.html index f1e4844b6f..6d3e1012d7 100644 --- a/_i_event_consumer_8cs_source.html +++ b/_i_event_consumer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/IEventConsumer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IEventConsumer.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
5 namespace Tgstation.Server.Host.Components
6 {
10  public interface IEventConsumer
11  {
19  Task<bool> HandleEvent(EventType eventType, IEnumerable<string> parameters, CancellationToken cancellationToken);
20  }
21 }
Consumes EventTypes and takes the appropriate actions
- - -
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
- +Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
6 {
10  public interface IEventConsumer
11  {
19  Task<bool> HandleEvent(EventType eventType, IEnumerable<string> parameters, CancellationToken cancellationToken);
20  }
21 }
Consumes EventTypes and takes the appropriate actions
+
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
+ +
Task< bool > HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
Handle a given eventType
diff --git a/_i_git_hub_client_factory_8cs.html b/_i_git_hub_client_factory_8cs.html index 938dc4cfef..a809684e7e 100644 --- a/_i_git_hub_client_factory_8cs.html +++ b/_i_git_hub_client_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IGitHubClientFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_git_hub_client_factory_8cs_source.html b/_i_git_hub_client_factory_8cs_source.html index 24feb5b019..18df6a5a99 100644 --- a/_i_git_hub_client_factory_8cs_source.html +++ b/_i_git_hub_client_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IGitHubClientFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IGitHubClientFactory.cs
-Go to the documentation of this file.
1 using Octokit;
2 
3 namespace Tgstation.Server.Host.Core
4 {
8  public interface IGitHubClientFactory
9  {
14  IGitHubClient CreateClient();
15 
21  IGitHubClient CreateClient(string accessToken);
22  }
23 }
- - - +Go to the documentation of this file.
1 using Octokit;
2 
4 {
8  public interface IGitHubClientFactory
9  {
14  IGitHubClient CreateClient();
15 
21  IGitHubClient CreateClient(string accessToken);
22  }
23 }
+ +
IGitHubClient CreateClient()
Create a client with anonymous authentication. Low rate limit
diff --git a/_i_http_client_8cs.html b/_i_http_client_8cs.html index bae70aa3a7..a588c1cffe 100644 --- a/_i_http_client_8cs.html +++ b/_i_http_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/IHttpClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_i_http_client_8cs_source.html b/_i_http_client_8cs_source.html index 136e0e8760..155e50378b 100644 --- a/_i_http_client_8cs_source.html +++ b/_i_http_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/IHttpClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IHttpClient.cs
-Go to the documentation of this file.
1 using System;
2 using System.Net.Http;
3 using System.Threading;
4 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Client
7 {
12  {
16  TimeSpan Timeout { get; set; }
17 
24  Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
25  }
26 }
- -
For sending HTTP requests
Definition: IHttpClient.cs:11
+Go to the documentation of this file.
1 using System;
2 using System.Net.Http;
3 using System.Threading;
4 using System.Threading.Tasks;
5 
7 {
12  {
16  TimeSpan Timeout { get; set; }
17 
24  Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
25  }
26 }
TimeSpan Timeout
The request timeout
Definition: IHttpClient.cs:16
+ +
For sending HTTP requests
Definition: IHttpClient.cs:11
- +
Task< HttpResponseMessage > SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
Send an HTTP request
diff --git a/_i_i_o_manager_8cs.html b/_i_i_o_manager_8cs.html index d97c8220a4..e1ac1dfd32 100644 --- a/_i_i_o_manager_8cs.html +++ b/_i_i_o_manager_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/IIOManager.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.IO
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_i_o_manager_8cs_source.html b/_i_i_o_manager_8cs_source.html index f02915c9a9..1ec261af44 100644 --- a/_i_i_o_manager_8cs_source.html +++ b/_i_i_o_manager_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/IIOManager.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
6 namespace Tgstation.Server.Host.IO
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 }
- -
Interface for using filesystems
Definition: IIOManager.cs:11
- +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
+
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
+
Task CopyDirectory(string src, string dest, IEnumerable< string > ignore, CancellationToken cancellationToken)
Copies a directory from src to dest
+
Task< byte[]> DownloadFile(Uri url, CancellationToken cancellationToken)
Downloads a file from url
+
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
+
Task CopyFile(string src, string dest, CancellationToken cancellationToken)
Copy a file from src to dest
+
string GetDirectoryName(string path)
Gets the directory portion of 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...
+
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
+
string GetFileNameWithoutExtension(string path)
Gets the file name portion of a path with
+
bool PathContainsParentAccess(string path)
Check if a path contains the '..' parent directory accessor
+
Task< IReadOnlyList< string > > GetFiles(string path, CancellationToken cancellationToken)
Returns file names in a given path
+
Interface for using filesystems
Definition: IIOManager.cs:11
+
Task MoveFile(string source, string destination, CancellationToken cancellationToken)
Moves a file at source to destination
+
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
+
Task< bool > DirectoryExists(string path, CancellationToken cancellationToken)
Check that the directory at path exists
+
string ConcatPath(params string[] paths)
Combines an array of strings into a path
+
diff --git a/_i_identity_cache_8cs.html b/_i_identity_cache_8cs.html index 906a00a3e6..3c1fd7bbad 100644 --- a/_i_identity_cache_8cs.html +++ b/_i_identity_cache_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/IIdentityCache.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

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

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_identity_cache_8cs_source.html b/_i_identity_cache_8cs_source.html index 67fb29ed3b..414d39fc8a 100644 --- a/_i_identity_cache_8cs_source.html +++ b/_i_identity_cache_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/IIdentityCache.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IIdentityCache.cs
-Go to the documentation of this file.
1 using System;
3 
4 namespace Tgstation.Server.Host.Security
5 {
9  public interface IIdentityCache
10  {
17  void CacheSystemIdentity(User user, ISystemIdentity systemIdentity, DateTimeOffset expiry);
18 
24  ISystemIdentity LoadCachedIdentity(User user);
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 System.Runtime.InteropServices.OSPlatform
- +
ISystemIdentity LoadCachedIdentity(User user)
Attempt to load a cached ISystemIdentity
- - - - + + +
void CacheSystemIdentity(User user, ISystemIdentity systemIdentity, DateTimeOffset expiry)
Keep a user 's systemIdentity alive until an expiry time
+ + +
diff --git a/_i_instance_8cs.html b/_i_instance_8cs.html index a13672f554..22c6a2b76e 100644 --- a/_i_instance_8cs.html +++ b/_i_instance_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/IInstance.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_instance_8cs_source.html b/_i_instance_8cs_source.html index 359e548e0d..8dcce5a24b 100644 --- a/_i_instance_8cs_source.html +++ b/_i_instance_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/IInstance.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
12 namespace Tgstation.Server.Host.Components
13 {
17  public interface IInstance : IHostedService, IDisposable
18  {
23 
28 
33 
37  IChat Chat { get; }
38 
43 
48  CompileJob LatestCompileJob();
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;
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 }
- - -
For managing connected chat services
Definition: IChat.cs:13
+
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....
+
For managing connected chat services
Definition: IChat.cs:13
-
For interacting with the instance services
Definition: IInstance.cs:17
-
For managing the BYOND installation
-
For managing the Configuration directory
+
For interacting with the instance services
Definition: IInstance.cs:17
+ + +
void Rename(string newName)
Rename the IInstance
- + -
Factory for creating and loading IRepositorys
+ - + - - +
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
+
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
diff --git a/_i_instance_client_8cs.html b/_i_instance_client_8cs.html index 6b7227265c..21a910a1f2 100644 --- a/_i_instance_client_8cs.html +++ b/_i_instance_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/IInstanceClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_instance_client_8cs_source.html b/_i_instance_client_8cs_source.html index 5db5121f14..e05c7ee8c1 100644 --- a/_i_instance_client_8cs_source.html +++ b/_i_instance_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/IInstanceClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IInstanceClient.cs
-Go to the documentation of this file.
1 using System;
3 
4 namespace Tgstation.Server.Client.Components
5 {
9  public interface IInstanceClient
10  {
14  Instance Metadata { get; }
15 
20 
25 
30 
34  IConfigurationClient Configuration { get; }
35 
39  IInstanceUserClient Users { get; }
40 
44  IChatBotsClient ChatBots { get; }
45 
50 
54  IJobsClient Jobs { get; }
55  }
56 }
-
Represents the state of the DreamMaker compiler. Create action starts a new compile. Delete action cancels the current compile
Definition: DreamMaker.cs:8
- +Go to the documentation of this file.
1 using System;
3 
5 {
9  public interface IInstanceClient
10  {
14  Instance Metadata { get; }
15 
20 
25 
30 
35 
40 
45 
50 
54  IJobsClient Jobs { get; }
55  }
56 }
IInstanceUserClient Users
Access the IInstanceUserClient
+ +
Represents the state of the DreamMaker compiler. Create action starts a new compile....
Definition: DreamMaker.cs:8
+ - - -
For managing the Byond installation
Definition: IByondClient.cs:11
- - + +
For managing the Byond installation
Definition: IByondClient.cs:11
+
Instance Metadata
The Instance used to create the IInstanceClient
+
IConfigurationClient Configuration
Access the IConfigurationClient
+ - - -
Represents a git repository
Definition: Repository.cs:8
- -
Metadata about a server instance
Definition: Instance.cs:9
- -
Represents a BYOND installation
Definition: Byond.cs:8
- -
Represents an instance of BYOND&#39;s DreamDaemon game server. Create action starts the server...
Definition: DreamDaemon.cs:8
- + + + +
Represents a git repository
Definition: Repository.cs:8
+
IChatBotsClient ChatBots
Access the IChatBotsClient
+ +
Metadata about a server instance
Definition: Instance.cs:9
+ +
Represents a BYOND installation
Definition: Byond.cs:8
+ +
Represents an instance of BYOND's DreamDaemon game server. Create action starts the server....
Definition: DreamDaemon.cs:8
+ +
diff --git a/_i_instance_factory_8cs.html b/_i_instance_factory_8cs.html index 1c7d3937ec..8333e7a884 100644 --- a/_i_instance_factory_8cs.html +++ b/_i_instance_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/IInstanceFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

interface  Tgstation.Server.Host.Components.IInstanceFactory - Factory for creating IInstances More...
+ Factory for creating IInstances More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_instance_factory_8cs_source.html b/_i_instance_factory_8cs_source.html index 0deef421df..4682cfb21e 100644 --- a/_i_instance_factory_8cs_source.html +++ b/_i_instance_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/IInstanceFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IInstanceFactory.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Hosting;
2 
3 namespace Tgstation.Server.Host.Components
4 {
9  {
15  IInstance CreateInstance(Models.Instance metadata);
16  }
17 }
- -
For interacting with the instance services
Definition: IInstance.cs:17
+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
+ -
diff --git a/_i_instance_manager_8cs.html b/_i_instance_manager_8cs.html index 68997e3803..26e98f80e4 100644 --- a/_i_instance_manager_8cs.html +++ b/_i_instance_manager_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/IInstanceManager.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

interface  Tgstation.Server.Host.Components.IInstanceManager - For managing IInstances More...
+ For managing IInstances More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_instance_manager_8cs_source.html b/_i_instance_manager_8cs_source.html index 0731e9df1f..9865275da4 100644 --- a/_i_instance_manager_8cs_source.html +++ b/_i_instance_manager_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/IInstanceManager.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IInstanceManager.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
4 
5 namespace Tgstation.Server.Host.Components
6 {
10  public interface IInstanceManager
11  {
17  IInstance GetInstance(Models.Instance metadata);
18 
25  Task OnlineInstance(Models.Instance metadata, CancellationToken cancellationToken);
26 
34  Task OfflineInstance(Models.Instance metadata, User user, CancellationToken cancellationToken);
35 
43  Task MoveInstance(Models.Instance metadata, string newPath, CancellationToken cancellationToken);
44  }
45 }
+Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
4 
6 {
10  public interface IInstanceManager
11  {
17  IInstance GetInstance(Models.Instance metadata);
18 
25  Task OnlineInstance(Models.Instance metadata, CancellationToken cancellationToken);
26 
34  Task OfflineInstance(Models.Instance metadata, User user, CancellationToken cancellationToken);
35 
43  Task MoveInstance(Models.Instance metadata, string newPath, CancellationToken cancellationToken);
44  }
45 }
Task MoveInstance(Models.Instance metadata, string newPath, CancellationToken cancellationToken)
Move an IInstance
+
IInstance GetInstance(Models.Instance metadata)
Get the IInstance associated with given metadata
- -
For interacting with the instance services
Definition: IInstance.cs:17
- - - - +
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
+ + + + +
diff --git a/_i_instance_manager_client_8cs.html b/_i_instance_manager_client_8cs.html index 4246d0a383..86e8806dc0 100644 --- a/_i_instance_manager_client_8cs.html +++ b/_i_instance_manager_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/IInstanceManagerClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_i_instance_manager_client_8cs_source.html b/_i_instance_manager_client_8cs_source.html index ba64cb9509..db0ba67e3d 100644 --- a/_i_instance_manager_client_8cs_source.html +++ b/_i_instance_manager_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/IInstanceManagerClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IInstanceManagerClient.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 using System.Threading.Tasks;
6 
7 namespace Tgstation.Server.Client
8 {
12  public interface IInstanceManagerClient
13  {
19  Task<IReadOnlyList<Instance>> List(CancellationToken cancellationToken);
20 
27  Task<Instance> CreateOrAttach(Instance instance, CancellationToken cancellationToken);
28 
35  Task<Instance> Update(Instance instance, CancellationToken cancellationToken);
36 
43  Task<Instance> GetId(Instance instance, CancellationToken cancellationToken);
44 
51  Task Detach(Instance instance, CancellationToken cancellationToken);
52 
58  IInstanceClient CreateClient(Instance instance);
59  }
60 }
+Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 using System.Threading.Tasks;
6 
8 {
12  public interface IInstanceManagerClient
13  {
19  Task<IReadOnlyList<Instance>> List(CancellationToken cancellationToken);
20 
27  Task<Instance> CreateOrAttach(Instance instance, CancellationToken cancellationToken);
28 
35  Task<Instance> Update(Instance instance, CancellationToken cancellationToken);
36 
43  Task<Instance> GetId(Instance instance, CancellationToken cancellationToken);
44 
51  Task Detach(Instance instance, CancellationToken cancellationToken);
52 
59  }
60 }
- - +
Task< Instance > CreateOrAttach(Instance instance, CancellationToken cancellationToken)
Create or attach an instance
+
IInstanceClient CreateClient(Instance instance)
Create an IInstanceClient for a given Instance
+
Task< IReadOnlyList< Instance > > List(CancellationToken cancellationToken)
Get all IInstanceClients for Instances the user can view
+
Task< Instance > GetId(Instance instance, CancellationToken cancellationToken)
Get a specific instance
+
Task Detach(Instance instance, CancellationToken cancellationToken)
Deletes an instance
- -
Metadata about a server instance
Definition: Instance.cs:9
- - +
Task< Instance > Update(Instance instance, CancellationToken cancellationToken)
Relocates, renamed, and/or on/offlines an instance
+ +
Metadata about a server instance
Definition: Instance.cs:9
+ +
diff --git a/_i_instance_user_client_8cs.html b/_i_instance_user_client_8cs.html index fff38d412a..ff716c6d6c 100644 --- a/_i_instance_user_client_8cs.html +++ b/_i_instance_user_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/IInstanceUserClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_instance_user_client_8cs_source.html b/_i_instance_user_client_8cs_source.html index e491ee3871..e1cc9d95dd 100644 --- a/_i_instance_user_client_8cs_source.html +++ b/_i_instance_user_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/IInstanceUserClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IInstanceUserClient.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Client.Components
7 {
11  public interface IInstanceUserClient
12  {
18  Task<InstanceUser> Read(CancellationToken cancellationToken);
19 
26  Task<InstanceUser> GetId(InstanceUser instanceUser, CancellationToken cancellationToken);
27 
33  Task<IReadOnlyList<InstanceUser>> List(CancellationToken cancellationToken);
34 
41  Task<InstanceUser> Update(InstanceUser instanceUser, CancellationToken cancellationToken);
42 
49  Task<InstanceUser> Create(InstanceUser instanceUser, CancellationToken cancellationToken);
50 
57  Task Delete(InstanceUser instanceUser, CancellationToken cancellationToken);
58  }
59 }
- - +Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
11  public interface IInstanceUserClient
12  {
18  Task<InstanceUser> Read(CancellationToken cancellationToken);
19 
26  Task<InstanceUser> GetId(InstanceUser instanceUser, CancellationToken cancellationToken);
27 
33  Task<IReadOnlyList<InstanceUser>> List(CancellationToken cancellationToken);
34 
41  Task<InstanceUser> Update(InstanceUser instanceUser, CancellationToken cancellationToken);
42 
49  Task<InstanceUser> Create(InstanceUser instanceUser, CancellationToken cancellationToken);
50 
57  Task Delete(InstanceUser instanceUser, CancellationToken cancellationToken);
58  }
59 }
Task< InstanceUser > GetId(InstanceUser instanceUser, CancellationToken cancellationToken)
Get a specific instanceUser
+ +
Task< InstanceUser > Update(InstanceUser instanceUser, CancellationToken cancellationToken)
Update a instanceUser
- -
Represents a Users permissions in an Instance
Definition: InstanceUser.cs:9
- - + + +
Represents a Users permissions in an Instance
Definition: InstanceUser.cs:9
+
Task< IReadOnlyList< InstanceUser > > List(CancellationToken cancellationToken)
Get the InstanceUsers in the Instance
+
Task< InstanceUser > Read(CancellationToken cancellationToken)
Get the InstanceUser associated with the logged on user
+
Task< InstanceUser > Create(InstanceUser instanceUser, CancellationToken cancellationToken)
Create a instanceUser
+
Task Delete(InstanceUser instanceUser, CancellationToken cancellationToken)
Delete a instanceUser
+ +
diff --git a/_i_job_manager_8cs.html b/_i_job_manager_8cs.html index bff2b5875e..51ae5e6d27 100644 --- a/_i_job_manager_8cs.html +++ b/_i_job_manager_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IJobManager.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_job_manager_8cs_source.html b/_i_job_manager_8cs_source.html index ff764f553c..9abd0525aa 100644 --- a/_i_job_manager_8cs_source.html +++ b/_i_job_manager_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IJobManager.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
7 namespace Tgstation.Server.Host.Core
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
- +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
+ +
Task< bool > CancelJob(Job job, User user, bool blocking, CancellationToken cancellationToken)
Cancels a give job
- + - - +
Task WaitForJobCompletion(Job job, User canceller, CancellationToken jobCancellationToken, CancellationToken cancellationToken)
Wait for a given job to complete
+ + +
int? JobProgress(Job job)
Get the Api.Models.Job.Progress for a job
diff --git a/_i_jobs_client_8cs.html b/_i_jobs_client_8cs.html index 2594d7c2fd..30f5a5e5b0 100644 --- a/_i_jobs_client_8cs.html +++ b/_i_jobs_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/IJobsClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_jobs_client_8cs_source.html b/_i_jobs_client_8cs_source.html index b49a0288d7..95f8fd3475 100644 --- a/_i_jobs_client_8cs_source.html +++ b/_i_jobs_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/IJobsClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IJobsClient.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;
6 
7 namespace Tgstation.Server.Client.Components
8 {
12  public interface IJobsClient
13  {
19  Task<IReadOnlyList<Job>> List(CancellationToken cancellationToken);
20 
26  Task<IReadOnlyList<Job>> ListActive(CancellationToken cancellationToken);
27 
34  Task<Job> GetId(Job job, CancellationToken cancellationToken);
35 
42  Task Cancel(Job job, CancellationToken cancellationToken);
43  }
44 }
- - +Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Threading;
4 using System.Threading.Tasks;
6 
8 {
12  public interface IJobsClient
13  {
19  Task<IReadOnlyList<Job>> List(CancellationToken cancellationToken);
20 
26  Task<IReadOnlyList<Job>> ListActive(CancellationToken cancellationToken);
27 
34  Task<Job> GetId(Job job, CancellationToken cancellationToken);
35 
42  Task Cancel(Job job, CancellationToken cancellationToken);
43  }
44 }
- - - -
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job ...
Definition: Job.cs:6
+ +
Task< IReadOnlyList< Job > > ListActive(CancellationToken cancellationToken)
List the active Jobs in the Instance
+ +
Task< IReadOnlyList< Job > > List(CancellationToken cancellationToken)
List the Api.Models.Internal.Job.Ids in the Instance
+ +
Task< Job > GetId(Job job, CancellationToken cancellationToken)
Get a job
+ +
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job
Definition: Job.cs:6
+
Task Cancel(Job job, CancellationToken cancellationToken)
Cancels a job
diff --git a/_i_json_tracking_context_8cs.html b/_i_json_tracking_context_8cs.html index cbd2e3243f..da5b6b150b 100644 --- a/_i_json_tracking_context_8cs.html +++ b/_i_json_tracking_context_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/IJsonTrackingContext.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_json_tracking_context_8cs_source.html b/_i_json_tracking_context_8cs_source.html index 644e4ff24c..3f1c88a3cb 100644 --- a/_i_json_tracking_context_8cs_source.html +++ b/_i_json_tracking_context_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/IJsonTrackingContext.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IJsonTrackingContext.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;
6 
7 namespace Tgstation.Server.Host.Components.Chat
8 {
12  public interface IJsonTrackingContext : IDisposable
13  {
17  bool Active { get; set; }
18 
24  Task<IReadOnlyList<CustomCommand>> GetCustomCommands(CancellationToken cancellationToken);
25 
32  Task SetChannels(IEnumerable<Channel> channels, CancellationToken cancellationToken);
33  }
34 }
- - +Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Threading;
4 using System.Threading.Tasks;
6 
8 {
12  public interface IJsonTrackingContext : IDisposable
13  {
17  bool Active { get; set; }
18 
24  Task<IReadOnlyList<CustomCommand>> GetCustomCommands(CancellationToken cancellationToken);
25 
32  Task SetChannels(IEnumerable<Channel> channels, CancellationToken cancellationToken);
33  }
34 }
+
bool Active
If the IJsonTrackingContext should be used for GetCustomCommands(CancellationToken)
+
Task< IReadOnlyList< CustomCommand > > GetCustomCommands(CancellationToken cancellationToken)
Read CustomCommands from the IJsonTrackingContext
-
Represents a tracking of dynamic chat json files
- - +
Represents a tracking of dynamic chat json files
+ + - - +
Task SetChannels(IEnumerable< Channel > channels, CancellationToken cancellationToken)
Writes information about connected channels to the IJsonTrackingContext
+ +
diff --git a/_i_network_prompt_reaper_8cs.html b/_i_network_prompt_reaper_8cs.html index 198bc91aaf..a9679dc2ba 100644 --- a/_i_network_prompt_reaper_8cs.html +++ b/_i_network_prompt_reaper_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/INetworkPromptReaper.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Watchdog
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_network_prompt_reaper_8cs_source.html b/_i_network_prompt_reaper_8cs_source.html index 594b6648f8..37f712e9da 100644 --- a/_i_network_prompt_reaper_8cs_source.html +++ b/_i_network_prompt_reaper_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/INetworkPromptReaper.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
INetworkPromptReaper.cs
-Go to the documentation of this file.
2 
3 namespace Tgstation.Server.Host.Components.Watchdog
4 {
9  {
14  void RegisterProcess(IProcess process);
15  }
16 }
+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
- -
On Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort(). This looks out for those prompts and immediately clicks "Yes" if the owning process has registered for it
- - +
Abstraction over a System.Diagnostics.Process
Definition: IProcess.cs:9
+ +
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 e505d96a8e..cb531bc420 100644 --- a/_i_platform_identifier_8cs.html +++ b/_i_platform_identifier_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IPlatformIdentifier.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_platform_identifier_8cs_source.html b/_i_platform_identifier_8cs_source.html index d9650b59b4..88316115b2 100644 --- a/_i_platform_identifier_8cs_source.html +++ b/_i_platform_identifier_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IPlatformIdentifier.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IPlatformIdentifier.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Host.Core
2 {
6  public interface IPlatformIdentifier
7  {
11  bool IsWindows { get; }
12 
16  string ScriptFileExtension { get; }
17  }
18 }
-
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 }
+
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
diff --git a/_i_post_write_handler_8cs.html b/_i_post_write_handler_8cs.html index 3e1d66207b..fbe375af97 100644 --- a/_i_post_write_handler_8cs.html +++ b/_i_post_write_handler_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/IPostWriteHandler.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.IO
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_post_write_handler_8cs_source.html b/_i_post_write_handler_8cs_source.html index 6440305d77..8f04047716 100644 --- a/_i_post_write_handler_8cs_source.html +++ b/_i_post_write_handler_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/IPostWriteHandler.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IPostWriteHandler.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Host.IO
2 {
6  interface IPostWriteHandler
7  {
12  void HandleWrite(string filePath);
13  }
14 }
Handles changing file modes/permissions after writing
- - +Go to the documentation of this file.
2 {
6  interface IPostWriteHandler
7  {
12  void HandleWrite(string filePath);
13  }
14 }
Handles changing file modes/permissions after writing
+
void HandleWrite(string filePath)
For handling system specific necessities after a write
+
diff --git a/_i_process_8cs.html b/_i_process_8cs.html index 84e2f73aa8..dad416e84b 100644 --- a/_i_process_8cs.html +++ b/_i_process_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IProcess.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_process_8cs_source.html b/_i_process_8cs_source.html index 98fba6f682..52b26db15c 100644 --- a/_i_process_8cs_source.html +++ b/_i_process_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IProcess.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IProcess.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading.Tasks;
3 
4 namespace Tgstation.Server.Host.Core
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 }
- -
Abstraction over a System.Diagnostics.Process
Definition: IProcess.cs:9
-
Represents process lifetime
Definition: IProcessBase.cs:9
- +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
+
diff --git a/_i_process_base_8cs.html b/_i_process_base_8cs.html index 8c9f9f7722..12c9c40c5f 100644 --- a/_i_process_base_8cs.html +++ b/_i_process_base_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IProcessBase.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_process_base_8cs_source.html b/_i_process_base_8cs_source.html index d0b2c7d0f3..f21f914dfc 100644 --- a/_i_process_base_8cs_source.html +++ b/_i_process_base_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IProcessBase.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IProcessBase.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading.Tasks;
3 
4 namespace Tgstation.Server.Host.Core
5 {
10  {
14  Task<int> Lifetime { get; }
15 
19  void SetHighPriority();
20  }
21 }
- -
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  }
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
-
diff --git a/_i_process_executor_8cs.html b/_i_process_executor_8cs.html index 5f2a6fee39..ee19cfcc87 100644 --- a/_i_process_executor_8cs.html +++ b/_i_process_executor_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IProcessExecutor.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

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

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_process_executor_8cs_source.html b/_i_process_executor_8cs_source.html index 8996988855..930be08f04 100644 --- a/_i_process_executor_8cs_source.html +++ b/_i_process_executor_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IProcessExecutor.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IProcessExecutor.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Host.Core
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 }
- -
Abstraction over a System.Diagnostics.Process
Definition: IProcess.cs:9
- +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
diff --git a/_i_provider_8cs.html b/_i_provider_8cs.html index 81f646db68..5487e20a3d 100644 --- a/_i_provider_8cs.html +++ b/_i_provider_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Providers/IProvider.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
namespace  Tgstation.Server.Host.Components.Chat.Providers
 
@@ -114,7 +103,7 @@ Namespaces diff --git a/_i_provider_8cs_source.html b/_i_provider_8cs_source.html index c7f4f8fafb..c6d9489a31 100644 --- a/_i_provider_8cs_source.html +++ b/_i_provider_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Providers/IProvider.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IProvider.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 
6 namespace Tgstation.Server.Host.Components.Chat.Providers
7 {
11  interface IProvider : IDisposable
12  {
16  bool Connected { get; }
17 
21  string BotMention { get; }
22 
29  Task<Message> NextMessage(CancellationToken cancellationToken);
30 
36  Task<bool> Connect(CancellationToken cancellationToken);
37 
43  Task Disconnect(CancellationToken cancellationToken);
44 
51  Task<IReadOnlyList<Channel>> MapChannels(IEnumerable<Api.Models.ChatChannel> channels, CancellationToken cancellationToken);
52 
60  Task SendMessage(ulong channelId, string message, CancellationToken cancellationToken);
61  }
62 }
- -
For interacting with a chat service
Definition: IProvider.cs:11
+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  interface IProvider : IDisposable
12  {
16  bool Connected { get; }
17 
21  string BotMention { get; }
22 
29  Task<Message> NextMessage(CancellationToken cancellationToken);
30 
36  Task<bool> Connect(CancellationToken cancellationToken);
37 
43  Task Disconnect(CancellationToken cancellationToken);
44 
51  Task<IReadOnlyList<Channel>> MapChannels(IEnumerable<Api.Models.ChatChannel> channels, CancellationToken cancellationToken);
52 
60  Task SendMessage(ulong channelId, string message, CancellationToken cancellationToken);
61  }
62 }
Task SendMessage(ulong channelId, string message, CancellationToken cancellationToken)
Send a message to the IProvider
+
Task Disconnect(CancellationToken cancellationToken)
Gracefully disconnects the provider. Implies a call to IDisposable.Dispose
+ + +
Task< IReadOnlyList< Channel > > MapChannels(IEnumerable< Api.Models.ChatChannel > channels, CancellationToken cancellationToken)
Get the Channels for given channels
+
Task< bool > Connect(CancellationToken cancellationToken)
Attempt to connect the IProvider
+ +
string BotMention
The string that indicates the IProvider was mentioned
Definition: IProvider.cs:21
- +
Task< Message > NextMessage(CancellationToken cancellationToken)
Get a Task<TResult> resulting in the next Message the IProvider recieves or null on a disconnect
diff --git a/_i_provider_factory_8cs.html b/_i_provider_factory_8cs.html index 36b7388f7c..03a91772d6 100644 --- a/_i_provider_factory_8cs.html +++ b/_i_provider_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/IProviderFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_provider_factory_8cs_source.html b/_i_provider_factory_8cs_source.html index f927d1e591..1e092b79d7 100644 --- a/_i_provider_factory_8cs_source.html +++ b/_i_provider_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/IProviderFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IProviderFactory.cs
-Go to the documentation of this file.
3 
4 namespace Tgstation.Server.Host.Components.Chat
5 {
9  interface IProviderFactory
10  {
16  IProvider CreateProvider(ChatBot settings);
17  }
18 }
+Go to the documentation of this file.
3 
5 {
9  interface IProviderFactory
10  {
17  }
18 }
- -
For interacting with a chat service
Definition: IProvider.cs:11
+ +
IProvider CreateProvider(ChatBot settings)
Create a IProvider
-
Manage the server chat bots
Definition: ChatBot.cs:10
+
Manage the server chat bots
Definition: ChatBot.cs:9
- - - - - - + + + + + +
diff --git a/_i_reattach_info_handler_8cs.html b/_i_reattach_info_handler_8cs.html index 71499e2c68..dd4e278c0f 100644 --- a/_i_reattach_info_handler_8cs.html +++ b/_i_reattach_info_handler_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/IReattachInfoHandler.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

interface  Tgstation.Server.Host.Components.Watchdog.IReattachInfoHandler - Handles saving and loading WatchdogReattachInformation More...
+ Handles saving and loading WatchdogReattachInformation More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Watchdog
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_reattach_info_handler_8cs_source.html b/_i_reattach_info_handler_8cs_source.html index 3b447efd2f..30f8b4c695 100644 --- a/_i_reattach_info_handler_8cs_source.html +++ b/_i_reattach_info_handler_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/IReattachInfoHandler.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IReattachInfoHandler.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
4 namespace Tgstation.Server.Host.Components.Watchdog
5 {
9  public interface IReattachInfoHandler
10  {
17  Task Save(WatchdogReattachInformation reattachInformation, CancellationToken cancellationToken);
18 
24  Task<WatchdogReattachInformation> Load(CancellationToken cancellationToken);
25  }
26 }
- - -
Handles saving and loading WatchdogReattachInformation
- +Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
5 {
9  public interface IReattachInfoHandler
10  {
17  Task Save(WatchdogReattachInformation reattachInformation, CancellationToken cancellationToken);
18 
24  Task<WatchdogReattachInformation> Load(CancellationToken cancellationToken);
25  }
26 }
+
Task Save(WatchdogReattachInformation reattachInformation, CancellationToken cancellationToken)
Save some reattachInformation
+ +
Task< WatchdogReattachInformation > Load(CancellationToken cancellationToken)
Load a saved WatchdogReattachInformation
+
Handles saving and loading WatchdogReattachInformation
diff --git a/_i_repository_8cs.html b/_i_repository_8cs.html index f530008556..caddc32ada 100644 --- a/_i_repository_8cs.html +++ b/_i_repository_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Repository/IRepository.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Repository
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_repository_8cs_source.html b/_i_repository_8cs_source.html index ac4ee92a43..e824b982fc 100644 --- a/_i_repository_8cs_source.html +++ b/_i_repository_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Repository/IRepository.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IRepository.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Host.Components.Repository
7 {
11  public interface IRepository : IDisposable
12  {
16  bool IsGitHubRepository { get; }
17 
21  string GitHubOwner { get; }
22 
26  string GitHubRepoName { get; }
27 
31  bool Tracking { get; }
32 
36  string Head { get; }
37 
41  string Reference { get; }
42 
46  string Origin { get; }
47 
54  Task<bool> IsSha(string committish, CancellationToken cancellationToken);
55 
63  Task CheckoutObject(string committish, Action<int> progressReporter, CancellationToken cancellationToken);
64 
76  Task<bool?> AddTestMerge(TestMergeParameters testMergeParameters, string committerName, string committerEmail, string username, string password, Action<int> progressReporter, CancellationToken cancellationToken);
77 
86  Task FetchOrigin(string username, string password, Action<int> progressReporter, CancellationToken cancellationToken);
87 
94  Task ResetToOrigin(Action<int> progressReporter, CancellationToken cancellationToken);
95 
103  Task ResetToSha(string sha, Action<int> progressReporter, CancellationToken cancellationToken);
104 
113  Task<bool?> MergeOrigin(string committerName, string committerEmail, Action<int> progressReporter, CancellationToken cancellationToken);
114 
126  Task<bool> Sychronize(string username, string password, string committerName, string committerEmail, Action<int> progressReporter, bool synchronizeTrackedBranch, CancellationToken cancellationToken);
127 
134  Task CopyTo(string path, CancellationToken cancellationToken);
135  }
136 }
- - -
Represents an on-disk git repository
Definition: IRepository.cs:11
+Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
11  public interface IRepository : IDisposable
12  {
16  bool IsGitHubRepository { get; }
17 
21  string GitHubOwner { get; }
22 
26  string GitHubRepoName { get; }
27 
31  bool Tracking { get; }
32 
36  string Head { get; }
37 
41  string Reference { get; }
42 
46  string Origin { get; }
47 
54  Task<bool> IsSha(string committish, CancellationToken cancellationToken);
55 
63  Task CheckoutObject(string committish, Action<int> progressReporter, CancellationToken cancellationToken);
64 
76  Task<bool?> AddTestMerge(TestMergeParameters testMergeParameters, string committerName, string committerEmail, string username, string password, Action<int> progressReporter, CancellationToken cancellationToken);
77 
86  Task FetchOrigin(string username, string password, Action<int> progressReporter, CancellationToken cancellationToken);
87 
94  Task ResetToOrigin(Action<int> progressReporter, CancellationToken cancellationToken);
95 
103  Task ResetToSha(string sha, Action<int> progressReporter, CancellationToken cancellationToken);
104 
113  Task<bool?> MergeOrigin(string committerName, string committerEmail, Action<int> progressReporter, CancellationToken cancellationToken);
114 
126  Task<bool> Sychronize(string username, string password, string committerName, string committerEmail, Action<int> progressReporter, bool synchronizeTrackedBranch, CancellationToken cancellationToken);
127 
134  Task CopyTo(string path, CancellationToken cancellationToken);
135  }
136 }
+
string GitHubOwner
The Octokit.Repository.Owner if this IsGitHubRepository
Definition: IRepository.cs:21
+
Task ResetToSha(string sha, Action< int > progressReporter, CancellationToken cancellationToken)
Requires the current HEAD to be a reference. Hard resets the reference to the given sha
+
Represents an on-disk git repository
Definition: IRepository.cs:11
+
Task< bool?> MergeOrigin(string committerName, string committerEmail, Action< int > progressReporter, CancellationToken cancellationToken)
Requires the current HEAD to be a tracked reference. Merges the reference to what it tracks on the or...
+
Task FetchOrigin(string username, string password, Action< int > progressReporter, CancellationToken cancellationToken)
Fetch commits from the origin repository
-
Represents a git repository
Definition: Repository.cs:8
-
Parameters for creating a TestMerge
- + +
Task ResetToOrigin(Action< int > progressReporter, CancellationToken cancellationToken)
Requires the current HEAD to be a tracked reference. Hard resets the reference to what it tracks on t...
+
string GitHubRepoName
The Octokit.Repository.Name if this IsGitHubRepository
Definition: IRepository.cs:26
+
Task< bool > IsSha(string committish, CancellationToken cancellationToken)
Checks if a given committish is a sha
+
string Origin
The current origin remote the IRepository is using
Definition: IRepository.cs:46
+ +
Task CopyTo(string path, CancellationToken cancellationToken)
Copies the current working directory to a given path
+
bool Tracking
If Reference tracks an upstream branch
Definition: IRepository.cs:31
+
Task< bool?> AddTestMerge(TestMergeParameters testMergeParameters, string committerName, string committerEmail, string username, string password, Action< int > progressReporter, CancellationToken cancellationToken)
Attempt to merge a GitHub pull request into HEAD
+
string Head
The SHA of the IRepository HEAD
Definition: IRepository.cs:36
+ +
bool IsGitHubRepository
If the IRepository was cloned from GitHub.com
Definition: IRepository.cs:16
+
Task< bool > Sychronize(string username, string password, string committerName, string committerEmail, Action< int > progressReporter, bool synchronizeTrackedBranch, CancellationToken cancellationToken)
Runs the synchronize event script and attempts to push any changes made to the IRepository if on a tr...
- +
string Reference
The current reference the IRepository HEAD is using. This can be a branch or tag
Definition: IRepository.cs:41
+ +
Task CheckoutObject(string committish, Action< int > progressReporter, CancellationToken cancellationToken)
Checks out a given committish
diff --git a/_i_repository_client_8cs.html b/_i_repository_client_8cs.html index f037794c56..0439b8f7e4 100644 --- a/_i_repository_client_8cs.html +++ b/_i_repository_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/IRepositoryClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_repository_client_8cs_source.html b/_i_repository_client_8cs_source.html index 2cb81ac431..130a6930dc 100644 --- a/_i_repository_client_8cs_source.html +++ b/_i_repository_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/IRepositoryClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IRepositoryClient.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
4 
5 namespace Tgstation.Server.Client.Components
6 {
10  public interface IRepositoryClient
11  {
17  Task<Repository> Read(CancellationToken cancellationToken);
18 
25  Task<Repository> Update(Repository repository, CancellationToken cancellationToken);
26 
33  Task<Repository> Clone(Repository repository, CancellationToken cancellationToken);
34 
40  Task<Repository> Delete(CancellationToken cancellationToken);
41  }
42 }
- - - +Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
4 
6 {
10  public interface IRepositoryClient
11  {
17  Task<Repository> Read(CancellationToken cancellationToken);
18 
25  Task<Repository> Update(Repository repository, CancellationToken cancellationToken);
26 
33  Task<Repository> Clone(Repository repository, CancellationToken cancellationToken);
34 
40  Task<Repository> Delete(CancellationToken cancellationToken);
41  }
42 }
+ +
Task< Repository > Read(CancellationToken cancellationToken)
Get the Repository represented by the IRepositoryClient
+
Task< Repository > Delete(CancellationToken cancellationToken)
Deletes the Repository
+
Task< Repository > Clone(Repository repository, CancellationToken cancellationToken)
Clones a repository
-
Represents a git repository
Definition: Repository.cs:8
- - + +
Represents a git repository
Definition: Repository.cs:8
+ +
Task< Repository > Update(Repository repository, CancellationToken cancellationToken)
Update the Repository
+
diff --git a/_i_repository_manager_8cs.html b/_i_repository_manager_8cs.html index f7961d1647..3c41bf8362 100644 --- a/_i_repository_manager_8cs.html +++ b/_i_repository_manager_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Repository/IRepositoryManager.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

interface  Tgstation.Server.Host.Components.Repository.IRepositoryManager - Factory for creating and loading IRepositorys More...
+ Factory for creating and loading IRepositorys More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Repository
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_repository_manager_8cs_source.html b/_i_repository_manager_8cs_source.html index 64f1e752a1..2dc2e41a01 100644 --- a/_i_repository_manager_8cs_source.html +++ b/_i_repository_manager_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Repository/IRepositoryManager.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IRepositoryManager.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
5 namespace Tgstation.Server.Host.Components.Repository
6 {
10  public interface IRepositoryManager : IDisposable
11  {
15  bool InUse { get; }
16 
20  bool CloneInProgress { get; }
21 
27  Task<IRepository> LoadRepository(CancellationToken cancellationToken);
28 
39  Task<IRepository> CloneRepository(Uri url, string initialBranch, string username, string password, Action<int> progressReporter, CancellationToken cancellationToken);
40 
46  Task DeleteRepository(CancellationToken cancellationToken);
47  }
48 }
- -
Factory for creating and loading IRepositorys
- +Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
6 {
10  public interface IRepositoryManager : IDisposable
11  {
15  bool InUse { get; }
16 
20  bool CloneInProgress { get; }
21 
27  Task<IRepository> LoadRepository(CancellationToken cancellationToken);
28 
39  Task<IRepository> CloneRepository(Uri url, string initialBranch, string username, string password, Action<int> progressReporter, CancellationToken cancellationToken);
40 
46  Task DeleteRepository(CancellationToken cancellationToken);
47  }
48 }
Task< IRepository > CloneRepository(Uri url, string initialBranch, string username, string password, Action< int > progressReporter, CancellationToken cancellationToken)
Clone the repository at url
+
Task DeleteRepository(CancellationToken cancellationToken)
Delete the current repository
+
bool InUse
If something is holding a lock on the repository
+ +
bool CloneInProgress
If a CloneRepository(Uri, string, string, string, Action<int>, CancellationToken) operation is in pro...
+
Task< IRepository > LoadRepository(CancellationToken cancellationToken)
Attempt to load the IRepository from the default location
+ -
diff --git a/_i_request_logger_8cs.html b/_i_request_logger_8cs.html index d96e5669ed..bd076f4e2d 100644 --- a/_i_request_logger_8cs.html +++ b/_i_request_logger_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/IRequestLogger.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_i_request_logger_8cs_source.html b/_i_request_logger_8cs_source.html index 6e4c1e8292..777cabaa7a 100644 --- a/_i_request_logger_8cs_source.html +++ b/_i_request_logger_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/IRequestLogger.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IRequestLogger.cs
-Go to the documentation of this file.
1 using System;
2 using System.Net.Http;
3 using System.Threading;
4 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Client
7 {
11  public interface IRequestLogger
12  {
19  Task LogRequest(HttpRequestMessage requestMessage, CancellationToken cancellationToken);
20 
27  Task LogResponse(HttpResponseMessage responseMessage, CancellationToken cancellationToken);
28  }
29 }
- -
For logging HTTP requests and responses
- +Go to the documentation of this file.
1 using System;
2 using System.Net.Http;
3 using System.Threading;
4 using System.Threading.Tasks;
5 
7 {
11  public interface IRequestLogger
12  {
19  Task LogRequest(HttpRequestMessage requestMessage, CancellationToken cancellationToken);
20 
27  Task LogResponse(HttpResponseMessage responseMessage, CancellationToken cancellationToken);
28  }
29 }
Task LogResponse(HttpResponseMessage responseMessage, CancellationToken cancellationToken)
Log a response
+ +
For logging HTTP requests and responses
+
Task LogRequest(HttpRequestMessage requestMessage, CancellationToken cancellationToken)
Log a request
diff --git a/_i_restart_handler_8cs.html b/_i_restart_handler_8cs.html index 62ad4d4e79..97ced4b655 100644 --- a/_i_restart_handler_8cs.html +++ b/_i_restart_handler_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IRestartHandler.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_restart_handler_8cs_source.html b/_i_restart_handler_8cs_source.html index 889a588302..afedd6c3ee 100644 --- a/_i_restart_handler_8cs_source.html +++ b/_i_restart_handler_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IRestartHandler.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IRestartHandler.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
5 namespace Tgstation.Server.Host.Core
6 {
10  public interface IRestartHandler
11  {
18  Task HandleRestart(Version updateVersion, CancellationToken cancellationToken);
19  }
20 }
- - - +Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
6 {
10  public interface IRestartHandler
11  {
18  Task HandleRestart(Version updateVersion, CancellationToken cancellationToken);
19  }
20 }
+ +
Task HandleRestart(Version updateVersion, CancellationToken cancellationToken)
Handle a restart of the server
diff --git a/_i_restart_registration_8cs.html b/_i_restart_registration_8cs.html index 4fb1327964..4a261c9fdd 100644 --- a/_i_restart_registration_8cs.html +++ b/_i_restart_registration_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IRestartRegistration.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

interface  Tgstation.Server.Host.Core.IRestartRegistration - Represents the lifetime of a IRestartHandler registration More...
+ Represents the lifetime of a IRestartHandler registration More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_restart_registration_8cs_source.html b/_i_restart_registration_8cs_source.html index 9abff566e9..9ee88cf2a7 100644 --- a/_i_restart_registration_8cs_source.html +++ b/_i_restart_registration_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IRestartRegistration.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IRestartRegistration.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Host.Core
4 {
8  public interface IRestartRegistration : IDisposable
9  {
10  }
11 }
- +Go to the documentation of this file.
1 using System;
2 
4 {
8  public interface IRestartRegistration : IDisposable
9  {
10  }
11 }
-
Represents the lifetime of a IRestartHandler registration
- +
Represents the lifetime of a IRestartHandler registration
diff --git a/_i_server_8cs.html b/_i_server_8cs.html index 03122e6400..17f2b443a6 100644 --- a/_i_server_8cs.html +++ b/_i_server_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IServer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_i_server_8cs_source.html b/_i_server_8cs_source.html index 5a484400fc..b3923cd026 100644 --- a/_i_server_8cs_source.html +++ b/_i_server_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IServer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IServer.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
4 namespace Tgstation.Server.Host
5 {
9  public interface IServer
10  {
14  bool RestartRequested { get; }
15 
21  Task RunAsync(CancellationToken cancellationToken);
22  }
23 }
- -
Represents the host
Definition: IServer.cs:9
- +Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
4 namespace Tgstation.Server.Host
5 {
9  public interface IServer
10  {
14  bool RestartRequested { get; }
15 
21  Task RunAsync(CancellationToken cancellationToken);
22  }
23 }
bool RestartRequested
If the IServer should restart
Definition: IServer.cs:14
+
Represents the host
Definition: IServer.cs:9
+
Task RunAsync(CancellationToken cancellationToken)
Runs the IServer
+
diff --git a/_i_server_client_8cs.html b/_i_server_client_8cs.html index 86b76a432c..6276877e65 100644 --- a/_i_server_client_8cs.html +++ b/_i_server_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/IServerClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_i_server_client_8cs_source.html b/_i_server_client_8cs_source.html index 6fac88b51e..e35fb5b4de 100644 --- a/_i_server_client_8cs_source.html +++ b/_i_server_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/IServerClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IServerClient.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Client
7 {
11  public interface IServerClient : IDisposable
12  {
16  Uri Url { get; }
17 
21  Token Token { get; set; }
22 
26  TimeSpan Timeout { get; set; }
27 
31  IInstanceManagerClient Instances { get; }
32 
37 
41  IUsersClient Users { get; }
42 
48  Task<ServerInformation> Version(CancellationToken cancellationToken);
49 
54  void AddRequestLogger(IRequestLogger requestLogger);
55  }
56 }
+Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
11  public interface IServerClient : IDisposable
12  {
16  Uri Url { get; }
17 
21  Token Token { get; set; }
22 
26  TimeSpan Timeout { get; set; }
27 
32 
37 
42 
48  Task<ServerInformation> Version(CancellationToken cancellationToken);
49 
54  void AddRequestLogger(IRequestLogger requestLogger);
55  }
56 }
- - + +
Task< ServerInformation > Version(CancellationToken cancellationToken)
The ServerInformation of the IServerClient
-
Represents administrative server information
-
Main client for communicating with a server
- -
Represents a JWT returned by the API
Definition: Token.cs:8
- -
For logging HTTP requests and responses
- +
Uri Url
The connected server Uri
+
Represents administrative server information
+
Main client for communicating with a server
+ +
void AddRequestLogger(IRequestLogger requestLogger)
Adds a requestLogger to the request pipeline
+
Represents a JWT returned by the API
Definition: Token.cs:8
+
TimeSpan Timeout
The connection timeout
+ +
IUsersClient Users
Access the IUsersClient
+
IInstanceManagerClient Instances
Access the IInstanceManagerClient
+
For logging HTTP requests and responses
+ - +
diff --git a/_i_server_client_factory_8cs.html b/_i_server_client_factory_8cs.html index 60e3d6fd09..c3b3b0ace5 100644 --- a/_i_server_client_factory_8cs.html +++ b/_i_server_client_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/IServerClientFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

interface  Tgstation.Server.Client.IServerClientFactory - Factory for creating IServerClients More...
+ Factory for creating IServerClients More...
  + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_i_server_client_factory_8cs_source.html b/_i_server_client_factory_8cs_source.html index 42c2bcc418..a5ebb98b2e 100644 --- a/_i_server_client_factory_8cs_source.html +++ b/_i_server_client_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/IServerClientFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IServerClientFactory.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Client
7 {
11  public interface IServerClientFactory
12  {
22  Task<IServerClient> CreateServerClient(Uri host, string username, string password, TimeSpan timeout = default, CancellationToken cancellationToken = default);
23 
31  IServerClient CreateServerClient(Uri host, Token token, TimeSpan timeout = default);
32  }
33 }
- - +Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
11  public interface IServerClientFactory
12  {
22  Task<IServerClient> CreateServerClient(Uri host, string username, string password, TimeSpan timeout = default, CancellationToken cancellationToken = default);
23 
31  IServerClient CreateServerClient(Uri host, Token token, TimeSpan timeout = default);
32  }
33 }
+ -
Main client for communicating with a server
-
Represents a JWT returned by the API
Definition: Token.cs:8
-
Factory for creating IServerClients
- - +
Main client for communicating with a server
+
Represents a JWT returned by the API
Definition: Token.cs:8
+
Factory for creating IServerClients
+ +
Task< IServerClient > CreateServerClient(Uri host, string username, string password, TimeSpan timeout=default, CancellationToken cancellationToken=default)
Create a IServerClient
+
diff --git a/_i_server_control_8cs.html b/_i_server_control_8cs.html index 22f0cf2abe..bd3a1fbda3 100644 --- a/_i_server_control_8cs.html +++ b/_i_server_control_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IServerControl.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_server_control_8cs_source.html b/_i_server_control_8cs_source.html index a29579902f..65859448f5 100644 --- a/_i_server_control_8cs_source.html +++ b/_i_server_control_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/IServerControl.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IServerControl.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 using Tgstation.Server.Host.IO;
5 
6 namespace Tgstation.Server.Host.Core
7 {
11  public interface IServerControl
12  {
16  bool WatchdogPresent { get; }
17 
25  bool ApplyUpdate(Version version, Uri updateZipUrl, IIOManager ioManager);
26 
32  IRestartRegistration RegisterForRestart(IRestartHandler handler);
33 
38  Task Restart();
39 
45  Task Die(Exception exception);
46  }
47 }
- - - -
Interface for using filesystems
Definition: IIOManager.cs:11
-
Represents the lifetime of a IRestartHandler registration
- - +Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 using Tgstation.Server.Host.IO;
5 
7 {
11  public interface IServerControl
12  {
16  bool WatchdogPresent { get; }
17 
25  bool ApplyUpdate(Version version, Uri updateZipUrl, IIOManager ioManager);
26 
33 
38  Task Restart();
39 
45  Task Die(Exception exception);
46  }
47 }
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...
+
bool WatchdogPresent
true if live updates are supported, false. ApplyUpdate(Version, Uri, IIOManager) and Restart will fai...
+
Task Die(Exception exception)
Kill the server with a fatal exception
+ + + + +
Interface for using filesystems
Definition: IIOManager.cs:11
+
Represents the lifetime of a IRestartHandler registration
+
IRestartRegistration RegisterForRestart(IRestartHandler handler)
Register a given handler to run before stopping the server for a restart
+ +
Represents a service that may take an updated Host assembly and run it, stopping the current assembly...
@@ -107,7 +90,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_i_server_factory_8cs.html b/_i_server_factory_8cs.html index 2ecdc0ffa8..ef7d8b30da 100644 --- a/_i_server_factory_8cs.html +++ b/_i_server_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IServerFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

interface  Tgstation.Server.Host.IServerFactory - For creating IServers More...
+ For creating IServers More...
  + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_i_server_factory_8cs_source.html b/_i_server_factory_8cs_source.html index 4f1355b77f..3aa775c0aa 100644 --- a/_i_server_factory_8cs_source.html +++ b/_i_server_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IServerFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IServerFactory.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Host
2 {
6  public interface IServerFactory
7  {
14  IServer CreateServer(string[] args, string updatePath);
15  }
16 }
- -
Represents the host
Definition: IServer.cs:9
- +Go to the documentation of this file.
1 namespace Tgstation.Server.Host
2 {
6  public interface IServerFactory
7  {
14  IServer CreateServer(string[] args, string updatePath);
15  }
16 }
+
Represents the host
Definition: IServer.cs:9
+
IServer CreateServer(string[] args, string updatePath)
Create a IServer
+
diff --git a/_i_session_controller_8cs.html b/_i_session_controller_8cs.html index ada1271205..ee8c7d6759 100644 --- a/_i_session_controller_8cs.html +++ b/_i_session_controller_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/ISessionController.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Watchdog
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_session_controller_8cs_source.html b/_i_session_controller_8cs_source.html index 9d5af8d949..accb84a39d 100644 --- a/_i_session_controller_8cs_source.html +++ b/_i_session_controller_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/ISessionController.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ISessionController.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
4 
5 namespace Tgstation.Server.Host.Components.Watchdog
6 {
11  {
15  Task<LaunchResult> LaunchResult { get; }
16 
20  bool IsPrimary { get; }
21 
25  bool TerminationWasRequested { get; }
26 
31 
35  IDmbProvider Dmb { get; }
36 
40  ushort? Port { get; }
41 
45  bool ClosePortOnReboot { get; set; }
46 
51 
55  Task OnReboot { get; }
56 
61  ReattachInformation Release();
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 
95  void EnableCustomChatCommands();
96  }
97 }
Represents the result of trying to start a DD process
Definition: LaunchResult.cs:9
- - -
Handles communication with a DreamDaemon 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 }
+
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
-
Represents process lifetime
Definition: IProcessBase.cs:9
- -
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
- -
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
-
Parameters necessary for duplicating a ISessionController session
- -
ApiValidationStatus
Status of DMAPI validation
+
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
+ +
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()
+ +
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
+
Parameters necessary for duplicating a ISessionController session
+ +
ApiValidationStatus
Status of DMAPI validation
diff --git a/_i_session_controller_factory_8cs.html b/_i_session_controller_factory_8cs.html index 8a974d388c..18b2ebef48 100644 --- a/_i_session_controller_factory_8cs.html +++ b/_i_session_controller_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/ISessionControllerFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

interface  Tgstation.Server.Host.Components.Watchdog.ISessionControllerFactory - Factory for ISessionControllers More...
+ Factory for ISessionControllers More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Watchdog
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_i_session_controller_factory_8cs_source.html b/_i_session_controller_factory_8cs_source.html index 444ca280d9..4aac88a3ba 100644 --- a/_i_session_controller_factory_8cs_source.html +++ b/_i_session_controller_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/ISessionControllerFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ISessionControllerFactory.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Host.Components.Watchdog
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 
39  ISessionController CreateDeadSession(IDmbProvider dmbProvider);
40  }
41 }
- - - +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
+ +
ISessionController CreateDeadSession(IDmbProvider dmbProvider)
Creates a ISessionController that appears to have started and died with exit code -1
+ + -
Handles communication with a DreamDaemon IProcess
- - -
Represents usage of the two primary BYOND server executables
- - -
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
- -
Parameters necessary for duplicating a ISessionController session
- +
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
+ +
Parameters necessary for duplicating a ISessionController session
+
diff --git a/_i_setup_wizard_8cs.html b/_i_setup_wizard_8cs.html index 050bf005ba..65dafe3d1c 100644 --- a/_i_setup_wizard_8cs.html +++ b/_i_setup_wizard_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/ISetupWizard.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_setup_wizard_8cs_source.html b/_i_setup_wizard_8cs_source.html index d100926ce1..19566760af 100644 --- a/_i_setup_wizard_8cs_source.html +++ b/_i_setup_wizard_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/ISetupWizard.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ISetupWizard.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
4 namespace Tgstation.Server.Host.Core
5 {
9  interface ISetupWizard
10  {
16  Task<bool> CheckRunWizard(CancellationToken cancellationToken);
17  }
18 }
- -
The command line Configuration setup wizard
Definition: ISetupWizard.cs:9
- +Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
5 {
9  interface ISetupWizard
10  {
16  Task<bool> CheckRunWizard(CancellationToken cancellationToken);
17  }
18 }
+
The command line Configuration setup wizard
Definition: ISetupWizard.cs:9
+
Task< bool > CheckRunWizard(CancellationToken cancellationToken)
Run the setup wizard if necessary
diff --git a/_i_symlink_factory_8cs.html b/_i_symlink_factory_8cs.html index a94e6b8716..7f81cff349 100644 --- a/_i_symlink_factory_8cs.html +++ b/_i_symlink_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/ISymlinkFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.IO
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_symlink_factory_8cs_source.html b/_i_symlink_factory_8cs_source.html index 3b9d145be2..8b932acb9e 100644 --- a/_i_symlink_factory_8cs_source.html +++ b/_i_symlink_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/ISymlinkFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ISymlinkFactory.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
4 namespace Tgstation.Server.Host.IO
5 {
9  interface ISymlinkFactory
10  {
18  Task CreateSymbolicLink(string targetPath, string linkPath, CancellationToken cancellationToken);
19  }
20 }
- - - +Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
5 {
9  interface ISymlinkFactory
10  {
18  Task CreateSymbolicLink(string targetPath, string linkPath, CancellationToken cancellationToken);
19  }
20 }
+ +
diff --git a/_i_synchronous_i_o_manager_8cs.html b/_i_synchronous_i_o_manager_8cs.html index 5ad06d3a7d..6e699b47a3 100644 --- a/_i_synchronous_i_o_manager_8cs.html +++ b/_i_synchronous_i_o_manager_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/ISynchronousIOManager.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.IO
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_synchronous_i_o_manager_8cs_source.html b/_i_synchronous_i_o_manager_8cs_source.html index ee28e40d63..df78b08e84 100644 --- a/_i_synchronous_i_o_manager_8cs_source.html +++ b/_i_synchronous_i_o_manager_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/ISynchronousIOManager.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ISynchronousIOManager.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 
4 namespace Tgstation.Server.Host.IO
5 {
10  {
17  IEnumerable<string> GetFiles(string path, CancellationToken cancellationToken);
18 
25  IEnumerable<string> GetDirectories(string path, CancellationToken cancellationToken);
26 
33  bool CreateDirectory(string path, CancellationToken cancellationToken);
34 
40  byte[] ReadFile(string path);
41 
47  bool DeleteDirectory(string path);
48 
57  bool WriteFileChecked(string path, byte[] data, ref string sha1InOut, CancellationToken cancellationToken);
58 
64  bool IsDirectory(string path);
65  }
66 }
- -
For accessing the disk in a synchronous manner
- +Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 
5 {
10  {
17  IEnumerable<string> GetFiles(string path, CancellationToken cancellationToken);
18 
25  IEnumerable<string> GetDirectories(string path, CancellationToken cancellationToken);
26 
33  bool CreateDirectory(string path, CancellationToken cancellationToken);
34 
40  byte[] ReadFile(string path);
41 
47  bool DeleteDirectory(string path);
48 
57  bool WriteFileChecked(string path, byte[] data, ref string sha1InOut, CancellationToken cancellationToken);
58 
64  bool IsDirectory(string path);
65  }
66 }
bool DeleteDirectory(string path)
Deletes a directory at path if it's empty
+
bool WriteFileChecked(string path, byte[] data, ref string sha1InOut, CancellationToken cancellationToken)
Write data to a file at a given path
+
byte [] ReadFile(string path)
Read the bytes of a file at a given path
+
For accessing the disk in a synchronous manner
+
IEnumerable< string > GetDirectories(string path, CancellationToken cancellationToken)
Enumerate directories in a given path
+
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
+
bool CreateDirectory(string path, CancellationToken cancellationToken)
Create an empty directory at path
+
diff --git a/_i_system_identity_8cs.html b/_i_system_identity_8cs.html index acf4e0abcf..e92f4002e1 100644 --- a/_i_system_identity_8cs.html +++ b/_i_system_identity_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/ISystemIdentity.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_system_identity_8cs_source.html b/_i_system_identity_8cs_source.html index 481577582d..c02bd66aa7 100644 --- a/_i_system_identity_8cs_source.html +++ b/_i_system_identity_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/ISystemIdentity.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
6 namespace Tgstation.Server.Host.Security
7 {
11  public interface ISystemIdentity : IDisposable
12  {
16  string Uid { get; }
17 
21  string Username { get; }
22 
27  ISystemIdentity Clone();
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.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
+
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
diff --git a/_i_system_identity_factory_8cs.html b/_i_system_identity_factory_8cs.html index 58b1ccdf84..422241176d 100644 --- a/_i_system_identity_factory_8cs.html +++ b/_i_system_identity_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/ISystemIdentityFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

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

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_system_identity_factory_8cs_source.html b/_i_system_identity_factory_8cs_source.html index 9cc96cff77..6a3d8b841a 100644 --- a/_i_system_identity_factory_8cs_source.html +++ b/_i_system_identity_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/ISystemIdentityFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ISystemIdentityFactory.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
4 
5 namespace Tgstation.Server.Host.Security
6 {
10  public interface ISystemIdentityFactory
11  {
18  Task<ISystemIdentity> CreateSystemIdentity(User user, CancellationToken cancellationToken);
19 
27  Task<ISystemIdentity> CreateSystemIdentity(string username, string password, CancellationToken cancellationToken);
28  }
29 }
+Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
4 
6 {
10  public interface ISystemIdentityFactory
11  {
18  Task<ISystemIdentity> CreateSystemIdentity(User user, CancellationToken cancellationToken);
19 
27  Task<ISystemIdentity> CreateSystemIdentity(string username, string password, CancellationToken cancellationToken);
28  }
29 }
Task< ISystemIdentity > CreateSystemIdentity(User user, CancellationToken cancellationToken)
Create a ISystemIdentity for a given user
- - - - - + + + + +
diff --git a/_i_token_factory_8cs.html b/_i_token_factory_8cs.html index e4d426dd8a..622bcc7239 100644 --- a/_i_token_factory_8cs.html +++ b/_i_token_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/ITokenFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_i_token_factory_8cs_source.html b/_i_token_factory_8cs_source.html index 5f39a106dc..5b1801531d 100644 --- a/_i_token_factory_8cs_source.html +++ b/_i_token_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/ITokenFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ITokenFactory.cs
-Go to the documentation of this file.
1 using Microsoft.IdentityModel.Tokens;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Host.Security
7 {
11  public interface ITokenFactory
12  {
16  TokenValidationParameters ValidationParameters { get; }
17 
24  Task<Token> CreateToken(Models.User user, CancellationToken cancellationToken);
25  }
26 }
- - +Go to the documentation of this file.
1 using Microsoft.IdentityModel.Tokens;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
11  public interface ITokenFactory
12  {
16  TokenValidationParameters ValidationParameters { get; }
17 
24  Task<Token> CreateToken(Models.User user, CancellationToken cancellationToken);
25  }
26 }
+
Task< Token > CreateToken(Models.User user, CancellationToken cancellationToken)
Create a Token for a given user
- - - + +
TokenValidationParameters ValidationParameters
The TokenValidationParameters for the ITokenFactory
+ + +
diff --git a/_i_users_client_8cs.html b/_i_users_client_8cs.html index 5df75fbcf6..16e41437f8 100644 --- a/_i_users_client_8cs.html +++ b/_i_users_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/IUsersClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_i_users_client_8cs_source.html b/_i_users_client_8cs_source.html index 2888a6efee..7f39e1d64a 100644 --- a/_i_users_client_8cs_source.html +++ b/_i_users_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/IUsersClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IUsersClient.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Client
7 {
11  public interface IUsersClient
12  {
18  Task<User> Read(CancellationToken cancellationToken);
19 
26  Task<User> GetId(User user, CancellationToken cancellationToken);
27 
33  Task<IReadOnlyList<User>> List(CancellationToken cancellationToken);
34 
41  Task<User> Create(UserUpdate user, CancellationToken cancellationToken);
42 
49  Task<User> Update(UserUpdate user, CancellationToken cancellationToken);
50  }
51 }
- - +Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
11  public interface IUsersClient
12  {
18  Task<User> Read(CancellationToken cancellationToken);
19 
26  Task<User> GetId(User user, CancellationToken cancellationToken);
27 
33  Task<IReadOnlyList<User>> List(CancellationToken cancellationToken);
34 
41  Task<User> Create(UserUpdate user, CancellationToken cancellationToken);
42 
49  Task<User> Update(UserUpdate user, CancellationToken cancellationToken);
50  }
51 }
Task< User > Read(CancellationToken cancellationToken)
Read the current user's information and general rights
+ +
Task< User > GetId(User user, CancellationToken cancellationToken)
Get a specific user
+
Task< User > Create(UserUpdate user, CancellationToken cancellationToken)
Create a new user
+ - + +
Task< User > Update(UserUpdate user, CancellationToken cancellationToken)
Update a user
- -
For editing a given User. Will never be returned by the API
Definition: UserUpdate.cs:6
- +
Task< IReadOnlyList< User > > List(CancellationToken cancellationToken)
List all Users
+ +
For editing a given User. Will never be returned by the API
Definition: UserUpdate.cs:6
+
diff --git a/_identity_cache_8cs.html b/_identity_cache_8cs.html index b9d91486cf..8628abb14d 100644 --- a/_identity_cache_8cs.html +++ b/_identity_cache_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/IdentityCache.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_identity_cache_8cs_source.html b/_identity_cache_8cs_source.html index 4484b93d09..7a6965aead 100644 --- a/_identity_cache_8cs_source.html +++ b/_identity_cache_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/IdentityCache.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
8 namespace Tgstation.Server.Host.Security
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 System.Runtime.InteropServices.OSPlatform
- -
readonly Dictionary< long, IdentityCacheObject > cachedIdentities
The map of Api.Models.Internal.User.Ids to IdentityCacheObjects
- +
readonly Dictionary< long, IdentityCacheObject > cachedIdentities
The map of Api.Models.Internal.User.Ids to IdentityCacheObjects
+ -
IdentityCache(IAsyncDelayer asyncDelayer, ILogger< IdentityCache > logger)
Construct an IdentityCache
-
void CacheSystemIdentity(User user, ISystemIdentity systemIdentity, DateTimeOffset expiry)
Keep a user &#39;s systemIdentity alive until an expiry time
-
long Id
The ID of the User
Definition: User.cs:15
-
ISystemIdentity LoadCachedIdentity(User user)
Attempt to load a cached ISystemIdentity
-
ISystemIdentity Clone()
Clone the ISystemIdentity creating another copy that must have IDisposable.Dispose called on it ...
-
readonly ILogger< IdentityCache > logger
The ILogger for the IdentityCache
- +
IdentityCache(IAsyncDelayer asyncDelayer, ILogger< IdentityCache > logger)
Construct an IdentityCache
+ +
void CacheSystemIdentity(User user, ISystemIdentity systemIdentity, DateTimeOffset expiry)
Keep a user 's systemIdentity alive until an expiry time
+
long Id
The ID of the User
Definition: User.cs:15
+
ISystemIdentity LoadCachedIdentity(User user)
Attempt to load a cached ISystemIdentity
+
ISystemIdentity Clone()
Clone the ISystemIdentity creating another copy that must have IDisposable.Dispose called on it
+
readonly ILogger< IdentityCache > logger
The ILogger for the IdentityCache
+ -
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
- - +
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
+ +
diff --git a/_identity_cache_object_8cs.html b/_identity_cache_object_8cs.html index 5ef020cb78..613eb5e8d6 100644 --- a/_identity_cache_object_8cs.html +++ b/_identity_cache_object_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/IdentityCacheObject.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

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...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_identity_cache_object_8cs_source.html b/_identity_cache_object_8cs_source.html index 0cff3ac264..9ee0d7bac3 100644 --- a/_identity_cache_object_8cs_source.html +++ b/_identity_cache_object_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/IdentityCacheObject.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IdentityCacheObject.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Host.Security
7 {
12  {
16  public ISystemIdentity SystemIdentity { get; }
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
- -
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;
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
- + -
Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan
-
readonly CancellationTokenSource cancellationTokenSource
The cancellationTokenSource for the IdentityCache
- +
Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan
+ +
readonly CancellationTokenSource cancellationTokenSource
The cancellationTokenSource for the IdentityCache
+ -
For keeping a specific ISystemIdentity alive for a period of time
- - +
For keeping a specific ISystemIdentity alive for a period of time
+ +
diff --git a/_instance_client_8cs.html b/_instance_client_8cs.html index 589129951a..9fafc7d7c0 100644 --- a/_instance_client_8cs.html +++ b/_instance_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/InstanceClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_instance_client_8cs_source.html b/_instance_client_8cs_source.html index e55f55d420..5229aa7a77 100644 --- a/_instance_client_8cs_source.html +++ b/_instance_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/InstanceClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
InstanceClient.cs
-Go to the documentation of this file.
1 using System;
3 
4 namespace Tgstation.Server.Client.Components
5 {
8  {
10  public Instance Metadata { get; }
11 
13  public IByondClient Byond { get; }
14 
16  public IRepositoryClient Repository { get; }
17 
20 
22  public IConfigurationClient Configuration { get; }
23 
25  public IInstanceUserClient Users { get; }
26 
28  public IChatBotsClient ChatBots { get; }
29 
31  public IDreamMakerClient DreamMaker { get; }
32 
34  public IJobsClient Jobs { get; }
35 
40 
46  public InstanceClient(IApiClient apiClient, Instance instance)
47  {
48  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
49  Metadata = instance ?? throw new ArgumentNullException(nameof(instance));
50 
51  Byond = new ByondClient(apiClient, instance);
52  Repository = new RepositoryClient(apiClient, instance);
53  DreamDaemon = new DreamDaemonClient(apiClient, instance);
54  Configuration = new ConfigurationClient(apiClient, instance);
55  Users = new InstanceUserClient(apiClient, instance);
56  ChatBots = new ChatBotsClient(apiClient, instance);
57  DreamMaker = new DreamMakerClient(apiClient, instance);
58  Jobs = new JobsClient(apiClient, instance);
59  }
60  }
61 }
-
Represents the state of the DreamMaker compiler. Create action starts a new compile. Delete action cancels the current compile
Definition: DreamMaker.cs:8
- +Go to the documentation of this file.
1 using System;
3 
5 {
8  {
10  public Instance Metadata { get; }
11 
13  public IByondClient Byond { get; }
14 
16  public IRepositoryClient Repository { get; }
17 
20 
23 
25  public IInstanceUserClient Users { get; }
26 
28  public IChatBotsClient ChatBots { get; }
29 
31  public IDreamMakerClient DreamMaker { get; }
32 
34  public IJobsClient Jobs { get; }
35 
40 
47  {
48  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
49  Metadata = instance ?? throw new ArgumentNullException(nameof(instance));
50 
51  Byond = new ByondClient(apiClient, instance);
52  Repository = new RepositoryClient(apiClient, instance);
53  DreamDaemon = new DreamDaemonClient(apiClient, instance);
55  Users = new InstanceUserClient(apiClient, instance);
56  ChatBots = new ChatBotsClient(apiClient, instance);
57  DreamMaker = new DreamMakerClient(apiClient, instance);
58  Jobs = new JobsClient(apiClient, instance);
59  }
60  }
61 }
+ +
Represents the state of the DreamMaker compiler. Create action starts a new compile....
Definition: DreamMaker.cs:8
+ + - - -
For managing the Byond installation
Definition: IByondClient.cs:11
-
readonly IApiClient apiClient
The IApiClient for the InstanceClient
- - + +
For managing the Byond installation
Definition: IByondClient.cs:11
+
readonly IApiClient apiClient
The IApiClient for the InstanceClient
+ + - + + - -
Represents a git repository
Definition: Repository.cs:8
+ + +
Represents a git repository
Definition: Repository.cs:8
- -
Metadata about a server instance
Definition: Instance.cs:9
- + +
Metadata about a server instance
Definition: Instance.cs:9
+ -
Represents a BYOND installation
Definition: Byond.cs:8
- -
Web interface for the API
Definition: IApiClient.cs:11
-
Represents an instance of BYOND&#39;s DreamDaemon game server. Create action starts the server...
Definition: DreamDaemon.cs:8
-
InstanceClient(IApiClient apiClient, Instance instance)
Construct a InstanceClient
+
Represents a BYOND installation
Definition: Byond.cs:8
+ + +
Web interface for the API
Definition: IApiClient.cs:11
+
Represents an instance of BYOND's DreamDaemon game server. Create action starts the server....
Definition: DreamDaemon.cs:8
+
InstanceClient(IApiClient apiClient, Instance instance)
Construct a InstanceClient
- +
diff --git a/_instance_controller_8cs.html b/_instance_controller_8cs.html index 49473fde4d..d936e7fb17 100644 --- a/_instance_controller_8cs.html +++ b/_instance_controller_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/InstanceController.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Controllers
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_instance_controller_8cs_source.html b/_instance_controller_8cs_source.html index e8b2b63d32..5ea4ff0039 100644 --- a/_instance_controller_8cs_source.html +++ b/_instance_controller_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/InstanceController.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
23 namespace Tgstation.Server.Host.Controllers
24 {
28  [Route(Routes.InstanceManager)]
29  #pragma warning disable CA1506 // TODO: Decomplexify
30  public sealed class InstanceController : ModelController<Api.Models.Instance>
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)
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);
93  if (platformIdentifier.IsWindows)
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 
112  [TgsAuthorize(InstanceManagerRights.Create)]
113  public override async Task<IActionResult> Create([FromBody] Api.Models.Instance model, CancellationToken cancellationToken)
114  {
115  if (model == null)
116  throw new ArgumentNullException(nameof(model));
117 
118  if (String.IsNullOrWhiteSpace(model.Name))
119  return BadRequest(new ErrorMessage { Message = "name must not be empty!" });
120 
121  if (model.Path == null)
122  return BadRequest(new ErrorMessage { Message = "path must not be empty!" });
123 
124  NormalizeModelPath(model, out var rawPath);
125 
126  var localPath = ioManager.ResolvePath(".");
127  NormalizeModelPath(new Api.Models.Instance
128  {
129  Path = localPath
130  }, out var normalizedLocalPath);
131 
132  if (rawPath.StartsWith(normalizedLocalPath, StringComparison.Ordinal))
133  return Conflict("Instances cannot be created in the installation directory!");
134 
135  var dirExistsTask = ioManager.DirectoryExists(model.Path, cancellationToken);
136  bool attached = false;
137  if (await ioManager.FileExists(model.Path, cancellationToken).ConfigureAwait(false) || await dirExistsTask.ConfigureAwait(false))
138  if (!await ioManager.FileExists(ioManager.ConcatPath(model.Path, InstanceAttachFileName), cancellationToken).ConfigureAwait(false))
139  return Conflict(new ErrorMessage { Message = "Path not empty!" });
140  else
141  attached = true;
142 
143  var newInstance = new Models.Instance
144  {
145  ConfigurationType = model.ConfigurationType ?? ConfigurationType.Disallowed,
147  {
148  AllowWebClient = false,
149  AutoStart = false,
150  PrimaryPort = 1337,
151  SecondaryPort = 1338,
152  SecurityLevel = DreamDaemonSecurity.Safe,
153  SoftRestart = false,
154  SoftShutdown = false,
155  StartupTimeout = 20
156  },
158  {
159  ApiValidationPort = 1339,
160  ApiValidationSecurityLevel = DreamDaemonSecurity.Safe
161  },
162  Name = model.Name,
163  Online = false,
164  Path = model.Path,
165  AutoUpdateInterval = model.AutoUpdateInterval ?? 0,
167  {
168  CommitterEmail = "tgstation-server@users.noreply.github.com",
169  CommitterName = application.VersionPrefix,
170  PushTestMergeCommits = false,
171  ShowTestMergeCommitters = false,
172  AutoUpdatesKeepTestMerges = false,
173  AutoUpdatesSynchronize = false,
174  PostTestMergeComment = false
175  },
176  InstanceUsers = new List<Models.InstanceUser> // give this user full privileges on the instance
177  {
178  InstanceAdminUser()
179  }
180  };
181 
182  DatabaseContext.Instances.Add(newInstance);
183  try
184  {
185  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
186 
187  try
188  {
189  // actually reserve it now
190  await ioManager.CreateDirectory(rawPath, cancellationToken).ConfigureAwait(false);
191  await ioManager.DeleteFile(ioManager.ConcatPath(rawPath, InstanceAttachFileName), cancellationToken).ConfigureAwait(false);
192  }
193  catch
194  {
195  // oh shit delete the model
196  DatabaseContext.Instances.Remove(newInstance);
197 
198  await DatabaseContext.Save(default).ConfigureAwait(false);
199  throw;
200  }
201  }
202  catch (IOException e)
203  {
204  return Conflict(new ErrorMessage { Message = e.Message });
205  }
206  catch (DbUpdateException e)
207  {
208  return Conflict(new ErrorMessage { Message = e.Message });
209  }
210 
211  Logger.LogInformation("{0} {1} instance {2}: {3} ({4})", AuthenticationContext.User.Name, attached ? "attached" : "created", newInstance.Name, newInstance.Id, newInstance.Path);
212 
213  var api = newInstance.ToApi();
214  return attached ? (IActionResult)Json(api) : StatusCode((int)HttpStatusCode.Created, api);
215  }
216 
218  [TgsAuthorize(InstanceManagerRights.Delete)]
219  public override async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
220  {
221  var originalModel = await DatabaseContext.Instances.Where(x => x.Id == id)
222  .Include(x => x.WatchdogReattachInformation)
223  .Include(x => x.WatchdogReattachInformation.Alpha)
224  .Include(x => x.WatchdogReattachInformation.Bravo)
225  .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
226  if (originalModel == default)
227  return StatusCode((int)HttpStatusCode.Gone);
228  if (originalModel.Online.Value)
229  return Conflict(new ErrorMessage
230  {
231  Message = "Cannot detach an online instance!"
232  });
233 
234  if (originalModel.WatchdogReattachInformation != null)
235  {
236  DatabaseContext.WatchdogReattachInformations.Remove(originalModel.WatchdogReattachInformation);
237  if (originalModel.WatchdogReattachInformation.Alpha != null)
238  DatabaseContext.ReattachInformations.Remove(originalModel.WatchdogReattachInformation.Alpha);
239  if (originalModel.WatchdogReattachInformation.Bravo != null)
240  DatabaseContext.ReattachInformations.Remove(originalModel.WatchdogReattachInformation.Bravo);
241  }
242 
243  DatabaseContext.Instances.Remove(originalModel);
244 
245  var attachFileName = ioManager.ConcatPath(originalModel.Path, InstanceAttachFileName);
246  await ioManager.WriteAllBytes(attachFileName, Array.Empty<byte>(), default).ConfigureAwait(false);
247  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false); // cascades everything
248  return Ok();
249  }
250 
252  [TgsAuthorize(InstanceManagerRights.Relocate | InstanceManagerRights.Rename | InstanceManagerRights.SetAutoUpdate | InstanceManagerRights.SetConfiguration | InstanceManagerRights.SetOnline)]
253  #pragma warning disable CA1502 // TODO: Decomplexify
254  public override async Task<IActionResult> Update([FromBody] Api.Models.Instance model, CancellationToken cancellationToken)
255  {
256  var instanceQuery = DatabaseContext.Instances.Where(x => x.Id == model.Id);
257 
258  var moveJob = await instanceQuery
259  .SelectMany(x => x.Jobs).
260 #pragma warning disable CA1307 // Specify StringComparison
261  Where(x => !x.StoppedAt.HasValue && x.Description.StartsWith(MoveInstanceJobPrefix))
262 #pragma warning restore CA1307 // Specify StringComparison
263  .Select(x => new Models.Job
264  {
265  Id = x.Id
266  }).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
267 
268  if (moveJob != default)
269  await jobManager.CancelJob(moveJob, AuthenticationContext.User, true, cancellationToken).ConfigureAwait(false); // cancel it now
270 
271  var usersInstanceUserTask = instanceQuery.SelectMany(x => x.InstanceUsers).Where(x => x.UserId == AuthenticationContext.User.Id).FirstOrDefaultAsync(cancellationToken);
272 
273  var originalModel = await instanceQuery
274  .Include(x => x.RepositorySettings)
275  .Include(x => x.ChatSettings)
276  .ThenInclude(x => x.Channels)
277  .Include(x => x.DreamDaemonSettings) // need these for onlining
278  .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
279  if (originalModel == default(Models.Instance))
280  return StatusCode((int)HttpStatusCode.Gone);
281 
282  var userRights = (InstanceManagerRights)AuthenticationContext.GetRight(RightsType.InstanceManager);
283  bool CheckModified<T>(Expression<Func<Api.Models.Instance, T>> expression, InstanceManagerRights requiredRight)
284  {
285  var memberSelectorExpression = (MemberExpression)expression.Body;
286  var property = (PropertyInfo)memberSelectorExpression.Member;
287 
288  var newVal = property.GetValue(model);
289  if (newVal == null)
290  return false;
291  if (!userRights.HasFlag(requiredRight) && property.GetValue(originalModel) != newVal)
292  return true;
293 
294  property.SetValue(originalModel, newVal);
295  return false;
296  }
297 
298  string originalModelPath = null;
299  string rawPath = null;
300  if (model.Path != null)
301  {
302  NormalizeModelPath(model, out rawPath);
303 
304  if (model.Path != originalModel.Path)
305  {
306  if (!userRights.HasFlag(InstanceManagerRights.Relocate))
307  return Forbid();
308  if (originalModel.Online.Value && model.Online != true)
309  return Conflict(new ErrorMessage { Message = "Cannot relocate an online instance!" });
310 
311  var dirExistsTask = ioManager.DirectoryExists(model.Path, cancellationToken);
312  if (await ioManager.FileExists(model.Path, cancellationToken).ConfigureAwait(false) || await dirExistsTask.ConfigureAwait(false))
313  return Conflict(new ErrorMessage { Message = "Path not empty!" });
314 
315  originalModelPath = originalModel.Path;
316  originalModel.Path = model.Path;
317  }
318  }
319 
320  var oldAutoUpdateInterval = originalModel.AutoUpdateInterval.Value;
321  var originalOnline = originalModel.Online.Value;
322  var renamed = model.Name != null && originalModel.Name != model.Name;
323 
324  if (CheckModified(x => x.AutoUpdateInterval, InstanceManagerRights.SetAutoUpdate)
325  || CheckModified(x => x.ConfigurationType, InstanceManagerRights.SetConfiguration)
326  || CheckModified(x => x.Name, InstanceManagerRights.Rename)
327  || CheckModified(x => x.Online, InstanceManagerRights.SetOnline))
328  return Forbid();
329 
330  // ensure the current user has write privilege on the instance
331  var usersInstanceUser = await usersInstanceUserTask.ConfigureAwait(false);
332  if (usersInstanceUser == default)
333  {
334  var instanceAdminUser = InstanceAdminUser();
335  instanceAdminUser.InstanceId = originalModel.Id;
336  DatabaseContext.InstanceUsers.Add(instanceAdminUser);
337  }
338  else
339  usersInstanceUser.InstanceUserRights |= InstanceUserRights.WriteUsers;
340 
341  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
342 
343  if (renamed)
344  instanceManager.GetInstance(originalModel).Rename(originalModel.Name);
345 
346  var oldAutoStart = originalModel.DreamDaemonSettings.AutoStart;
347  try
348  {
349  if (originalOnline && model.Online == false)
350  await instanceManager.OfflineInstance(originalModel, AuthenticationContext.User, cancellationToken).ConfigureAwait(false);
351  else if (!originalOnline && model.Online == true)
352  {
353  // force autostart false here because we don't want any long running jobs right now
354  // remember to document this
355  originalModel.DreamDaemonSettings.AutoStart = false;
356  await instanceManager.OnlineInstance(originalModel, cancellationToken).ConfigureAwait(false);
357  }
358  }
359  catch (Exception e)
360  {
361  if(!(e is OperationCanceledException))
362  Logger.LogError("Error changing instance online state! Exception: {0}", e);
363  originalModel.Online = originalOnline;
364  originalModel.DreamDaemonSettings.AutoStart = oldAutoStart;
365  if (originalModelPath != null)
366  originalModel.Path = originalModelPath;
367  await DatabaseContext.Save(default).ConfigureAwait(false);
368  throw;
369  }
370 
371  var api = (AuthenticationContext.GetRight(RightsType.InstanceManager) & (ulong)InstanceManagerRights.Read) != 0 ? originalModel.ToApi() : new Api.Models.Instance
372  {
373  Id = originalModel.Id
374  };
375  if (originalModelPath != null)
376  {
377  var job = new Models.Job
378  {
379  Description = String.Format(CultureInfo.InvariantCulture, MoveInstanceJobPrefix + "{0} from {1} to {2}", originalModel.Id, originalModel.Path, rawPath),
380  Instance = originalModel,
381  CancelRightsType = RightsType.InstanceManager,
382  CancelRight = (ulong)InstanceManagerRights.Relocate,
383  StartedBy = AuthenticationContext.User
384  };
385 
386  await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressHandler, ct) => instanceManager.MoveInstance(originalModel, rawPath, ct), cancellationToken).ConfigureAwait(false);
387  api.MoveJob = job.ToApi();
388  }
389 
390  if (originalModel.Online.Value && model.AutoUpdateInterval.HasValue && oldAutoUpdateInterval != model.AutoUpdateInterval)
391  await instanceManager.GetInstance(originalModel).SetAutoUpdateInterval(model.AutoUpdateInterval.Value).ConfigureAwait(false);
392 
393  return Json(api);
394  }
395  #pragma warning restore CA1502
396 
398  [TgsAuthorize(InstanceManagerRights.List | InstanceManagerRights.Read)]
399  public override async Task<IActionResult> List(CancellationToken cancellationToken)
400  {
401  IQueryable<Models.Instance> query = DatabaseContext.Instances;
403  query = query.Where(x => x.InstanceUsers.Any(y => y.UserId == AuthenticationContext.User.Id)).Where(x => x.InstanceUsers.Any(y => y.AnyRights));
404 
405  var moveJobTasks = query
406  .SelectMany(x => x.Jobs)
407 #pragma warning disable CA1307 // Specify StringComparison
408  .Where(x => !x.StoppedAt.HasValue && x.Description.StartsWith(MoveInstanceJobPrefix))
409 #pragma warning restore CA1307 // Specify StringComparison
410  .Include(x => x.StartedBy).ThenInclude(x => x.CreatedBy)
411  .Include(x => x.Instance)
412  .ToListAsync(cancellationToken);
413  var instances = await query.ToListAsync(cancellationToken).ConfigureAwait(false);
414  var apis = instances.Select(x => x.ToApi());
415  var moveJobs = await moveJobTasks.ConfigureAwait(false);
416  foreach(var I in moveJobs)
417  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
418  return Json(apis);
419  }
420 
422  [TgsAuthorize(InstanceManagerRights.List | InstanceManagerRights.Read)]
423  public override async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
424  {
425  var query = DatabaseContext.Instances.Where(x => x.Id == id);
426  var cantList = !AuthenticationContext.User.InstanceManagerRights.Value.HasFlag(InstanceManagerRights.List);
427 
428  if (cantList)
429  query = query.Include(x => x.InstanceUsers);
430 
431  var moveJobTask = query
432  .SelectMany(x => x.Jobs)
433 #pragma warning disable CA1307 // Specify StringComparison
434  .Where(x => !x.StoppedAt.HasValue && x.Description.StartsWith(MoveInstanceJobPrefix))
435 #pragma warning restore CA1307 // Specify StringComparison
436  .Include(x => x.StartedBy).ThenInclude(x => x.CreatedBy)
437  .FirstOrDefaultAsync(cancellationToken);
438  var instance = await query.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
439 
440  if (instance == null)
441  return StatusCode((int)HttpStatusCode.Gone);
442 
443  if (cantList && !instance.InstanceUsers.Any(x => x.UserId == AuthenticationContext.User.Id && x.AnyRights))
444  return Forbid();
445 
446  var api = instance.ToApi();
447  api.MoveJob = (await moveJobTask.ConfigureAwait(false))?.ToApi();
448  return Json(api);
449  }
450  }
451 }
string Name
The name of the User
Definition: User.cs:38
- -
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
- -
User can enable Models.Internal.DreamDaemonSettings.SoftRestart
+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 : ModelController<Api.Models.Instance>
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)
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 
112  [TgsAuthorize(InstanceManagerRights.Create)]
113  public override async Task<IActionResult> Create([FromBody] Api.Models.Instance model, CancellationToken cancellationToken)
114  {
115  if (model == null)
116  throw new ArgumentNullException(nameof(model));
117 
118  if (String.IsNullOrWhiteSpace(model.Name))
119  return BadRequest(new ErrorMessage { Message = "name must not be empty!" });
120 
121  if (model.Path == null)
122  return BadRequest(new ErrorMessage { Message = "path must not be empty!" });
123 
124  NormalizeModelPath(model, out var rawPath);
125 
126  var localPath = ioManager.ResolvePath(".");
127  NormalizeModelPath(new Api.Models.Instance
128  {
129  Path = localPath
130  }, out var normalizedLocalPath);
131 
132  if (rawPath.StartsWith(normalizedLocalPath, StringComparison.Ordinal))
133  return Conflict("Instances cannot be created in the installation directory!");
134 
135  var dirExistsTask = ioManager.DirectoryExists(model.Path, cancellationToken);
136  bool attached = false;
137  if (await ioManager.FileExists(model.Path, cancellationToken).ConfigureAwait(false) || await dirExistsTask.ConfigureAwait(false))
138  if (!await ioManager.FileExists(ioManager.ConcatPath(model.Path, InstanceAttachFileName), cancellationToken).ConfigureAwait(false))
139  return Conflict(new ErrorMessage { Message = "Path not empty!" });
140  else
141  attached = true;
142 
143  var newInstance = new Models.Instance
144  {
145  ConfigurationType = model.ConfigurationType ?? ConfigurationType.Disallowed,
147  {
148  AllowWebClient = false,
149  AutoStart = false,
150  PrimaryPort = 1337,
151  SecondaryPort = 1338,
152  SecurityLevel = DreamDaemonSecurity.Safe,
153  SoftRestart = false,
154  SoftShutdown = false,
155  StartupTimeout = 20
156  },
158  {
159  ApiValidationPort = 1339,
160  ApiValidationSecurityLevel = DreamDaemonSecurity.Safe
161  },
162  Name = model.Name,
163  Online = false,
164  Path = model.Path,
165  AutoUpdateInterval = model.AutoUpdateInterval ?? 0,
167  {
168  CommitterEmail = "tgstation-server@users.noreply.github.com",
169  CommitterName = application.VersionPrefix,
170  PushTestMergeCommits = false,
171  ShowTestMergeCommitters = false,
172  AutoUpdatesKeepTestMerges = false,
173  AutoUpdatesSynchronize = false,
174  PostTestMergeComment = false
175  },
176  InstanceUsers = new List<Models.InstanceUser> // give this user full privileges on the instance
177  {
179  }
180  };
181 
182  DatabaseContext.Instances.Add(newInstance);
183  try
184  {
185  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
186 
187  try
188  {
189  // actually reserve it now
190  await ioManager.CreateDirectory(rawPath, cancellationToken).ConfigureAwait(false);
191  await ioManager.DeleteFile(ioManager.ConcatPath(rawPath, InstanceAttachFileName), cancellationToken).ConfigureAwait(false);
192  }
193  catch
194  {
195  // oh shit delete the model
196  DatabaseContext.Instances.Remove(newInstance);
197 
198  await DatabaseContext.Save(default).ConfigureAwait(false);
199  throw;
200  }
201  }
202  catch (IOException e)
203  {
204  return Conflict(new ErrorMessage { Message = e.Message });
205  }
206  catch (DbUpdateException e)
207  {
208  return Conflict(new ErrorMessage { Message = e.Message });
209  }
210 
211  Logger.LogInformation("{0} {1} instance {2}: {3} ({4})", AuthenticationContext.User.Name, attached ? "attached" : "created", newInstance.Name, newInstance.Id, newInstance.Path);
212 
213  var api = newInstance.ToApi();
214  return attached ? (IActionResult)Json(api) : StatusCode((int)HttpStatusCode.Created, api);
215  }
216 
218  [TgsAuthorize(InstanceManagerRights.Delete)]
219  public override async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
220  {
221  var originalModel = await DatabaseContext.Instances.Where(x => x.Id == id)
222  .Include(x => x.WatchdogReattachInformation)
223  .Include(x => x.WatchdogReattachInformation.Alpha)
224  .Include(x => x.WatchdogReattachInformation.Bravo)
225  .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
226  if (originalModel == default)
227  return StatusCode((int)HttpStatusCode.Gone);
228  if (originalModel.Online.Value)
229  return Conflict(new ErrorMessage
230  {
231  Message = "Cannot detach an online instance!"
232  });
233 
234  if (originalModel.WatchdogReattachInformation != null)
235  {
236  DatabaseContext.WatchdogReattachInformations.Remove(originalModel.WatchdogReattachInformation);
237  if (originalModel.WatchdogReattachInformation.Alpha != null)
238  DatabaseContext.ReattachInformations.Remove(originalModel.WatchdogReattachInformation.Alpha);
239  if (originalModel.WatchdogReattachInformation.Bravo != null)
240  DatabaseContext.ReattachInformations.Remove(originalModel.WatchdogReattachInformation.Bravo);
241  }
242 
243  DatabaseContext.Instances.Remove(originalModel);
244 
245  var attachFileName = ioManager.ConcatPath(originalModel.Path, InstanceAttachFileName);
246  await ioManager.WriteAllBytes(attachFileName, Array.Empty<byte>(), default).ConfigureAwait(false);
247  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false); // cascades everything
248  return Ok();
249  }
250 
252  [TgsAuthorize(InstanceManagerRights.Relocate | InstanceManagerRights.Rename | InstanceManagerRights.SetAutoUpdate | InstanceManagerRights.SetConfiguration | InstanceManagerRights.SetOnline)]
253  #pragma warning disable CA1502 // TODO: Decomplexify
254  public override async Task<IActionResult> Update([FromBody] Api.Models.Instance model, CancellationToken cancellationToken)
255  {
256  var instanceQuery = DatabaseContext.Instances.Where(x => x.Id == model.Id);
257 
258  var moveJob = await instanceQuery
259  .SelectMany(x => x.Jobs).
260 #pragma warning disable CA1307 // Specify StringComparison
261  Where(x => !x.StoppedAt.HasValue && x.Description.StartsWith(MoveInstanceJobPrefix))
262 #pragma warning restore CA1307 // Specify StringComparison
263  .Select(x => new Models.Job
264  {
265  Id = x.Id
266  }).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
267 
268  if (moveJob != default)
269  await jobManager.CancelJob(moveJob, AuthenticationContext.User, true, cancellationToken).ConfigureAwait(false); // cancel it now
270 
271  var usersInstanceUserTask = instanceQuery.SelectMany(x => x.InstanceUsers).Where(x => x.UserId == AuthenticationContext.User.Id).FirstOrDefaultAsync(cancellationToken);
272 
273  var originalModel = await instanceQuery
274  .Include(x => x.RepositorySettings)
275  .Include(x => x.ChatSettings)
276  .ThenInclude(x => x.Channels)
277  .Include(x => x.DreamDaemonSettings) // need these for onlining
278  .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
279  if (originalModel == default(Models.Instance))
280  return StatusCode((int)HttpStatusCode.Gone);
281 
282  var userRights = (InstanceManagerRights)AuthenticationContext.GetRight(RightsType.InstanceManager);
283  bool CheckModified<T>(Expression<Func<Api.Models.Instance, T>> expression, InstanceManagerRights requiredRight)
284  {
285  var memberSelectorExpression = (MemberExpression)expression.Body;
286  var property = (PropertyInfo)memberSelectorExpression.Member;
287 
288  var newVal = property.GetValue(model);
289  if (newVal == null)
290  return false;
291  if (!userRights.HasFlag(requiredRight) && property.GetValue(originalModel) != newVal)
292  return true;
293 
294  property.SetValue(originalModel, newVal);
295  return false;
296  }
297 
298  string originalModelPath = null;
299  string rawPath = null;
300  if (model.Path != null)
301  {
302  NormalizeModelPath(model, out rawPath);
303 
304  if (model.Path != originalModel.Path)
305  {
306  if (!userRights.HasFlag(InstanceManagerRights.Relocate))
307  return Forbid();
308  if (originalModel.Online.Value && model.Online != true)
309  return Conflict(new ErrorMessage { Message = "Cannot relocate an online instance!" });
310 
311  var dirExistsTask = ioManager.DirectoryExists(model.Path, cancellationToken);
312  if (await ioManager.FileExists(model.Path, cancellationToken).ConfigureAwait(false) || await dirExistsTask.ConfigureAwait(false))
313  return Conflict(new ErrorMessage { Message = "Path not empty!" });
314 
315  originalModelPath = originalModel.Path;
316  originalModel.Path = model.Path;
317  }
318  }
319 
320  var oldAutoUpdateInterval = originalModel.AutoUpdateInterval.Value;
321  var originalOnline = originalModel.Online.Value;
322  var renamed = model.Name != null && originalModel.Name != model.Name;
323 
324  if (CheckModified(x => x.AutoUpdateInterval, InstanceManagerRights.SetAutoUpdate)
325  || CheckModified(x => x.ConfigurationType, InstanceManagerRights.SetConfiguration)
326  || CheckModified(x => x.Name, InstanceManagerRights.Rename)
327  || CheckModified(x => x.Online, InstanceManagerRights.SetOnline))
328  return Forbid();
329 
330  // ensure the current user has write privilege on the instance
331  var usersInstanceUser = await usersInstanceUserTask.ConfigureAwait(false);
332  if (usersInstanceUser == default)
333  {
334  var instanceAdminUser = InstanceAdminUser();
335  instanceAdminUser.InstanceId = originalModel.Id;
336  DatabaseContext.InstanceUsers.Add(instanceAdminUser);
337  }
338  else
339  usersInstanceUser.InstanceUserRights |= InstanceUserRights.WriteUsers;
340 
341  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
342 
343  if (renamed)
344  instanceManager.GetInstance(originalModel).Rename(originalModel.Name);
345 
346  var oldAutoStart = originalModel.DreamDaemonSettings.AutoStart;
347  try
348  {
349  if (originalOnline && model.Online == false)
350  await instanceManager.OfflineInstance(originalModel, AuthenticationContext.User, cancellationToken).ConfigureAwait(false);
351  else if (!originalOnline && model.Online == true)
352  {
353  // force autostart false here because we don't want any long running jobs right now
354  // remember to document this
355  originalModel.DreamDaemonSettings.AutoStart = false;
356  await instanceManager.OnlineInstance(originalModel, cancellationToken).ConfigureAwait(false);
357  }
358  }
359  catch (Exception e)
360  {
361  if(!(e is OperationCanceledException))
362  Logger.LogError("Error changing instance online state! Exception: {0}", e);
363  originalModel.Online = originalOnline;
364  originalModel.DreamDaemonSettings.AutoStart = oldAutoStart;
365  if (originalModelPath != null)
366  originalModel.Path = originalModelPath;
367  await DatabaseContext.Save(default).ConfigureAwait(false);
368  throw;
369  }
370 
371  var api = (AuthenticationContext.GetRight(RightsType.InstanceManager) & (ulong)InstanceManagerRights.Read) != 0 ? originalModel.ToApi() : new Api.Models.Instance
372  {
373  Id = originalModel.Id
374  };
375  if (originalModelPath != null)
376  {
377  var job = new Models.Job
378  {
379  Description = String.Format(CultureInfo.InvariantCulture, MoveInstanceJobPrefix + "{0} from {1} to {2}", originalModel.Id, originalModel.Path, rawPath),
380  Instance = originalModel,
381  CancelRightsType = RightsType.InstanceManager,
382  CancelRight = (ulong)InstanceManagerRights.Relocate,
383  StartedBy = AuthenticationContext.User
384  };
385 
386  await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressHandler, ct) => instanceManager.MoveInstance(originalModel, rawPath, ct), cancellationToken).ConfigureAwait(false);
387  api.MoveJob = job.ToApi();
388  }
389 
390  if (originalModel.Online.Value && model.AutoUpdateInterval.HasValue && oldAutoUpdateInterval != model.AutoUpdateInterval)
391  await instanceManager.GetInstance(originalModel).SetAutoUpdateInterval(model.AutoUpdateInterval.Value).ConfigureAwait(false);
392 
393  return Json(api);
394  }
395  #pragma warning restore CA1502
396 
398  [TgsAuthorize(InstanceManagerRights.List | InstanceManagerRights.Read)]
399  public override async Task<IActionResult> List(CancellationToken cancellationToken)
400  {
401  IQueryable<Models.Instance> query = DatabaseContext.Instances;
403  query = query.Where(x => x.InstanceUsers.Any(y => y.UserId == AuthenticationContext.User.Id)).Where(x => x.InstanceUsers.Any(y => y.AnyRights));
404 
405  var moveJobTasks = query
406  .SelectMany(x => x.Jobs)
407 #pragma warning disable CA1307 // Specify StringComparison
408  .Where(x => !x.StoppedAt.HasValue && x.Description.StartsWith(MoveInstanceJobPrefix))
409 #pragma warning restore CA1307 // Specify StringComparison
410  .Include(x => x.StartedBy).ThenInclude(x => x.CreatedBy)
411  .Include(x => x.Instance)
412  .ToListAsync(cancellationToken);
413  var instances = await query.ToListAsync(cancellationToken).ConfigureAwait(false);
414  var apis = instances.Select(x => x.ToApi());
415  var moveJobs = await moveJobTasks.ConfigureAwait(false);
416  foreach(var I in moveJobs)
417  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
418  return Json(apis);
419  }
420 
422  [TgsAuthorize(InstanceManagerRights.List | InstanceManagerRights.Read)]
423  public override async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
424  {
425  var query = DatabaseContext.Instances.Where(x => x.Id == id);
426  var cantList = !AuthenticationContext.User.InstanceManagerRights.Value.HasFlag(InstanceManagerRights.List);
427 
428  if (cantList)
429  query = query.Include(x => x.InstanceUsers);
430 
431  var moveJobTask = query
432  .SelectMany(x => x.Jobs)
433 #pragma warning disable CA1307 // Specify StringComparison
434  .Where(x => !x.StoppedAt.HasValue && x.Description.StartsWith(MoveInstanceJobPrefix))
435 #pragma warning restore CA1307 // Specify StringComparison
436  .Include(x => x.StartedBy).ThenInclude(x => x.CreatedBy)
437  .FirstOrDefaultAsync(cancellationToken);
438  var instance = await query.FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
439 
440  if (instance == null)
441  return StatusCode((int)HttpStatusCode.Gone);
442 
443  if (cantList && !instance.InstanceUsers.Any(x => x.UserId == AuthenticationContext.User.Id && x.AnyRights))
444  return Forbid();
445 
446  var api = instance.ToApi();
447  api.MoveJob = (await moveJobTask.ConfigureAwait(false))?.ToApi();
448  return Json(api);
449  }
450  }
451 }
string Name
The name of the User
Definition: User.cs:38
+ + +
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
+ +
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
+
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
-
InstanceUserRights
Rights for an Models.Instance
-
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
- -
InstanceManagerRights InstanceManagerRights
The Rights.InstanceManagerRights for the User
Definition: User.cs:50
-
readonly IInstanceManager instanceManager
The IInstanceManager for the InstanceController
-
readonly IApplication application
The IApplication for the InstanceController
+
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
+
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
-
ConfigurationType
The type of configuration allowed on an Instance
-
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
-
Controller for managing Components.Instances
+
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
+
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
+
Controller 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...
-
readonly IIOManager ioManager
The IIOManager for the InstanceController
-
readonly IJobManager jobManager
The IJobManager for the InstanceController
+
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
-
Routes to a server actions
Definition: Routes.cs:9
-
DreamDaemonRights
Rights for Models.DreamDaemon
-
InstanceManagerRights
Rights for managing Models.Instances
-
string Message
A human readable description of the error
Definition: ErrorMessage.cs:13
-
DreamMakerRights
Rights for Models.DreamMaker
+
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
+
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
override async Task< IActionResult > Create([FromBody] Api.Models.Instance model, CancellationToken cancellationToken)
-
RepositoryRights
Rights for a Models.Repository
-
An ApiController representing a TModel
+
RepositoryRights
Rights for a Models.Repository
+
An ApiController representing a TModel
-
override async Task< IActionResult > List(CancellationToken cancellationToken)
Attempt to list entries of the TModel
+
override async Task< IActionResult > List(CancellationToken cancellationToken)
Attempt to list entries of the TModel
+
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
- -
long Id
The ID of the User
Definition: User.cs:15
-
Metadata about a server instance
Definition: Instance.cs:9
- -
override async Task< IActionResult > Delete(long id, CancellationToken cancellationToken)
Attempt to delete a model with a particular id
- +
const string InstanceManager
The Models.Instance controller
Definition: Routes.cs:29
+
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
+
Metadata about a server instance
Definition: Instance.cs:9
+ +
override async Task< IActionResult > Delete(long id, CancellationToken cancellationToken)
Attempt to delete a model with a particular id
+ +
DbSet< WatchdogReattachInformation > WatchdogReattachInformations
-
DreamDaemonSecurity
DreamDaemon&#39;s security level
-
Interface for using filesystems
Definition: IIOManager.cs:11
+
DreamDaemonSecurity
DreamDaemon's security level
+
Interface for using filesystems
Definition: IIOManager.cs:11
override async Task< IActionResult > Update([FromBody] Api.Models.Instance model, CancellationToken cancellationToken)
-
override async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Attempt to get a specific a TModel
-
For identifying the current platform
-
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
+
override async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Attempt to get a specific a TModel
+
For identifying the current platform
+
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)
-
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
-
User can enable Models.Internal.DreamDaemonSettings.SoftShutdown
- +
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+
User can enable Models.Internal.DreamDaemonSettings.SoftShutdown
+ +
Task< bool > DirectoryExists(string path, CancellationToken cancellationToken)
Check that the directory at path exists
- - + +
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
+
diff --git a/_instance_factory_8cs.html b/_instance_factory_8cs.html index 5e626d393c..16940797fb 100644 --- a/_instance_factory_8cs.html +++ b/_instance_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/InstanceFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_instance_factory_8cs_source.html b/_instance_factory_8cs_source.html index d7c3d79b62..d44719ff4b 100644 --- a/_instance_factory_8cs_source.html +++ b/_instance_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/InstanceFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
InstanceFactory.cs
-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 
16 namespace Tgstation.Server.Host.Components
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 
132  public 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)
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;
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
+
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 ...
-
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
- +
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
+
Task StopAsync(CancellationToken cancellationToken)
- -
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the InstanceFactory
-
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
- +
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 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 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
-
Contains various cryptographic functions
-
readonly IProcessExecutor processExecutor
The IProcessExecutor for the InstanceFactory
- +
readonly ICryptographySuite cryptographySuite
The ICryptographySuite 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
+
Contains various cryptographic functions
+
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
-
For downloading and installing BYOND extractions for a given system
+
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
- +
For accessing the disk in a synchronous manner
+
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: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
-
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
+ - -
IInstance CreateInstance(Models.Instance metadata)
Create an IInstance
-
Interface for using filesystems
Definition: IIOManager.cs:11
+ +
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(). This looks out for those prompts and immediately clicks "Yes" if the owning process has registered for it
-
For identifying the current platform
- +
On Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort()....
+
For identifying the current platform
+ - + - +
diff --git a/_instance_manager_8cs.html b/_instance_manager_8cs.html index 157874e18a..283b5d5c35 100644 --- a/_instance_manager_8cs.html +++ b/_instance_manager_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/InstanceManager.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_instance_manager_8cs_source.html b/_instance_manager_8cs_source.html index 71161acc59..2b053270e3 100644 --- a/_instance_manager_8cs_source.html +++ b/_instance_manager_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/InstanceManager.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
12 namespace Tgstation.Server.Host.Components
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 
77  public InstanceManager(IInstanceFactory instanceFactory, IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, IApplication application, IJobManager jobManager, IServerControl serverControl, ILogger<InstanceManager> logger)
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 
87  serverControl.RegisterForRestart(this);
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);
128  await databaseContextFactory.UseContext(db =>
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
-
readonly IServerControl serverControl
The IServerControl for the InstanceManager
-
IInstance GetInstance(Models.Instance metadata)
Get the IInstance associated with given metadata
-
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
- -
async Task OnlineInstance(Models.Instance metadata, CancellationToken cancellationToken)
Online an IInstance
- -
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
+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
+
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
+
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)
+
Task StartAsync(CancellationToken cancellationToken)
- -
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 ...
-
For interacting with the instance services
Definition: IInstance.cs:17
+ +
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
+
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
- -
readonly IInstanceFactory instanceFactory
The IInstanceFactory for the InstanceManager
-
readonly Dictionary< long, IInstance > instances
Map of Api.Models.Instance.Ids to respective IInstances
- +
readonly ILogger< InstanceManager > logger
The ILogger for the InstanceManager
+
Task< bool > CancelJob(Job job, User user, bool blocking, CancellationToken cancellationToken)
Cancels a give job
+ +
readonly IInstanceFactory instanceFactory
The IInstanceFactory for the InstanceManager
+ +
readonly Dictionary< long, IInstance > instances
Map of Api.Models.Instance.Ids to respective IInstances
+ -
readonly IApplication application
The IApplication for the InstanceManager
+
readonly IApplication application
The IApplication for the InstanceManager
+
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
-
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
-
IRestartRegistration RegisterForRestart(IRestartHandler handler)
Register a given handler to run before stopping the server for a restart
- - -
InstanceManager(IInstanceFactory instanceFactory, IIOManager ioManager, IDatabaseContextFactory databaseContextFactory, IApplication application, IJobManager jobManager, IServerControl serverControl, ILogger< InstanceManager > logger)
Construct an 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
+
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
Represents a service that may take an updated Host assembly and run it, stopping the current assembly...
@@ -135,7 +122,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_instance_manager_client_8cs.html b/_instance_manager_client_8cs.html index 98b87f8c01..65bbd0c923 100644 --- a/_instance_manager_client_8cs.html +++ b/_instance_manager_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/InstanceManagerClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -113,7 +96,7 @@ Namespaces diff --git a/_instance_manager_client_8cs_source.html b/_instance_manager_client_8cs_source.html index 7177db3bc2..cba2069604 100644 --- a/_instance_manager_client_8cs_source.html +++ b/_instance_manager_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/InstanceManagerClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
InstanceManagerClient.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 using Tgstation.Server.Api;
8 
9 namespace Tgstation.Server.Client
10 {
13  {
18 
22  readonly Dictionary<long, IInstanceClient> cachedClients;
23 
29  {
30  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
31 
32  cachedClients = new Dictionary<long, IInstanceClient>();
33  }
34 
36  public Task<Instance> CreateOrAttach(Instance instance, CancellationToken cancellationToken) => apiClient.Create<Instance, Instance>(Routes.InstanceManager, instance ?? throw new ArgumentNullException(nameof(instance)), cancellationToken);
37 
39  public Task Detach(Instance instance, CancellationToken cancellationToken) => apiClient.Delete(Routes.SetID(Routes.InstanceManager, instance?.Id ?? throw new ArgumentNullException(nameof(instance))), cancellationToken);
40 
42  public Task<IReadOnlyList<Instance>> List(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<Instance>>(Routes.List(Routes.InstanceManager), cancellationToken);
43 
45  public Task<Instance> Update(Instance instance, CancellationToken cancellationToken) => apiClient.Update<Instance, Instance>(Routes.InstanceManager, instance ?? throw new ArgumentNullException(nameof(instance)), cancellationToken);
46 
48  public Task<Instance> GetId(Instance instance, CancellationToken cancellationToken) => apiClient.Read<Instance>(Routes.SetID(Routes.InstanceManager, instance?.Id ?? throw new ArgumentNullException(nameof(instance))), cancellationToken);
49 
52  {
53  if (!cachedClients.TryGetValue(instance?.Id ?? throw new ArgumentNullException(nameof(instance)), out var client))
54  {
55  client = new InstanceClient(apiClient, instance);
56  cachedClients.Add(instance.Id, client);
57  }
58 
59  return client;
60  }
61  }
62 }
+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 using Tgstation.Server.Api;
8 
10 {
13  {
18 
22  readonly Dictionary<long, IInstanceClient> cachedClients;
23 
29  {
30  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
31 
32  cachedClients = new Dictionary<long, IInstanceClient>();
33  }
34 
36  public Task<Instance> CreateOrAttach(Instance instance, CancellationToken cancellationToken) => apiClient.Create<Instance, Instance>(Routes.InstanceManager, instance ?? throw new ArgumentNullException(nameof(instance)), cancellationToken);
37 
39  public Task Detach(Instance instance, CancellationToken cancellationToken) => apiClient.Delete(Routes.SetID(Routes.InstanceManager, instance?.Id ?? throw new ArgumentNullException(nameof(instance))), cancellationToken);
40 
42  public Task<IReadOnlyList<Instance>> List(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<Instance>>(Routes.List(Routes.InstanceManager), cancellationToken);
43 
45  public Task<Instance> Update(Instance instance, CancellationToken cancellationToken) => apiClient.Update<Instance, Instance>(Routes.InstanceManager, instance ?? throw new ArgumentNullException(nameof(instance)), cancellationToken);
46 
48  public Task<Instance> GetId(Instance instance, CancellationToken cancellationToken) => apiClient.Read<Instance>(Routes.SetID(Routes.InstanceManager, instance?.Id ?? throw new ArgumentNullException(nameof(instance))), cancellationToken);
49 
52  {
53  if (!cachedClients.TryGetValue(instance?.Id ?? throw new ArgumentNullException(nameof(instance)), out var client))
54  {
55  client = new InstanceClient(apiClient, instance);
56  cachedClients.Add(instance.Id, client);
57  }
58 
59  return client;
60  }
61  }
62 }
- - -
IInstanceClient CreateClient(Instance instance)
Create an IInstanceClient for a given Instance
+
IInstanceClient CreateClient(Instance instance)
Create an IInstanceClient for a given Instance
+
Task< IReadOnlyList< Instance > > List(CancellationToken cancellationToken)
Get all IInstanceClients for Instances the user can view
+
Task Detach(Instance instance, CancellationToken cancellationToken)
Deletes an instance
-
Routes to a server actions
Definition: Routes.cs:9
+
Routes to a server actions
Definition: Routes.cs:9
-
readonly IApiClient apiClient
The IApiClient for the InstanceManagerClient
-
InstanceManagerClient(IApiClient apiClient)
Construct an InstanceManagerClient
+
readonly IApiClient apiClient
The IApiClient for the InstanceManagerClient
+
InstanceManagerClient(IApiClient apiClient)
Construct an InstanceManagerClient
+
Task< Instance > Update(Instance instance, CancellationToken cancellationToken)
Relocates, renamed, and/or on/offlines an instance
-
readonly Dictionary< long, IInstanceClient > cachedClients
Map of already created IInstanceClients
-
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
- -
const string InstanceManager
The Models.Instance controller
Definition: Routes.cs:29
-
Metadata about a server instance
Definition: Instance.cs:9
-
static string SetID(string route, long id)
Apply an id postfix to a route
-
static string List(string route)
Get the /List postfix for a route
- -
Web interface for the API
Definition: IApiClient.cs:11
- +
readonly Dictionary< long, IInstanceClient > cachedClients
Map of already created IInstanceClients
+
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
+
Task< Instance > Instance(Routes.InstanceManager, instance ?? throw new ArgumentNullException(nameof(instance)), cancellationToken)
+ +
const string InstanceManager
The Models.Instance controller
Definition: Routes.cs:29
+
Metadata about a server instance
Definition: Instance.cs:9
+
static string SetID(string route, long id)
Apply an id postfix to a route
+
Task Delete(string route, CancellationToken cancellationToken)
Run an HTTP DELETE request
+
static string List(string route)
Get the /List postfix for a route
+ +
Web interface for the API
Definition: IApiClient.cs:11
+
Task< Instance > GetId(Instance instance, CancellationToken cancellationToken)
Get a specific instance
+
Task< Instance > CreateOrAttach(Instance instance, CancellationToken cancellationToken)
Create or attach an instance
+
diff --git a/_instance_manager_rights_8cs.html b/_instance_manager_rights_8cs.html index 168a934208..8877f947e2 100644 --- a/_instance_manager_rights_8cs.html +++ b/_instance_manager_rights_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/InstanceManagerRights.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Api +  namespace  Tgstation.Server.Api.Rights   @@ -119,8 +104,8 @@ Enumerations   Tgstation.Server.Api.Rights.InstanceManagerRights.SetConfiguration = 128, Tgstation.Server.Api.Rights.InstanceManagerRights.SetAutoUpdate = 256
- } - + } +
 Rights for managing Models.Instances More...
 Rights for managing Models.Instances More...
 
@@ -128,7 +113,7 @@ Enumerations diff --git a/_instance_manager_rights_8cs_source.html b/_instance_manager_rights_8cs_source.html index 4266fc00a6..22df8772f0 100644 --- a/_instance_manager_rights_8cs_source.html +++ b/_instance_manager_rights_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/InstanceManagerRights.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
InstanceManagerRights.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Api.Rights
4 {
8  [Flags]
9  public enum InstanceManagerRights : ulong
10  {
14  None = 0,
15 
19  Read = 1,
20 
24  Create = 2,
25 
29  Rename = 4,
30 
34  Relocate = 8,
35 
39  SetOnline = 16,
40 
44  Delete = 32,
45 
49  List = 64,
50 
54  SetConfiguration = 128,
55 
59  SetAutoUpdate = 256
60  }
61 }
- - -
User can change Models.Instance.ConfigurationType
- - -
InstanceManagerRights
Rights for managing Models.Instances
-
User can create new Models.ChatBot
-
User can change Models.Instance.AutoUpdateInterval
-
User can online Models.Instances they can view
-
User can relocate Models.Instances they can view
-
User can read all chat settings except Models.Internal.ChatBot.ConnectionString
-
User can rename Models.Instances they can view
- +Go to the documentation of this file.
1 using System;
2 
4 {
8  [Flags]
9  public enum InstanceManagerRights : ulong
10  {
14  None = 0,
15 
19  Read = 1,
20 
24  Create = 2,
25 
29  Rename = 4,
30 
34  Relocate = 8,
35 
39  SetOnline = 16,
40 
44  Delete = 32,
45 
49  List = 64,
50 
54  SetConfiguration = 128,
55 
59  SetAutoUpdate = 256
60  }
61 }
+
User can change Models.Instance.ConfigurationType
+ + +
InstanceManagerRights
Rights for managing Models.Instances
+
User can create new Models.ChatBot
+
User can change Models.Instance.AutoUpdateInterval
+
User can online Models.Instances they can view
+
User can relocate Models.Instances they can view
+ +
User can read all chat settings except Models.Internal.ChatBot.ConnectionString
+
User can rename Models.Instances they can view
diff --git a/_instance_manager_test_8cs.html b/_instance_manager_test_8cs.html index 3c472f677d..8658a14192 100644 --- a/_instance_manager_test_8cs.html +++ b/_instance_manager_test_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Tests/InstanceManagerTest.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Tests
 
@@ -113,7 +96,7 @@ Namespaces diff --git a/_instance_manager_test_8cs_source.html b/_instance_manager_test_8cs_source.html index 9e8fa79aa7..5ae8b1424b 100644 --- a/_instance_manager_test_8cs_source.html +++ b/_instance_manager_test_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Tests/InstanceManagerTest.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
21  public InstanceManagerTest(IInstanceManagerClient instanceManagerClient, string testRootPath)
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
readonly IInstanceManagerClient instanceManagerClient
- - +
Task< Instance > CreateOrAttach(Instance instance, CancellationToken cancellationToken)
Create or attach an instance
-
ConfigurationType
The type of configuration allowed on an Instance
-
Controller for managing Components.Instances
+
IInstanceClient CreateClient(Instance instance)
Create an IInstanceClient for a given Instance
+
ConfigurationType
The type of configuration allowed on an Instance
+
Controller for managing Components.Instances
async Task Run(CancellationToken cancellationToken)
+
Task< Instance > GetId(Instance instance, CancellationToken cancellationToken)
Get a specific instance
+
Task Detach(Instance instance, CancellationToken cancellationToken)
Deletes an instance
+
Task< Instance > Update(Instance instance, CancellationToken cancellationToken)
Relocates, renamed, and/or on/offlines an instance
-
Occurs when the client performs an action that would result in data conflict
- -
Occurs when the client attempts to perform an action they do not have the rights for ...
+
Occurs when the client performs an action that would result in data conflict
+ +
Occurs when the client attempts to perform an action they do not have the rights for
InstanceManagerTest(IInstanceManagerClient instanceManagerClient, string testRootPath)
- - - + +
Task< Api.Models.Instance > CreateTestInstance(CancellationToken cancellationToken)
+ +
diff --git a/_instance_test_8cs.html b/_instance_test_8cs.html index c2d6b72d67..6d0ca9a288 100644 --- a/_instance_test_8cs.html +++ b/_instance_test_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Tests/Instance/InstanceTest.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Tests
 
namespace  Tgstation.Server.Tests.Instance
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_instance_test_8cs_source.html b/_instance_test_8cs_source.html index 968d009666..8671d9cd38 100644 --- a/_instance_test_8cs_source.html +++ b/_instance_test_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Tests/Instance/InstanceTest.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
InstanceTest.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Tests.Instance
7 {
8  sealed class InstanceTest
9  {
11 
12  public InstanceTest(IInstanceClient instanceClient)
13  {
14  this.instanceClient = instanceClient ?? throw new ArgumentNullException(nameof(instanceClient));
15  }
16 
17  public async Task RunTests(CancellationToken cancellationToken)
18  {
19  var byondTests = new ByondTest(instanceClient.Byond, instanceClient.Jobs);
20  var configTests = new ConfigurationTest(instanceClient.Configuration, instanceClient.Metadata);
21 
22  var byondTest = byondTests.Run(cancellationToken);
23  await configTests.Run(cancellationToken).ConfigureAwait(false);
24  await byondTest.ConfigureAwait(false);
25  }
26  }
27 }
+Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
8  sealed class InstanceTest
9  {
11 
13  {
14  this.instanceClient = instanceClient ?? throw new ArgumentNullException(nameof(instanceClient));
15  }
16 
17  public async Task RunTests(CancellationToken cancellationToken)
18  {
19  var byondTests = new ByondTest(instanceClient.Byond, instanceClient.Jobs);
21 
22  var byondTest = byondTests.Run(cancellationToken);
23  await configTests.Run(cancellationToken).ConfigureAwait(false);
24  await byondTest.ConfigureAwait(false);
25  }
26  }
27 }
async Task RunTests(CancellationToken cancellationToken)
Definition: InstanceTest.cs:17
- - +
Instance Metadata
The Instance used to create the IInstanceClient
+
IConfigurationClient Configuration
Access the IConfigurationClient
+
IByondClient Byond
Access the IByondClient
+
InstanceTest(IInstanceClient instanceClient)
Definition: InstanceTest.cs:12
- - + + +
diff --git a/_instance_user_client_8cs.html b/_instance_user_client_8cs.html index dbd5f453ab..e6c4bf2aac 100644 --- a/_instance_user_client_8cs.html +++ b/_instance_user_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/InstanceUserClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_instance_user_client_8cs_source.html b/_instance_user_client_8cs_source.html index 9f430d0348..b72204b840 100644 --- a/_instance_user_client_8cs_source.html +++ b/_instance_user_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/InstanceUserClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
InstanceUserClient.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 using Tgstation.Server.Api;
7 
8 namespace Tgstation.Server.Client.Components
9 {
12  {
17 
21  readonly Instance instance;
22 
28  public InstanceUserClient(IApiClient apiClient, Instance instance)
29  {
30  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
31  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
32  }
33 
35  public Task<InstanceUser> Create(InstanceUser instanceUser, CancellationToken cancellationToken) => apiClient.Create<InstanceUser, InstanceUser>(Routes.InstanceUser, instanceUser ?? throw new ArgumentNullException(nameof(instanceUser)), instance.Id, cancellationToken);
36 
38  public Task Delete(InstanceUser instanceUser, CancellationToken cancellationToken) => apiClient.Delete(Routes.SetID(Routes.InstanceUser, instanceUser.UserId.Value), instance.Id, cancellationToken);
39 
41  public Task<InstanceUser> Read(CancellationToken cancellationToken) => apiClient.Read<InstanceUser>(Routes.InstanceUser, instance.Id, cancellationToken);
42 
44  public Task<InstanceUser> Update(InstanceUser instanceUser, CancellationToken cancellationToken) => apiClient.Update<InstanceUser, InstanceUser>(Routes.InstanceUser, instanceUser ?? throw new ArgumentNullException(nameof(instanceUser)), instance.Id, cancellationToken);
45 
47  public Task<IReadOnlyList<InstanceUser>> List(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<InstanceUser>>(Routes.List(Routes.InstanceUser), instance.Id, cancellationToken);
48 
50  public Task<InstanceUser> GetId(InstanceUser instanceUser, CancellationToken cancellationToken) => apiClient.Read<InstanceUser>(Routes.SetID(Routes.InstanceUser, instanceUser?.UserId ?? throw new ArgumentNullException(nameof(instanceUser))), instance.Id, cancellationToken);
51  }
52 }
readonly IApiClient apiClient
The IApiClient for the InstanceUserClient
+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 using Tgstation.Server.Api;
7 
9 {
12  {
17 
21  readonly Instance instance;
22 
29  {
30  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
31  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
32  }
33 
35  public Task<InstanceUser> Create(InstanceUser instanceUser, CancellationToken cancellationToken) => apiClient.Create<InstanceUser, InstanceUser>(Routes.InstanceUser, instanceUser ?? throw new ArgumentNullException(nameof(instanceUser)), instance.Id, cancellationToken);
36 
38  public Task Delete(InstanceUser instanceUser, CancellationToken cancellationToken) => apiClient.Delete(Routes.SetID(Routes.InstanceUser, instanceUser.UserId.Value), instance.Id, cancellationToken);
39 
41  public Task<InstanceUser> Read(CancellationToken cancellationToken) => apiClient.Read<InstanceUser>(Routes.InstanceUser, instance.Id, cancellationToken);
42 
44  public Task<InstanceUser> Update(InstanceUser instanceUser, CancellationToken cancellationToken) => apiClient.Update<InstanceUser, InstanceUser>(Routes.InstanceUser, instanceUser ?? throw new ArgumentNullException(nameof(instanceUser)), instance.Id, cancellationToken);
45 
47  public Task<IReadOnlyList<InstanceUser>> List(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<InstanceUser>>(Routes.List(Routes.InstanceUser), instance.Id, cancellationToken);
48 
50  public Task<InstanceUser> GetId(InstanceUser instanceUser, CancellationToken cancellationToken) => apiClient.Read<InstanceUser>(Routes.SetID(Routes.InstanceUser, instanceUser?.UserId ?? throw new ArgumentNullException(nameof(instanceUser))), instance.Id, cancellationToken);
51  }
52 }
readonly IApiClient apiClient
The IApiClient for the InstanceUserClient
- -
readonly Instance instance
The Instance for the InstanceUserClient
-
const string InstanceUser
The Models.InstanceUser controller
Definition: Routes.cs:64
- -
InstanceUserClient(IApiClient apiClient, Instance instance)
Construct an InstanceUserClient
+
readonly Instance instance
The Instance for the InstanceUserClient
+
const string InstanceUser
The Models.InstanceUser controller
Definition: Routes.cs:64
+
Task< InstanceUser > GetId(InstanceUser instanceUser, CancellationToken cancellationToken)
Get a specific instanceUser
+
InstanceUserClient(IApiClient apiClient, Instance instance)
Construct an InstanceUserClient
+
Task Delete(InstanceUser instanceUser, CancellationToken cancellationToken)
Delete a instanceUser
-
Routes to a server actions
Definition: Routes.cs:9
- -
Represents a Users permissions in an Instance
Definition: InstanceUser.cs:9
+
Task< InstanceUser > Update(InstanceUser instanceUser, CancellationToken cancellationToken)
Update a instanceUser
+
Routes to a server actions
Definition: Routes.cs:9
+ + +
Represents a Users permissions in an Instance
Definition: InstanceUser.cs:9
+
Task< InstanceUser > Read(CancellationToken cancellationToken)
Get the InstanceUser associated with the logged on user
+
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
-
Metadata about a server instance
Definition: Instance.cs:9
-
static string SetID(string route, long id)
Apply an id postfix to a route
-
static string List(string route)
Get the /List postfix for a route
- -
Web interface for the API
Definition: IApiClient.cs:11
-
long UserId
The Internal.User.Id of the User the InstanceUser belongs to
Definition: InstanceUser.cs:15
- +
Metadata about a server instance
Definition: Instance.cs:9
+
static string SetID(string route, long id)
Apply an id postfix to a route
+
Task Delete(string route, CancellationToken cancellationToken)
Run an HTTP DELETE request
+
static string List(string route)
Get the /List postfix for a route
+ +
Task< IReadOnlyList< InstanceUser > > List(CancellationToken cancellationToken)
Get the InstanceUsers in the Instance
+
Web interface for the API
Definition: IApiClient.cs:11
+
Task< InstanceUser > InstanceUser(Routes.InstanceUser, instanceUser ?? throw new ArgumentNullException(nameof(instanceUser)), instance.Id, cancellationToken)
+
Task< InstanceUser > Create(InstanceUser instanceUser, CancellationToken cancellationToken)
Create a instanceUser
+
diff --git a/_instance_user_controller_8cs.html b/_instance_user_controller_8cs.html index c26df40302..a932650a1a 100644 --- a/_instance_user_controller_8cs.html +++ b/_instance_user_controller_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/InstanceUserController.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Controllers
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_instance_user_controller_8cs_source.html b/_instance_user_controller_8cs_source.html index bf4d2a89cc..8affdc9869 100644 --- a/_instance_user_controller_8cs_source.html +++ b/_instance_user_controller_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/InstanceUserController.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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.Linq;
6 using System.Net;
7 using System.Threading;
8 using System.Threading.Tasks;
9 using Tgstation.Server.Api;
14 using Z.EntityFramework.Plus;
15 
16 namespace Tgstation.Server.Host.Controllers
17 {
21  [Route(Routes.InstanceUser)]
22  public sealed class InstanceUserController : ModelController<Api.Models.InstanceUser>
23  {
30  public InstanceUserController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ILogger<InstanceUserController> logger) : base(databaseContext, authenticationContextFactory, logger, true) // false instance requirement, we handle this ourself
31  { }
32 
38  BadRequestObjectResult StandardModelChecks(Api.Models.InstanceUser model)
39  {
40  if (model == null)
41  throw new ArgumentNullException(nameof(model));
42 
43  if (!model.UserId.HasValue)
44  return BadRequest(new ErrorMessage { Message = "Missing UserId!" });
45 
46  return null;
47  }
48 
50  [TgsAuthorize(InstanceUserRights.CreateUsers)]
51  public override async Task<IActionResult> Create([FromBody] Api.Models.InstanceUser model, CancellationToken cancellationToken)
52  {
53  var test = StandardModelChecks(model);
54  if (test != null)
55  return test;
56 
57  var dbUser = new Models.InstanceUser
58  {
59  ByondRights = model.ByondRights ?? ByondRights.None,
60  ChatBotRights = model.ChatBotRights ?? ChatBotRights.None,
61  ConfigurationRights = model.ConfigurationRights ?? ConfigurationRights.None,
62  DreamDaemonRights = model.DreamDaemonRights ?? DreamDaemonRights.None,
63  DreamMakerRights = model.DreamMakerRights ?? DreamMakerRights.None,
64  RepositoryRights = model.RepositoryRights ?? RepositoryRights.None,
65  InstanceUserRights = model.InstanceUserRights ?? InstanceUserRights.None,
66  UserId = model.UserId,
67  InstanceId = Instance.Id
68  };
69 
70  DatabaseContext.InstanceUsers.Add(dbUser);
71 
72  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
73  return StatusCode((int)HttpStatusCode.Created, dbUser.ToApi());
74  }
75 
77  [TgsAuthorize(InstanceUserRights.WriteUsers)]
78  #pragma warning disable CA1506 // TODO: Decomplexify
79  public override async Task<IActionResult> Update([FromBody] Api.Models.InstanceUser model, CancellationToken cancellationToken)
80  {
81  var test = StandardModelChecks(model);
82  if (test != null)
83  return test;
84 
85  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);
86  if (originalUser == null)
87  return StatusCode((int)HttpStatusCode.Gone);
88 
89  originalUser.ByondRights = model.ByondRights ?? originalUser.ByondRights;
90  originalUser.RepositoryRights = model.RepositoryRights ?? originalUser.RepositoryRights;
91  originalUser.InstanceUserRights = model.InstanceUserRights ?? originalUser.InstanceUserRights;
92  originalUser.ChatBotRights = model.ChatBotRights ?? originalUser.ChatBotRights;
93  originalUser.ConfigurationRights = model.ConfigurationRights ?? originalUser.ConfigurationRights;
94  originalUser.DreamDaemonRights = model.DreamDaemonRights ?? originalUser.DreamDaemonRights;
95  originalUser.DreamMakerRights = model.DreamMakerRights ?? originalUser.DreamMakerRights;
96 
97  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
98  return Json(originalUser.UserId == AuthenticationContext.User.Id || (AuthenticationContext.GetRight(RightsType.InstanceUser) & (ulong)InstanceUserRights.ReadUsers) != 0 ? originalUser.ToApi() : new Api.Models.InstanceUser
99  {
100  UserId = originalUser.UserId
101  });
102  }
103  #pragma warning restore CA1506
104 
106  [TgsAuthorize]
107  public override Task<IActionResult> Read(CancellationToken cancellationToken) => Task.FromResult(AuthenticationContext.InstanceUser != null ? (IActionResult)Json(AuthenticationContext.InstanceUser.ToApi()) : NotFound());
108 
110  [TgsAuthorize(InstanceUserRights.ReadUsers)]
111  public override async Task<IActionResult> List(CancellationToken cancellationToken)
112  {
113  var users = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).ToListAsync(cancellationToken).ConfigureAwait(false);
114  return Json(users.Select(x => x.ToApi()));
115  }
116 
118  [TgsAuthorize(InstanceUserRights.ReadUsers)]
119  public override async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
120  {
121  // this functions as userId
122  var user = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).Where(x => x.UserId == id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
123  if (user == default)
124  return StatusCode((int)HttpStatusCode.Gone);
125  return Json(user.ToApi());
126  }
127 
129  [TgsAuthorize(InstanceUserRights.WriteUsers)]
130  public override async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
131  {
132  await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).Where(x => x.UserId == id).DeleteAsync(cancellationToken).ConfigureAwait(false);
133  return Ok();
134  }
135  }
136 }
InstanceUserController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ILogger< InstanceUserController > logger)
Construct a UserController
- - -
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
+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.Net;
7 using System.Threading;
8 using System.Threading.Tasks;
9 using Tgstation.Server.Api;
14 using Z.EntityFramework.Plus;
15 
17 {
21  [Route(Routes.InstanceUser)]
22  public sealed class InstanceUserController : ModelController<Api.Models.InstanceUser>
23  {
30  public InstanceUserController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ILogger<InstanceUserController> logger) : base(databaseContext, authenticationContextFactory, logger, true) // false instance requirement, we handle this ourself
31  { }
32 
38  BadRequestObjectResult StandardModelChecks(Api.Models.InstanceUser model)
39  {
40  if (model == null)
41  throw new ArgumentNullException(nameof(model));
42 
43  if (!model.UserId.HasValue)
44  return BadRequest(new ErrorMessage { Message = "Missing UserId!" });
45 
46  return null;
47  }
48 
50  [TgsAuthorize(InstanceUserRights.CreateUsers)]
51  public override async Task<IActionResult> Create([FromBody] Api.Models.InstanceUser model, CancellationToken cancellationToken)
52  {
53  var test = StandardModelChecks(model);
54  if (test != null)
55  return test;
56 
57  var dbUser = new Models.InstanceUser
58  {
59  ByondRights = model.ByondRights ?? ByondRights.None,
60  ChatBotRights = model.ChatBotRights ?? ChatBotRights.None,
61  ConfigurationRights = model.ConfigurationRights ?? ConfigurationRights.None,
62  DreamDaemonRights = model.DreamDaemonRights ?? DreamDaemonRights.None,
63  DreamMakerRights = model.DreamMakerRights ?? DreamMakerRights.None,
64  RepositoryRights = model.RepositoryRights ?? RepositoryRights.None,
65  InstanceUserRights = model.InstanceUserRights ?? InstanceUserRights.None,
66  UserId = model.UserId,
67  InstanceId = Instance.Id
68  };
69 
70  DatabaseContext.InstanceUsers.Add(dbUser);
71 
72  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
73  return StatusCode((int)HttpStatusCode.Created, dbUser.ToApi());
74  }
75 
77  [TgsAuthorize(InstanceUserRights.WriteUsers)]
78  #pragma warning disable CA1506 // TODO: Decomplexify
79  public override async Task<IActionResult> Update([FromBody] Api.Models.InstanceUser model, CancellationToken cancellationToken)
80  {
81  var test = StandardModelChecks(model);
82  if (test != null)
83  return test;
84 
85  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);
86  if (originalUser == null)
87  return StatusCode((int)HttpStatusCode.Gone);
88 
89  originalUser.ByondRights = model.ByondRights ?? originalUser.ByondRights;
90  originalUser.RepositoryRights = model.RepositoryRights ?? originalUser.RepositoryRights;
91  originalUser.InstanceUserRights = model.InstanceUserRights ?? originalUser.InstanceUserRights;
92  originalUser.ChatBotRights = model.ChatBotRights ?? originalUser.ChatBotRights;
93  originalUser.ConfigurationRights = model.ConfigurationRights ?? originalUser.ConfigurationRights;
94  originalUser.DreamDaemonRights = model.DreamDaemonRights ?? originalUser.DreamDaemonRights;
95  originalUser.DreamMakerRights = model.DreamMakerRights ?? originalUser.DreamMakerRights;
96 
97  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
98  return Json(originalUser.UserId == AuthenticationContext.User.Id || (AuthenticationContext.GetRight(RightsType.InstanceUser) & (ulong)InstanceUserRights.ReadUsers) != 0 ? originalUser.ToApi() : new Api.Models.InstanceUser
99  {
100  UserId = originalUser.UserId
101  });
102  }
103  #pragma warning restore CA1506
104 
106  [TgsAuthorize]
107  public override Task<IActionResult> Read(CancellationToken cancellationToken) => Task.FromResult(AuthenticationContext.InstanceUser != null ? (IActionResult)Json(AuthenticationContext.InstanceUser.ToApi()) : NotFound());
108 
110  [TgsAuthorize(InstanceUserRights.ReadUsers)]
111  public override async Task<IActionResult> List(CancellationToken cancellationToken)
112  {
113  var users = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).ToListAsync(cancellationToken).ConfigureAwait(false);
114  return Json(users.Select(x => x.ToApi()));
115  }
116 
118  [TgsAuthorize(InstanceUserRights.ReadUsers)]
119  public override async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
120  {
121  // this functions as userId
122  var user = await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).Where(x => x.UserId == id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
123  if (user == default)
124  return StatusCode((int)HttpStatusCode.Gone);
125  return Json(user.ToApi());
126  }
127 
129  [TgsAuthorize(InstanceUserRights.WriteUsers)]
130  public override async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
131  {
132  await DatabaseContext.Instances.Where(x => x.Id == Instance.Id).SelectMany(x => x.InstanceUsers).Where(x => x.UserId == id).DeleteAsync(cancellationToken).ConfigureAwait(false);
133  return Ok();
134  }
135  }
136 }
InstanceUserController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ILogger< InstanceUserController > logger)
Construct a UserController
+ + +
ConfigurationRights
Rights for Models.ConfigurationFile
+ + +
override Task< IActionResult > Read(CancellationToken cancellationToken)
Attempt to read a TModel
+
ByondRights
Rights for Models.Byond
Definition: ByondRights.cs:9
+
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
-
InstanceUserRights
Rights for an Models.Instance
- +
InstanceUserRights
Rights for an Models.Instance
-
const string InstanceUser
The Models.InstanceUser controller
Definition: Routes.cs:64
- +
const string InstanceUser
The Models.InstanceUser controller
Definition: Routes.cs:64
-
override async Task< IActionResult > Delete(long id, CancellationToken cancellationToken)
Attempt to delete a model with a particular id
-
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
+
override async Task< IActionResult > Delete(long id, CancellationToken cancellationToken)
Attempt to delete a model with a particular id
+
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
override async Task< IActionResult > Create([FromBody] Api.Models.InstanceUser model, CancellationToken cancellationToken)
-
override async Task< IActionResult > List(CancellationToken cancellationToken)
Attempt to list entries of the TModel
-
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
+
override async Task< IActionResult > List(CancellationToken cancellationToken)
Attempt to list entries of the TModel
+
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
-
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
-
DreamMakerRights
Rights for Models.DreamMaker
+
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
+
DreamMakerRights
Rights for Models.DreamMaker
-
RepositoryRights
Rights for a Models.Repository
-
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
-
override async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Attempt to get a specific a TModel
-
An ApiController representing a TModel
+
RepositoryRights
Rights for a Models.Repository
+
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
+
override async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Attempt to get a specific a TModel
+
An ApiController representing a TModel
-
long Id
The ID of the User
Definition: User.cs:15
-
Metadata about a server instance
Definition: Instance.cs:9
+
long Id
The ID of the User
Definition: User.cs:15
+
Metadata about a server instance
Definition: Instance.cs:9
override async Task< IActionResult > Update([FromBody] Api.Models.InstanceUser model, CancellationToken cancellationToken)
- -
User can read all chat settings except Models.Internal.ChatBot.ConnectionString
-
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
-
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+ +
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
+
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- - + +
diff --git a/_instance_user_rights_8cs.html b/_instance_user_rights_8cs.html index c9a644e911..7c56c83ec3 100644 --- a/_instance_user_rights_8cs.html +++ b/_instance_user_rights_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/InstanceUserRights.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Api +  namespace  Tgstation.Server.Api.Rights   @@ -109,8 +94,8 @@ EnumerationsTgstation.Server.Api.Rights.InstanceUserRights.ReadUsers = 1, Tgstation.Server.Api.Rights.InstanceUserRights.WriteUsers = 2, Tgstation.Server.Api.Rights.InstanceUserRights.CreateUsers = 4 - } - + } +
 Rights for an Models.Instance More...
 Rights for an Models.Instance More...
 
@@ -118,7 +103,7 @@ Enumerations diff --git a/_instance_user_rights_8cs_source.html b/_instance_user_rights_8cs_source.html index d8e55bfa17..bcf563a547 100644 --- a/_instance_user_rights_8cs_source.html +++ b/_instance_user_rights_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/InstanceUserRights.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
InstanceUserRights.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Api.Rights
4 {
8  [Flags]
9  public enum InstanceUserRights : ulong
10  {
14  None = 0,
15 
19  ReadUsers = 1,
20 
24  WriteUsers = 2,
25 
29  CreateUsers = 4
30  }
31 }
User can edit themself and other Models.Users and also create others
-
InstanceUserRights
Rights for an Models.Instance
- - - -
User can read info and rights of other users
-
Allow adding additional Models.InstanceUser to the Models.Instance
- +Go to the documentation of this file.
1 using System;
2 
4 {
8  [Flags]
9  public enum InstanceUserRights : ulong
10  {
14  None = 0,
15 
19  ReadUsers = 1,
20 
24  WriteUsers = 2,
25 
29  CreateUsers = 4
30  }
31 }
User can edit themself and other Models.Users and also create others
+
InstanceUserRights
Rights for an Models.Instance
+ +
User can read info and rights of other users
+ +
Allow adding additional Models.InstanceUser to the Models.Instance
diff --git a/_insufficient_permissions_exception_8cs.html b/_insufficient_permissions_exception_8cs.html index 346eb2b9d7..0d86e3fccb 100644 --- a/_insufficient_permissions_exception_8cs.html +++ b/_insufficient_permissions_exception_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/InsufficientPermissionsException.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_insufficient_permissions_exception_8cs_source.html b/_insufficient_permissions_exception_8cs_source.html index 5564174664..90ac2a2c68 100644 --- a/_insufficient_permissions_exception_8cs_source.html +++ b/_insufficient_permissions_exception_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/InsufficientPermissionsException.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
InsufficientPermissionsException.cs
-Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
5 namespace Tgstation.Server.Client
6 {
11  {
16  {
17  Message = "The credentials provided do not have sufficient rights to make this request!",
18  SeverApiVersion = null
19  }, HttpStatusCode.Forbidden)
20  { }
21 
26  public InsufficientPermissionsException(string message) : base(message) { }
27 
33  public InsufficientPermissionsException(string message, Exception innerException) : base(message, innerException) { }
34  }
35 }
- - +Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
6 {
11  {
16  {
17  Message = "The credentials provided do not have sufficient rights to make this request!",
18  SeverApiVersion = null
19  }, HttpStatusCode.Forbidden)
20  { }
21 
26  public InsufficientPermissionsException(string message) : base(message) { }
27 
33  public InsufficientPermissionsException(string message, Exception innerException) : base(message, innerException) { }
34  }
35 }
+ -
InsufficientPermissionsException(string message, Exception innerException)
Construct an InsufficientPermissionsException with a message and innerException ...
-
InsufficientPermissionsException(string message)
Construct an InsufficientPermissionsException with a message
-
Occurs when the client attempts to perform an action they do not have the rights for ...
- -
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
-
InsufficientPermissionsException()
Construct an InsufficientPermissionsException
- -
Exceptions thrown by IServerClients
+
InsufficientPermissionsException(string message, Exception innerException)
Construct an InsufficientPermissionsException with a message and innerException
+
InsufficientPermissionsException(string message)
Construct an InsufficientPermissionsException with a message
+
Occurs when the client attempts to perform an action they do not have the rights for
+ +
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+
InsufficientPermissionsException()
Construct an InsufficientPermissionsException
+ +
Exceptions thrown by IServerClients
diff --git a/_integration_test_8cs.html b/_integration_test_8cs.html index fc0a0306a3..cd676bc268 100644 --- a/_integration_test_8cs.html +++ b/_integration_test_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Tests/IntegrationTest.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Tests
 
@@ -113,7 +96,7 @@ Namespaces diff --git a/_integration_test_8cs_source.html b/_integration_test_8cs_source.html index cfe940c218..205f740257 100644 --- a/_integration_test_8cs_source.html +++ b/_integration_test_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Tests/IntegrationTest.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IntegrationTest.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.Diagnostics;
4 using System.IO;
5 using System.Linq;
6 using System.Net.Http.Headers;
7 using System.Reflection;
8 using System.Threading;
9 using System.Threading.Tasks;
10 using Tgstation.Server.Api;
12 using Tgstation.Server.Client;
13 using Tgstation.Server.Host;
14 
15 namespace Tgstation.Server.Tests
16 {
17  [TestClass]
18  public sealed class IntegrationTest
19  {
20  readonly IServerClientFactory clientFactory = new ServerClientFactory(new ProductHeaderValue(Assembly.GetExecutingAssembly().GetName().Name, Assembly.GetExecutingAssembly().GetName().Version.ToString()));
21 
22  [TestMethod]
23  [TestCategory("SkipWhenLiveUnitTesting")]
24  public async Task TestUpdate()
25  {
26  var updatePathRoot = Path.GetTempFileName();
27  File.Delete(updatePathRoot);
28  Directory.CreateDirectory(updatePathRoot);
29  try
30  {
31  var updatePath = Path.Combine(updatePathRoot, Guid.NewGuid().ToString());
32  var server = new TestingServer(updatePath);
33  using (var serverCts = new CancellationTokenSource())
34  {
35  var cancellationToken = serverCts.Token;
36  var serverTask = server.RunAsync(cancellationToken);
37  try
38  {
39  IServerClient adminClient;
40 
41  var giveUpAt = DateTimeOffset.Now.AddSeconds(60);
42  do
43  {
44  try
45  {
46  adminClient = await clientFactory.CreateServerClient(server.Url, User.AdminName, User.DefaultAdminPassword).ConfigureAwait(false);
47  break;
48  }
50  {
51  //migrating, to be expected
52  if (DateTimeOffset.Now > giveUpAt)
53  throw;
54  await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
55  }
56  } while (true);
57 
58  var testUpdateVersion = new Version(4, 0, 0, 6);
59  using (adminClient)
60  //attempt to update to stable
61  await adminClient.Administration.Update(new Administration
62  {
63  NewVersion = testUpdateVersion
64  }, cancellationToken).ConfigureAwait(false);
65 
66  //wait up to 3 minutes for the dl and install
67  await Task.WhenAny(serverTask, Task.Delay(TimeSpan.FromMinutes(3), cancellationToken)).ConfigureAwait(false);
68 
69  Assert.IsTrue(serverTask.IsCompleted, "Sever still running!");
70 
71  Assert.IsTrue(Directory.Exists(updatePath), "Update directory not present!");
72 
73  var updatedAssemblyPath = Path.Combine(updatePath, "Tgstation.Server.Host.dll");
74  Assert.IsTrue(File.Exists(updatedAssemblyPath), "Updated assembly missing!");
75 
76  var updatedAssemblyVersion = FileVersionInfo.GetVersionInfo(updatedAssemblyPath);
77  Assert.AreEqual(testUpdateVersion, Version.Parse(updatedAssemblyVersion.FileVersion));
78  }
79  finally
80  {
81  serverCts.Cancel();
82  try
83  {
84  await serverTask.ConfigureAwait(false);
85  }
86  catch (OperationCanceledException) { }
87  }
88  Assert.IsTrue(server.RestartRequested, "Server not requesting restart!");
89  }
90  }
91  finally
92  {
93  Directory.Delete(updatePathRoot, true);
94  }
95  }
96 
97  [TestMethod]
98  [TestCategory("SkipWhenLiveUnitTesting")]
99  public async Task TestStandardOperation()
100  {
101  var server = new TestingServer(null);
102  using (var serverCts = new CancellationTokenSource())
103  {
104  var cancellationToken = serverCts.Token;
105  var serverTask = server.RunAsync(cancellationToken);
106  try
107  {
108  IServerClient adminClient;
109 
110  var giveUpAt = DateTimeOffset.Now.AddSeconds(60);
111  do
112  {
113  try
114  {
115  adminClient = await clientFactory.CreateServerClient(server.Url, User.AdminName, User.DefaultAdminPassword).ConfigureAwait(false);
116  break;
117  }
119  {
120  //migrating, to be expected
121  if (DateTimeOffset.Now > giveUpAt)
122  throw;
123  await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
124  }
125  } while (true);
126 
127  using (adminClient)
128  {
129  var serverInfo = await adminClient.Version(default).ConfigureAwait(false);
130 
131  Assert.AreEqual(ApiHeaders.Version, serverInfo.ApiVersion);
132  Assert.AreEqual(typeof(IServer).Assembly.GetName().Version, serverInfo.Version);
133 
134  //check that modifying the token even slightly fucks up the auth
135  var newToken = new Token
136  {
137  ExpiresAt = adminClient.Token.ExpiresAt,
138  Bearer = adminClient.Token.Bearer + '0'
139  };
140 
141  var badClient = clientFactory.CreateServerClient(server.Url, newToken);
142  await Assert.ThrowsExceptionAsync<UnauthorizedException>(() => badClient.Version(cancellationToken)).ConfigureAwait(false);
143 
144  await new AdministrationTest(adminClient.Administration).Run(cancellationToken).ConfigureAwait(false);
145  await new InstanceManagerTest(adminClient.Instances, server.Directory).Run(cancellationToken).ConfigureAwait(false);
146  }
147  }
148  finally
149  {
150  serverCts.Cancel();
151  try
152  {
153  await serverTask.ConfigureAwait(false);
154  }
155  catch (OperationCanceledException) { }
156  }
157  }
158  }
159  }
160 }
DateTimeOffset ExpiresAt
When the Token expires
Definition: Token.cs:18
-
async Task Run(CancellationToken cancellationToken)
+Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.Diagnostics;
4 using System.IO;
5 using System.Linq;
6 using System.Net.Http.Headers;
7 using System.Reflection;
8 using System.Threading;
9 using System.Threading.Tasks;
10 using Tgstation.Server.Api;
12 using Tgstation.Server.Client;
13 using Tgstation.Server.Host;
14 
15 namespace Tgstation.Server.Tests
16 {
17  [TestClass]
18  public sealed class IntegrationTest
19  {
20  readonly IServerClientFactory clientFactory = new ServerClientFactory(new ProductHeaderValue(Assembly.GetExecutingAssembly().GetName().Name, Assembly.GetExecutingAssembly().GetName().Version.ToString()));
21 
22  [TestMethod]
23  [TestCategory("SkipWhenLiveUnitTesting")]
24  public async Task TestUpdate()
25  {
26  var updatePathRoot = Path.GetTempFileName();
27  File.Delete(updatePathRoot);
28  Directory.CreateDirectory(updatePathRoot);
29  try
30  {
31  var updatePath = Path.Combine(updatePathRoot, Guid.NewGuid().ToString());
32  var server = new TestingServer(updatePath);
33  using (var serverCts = new CancellationTokenSource())
34  {
35  var cancellationToken = serverCts.Token;
36  var serverTask = server.RunAsync(cancellationToken);
37  try
38  {
39  IServerClient adminClient;
40 
41  var giveUpAt = DateTimeOffset.Now.AddSeconds(60);
42  do
43  {
44  try
45  {
46  adminClient = await clientFactory.CreateServerClient(server.Url, User.AdminName, User.DefaultAdminPassword).ConfigureAwait(false);
47  break;
48  }
50  {
51  //migrating, to be expected
52  if (DateTimeOffset.Now > giveUpAt)
53  throw;
54  await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
55  }
56  } while (true);
57 
58  var testUpdateVersion = new Version(4, 0, 0, 6);
59  using (adminClient)
60  //attempt to update to stable
61  await adminClient.Administration.Update(new Administration
62  {
63  NewVersion = testUpdateVersion
64  }, cancellationToken).ConfigureAwait(false);
65 
66  //wait up to 3 minutes for the dl and install
67  await Task.WhenAny(serverTask, Task.Delay(TimeSpan.FromMinutes(3), cancellationToken)).ConfigureAwait(false);
68 
69  Assert.IsTrue(serverTask.IsCompleted, "Sever still running!");
70 
71  Assert.IsTrue(Directory.Exists(updatePath), "Update directory not present!");
72 
73  var updatedAssemblyPath = Path.Combine(updatePath, "Tgstation.Server.Host.dll");
74  Assert.IsTrue(File.Exists(updatedAssemblyPath), "Updated assembly missing!");
75 
76  var updatedAssemblyVersion = FileVersionInfo.GetVersionInfo(updatedAssemblyPath);
77  Assert.AreEqual(testUpdateVersion, Version.Parse(updatedAssemblyVersion.FileVersion));
78  }
79  finally
80  {
81  serverCts.Cancel();
82  try
83  {
84  await serverTask.ConfigureAwait(false);
85  }
86  catch (OperationCanceledException) { }
87  }
88  Assert.IsTrue(server.RestartRequested, "Server not requesting restart!");
89  }
90  }
91  finally
92  {
93  Directory.Delete(updatePathRoot, true);
94  }
95  }
96 
97  [TestMethod]
98  [TestCategory("SkipWhenLiveUnitTesting")]
99  public async Task TestStandardOperation()
100  {
101  var server = new TestingServer(null);
102  using (var serverCts = new CancellationTokenSource())
103  {
104  var cancellationToken = serverCts.Token;
105  var serverTask = server.RunAsync(cancellationToken);
106  try
107  {
108  IServerClient adminClient;
109 
110  var giveUpAt = DateTimeOffset.Now.AddSeconds(60);
111  do
112  {
113  try
114  {
115  adminClient = await clientFactory.CreateServerClient(server.Url, User.AdminName, User.DefaultAdminPassword).ConfigureAwait(false);
116  break;
117  }
119  {
120  // migrating, to be expected
121  if (DateTimeOffset.Now > giveUpAt)
122  throw;
123  await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
124  }
125  } while (true);
126 
127  using (adminClient)
128  {
129  var serverInfo = await adminClient.Version(default).ConfigureAwait(false);
130 
131  Assert.AreEqual(ApiHeaders.Version, serverInfo.ApiVersion);
132  Assert.AreEqual(typeof(IServer).Assembly.GetName().Version, serverInfo.Version);
133 
134  //check that modifying the token even slightly fucks up the auth
135  var newToken = new Token
136  {
137  ExpiresAt = adminClient.Token.ExpiresAt,
138  Bearer = adminClient.Token.Bearer + '0'
139  };
140 
141  var badClient = clientFactory.CreateServerClient(server.Url, newToken);
142  await Assert.ThrowsExceptionAsync<UnauthorizedException>(() => badClient.Version(cancellationToken)).ConfigureAwait(false);
143 
144  await new AdministrationTest(adminClient.Administration).Run(cancellationToken).ConfigureAwait(false);
145  await new InstanceManagerTest(adminClient.Instances, server.Directory).Run(cancellationToken).ConfigureAwait(false);
146  }
147  }
148  finally
149  {
150  serverCts.Cancel();
151  try
152  {
153  await serverTask.ConfigureAwait(false);
154  }
155  catch (OperationCanceledException) { }
156  }
157  }
158  }
159  }
160 }
async Task Run(CancellationToken cancellationToken)
-
Task< ServerInformation > Version(CancellationToken cancellationToken)
The ServerInformation of the IServerClient
+
Task< ServerInformation > Version(CancellationToken cancellationToken)
The ServerInformation of the IServerClient
- -
const string AdminName
The name of the default admin user
Definition: User.cs:9
+
const string AdminName
The name of the default admin user
Definition: User.cs:9
async Task Run(CancellationToken cancellationToken)
-
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
-
Represents administrative server information
-
Occurs when the client makes a request while the server is starting or stopping
-
Token Token
The Token used to access the server
-
Main client for communicating with a server
-
Represents the host
Definition: IServer.cs:9
+
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
+
Represents administrative server information
+ +
Occurs when the client makes a request while the server is starting or stopping
+
Token Token
The Token used to access the server
+
Main client for communicating with a server
+
Represents the host
Definition: IServer.cs:9
+
readonly IServerClientFactory clientFactory
-
Represents a JWT returned by the API
Definition: Token.cs:8
-
Factory for creating IServerClients
+
DateTimeOffset? ExpiresAt
When the Token expires
Definition: Token.cs:18
+
Represents a JWT returned by the API
Definition: Token.cs:8
+
Factory for creating IServerClients
-
const string DefaultAdminPassword
The default admin password
Definition: User.cs:14
+
const string DefaultAdminPassword
The default admin password
Definition: User.cs:14
-
IInstanceManagerClient Instances
Access the IInstanceManagerClient
+
IInstanceManagerClient Instances
Access the IInstanceManagerClient
-
Occurs when the client provides invalid credentials
- -
Task Update(Administration administration, CancellationToken cancellationToken)
Updates the Administration setttings
- -
IAdministrationClient Administration
Access the IAdministrationClient
-
string Bearer
The value of the JWT
Definition: Token.cs:13
-
static Version Version
Get the version of the Api the caller is using
Definition: ApiHeaders.cs:56
- - +
Occurs when the client provides invalid credentials
+ +
Task Update(Administration administration, CancellationToken cancellationToken)
Updates the Administration setttings
+
IAdministrationClient Administration
Access the IAdministrationClient
+
string Bearer
The value of the JWT
Definition: Token.cs:13
+
static Version Version
Get the version of the Api the caller is using
Definition: ApiHeaders.cs:56
+ +
Task< IServerClient > CreateServerClient(Uri host, string username, string password, TimeSpan timeout=default, CancellationToken cancellationToken=default)
Create a IServerClient
+
diff --git a/_irc_connection_string_builder_8cs.html b/_irc_connection_string_builder_8cs.html index 19fb952824..1f8af9f108 100644 --- a/_irc_connection_string_builder_8cs.html +++ b/_irc_connection_string_builder_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/IrcConnectionStringBuilder.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Api.Models.IrcConnectionStringBuilder - ChatConnectionStringBuilder for ChatProvider.Irc More...
+ ChatConnectionStringBuilder for ChatProvider.Irc More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_irc_connection_string_builder_8cs_source.html b/_irc_connection_string_builder_8cs_source.html index 41f9f026f4..72d450022b 100644 --- a/_irc_connection_string_builder_8cs_source.html +++ b/_irc_connection_string_builder_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/IrcConnectionStringBuilder.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IrcConnectionStringBuilder.cs
-Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
5 
6 namespace Tgstation.Server.Api.Models
7 {
12  {
14  public override bool Valid => Address != null && Port.HasValue && Port != 0 && UseSsl.HasValue && (PasswordType.HasValue ^ Password == null);
15 
19  public string Address { get; set; }
20 
24  public ushort? Port { get; set; }
25 
29  public string Nickname { get; set; }
30 
34  public bool? UseSsl { get; set; }
35 
39  public IrcPasswordType? PasswordType { get; set; }
40 
44  public string Password { get; set; }
45 
50 
55  public IrcConnectionStringBuilder(string connectionString)
56  {
57  if (connectionString == null)
58  throw new ArgumentNullException(nameof(connectionString));
59  var splits = connectionString.Split(';');
60 
61  Address = splits[0];
62 
63  if (splits.Length < 2)
64  return;
65 
66  if (UInt16.TryParse(splits[1], out var port))
67  Port = port;
68 
69  if (splits.Length < 3)
70  return;
71 
72  Nickname = splits[2];
73 
74  if (splits.Length < 4)
75  return;
76 
77  if (Int32.TryParse(splits[3], out var intSsl))
78  UseSsl = Convert.ToBoolean(intSsl);
79 
80  if (splits.Length < 5)
81  return;
82  if (Enum.TryParse<IrcPasswordType>(splits[4], out var passwordType))
83  switch (passwordType)
84  {
85  case IrcPasswordType.NickServ:
86  case IrcPasswordType.Sasl:
87  case IrcPasswordType.Server:
88  PasswordType = passwordType;
89  break;
90  default:
91  break;
92  }
93 
94  if (splits.Length < 6)
95  return;
96 
97  var rest = new List<string>(splits);
98  rest.RemoveRange(0, 5);
99  Password = String.Join(";", rest);
100  }
101 
103  public override string ToString()
104  {
105  var sb = new StringBuilder();
106  sb.Append(Address);
107  sb.Append(';');
108  sb.Append(Port);
109  sb.Append(';');
110  sb.Append(Nickname);
111  sb.Append(';');
112  if(UseSsl.HasValue)
113  sb.Append(Convert.ToInt32(UseSsl.Value));
114  if (PasswordType.HasValue)
115  {
116  sb.Append(';');
117  sb.Append((int)PasswordType);
118  sb.Append(';');
119  sb.Append(Password);
120  }
121 
122  return sb.ToString();
123  }
124  }
125 }
- - +Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Text;
5 
7 {
12  {
14  public override bool Valid => Address != null && Port.HasValue && Port != 0 && UseSsl.HasValue && (PasswordType.HasValue ^ Password == null);
15 
19  public string Address { get; set; }
20 
24  public ushort? Port { get; set; }
25 
29  public string Nickname { get; set; }
30 
34  public bool? UseSsl { get; set; }
35 
39  public IrcPasswordType? PasswordType { get; set; }
40 
44  public string Password { get; set; }
45 
50 
55  public IrcConnectionStringBuilder(string connectionString)
56  {
57  if (connectionString == null)
58  throw new ArgumentNullException(nameof(connectionString));
59  var splits = connectionString.Split(';');
60 
61  Address = splits[0];
62 
63  if (splits.Length < 2)
64  return;
65 
66  if (UInt16.TryParse(splits[1], out var port))
67  Port = port;
68 
69  if (splits.Length < 3)
70  return;
71 
72  Nickname = splits[2];
73 
74  if (splits.Length < 4)
75  return;
76 
77  if (Int32.TryParse(splits[3], out var intSsl))
78  UseSsl = Convert.ToBoolean(intSsl);
79 
80  if (splits.Length < 5)
81  return;
82  if (Enum.TryParse<IrcPasswordType>(splits[4], out var passwordType))
83  switch (passwordType)
84  {
85  case IrcPasswordType.NickServ:
86  case IrcPasswordType.Sasl:
87  case IrcPasswordType.Server:
88  PasswordType = passwordType;
89  break;
90  default:
91  break;
92  }
93 
94  if (splits.Length < 6)
95  return;
96 
97  var rest = new List<string>(splits);
98  rest.RemoveRange(0, 5);
99  Password = String.Join(";", rest);
100  }
101 
103  public override string ToString()
104  {
105  var sb = new StringBuilder();
106  sb.Append(Address);
107  sb.Append(';');
108  sb.Append(Port);
109  sb.Append(';');
110  sb.Append(Nickname);
111  sb.Append(';');
112  if(UseSsl.HasValue)
113  sb.Append(Convert.ToInt32(UseSsl.Value));
114  if (PasswordType.HasValue)
115  {
116  sb.Append(';');
117  sb.Append((int)PasswordType);
118  sb.Append(';');
119  sb.Append(Password);
120  }
121 
122  return sb.ToString();
123  }
124  }
125 }
string Address
The IP address or URL of the IRC server
+ + + + -
IrcConnectionStringBuilder(string connectionString)
Construct a DiscordConnectionStringBuilder from a connectionString
- - -
IrcConnectionStringBuilder()
Construct an IrcConnectionStringBuilder
-
IrcPasswordType
Represents the type of a password for a ChatProvider.Irc
- -
ChatConnectionStringBuilder for ChatProvider.Irc
-
override string ToString()
Gets the ChatBot.ConnectionString associated with the ChatConnectionStringBuilder ...
- +
bool? UseSsl
If the connection should be made using SSL
+
IrcConnectionStringBuilder(string connectionString)
Construct a DiscordConnectionStringBuilder from a connectionString
+ + + +
IrcConnectionStringBuilder()
Construct an IrcConnectionStringBuilder
+
IrcPasswordType
Represents the type of a password for a ChatProvider.Irc
+ +
ChatConnectionStringBuilder for ChatProvider.Irc
+
override string ToString()
Gets the ChatBot.ConnectionString associated with the ChatConnectionStringBuilder
+
IrcPasswordType? PasswordType
The optional IrcPasswordType to use
+
diff --git a/_irc_password_type_8cs.html b/_irc_password_type_8cs.html index 8ec1116c31..fb20ef63f6 100644 --- a/_irc_password_type_8cs.html +++ b/_irc_password_type_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/IrcPasswordType.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Api +  namespace  Tgstation.Server.Api.Models   @@ -108,8 +93,8 @@ Enumerations - + } +
enum  Tgstation.Server.Api.Models.IrcPasswordType { Tgstation.Server.Api.Models.IrcPasswordType.Server, Tgstation.Server.Api.Models.IrcPasswordType.Sasl, Tgstation.Server.Api.Models.IrcPasswordType.NickServ - }
 Represents the type of a password for a ChatProvider.Irc More...
 Represents the type of a password for a ChatProvider.Irc More...
 
@@ -117,7 +102,7 @@ Enumerations diff --git a/_irc_password_type_8cs_source.html b/_irc_password_type_8cs_source.html index 01fa88718f..32640120d7 100644 --- a/_irc_password_type_8cs_source.html +++ b/_irc_password_type_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/IrcPasswordType.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
IrcPasswordType.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Api.Models
2 {
6  public enum IrcPasswordType
7  {
11  Server,
12 
16  Sasl,
17 
21  NickServ
22  }
23 }
- - -
IrcPasswordType
Represents the type of a password for a ChatProvider.Irc
- +Go to the documentation of this file.
2 {
6  public enum IrcPasswordType
7  {
11  Server,
12 
16  Sasl,
17 
21  NickServ
22  }
23 }
+ + + +
IrcPasswordType
Represents the type of a password for a ChatProvider.Irc
diff --git a/_irc_provider_8cs.html b/_irc_provider_8cs.html index 3378029360..eab4fa5af4 100644 --- a/_irc_provider_8cs.html +++ b/_irc_provider_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Components.Chat.Providers.IrcProviderIProvider for internet relay chat More...
IProvider for internet relay chat More...
  + + + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
namespace  Tgstation.Server.Host.Components.Chat.Providers
 
@@ -114,7 +103,7 @@ Namespaces diff --git a/_irc_provider_8cs_source.html b/_irc_provider_8cs_source.html index edfac8c1ad..b6253e6ad4 100644 --- a/_irc_provider_8cs_source.html +++ b/_irc_provider_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Providers/IrcProvider.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IrcProvider.cs
-Go to the documentation of this file.
1 using Meebey.SmartIrc4net;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Collections.Generic;
5 using System.Globalization;
6 using System.Linq;
7 using System.Text;
8 using System.Threading;
9 using System.Threading.Tasks;
12 
13 namespace Tgstation.Server.Host.Components.Chat.Providers
14 {
18  sealed class IrcProvider : Provider
19  {
20  const int TimeoutSeconds = 5;
21 
23  public override bool Connected => client.IsConnected;
24 
26  public override string BotMention => client.Nickname;
27 
32 
36  readonly ILogger<IrcProvider> logger;
37 
41  readonly IrcFeatures client;
42 
46  readonly string address;
47 
51  readonly ushort port;
52 
56  readonly string nickname;
57 
61  readonly string password;
62 
67 
71  readonly Dictionary<ulong, string> channelIdMap;
72 
76  readonly Dictionary<ulong, string> queryChannelIdMap;
77 
82 
86  Task listenTask;
87 
92 
105  public IrcProvider(IApplication application, IAsyncDelayer asyncDelayer, ILogger<IrcProvider> logger, string address, ushort port, string nickname, string password, IrcPasswordType? passwordType, bool useSsl)
106  {
107  if (application == null)
108  throw new ArgumentNullException(nameof(application));
109  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
110  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
111 
112  this.address = address ?? throw new ArgumentNullException(nameof(address));
113  this.port = port;
114  this.nickname = nickname ?? throw new ArgumentNullException(nameof(nickname));
115 
116  if (passwordType.HasValue && password == null)
117  throw new ArgumentNullException(nameof(password));
118 
119  if (password != null && !passwordType.HasValue)
120  throw new ArgumentNullException(nameof(passwordType));
121 
122  this.password = password;
123  this.passwordType = passwordType;
124 
125  client = new IrcFeatures
126  {
127  SupportNonRfc = true,
128  CtcpUserInfo = "You are going to play. And I am going to watch. And everything will be just fine...",
129  AutoRejoin = true,
130  AutoRejoinOnKick = true,
131  AutoRelogin = true,
132  AutoRetry = true,
133  AutoRetryLimit = TimeoutSeconds,
134  AutoRetryDelay = TimeoutSeconds,
135  ActiveChannelSyncing = true,
136  AutoNickHandling = true,
137  CtcpVersion = application.VersionString,
138  UseSsl = useSsl
139  };
140  if (useSsl)
141  client.ValidateServerCertificate = true; // dunno if it defaults to that or what
142 
143  client.OnChannelMessage += Client_OnChannelMessage;
144  client.OnQueryMessage += Client_OnQueryMessage;
145 
146  channelIdMap = new Dictionary<ulong, string>();
147  queryChannelIdMap = new Dictionary<ulong, string>();
148  channelIdCounter = 1;
149  disconnecting = false;
150  }
151 
153  public override void Dispose()
154  {
155  if (Connected)
156  {
157  disconnecting = true;
158  client.Disconnect(); // just closes the socket
159  }
160  }
161 
167  void HandleMessage(IrcEventArgs e, bool isPrivate)
168  {
169  if (e.Data.Nick.ToUpperInvariant() == client.Nickname.ToUpperInvariant())
170  return;
171 
172  var username = e.Data.Nick;
173  var channelName = isPrivate ? username : e.Data.Channel;
174 
175  ulong MapAndGetChannelId(Dictionary<ulong, string> dicToCheck)
176  {
177  ulong? resultId = null;
178  if (!dicToCheck.Any(x =>
179  {
180  if (x.Value != channelName)
181  return false;
182  resultId = x.Key;
183  return true;
184  }))
185  {
186  resultId = channelIdCounter++;
187  dicToCheck.Add(resultId.Value, channelName);
188  if (dicToCheck == queryChannelIdMap)
189  channelIdMap.Add(resultId.Value, null);
190  }
191 
192  return resultId.Value;
193  }
194 
195  ulong userId, channelId;
196  lock (this)
197  {
198  userId = MapAndGetChannelId(queryChannelIdMap);
199  channelId = isPrivate ? userId : MapAndGetChannelId(channelIdMap);
200  }
201 
202  var message = new Message
203  {
204  Content = e.Data.Message,
205  User = new User
206  {
207  Channel = new Channel
208  {
209  ConnectionName = address,
210  FriendlyName = isPrivate ? String.Format(CultureInfo.InvariantCulture, "PM: {0}", channelName) : channelName,
211  RealId = channelId,
212  IsPrivateChannel = isPrivate
213 
214  // isAdmin and Tag populated by manager
215  },
216  FriendlyName = username,
217  RealId = userId,
218  Mention = username
219  }
220  };
221 
222  EnqueueMessage(message);
223  }
224 
230  void Client_OnQueryMessage(object sender, IrcEventArgs e) => HandleMessage(e, true);
231 
237  void Client_OnChannelMessage(object sender, IrcEventArgs e) => HandleMessage(e, false);
238 
240  public override Task<bool> Connect(CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
241  {
242  disconnecting = false;
243  lock (this)
244  try
245  {
246  client.Connect(address, port);
247 
248  cancellationToken.ThrowIfCancellationRequested();
249 
250  if (passwordType == IrcPasswordType.Server)
251  client.Login(nickname, nickname, 0, nickname, password);
252  else
253  {
254  if (passwordType == IrcPasswordType.Sasl)
255  {
256  client.WriteLine("CAP REQ :sasl", Priority.Critical); // needs to be put in the buffer before anything else
257  cancellationToken.ThrowIfCancellationRequested();
258  }
259 
260  client.Login(nickname, nickname, 0, nickname);
261  }
262 
263  if (passwordType == IrcPasswordType.NickServ)
264  {
265  cancellationToken.ThrowIfCancellationRequested();
266  client.SendMessage(SendType.Message, "NickServ", String.Format(CultureInfo.InvariantCulture, "IDENTIFY {0}", password));
267  }
268  else if (passwordType == IrcPasswordType.Sasl)
269  {
270  // wait for the sasl ack or timeout
271  var recievedAck = false;
272  var recievedPlus = false;
273  client.OnReadLine += (sender, e) =>
274  {
275  if (e.Line.Contains("ACK :sasl", StringComparison.Ordinal))
276  recievedAck = true;
277  else if (e.Line.Contains("AUTHENTICATE +", StringComparison.Ordinal))
278  recievedPlus = true;
279  };
280 
281  var startTime = DateTimeOffset.Now;
282  var endTime = DateTimeOffset.Now.AddSeconds(TimeoutSeconds);
283  cancellationToken.ThrowIfCancellationRequested();
284 
285  var listenTimeSpan = TimeSpan.FromMilliseconds(10);
286  for (; !recievedAck && DateTimeOffset.Now <= endTime; asyncDelayer.Delay(listenTimeSpan, cancellationToken).GetAwaiter().GetResult())
287  client.Listen(false);
288 
289  client.WriteLine("AUTHENTICATE PLAIN", Priority.Critical);
290  cancellationToken.ThrowIfCancellationRequested();
291 
292  for (; !recievedPlus && DateTimeOffset.Now <= endTime; asyncDelayer.Delay(listenTimeSpan, cancellationToken).GetAwaiter().GetResult())
293  client.Listen(false);
294 
295  // Stolen! https://github.com/znc/znc/blob/1e697580155d5a38f8b5a377f3b1d94aaa979539/modules/sasl.cpp#L196
296  var authString = String.Format(CultureInfo.InvariantCulture, "{0}{1}{0}{1}{2}", nickname, '\0', password);
297  var b64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(authString));
298  var authLine = String.Format(CultureInfo.InvariantCulture, "AUTHENTICATE {0}", b64);
299  var chars = authLine.ToCharArray();
300  client.WriteLine(authLine, Priority.Critical);
301 
302  cancellationToken.ThrowIfCancellationRequested();
303  client.WriteLine("CAP END", Priority.Critical);
304  }
305 
306  client.Listen(false);
307 
308  listenTask = Task.Factory.StartNew(() =>
309  {
310  while (!disconnecting && client.IsConnected && client.Nickname != nickname)
311  {
312  client.ListenOnce(true);
313  if (disconnecting || !client.IsConnected)
314  break;
315  client.Listen(false);
316 
317  // ensure we have the correct nick
318  if (client.GetIrcUser(nickname) == null)
319  client.RfcNick(nickname);
320  }
321 
322  client.Listen();
323  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
324  }
325  catch (OperationCanceledException)
326  {
327  throw;
328  }
329  catch (Exception e)
330  {
331  logger.LogWarning("Unable to connect to IRC: {0}", e);
332  return false;
333  }
334 
335  return true;
336  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
337 
339  public override async Task Disconnect(CancellationToken cancellationToken)
340  {
341  if (!Connected)
342  return;
343  try
344  {
345  await Task.Factory.StartNew(() =>
346  {
347  try
348  {
349  client.RfcQuit("Mr. Stark, I don't feel so good...", Priority.Critical); // priocritical otherwise it wont go through
350  }
351  catch (Exception e)
352  {
353  logger.LogWarning("Error quitting IRC: {0}", e);
354  }
355  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
356  Dispose();
357  await listenTask.ConfigureAwait(false);
358  }
359  catch (OperationCanceledException)
360  {
361  throw;
362  }
363  catch (Exception e)
364  {
365  logger.LogWarning("Error disconnecting from IRC! Exception: {0}", e);
366  }
367  }
368 
370  public override Task<IReadOnlyList<Channel>> MapChannels(IEnumerable<ChatChannel> channels, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
371  {
372  if (channels.Any(x => x.IrcChannel == null))
373  throw new InvalidOperationException("ChatChannel missing IrcChannel!");
374  lock (this)
375  {
376  var hs = new HashSet<string>(); // for unique inserts
377  foreach (var I in channels)
378  hs.Add(I.IrcChannel);
379  var toPart = new List<string>();
380  foreach (var I in client.JoinedChannels)
381  if (!hs.Remove(I))
382  toPart.Add(I);
383 
384  foreach (var I in toPart)
385  client.RfcPart(I, "Pretty nice abscond!");
386  foreach (var I in hs)
387  client.RfcJoin(I);
388 
389  return (IReadOnlyList<Channel>)channels.Select(x =>
390  {
391  ulong? id = null;
392  if (!channelIdMap.Any(y =>
393  {
394  if (y.Value != x.IrcChannel)
395  return false;
396  id = y.Key;
397  return true;
398  }))
399  {
400  id = channelIdCounter++;
401  channelIdMap.Add(id.Value, x.IrcChannel);
402  }
403 
404  return new Channel
405  {
406  RealId = id.Value,
407  IsAdminChannel = x.IsAdminChannel == true,
408  ConnectionName = address,
409  FriendlyName = channelIdMap[id.Value],
410  IsPrivateChannel = false,
411  Tag = x.Tag
412  };
413  }).ToList();
414  }
415  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
416 
418  public override Task SendMessage(ulong channelId, string message, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
419  {
420  var channelName = channelIdMap[channelId];
421  SendType sendType;
422  if (channelName == null)
423  {
424  channelName = queryChannelIdMap[channelId];
425  sendType = SendType.Notice;
426  }
427  else
428  sendType = SendType.Message;
429  try
430  {
431  client.SendMessage(sendType, channelName, message);
432  }
433  catch (Exception e)
434  {
435  logger.LogWarning("Unable to send to channel: {0}", e);
436  }
437  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
438  }
439 }
ulong channelIdCounter
Id counter for channelIdMap
Definition: IrcProvider.cs:81
-
readonly Dictionary< ulong, string > queryChannelIdMap
Map of Channel.RealIds to query users
Definition: IrcProvider.cs:76
-
readonly IrcFeatures client
The IrcFeatures client
Definition: IrcProvider.cs:41
+Go to the documentation of this file.
1 using Meebey.SmartIrc4net;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Collections.Generic;
5 using System.Globalization;
6 using System.Linq;
7 using System.Text;
8 using System.Threading;
9 using System.Threading.Tasks;
12 
14 {
18  sealed class IrcProvider : Provider
19  {
20  const int TimeoutSeconds = 5;
21 
23  public override bool Connected => client.IsConnected;
24 
26  public override string BotMention => client.Nickname;
27 
32 
36  readonly ILogger<IrcProvider> logger;
37 
41  readonly IrcFeatures client;
42 
46  readonly string address;
47 
51  readonly ushort port;
52 
56  readonly string nickname;
57 
61  readonly string password;
62 
67 
71  readonly Dictionary<ulong, string> channelIdMap;
72 
76  readonly Dictionary<ulong, string> queryChannelIdMap;
77 
82 
86  Task listenTask;
87 
92 
105  public IrcProvider(IApplication application, IAsyncDelayer asyncDelayer, ILogger<IrcProvider> logger, string address, ushort port, string nickname, string password, IrcPasswordType? passwordType, bool useSsl)
106  {
107  if (application == null)
108  throw new ArgumentNullException(nameof(application));
109  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
110  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
111 
112  this.address = address ?? throw new ArgumentNullException(nameof(address));
113  this.port = port;
114  this.nickname = nickname ?? throw new ArgumentNullException(nameof(nickname));
115 
116  if (passwordType.HasValue && password == null)
117  throw new ArgumentNullException(nameof(password));
118 
119  if (password != null && !passwordType.HasValue)
120  throw new ArgumentNullException(nameof(passwordType));
121 
122  this.password = password;
123  this.passwordType = passwordType;
124 
125  client = new IrcFeatures
126  {
127  SupportNonRfc = true,
128  CtcpUserInfo = "You are going to play. And I am going to watch. And everything will be just fine...",
129  AutoRejoin = true,
130  AutoRejoinOnKick = true,
131  AutoRelogin = true,
132  AutoRetry = true,
133  AutoRetryLimit = TimeoutSeconds,
134  AutoRetryDelay = TimeoutSeconds,
135  ActiveChannelSyncing = true,
136  AutoNickHandling = true,
137  CtcpVersion = application.VersionString,
138  UseSsl = useSsl
139  };
140  if (useSsl)
141  client.ValidateServerCertificate = true; // dunno if it defaults to that or what
142 
143  client.OnChannelMessage += Client_OnChannelMessage;
144  client.OnQueryMessage += Client_OnQueryMessage;
145 
146  channelIdMap = new Dictionary<ulong, string>();
147  queryChannelIdMap = new Dictionary<ulong, string>();
148  channelIdCounter = 1;
149  disconnecting = false;
150  }
151 
153  public override void Dispose()
154  {
155  if (Connected)
156  {
157  disconnecting = true;
158  client.Disconnect(); // just closes the socket
159  }
160  }
161 
167  void HandleMessage(IrcEventArgs e, bool isPrivate)
168  {
169  if (e.Data.Nick.ToUpperInvariant() == client.Nickname.ToUpperInvariant())
170  return;
171 
172  var username = e.Data.Nick;
173  var channelName = isPrivate ? username : e.Data.Channel;
174 
175  ulong MapAndGetChannelId(Dictionary<ulong, string> dicToCheck)
176  {
177  ulong? resultId = null;
178  if (!dicToCheck.Any(x =>
179  {
180  if (x.Value != channelName)
181  return false;
182  resultId = x.Key;
183  return true;
184  }))
185  {
186  resultId = channelIdCounter++;
187  dicToCheck.Add(resultId.Value, channelName);
188  if (dicToCheck == queryChannelIdMap)
189  channelIdMap.Add(resultId.Value, null);
190  }
191 
192  return resultId.Value;
193  }
194 
195  ulong userId, channelId;
196  lock (this)
197  {
198  userId = MapAndGetChannelId(queryChannelIdMap);
199  channelId = isPrivate ? userId : MapAndGetChannelId(channelIdMap);
200  }
201 
202  var message = new Message
203  {
204  Content = e.Data.Message,
205  User = new User
206  {
207  Channel = new Channel
208  {
209  ConnectionName = address,
210  FriendlyName = isPrivate ? String.Format(CultureInfo.InvariantCulture, "PM: {0}", channelName) : channelName,
211  RealId = channelId,
212  IsPrivateChannel = isPrivate
213 
214  // isAdmin and Tag populated by manager
215  },
216  FriendlyName = username,
217  RealId = userId,
218  Mention = username
219  }
220  };
221 
222  EnqueueMessage(message);
223  }
224 
230  void Client_OnQueryMessage(object sender, IrcEventArgs e) => HandleMessage(e, true);
231 
237  void Client_OnChannelMessage(object sender, IrcEventArgs e) => HandleMessage(e, false);
238 
240  public override Task<bool> Connect(CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
241  {
242  disconnecting = false;
243  lock (this)
244  try
245  {
246  client.Connect(address, port);
247 
248  cancellationToken.ThrowIfCancellationRequested();
249 
250  if (passwordType == IrcPasswordType.Server)
252  else
253  {
254  if (passwordType == IrcPasswordType.Sasl)
255  {
256  client.WriteLine("CAP REQ :sasl", Priority.Critical); // needs to be put in the buffer before anything else
257  cancellationToken.ThrowIfCancellationRequested();
258  }
259 
260  client.Login(nickname, nickname, 0, nickname);
261  }
262 
263  if (passwordType == IrcPasswordType.NickServ)
264  {
265  cancellationToken.ThrowIfCancellationRequested();
266  client.SendMessage(SendType.Message, "NickServ", String.Format(CultureInfo.InvariantCulture, "IDENTIFY {0}", password));
267  }
268  else if (passwordType == IrcPasswordType.Sasl)
269  {
270  // wait for the sasl ack or timeout
271  var recievedAck = false;
272  var recievedPlus = false;
273  client.OnReadLine += (sender, e) =>
274  {
275  if (e.Line.Contains("ACK :sasl", StringComparison.Ordinal))
276  recievedAck = true;
277  else if (e.Line.Contains("AUTHENTICATE +", StringComparison.Ordinal))
278  recievedPlus = true;
279  };
280 
281  var startTime = DateTimeOffset.Now;
282  var endTime = DateTimeOffset.Now.AddSeconds(TimeoutSeconds);
283  cancellationToken.ThrowIfCancellationRequested();
284 
285  var listenTimeSpan = TimeSpan.FromMilliseconds(10);
286  for (; !recievedAck && DateTimeOffset.Now <= endTime; asyncDelayer.Delay(listenTimeSpan, cancellationToken).GetAwaiter().GetResult())
287  client.Listen(false);
288 
289  client.WriteLine("AUTHENTICATE PLAIN", Priority.Critical);
290  cancellationToken.ThrowIfCancellationRequested();
291 
292  for (; !recievedPlus && DateTimeOffset.Now <= endTime; asyncDelayer.Delay(listenTimeSpan, cancellationToken).GetAwaiter().GetResult())
293  client.Listen(false);
294 
295  // Stolen! https://github.com/znc/znc/blob/1e697580155d5a38f8b5a377f3b1d94aaa979539/modules/sasl.cpp#L196
296  var authString = String.Format(CultureInfo.InvariantCulture, "{0}{1}{0}{1}{2}", nickname, '\0', password);
297  var b64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(authString));
298  var authLine = String.Format(CultureInfo.InvariantCulture, "AUTHENTICATE {0}", b64);
299  var chars = authLine.ToCharArray();
300  client.WriteLine(authLine, Priority.Critical);
301 
302  cancellationToken.ThrowIfCancellationRequested();
303  client.WriteLine("CAP END", Priority.Critical);
304  }
305 
306  client.Listen(false);
307 
308  listenTask = Task.Factory.StartNew(() =>
309  {
310  while (!disconnecting && client.IsConnected && client.Nickname != nickname)
311  {
312  client.ListenOnce(true);
313  if (disconnecting || !client.IsConnected)
314  break;
315  client.Listen(false);
316 
317  // ensure we have the correct nick
318  if (client.GetIrcUser(nickname) == null)
319  client.RfcNick(nickname);
320  }
321 
322  client.Listen();
323  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
324  }
325  catch (OperationCanceledException)
326  {
327  throw;
328  }
329  catch (Exception e)
330  {
331  logger.LogWarning("Unable to connect to IRC: {0}", e);
332  return false;
333  }
334 
335  return true;
336  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
337 
339  public override async Task Disconnect(CancellationToken cancellationToken)
340  {
341  if (!Connected)
342  return;
343  try
344  {
345  await Task.Factory.StartNew(() =>
346  {
347  try
348  {
349  client.RfcQuit("Mr. Stark, I don't feel so good...", Priority.Critical); // priocritical otherwise it wont go through
350  }
351  catch (Exception e)
352  {
353  logger.LogWarning("Error quitting IRC: {0}", e);
354  }
355  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
356  Dispose();
357  await listenTask.ConfigureAwait(false);
358  }
359  catch (OperationCanceledException)
360  {
361  throw;
362  }
363  catch (Exception e)
364  {
365  logger.LogWarning("Error disconnecting from IRC! Exception: {0}", e);
366  }
367  }
368 
370  public override Task<IReadOnlyList<Channel>> MapChannels(IEnumerable<ChatChannel> channels, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
371  {
372  if (channels.Any(x => x.IrcChannel == null))
373  throw new InvalidOperationException("ChatChannel missing IrcChannel!");
374  lock (this)
375  {
376  var hs = new HashSet<string>(); // for unique inserts
377  foreach (var I in channels)
378  hs.Add(I.IrcChannel);
379  var toPart = new List<string>();
380  foreach (var I in client.JoinedChannels)
381  if (!hs.Remove(I))
382  toPart.Add(I);
383 
384  foreach (var I in toPart)
385  client.RfcPart(I, "Pretty nice abscond!");
386  foreach (var I in hs)
387  client.RfcJoin(I);
388 
389  return (IReadOnlyList<Channel>)channels.Select(x =>
390  {
391  ulong? id = null;
392  if (!channelIdMap.Any(y =>
393  {
394  if (y.Value != x.IrcChannel)
395  return false;
396  id = y.Key;
397  return true;
398  }))
399  {
400  id = channelIdCounter++;
401  channelIdMap.Add(id.Value, x.IrcChannel);
402  }
403 
404  return new Channel
405  {
406  RealId = id.Value,
407  IsAdminChannel = x.IsAdminChannel == true,
408  ConnectionName = address,
409  FriendlyName = channelIdMap[id.Value],
410  IsPrivateChannel = false,
411  Tag = x.Tag
412  };
413  }).ToList();
414  }
415  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
416 
418  public override Task SendMessage(ulong channelId, string message, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
419  {
420  var channelName = channelIdMap[channelId];
421  SendType sendType;
422  if (channelName == null)
423  {
424  channelName = queryChannelIdMap[channelId];
425  sendType = SendType.Notice;
426  }
427  else
428  sendType = SendType.Message;
429  try
430  {
431  client.SendMessage(sendType, channelName, message);
432  }
433  catch (Exception e)
434  {
435  logger.LogWarning("Unable to send to channel: {0}", e);
436  }
437  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
438  }
439 }
+
readonly Dictionary< ulong, string > queryChannelIdMap
Map of Channel.RealIds to query users
Definition: IrcProvider.cs:76
+
readonly IrcFeatures client
The IrcFeatures client
Definition: IrcProvider.cs:41
-
readonly ushort port
Port of the server to connect to
Definition: IrcProvider.cs:51
-
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
- -
readonly ILogger< IrcProvider > logger
The ILogger for the IrcProvider
Definition: IrcProvider.cs:36
- +
readonly ushort port
Port of the server to connect to
Definition: IrcProvider.cs:51
+
readonly? IrcPasswordType passwordType
The IrcPasswordType of password
Definition: IrcProvider.cs:66
+
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
+
readonly ILogger< IrcProvider > logger
The ILogger for the IrcProvider
Definition: IrcProvider.cs:36
-
readonly string address
Address of the server to connect to
Definition: IrcProvider.cs:46
-
override async Task Disconnect(CancellationToken cancellationToken)
Gracefully disconnects the provider. Implies a call to IDisposable.Dispose
Definition: IrcProvider.cs:339
-
readonly Dictionary< ulong, string > channelIdMap
Map of Channel.RealIds to channel names
Definition: IrcProvider.cs:71
-
Represents a message recieved by a IProvider
Definition: Message.cs:6
- +
IrcProvider(IApplication application, IAsyncDelayer asyncDelayer, ILogger< IrcProvider > logger, string address, ushort port, string nickname, string password, IrcPasswordType? passwordType, bool useSsl)
Construct an IrcProvider
Definition: IrcProvider.cs:105
+
readonly string address
Address of the server to connect to
Definition: IrcProvider.cs:46
+
override async Task Disconnect(CancellationToken cancellationToken)
Gracefully disconnects the provider. Implies a call to IDisposable.Dispose
Definition: IrcProvider.cs:339
+
readonly Dictionary< ulong, string > channelIdMap
Map of Channel.RealIds to channel names
Definition: IrcProvider.cs:71
+
Represents a message recieved by a IProvider
Definition: Message.cs:6
+ + -
void HandleMessage(IrcEventArgs e, bool isPrivate)
Handle an IRC message
Definition: IrcProvider.cs:167
- +
void HandleMessage(IrcEventArgs e, bool isPrivate)
Handle an IRC message
Definition: IrcProvider.cs:167
+ -
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the IrcProvider
Definition: IrcProvider.cs:31
- -
Task listenTask
The Task used for IrcConnection.Listen(bool)
Definition: IrcProvider.cs:86
-
Represents a Providers.IProvider channel
Definition: Channel.cs:10
-
readonly IrcPasswordType passwordType
The IrcPasswordType of password
Definition: IrcProvider.cs:66
-
Represents a tgs_chat_user datum
Definition: User.cs:10
-
IrcPasswordType
Represents the type of a password for a ChatProvider.Irc
-
string VersionString
A more verbose version of Version
Definition: IApplication.cs:18
- -
bool IsAdminChannel
If this is considered a channel for admin commands
Definition: Channel.cs:41
- -
readonly string password
Password which will used for authentication
Definition: IrcProvider.cs:61
-
IrcProvider(IApplication application, IAsyncDelayer asyncDelayer, ILogger< IrcProvider > logger, string address, ushort port, string nickname, string password, IrcPasswordType?passwordType, bool useSsl)
Construct an IrcProvider
Definition: IrcProvider.cs:105
- - +
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the IrcProvider
Definition: IrcProvider.cs:31
+ +
Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan
+
Task listenTask
The Task used for IrcConnection.Listen(bool)
Definition: IrcProvider.cs:86
+
Represents a Providers.IProvider channel
Definition: Channel.cs:10
+
override Task< bool > Connect(CancellationToken cancellationToken)
Attempt to connect the IProvider
+
override Task SendMessage(ulong channelId, string message, CancellationToken cancellationToken)
Send a message to the IProvider
+
Represents a tgs_chat_user datum
Definition: User.cs:10
+
IrcPasswordType
Represents the type of a password for a ChatProvider.Irc
+
string VersionString
A more verbose version of Version
Definition: IApplication.cs:18
+
void Client_OnChannelMessage(object sender, IrcEventArgs e)
When a channel message is received in IRC
+ + +
void Client_OnQueryMessage(object sender, IrcEventArgs e)
When a query message is received in IRC
+
override Task< IReadOnlyList< Channel > > MapChannels(IEnumerable< ChatChannel > channels, CancellationToken cancellationToken)
+
bool IsAdminChannel
If this is considered a channel for admin commands
Definition: Channel.cs:41
+ + +
readonly string password
Password which will used for authentication
Definition: IrcProvider.cs:61
+
void EnqueueMessage(Message message)
Queues a message for NextMessage(CancellationToken)
Definition: Provider.cs:40
+ + +
diff --git a/_job_controller_8cs.html b/_job_controller_8cs.html index 4fccc4452c..d64028918c 100644 --- a/_job_controller_8cs.html +++ b/_job_controller_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/JobController.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Controllers.JobControllerModelController<TModel> for Api.Models.Jobs More...
ModelController<TModel> for Api.Models.Jobs More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Controllers
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_job_controller_8cs_source.html b/_job_controller_8cs_source.html index 0823d3e8ee..38ab36ffac 100644 --- a/_job_controller_8cs_source.html +++ b/_job_controller_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/JobController.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
JobController.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.Net;
7 using System.Threading;
8 using System.Threading.Tasks;
9 using Tgstation.Server.Api;
13 
14 namespace Tgstation.Server.Host.Controllers
15 {
19  [Route(Routes.Jobs)]
20  public sealed class JobController : ModelController<Api.Models.Job>
21  {
26 
34  public JobController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, ILogger<JobController> logger) : base(databaseContext, authenticationContextFactory, logger, true)
35  {
36  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
37  }
38 
40  [TgsAuthorize]
41  public override async Task<IActionResult> Read(CancellationToken cancellationToken)
42  {
43  var result = await DatabaseContext.Jobs.Where(x => x.Instance.Id == Instance.Id && !x.StoppedAt.HasValue).OrderByDescending(x => x.StartedAt).ToListAsync(cancellationToken).ConfigureAwait(false);
44  return Json(result.Select(x => x.ToApi()));
45  }
46 
48  [TgsAuthorize]
49  public override async Task<IActionResult> List(CancellationToken cancellationToken)
50  {
51  // you KNOW this will need pagination eventually right?
52  var jobs = await DatabaseContext.Jobs.Where(x => x.Instance.Id == Instance.Id).OrderByDescending(x => x.StartedAt).Select(x => new Api.Models.Job
53  {
54  Id = x.Id
55  }).ToListAsync(cancellationToken).ConfigureAwait(false);
56  return Json(jobs);
57  }
58 
60  [TgsAuthorize]
61  public override async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
62  {
63  // don't care if an instance post or not at this point
64  var job = await DatabaseContext.Jobs.Where(x => x.Id == id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
65  if (job == default(Job))
66  return NotFound();
67 
68  if (job.StoppedAt != null)
69  return StatusCode((int)HttpStatusCode.Gone);
70 
71  if (job.CancelRight.HasValue && job.CancelRightsType.HasValue && (AuthenticationContext.GetRight(job.CancelRightsType.Value) & job.CancelRight.Value) == 0)
72  return Forbid();
73 
74  var cancelled = await jobManager.CancelJob(job, AuthenticationContext.User, false, cancellationToken).ConfigureAwait(false);
75  return cancelled ? (IActionResult)Accepted() : StatusCode((int)HttpStatusCode.Gone);
76  }
77 
79  [TgsAuthorize]
80  public override async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
81  {
82  var job = await DatabaseContext.Jobs.Where(x => x.Id == id).Include(x => x.StartedBy).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
83  if (job == default(Job))
84  return NotFound();
85  var api = job.ToApi();
86  api.Progress = jobManager.JobProgress(job);
87  return Json(api);
88  }
89  }
90 }
-
Manages the runtime of Jobs
Definition: IJobManager.cs:12
- - -
override async Task< IActionResult > List(CancellationToken cancellationToken)
Attempt to list entries of the TModel
-
override async Task< IActionResult > Read(CancellationToken cancellationToken)
Attempt to read a TModel
+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.Net;
7 using System.Threading;
8 using System.Threading.Tasks;
9 using Tgstation.Server.Api;
13 
15 {
19  [Route(Routes.Jobs)]
20  public sealed class JobController : ModelController<Api.Models.Job>
21  {
26 
34  public JobController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, ILogger<JobController> logger) : base(databaseContext, authenticationContextFactory, logger, true)
35  {
36  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
37  }
38 
40  [TgsAuthorize]
41  public override async Task<IActionResult> Read(CancellationToken cancellationToken)
42  {
43  var result = await DatabaseContext.Jobs.Where(x => x.Instance.Id == Instance.Id && !x.StoppedAt.HasValue).OrderByDescending(x => x.StartedAt).ToListAsync(cancellationToken).ConfigureAwait(false);
44  return Json(result.Select(x => x.ToApi()));
45  }
46 
48  [TgsAuthorize]
49  public override async Task<IActionResult> List(CancellationToken cancellationToken)
50  {
51  // you KNOW this will need pagination eventually right?
52  var jobs = await DatabaseContext.Jobs.Where(x => x.Instance.Id == Instance.Id).OrderByDescending(x => x.StartedAt).Select(x => new Api.Models.Job
53  {
54  Id = x.Id
55  }).ToListAsync(cancellationToken).ConfigureAwait(false);
56  return Json(jobs);
57  }
58 
60  [TgsAuthorize]
61  public override async Task<IActionResult> Delete(long id, CancellationToken cancellationToken)
62  {
63  // don't care if an instance post or not at this point
64  var job = await DatabaseContext.Jobs.Where(x => x.Id == id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
65  if (job == default(Job))
66  return NotFound();
67 
68  if (job.StoppedAt != null)
69  return StatusCode((int)HttpStatusCode.Gone);
70 
71  if (job.CancelRight.HasValue && job.CancelRightsType.HasValue && (AuthenticationContext.GetRight(job.CancelRightsType.Value) & job.CancelRight.Value) == 0)
72  return Forbid();
73 
74  var cancelled = await jobManager.CancelJob(job, AuthenticationContext.User, false, cancellationToken).ConfigureAwait(false);
75  return cancelled ? (IActionResult)Accepted() : StatusCode((int)HttpStatusCode.Gone);
76  }
77 
79  [TgsAuthorize]
80  public override async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
81  {
82  var job = await DatabaseContext.Jobs.Where(x => x.Id == id).Include(x => x.StartedBy).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
83  if (job == default(Job))
84  return NotFound();
85  var api = job.ToApi();
86  api.Progress = jobManager.JobProgress(job);
87  return Json(api);
88  }
89  }
90 }
+
Manages the runtime of Jobs
Definition: IJobManager.cs:12
+ + + +
override async Task< IActionResult > List(CancellationToken cancellationToken)
Attempt to list entries of the TModel
+
override async Task< IActionResult > Read(CancellationToken cancellationToken)
Attempt to read a TModel
- - -
JobController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, ILogger< JobController > logger)
Construct a HomeController
-
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
-
override async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Attempt to get a specific a TModel
+
JobController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IJobManager jobManager, ILogger< JobController > logger)
Construct a HomeController
+
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
+
override async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Attempt to get a specific a TModel
-
override async Task< IActionResult > Delete(long id, CancellationToken cancellationToken)
Attempt to delete a model with a particular id
-
Routes to a server actions
Definition: Routes.cs:9
+
override async Task< IActionResult > Delete(long id, CancellationToken cancellationToken)
Attempt to delete a model with a particular id
+
Routes to a server actions
Definition: Routes.cs:9
-
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
+
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
-
const string Jobs
The Models.Job controller
Definition: Routes.cs:79
-
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
-
An ApiController representing a TModel
+
const string Jobs
The Models.Job controller
Definition: Routes.cs:79
+
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
+
An ApiController representing a TModel
+
Task< bool > CancelJob(Job job, User user, bool blocking, CancellationToken cancellationToken)
Cancels a give job
- -
readonly IJobManager jobManager
The IJobManager for the JobController
-
ModelController<TModel> for Api.Models.Jobs
+ +
readonly IJobManager jobManager
The IJobManager for the JobController
+
ModelController<TModel> for Api.Models.Jobs
- - + + +
int? JobProgress(Job job)
Get the Api.Models.Job.Progress for a job
diff --git a/_job_exception_8cs.html b/_job_exception_8cs.html index 6ca628f226..2c10b79180 100644 --- a/_job_exception_8cs.html +++ b/_job_exception_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/JobException.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_job_exception_8cs_source.html b/_job_exception_8cs_source.html index 2d00b79d42..3fe06b6c48 100644 --- a/_job_exception_8cs_source.html +++ b/_job_exception_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/JobException.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
JobException.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Host.Core
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()
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
diff --git a/_job_handler_8cs.html b/_job_handler_8cs.html index f7e9963f15..b0a9772180 100644 --- a/_job_handler_8cs.html +++ b/_job_handler_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/JobHandler.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_job_handler_8cs_source.html b/_job_handler_8cs_source.html index 4447a5b4b1..6d52beef47 100644 --- a/_job_handler_8cs_source.html +++ b/_job_handler_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/JobHandler.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
JobHandler.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
5 namespace Tgstation.Server.Host.Core
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 }
- -
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 }
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
- -
Class for pairing Tasks with CancellationTokenSources
Definition: JobHandler.cs:10
+
Class for pairing Tasks with CancellationTokenSources
Definition: JobHandler.cs:10
diff --git a/_job_manager_8cs.html b/_job_manager_8cs.html index 44953953be..2019e7e4ad 100644 --- a/_job_manager_8cs.html +++ b/_job_manager_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/JobManager.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_job_manager_8cs_source.html b/_job_manager_8cs_source.html index 5551f3b0e8..6216c27d2d 100644 --- a/_job_manager_8cs_source.html +++ b/_job_manager_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/JobManager.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
10 namespace Tgstation.Server.Host.Core
11 {
14  {
19 
23  readonly ILogger<JobManager> logger;
24 
28  readonly Dictionary<long, JobHandler> jobs;
29 
35  public JobManager(IDatabaseContextFactory databaseContextFactory, ILogger<JobManager> logger)
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
+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
async Task StartAsync(CancellationToken cancellationToken)
Definition: JobManager.cs:184
-
User StartedBy
See Api.Models.Job.StartedBy
Definition: Job.cs:16
- -
readonly Dictionary< long, JobHandler > jobs
Dictionary<TKey, TValue> of Api.Models.Internal.Job.Id to running JobHandlers
Definition: JobManager.cs:28
+
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 Api.Models.Internal.Job.Id to running JobHandlers
Definition: JobManager.cs:28
- -
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
-
DateTimeOffset StoppedAt
When the Job stopped
Definition: Job.cs:37
-
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
-
DateTimeOffset StartedAt
When the Job was started
Definition: Job.cs:32
-
string Description
English description of the Job
Definition: Job.cs:21
-
string ExceptionDetails
Details of any exceptions caught during the Job
Definition: Job.cs:26
-
User CancelledBy
See Api.Models.Job.CancelledBy
Definition: Job.cs:21
+
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
+
string ExceptionDetails
Details of any exceptions caught during the Job
Definition: Job.cs:26
+
Task RegisterOperation(Job job, Func< Job, IDatabaseContext, Action< int >, CancellationToken, Task > operation, CancellationToken cancellationToken)
Registers a given Job and begins running it
+
User CancelledBy
See Api.Models.Job.CancelledBy
Definition: Job.cs:21
-
Instance Instance
The Models.Instance the job belongs to if any
Definition: Job.cs:27
+ +
DateTimeOffset? StoppedAt
When the Job stopped
Definition: Job.cs:37
+
bool? Cancelled
If the Job was cancelled
Definition: Job.cs:43
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.Job.StoppedAt time, unless it is cancelled or errors
Definition: Job.cs:34
- -
readonly ILogger< JobManager > logger
The ILogger for the JobManager
Definition: JobManager.cs:23
-
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
-
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
-
int JobProgress(Job job)
Get the Api.Models.Job.Progress for a job
Definition: JobManager.cs:255
-
long Id
The ID of the User
Definition: User.cs:15
+
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
+
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
+
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
+
long Id
The ID of the User
Definition: User.cs:15
-
readonly IDatabaseContextFactory databaseContextFactory
The IServiceProvider for the JobManager
Definition: JobManager.cs:18
- -
async Task RunJob(Job job, Func< Job, IDatabaseContext, CancellationToken, Task > operation, CancellationToken cancellationToken)
Runner for JobHandlers
Definition: JobManager.cs:71
+
readonly IDatabaseContextFactory databaseContextFactory
The IServiceProvider for the JobManager
Definition: JobManager.cs:18
+ +
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
-
bool Cancelled
If the Job was cancelled
Definition: Job.cs:43
- -
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
- -
Class for pairing Tasks with CancellationTokenSources
Definition: JobHandler.cs:10
+ +
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
+ +
Class for pairing Tasks with CancellationTokenSources
Definition: JobHandler.cs:10
diff --git a/_jobs_client_8cs.html b/_jobs_client_8cs.html index 04c78a0923..cb34f32326 100644 --- a/_jobs_client_8cs.html +++ b/_jobs_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/JobsClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_jobs_client_8cs_source.html b/_jobs_client_8cs_source.html index ebd3530515..6afad7a040 100644 --- a/_jobs_client_8cs_source.html +++ b/_jobs_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/JobsClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
JobsClient.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 using Tgstation.Server.Api;
7 
8 namespace Tgstation.Server.Client.Components
9 {
11  sealed class JobsClient : IJobsClient
12  {
17 
21  readonly Instance instance;
22 
28  public JobsClient(IApiClient apiClient, Instance instance)
29  {
30  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
31  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
32  }
33 
35  public Task Cancel(Job job, CancellationToken cancellationToken) => apiClient.Delete(Routes.SetID(Routes.Jobs, job?.Id ?? throw new ArgumentNullException(nameof(job))), instance.Id, cancellationToken);
36 
38  public Task<IReadOnlyList<Job>> List(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<Job>>(Routes.List(Routes.Jobs), instance.Id, cancellationToken);
39 
41  public Task<IReadOnlyList<Job>> ListActive(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<Job>>(Routes.Jobs, instance.Id, cancellationToken);
42 
44  public Task<Job> GetId(Job job, CancellationToken cancellationToken) => apiClient.Read<Job>(Routes.SetID(Routes.Jobs, job?.Id ?? throw new ArgumentNullException(nameof(job))), instance.Id, cancellationToken);
45  }
46 }
- -
JobsClient(IApiClient apiClient, Instance instance)
Construct a JobsClient
Definition: JobsClient.cs:28
- +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 using Tgstation.Server.Api;
7 
9 {
11  sealed class JobsClient : IJobsClient
12  {
17 
21  readonly Instance instance;
22 
29  {
30  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
31  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
32  }
33 
35  public Task Cancel(Job job, CancellationToken cancellationToken) => apiClient.Delete(Routes.SetID(Routes.Jobs, job?.Id ?? throw new ArgumentNullException(nameof(job))), instance.Id, cancellationToken);
36 
38  public Task<IReadOnlyList<Job>> List(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<Job>>(Routes.List(Routes.Jobs), instance.Id, cancellationToken);
39 
41  public Task<IReadOnlyList<Job>> ListActive(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<Job>>(Routes.Jobs, instance.Id, cancellationToken);
42 
44  public Task<Job> GetId(Job job, CancellationToken cancellationToken) => apiClient.Read<Job>(Routes.SetID(Routes.Jobs, job?.Id ?? throw new ArgumentNullException(nameof(job))), instance.Id, cancellationToken);
45  }
46 }
+
Task< IReadOnlyList< Job > > ListActive(CancellationToken cancellationToken)
List the active Jobs in the Instance
+
JobsClient(IApiClient apiClient, Instance instance)
Construct a JobsClient
Definition: JobsClient.cs:28
+
Task< IReadOnlyList< Job > > List(CancellationToken cancellationToken)
List the Api.Models.Internal.Job.Ids in the Instance
-
Routes to a server actions
Definition: Routes.cs:9
- - -
const string Jobs
The Models.Job controller
Definition: Routes.cs:79
-
readonly IApiClient apiClient
The IApiClient for the JobsClient
Definition: JobsClient.cs:16
+
Routes to a server actions
Definition: Routes.cs:9
+ + +
Task< Job > GetId(Job job, CancellationToken cancellationToken)
Get a 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
+
readonly IApiClient apiClient
The IApiClient for the JobsClient
Definition: JobsClient.cs:16
-
Metadata about a server instance
Definition: Instance.cs:9
-
static string SetID(string route, long id)
Apply an id postfix to a route
-
static string List(string route)
Get the /List postfix for a route
- -
Web interface for the API
Definition: IApiClient.cs:11
-
readonly Instance instance
The Instance for the JobsClient
Definition: JobsClient.cs:21
- -
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job ...
Definition: Job.cs:6
+
Metadata about a server instance
Definition: Instance.cs:9
+
static string SetID(string route, long id)
Apply an id postfix to a route
+
Task Delete(string route, CancellationToken cancellationToken)
Run an HTTP DELETE request
+
static string List(string route)
Get the /List postfix for a route
+ +
Web interface for the API
Definition: IApiClient.cs:11
+
readonly Instance instance
The Instance for the JobsClient
Definition: JobsClient.cs:21
+
Task Cancel(Job job, CancellationToken cancellationToken)
Cancels a job
+ +
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job
Definition: Job.cs:6
diff --git a/_json_file_8cs.html b/_json_file_8cs.html index 6b1e90ca62..a5a6b71b6b 100644 --- a/_json_file_8cs.html +++ b/_json_file_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/JsonFile.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Interop
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_json_file_8cs_source.html b/_json_file_8cs_source.html index 8bc0d189ca..6e2710cc5f 100644 --- a/_json_file_8cs_source.html +++ b/_json_file_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/JsonFile.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
JsonFile.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
4 
5 namespace Tgstation.Server.Host.Components.Interop
6 {
10  sealed class JsonFile
11  {
15  public string AccessIdentifier { get; set; }
16 
20  public bool ApiValidateOnly { get; set; }
21 
25  public string InstanceName { get; set; }
26 
30  public string ChatChannelsJson { get; set; }
31 
35  public string ChatCommandsJson { get; set; }
36 
40  public string ServerCommandsJson { get; set; }
41 
45  public Api.Models.Internal.RevisionInformation Revision { get; set; }
46 
50  public DreamDaemonSecurity SecurityLevel { get; set; }
51 
55  public List<TestMerge> TestMerges { get; } = new List<TestMerge>();
56  }
57 }
- - -
Representation of the initial json passed to DreamDaemon
Definition: JsonFile.cs:10
+Go to the documentation of this file.
1 using System.Collections.Generic;
4 
6 {
10  sealed class JsonFile
11  {
15  public string AccessIdentifier { get; set; }
16 
20  public bool ApiValidateOnly { get; set; }
21 
25  public string InstanceName { get; set; }
26 
30  public string ChatChannelsJson { get; set; }
31 
35  public string ChatCommandsJson { get; set; }
36 
40  public string ServerCommandsJson { get; set; }
41 
45  public Api.Models.Internal.RevisionInformation Revision { get; set; }
46 
50  public DreamDaemonSecurity SecurityLevel { get; set; }
51 
55  public List<TestMerge> TestMerges { get; } = new List<TestMerge>();
56  }
57 }
+
string ChatCommandsJson
JSON file DD should write to with available chat commands
Definition: JsonFile.cs:35
+
Representation of the initial json passed to DreamDaemon
Definition: JsonFile.cs:10
+
string ServerCommandsJson
JSON file DD should write to to send commands to the server
Definition: JsonFile.cs:40
- - -
DreamDaemonSecurity
DreamDaemon&#39;s security level
- +
DreamDaemonSecurity SecurityLevel
The DreamDaemonSecurity level of the launch
Definition: JsonFile.cs:50
+
List< TestMerge > TestMerges
The TestMerges in the launch
Definition: JsonFile.cs:55
+ +
Api.Models.Internal.RevisionInformation Revision
The Api.Models.Internal.RevisionInformation of the launch
Definition: JsonFile.cs:45
+ +
string AccessIdentifier
The code used by the server to authenticate command Topics
Definition: JsonFile.cs:15
+
bool ApiValidateOnly
If DD should just respond if it's API is working and then exit
Definition: JsonFile.cs:20
+ +
string ChatChannelsJson
JSON file name that contains current active chat channel information
Definition: JsonFile.cs:30
+
DreamDaemonSecurity
DreamDaemon's security level
+
string InstanceName
The Api.Models.Instance.Name of the owner at the time of launch
Definition: JsonFile.cs:25
+
diff --git a/_json_sub_file_list_8cs.html b/_json_sub_file_list_8cs.html index 42f1d112ac..971a89fd68 100644 --- a/_json_sub_file_list_8cs.html +++ b/_json_sub_file_list_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/JsonSubFileList.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Interop
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_json_sub_file_list_8cs_source.html b/_json_sub_file_list_8cs_source.html index a9de74148a..599ddb8280 100644 --- a/_json_sub_file_list_8cs_source.html +++ b/_json_sub_file_list_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/JsonSubFileList.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
JsonSubFileList.cs
-Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
3 
4 namespace Tgstation.Server.Host.Components.Interop
5 {
9  public class JsonSubFileList
10  {
14  [Required]
15  public string ChatCommandsJson { get; set; }
16 
20  [Required]
21  public string ChatChannelsJson { get; set; }
22 
26  [Required]
27  public string ServerCommandsJson { get; set; }
28 
32  protected JsonSubFileList() { }
33 
39  {
40  if (copy == null)
41  throw new ArgumentNullException(nameof(copy));
42  ChatChannelsJson = copy.ChatChannelsJson;
43  ChatCommandsJson = copy.ChatCommandsJson;
44  ServerCommandsJson = copy.ServerCommandsJson;
45  }
46  }
47 }
string ServerCommandsJson
Path to the server commands json file
- - -
string ChatCommandsJson
Path to the chat commands json file
-
JsonSubFileList(JsonSubFileList copy)
Construct an JsonSubFileList from a copy
-
Information used in for reattaching and interop
- -
string ChatChannelsJson
Path to the chat channels json file
- +Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
3 
5 {
9  public class JsonSubFileList
10  {
14  [Required]
15  public string ChatCommandsJson { get; set; }
16 
20  [Required]
21  public string ChatChannelsJson { get; set; }
22 
26  [Required]
27  public string ServerCommandsJson { get; set; }
28 
32  protected JsonSubFileList() { }
33 
39  {
40  if (copy == null)
41  throw new ArgumentNullException(nameof(copy));
45  }
46  }
47 }
string ServerCommandsJson
Path to the server commands json file
+
string ChatCommandsJson
Path to the chat commands json file
+
JsonSubFileList(JsonSubFileList copy)
Construct an JsonSubFileList from a copy
+
Information used in for reattaching and interop
+ +
string ChatChannelsJson
Path to the chat channels json file
+
diff --git a/_json_tracking_context_8cs.html b/_json_tracking_context_8cs.html index 9337d59a3e..f60803bd78 100644 --- a/_json_tracking_context_8cs.html +++ b/_json_tracking_context_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/JsonTrackingContext.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_json_tracking_context_8cs_source.html b/_json_tracking_context_8cs_source.html index 8c592d38b1..56cb36d505 100644 --- a/_json_tracking_context_8cs_source.html +++ b/_json_tracking_context_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/JsonTrackingContext.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
JsonTrackingContext.cs
-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 
13 namespace Tgstation.Server.Host.Components.Chat
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 
50  public JsonTrackingContext(IIOManager ioManager, ICustomCommandHandler customCommandHandler, ILogger<JsonTrackingContext> logger, Action onDispose, string commandsPath, string channelsPath)
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  onDispose();
70  }
71 
73  public async Task<IReadOnlyList<CustomCommand>> GetCustomCommands(CancellationToken cancellationToken)
74  {
75  try
76  {
77  if (Active && await ioManager.FileExists(commandsPath, cancellationToken).ConfigureAwait(false))
78  {
79  var resultBytes = await ioManager.ReadAllBytes(commandsPath, cancellationToken).ConfigureAwait(false);
80  var resultJson = Encoding.UTF8.GetString(resultBytes);
81  logger.LogTrace("Read commands JSON: {0}", resultJson);
82  var result = JsonConvert.DeserializeObject<List<CustomCommand>>(resultJson, new JsonSerializerSettings
83  {
84  ContractResolver = new DefaultContractResolver
85  {
86  NamingStrategy = new SnakeCaseNamingStrategy()
87  }
88  });
89  foreach (var I in result)
90  I.SetHandler(customCommandHandler);
91  return result;
92  }
93  }
94  catch (OperationCanceledException)
95  {
96  throw;
97  }
98  catch (Exception e)
99  {
100  logger.LogWarning("Error retrieving custom commands! Exception: {0}", e);
101  }
102 
103  return new List<CustomCommand>();
104  }
105 
107  public async Task SetChannels(IEnumerable<Channel> channels, CancellationToken cancellationToken)
108  {
109  using (await SemaphoreSlimContext.Lock(channelsSemaphore, cancellationToken).ConfigureAwait(false))
110  {
111  var json = JsonConvert.SerializeObject(channels, new JsonSerializerSettings
112  {
113  ContractResolver = new CamelCasePropertyNamesContractResolver()
114  });
115  logger.LogTrace("Writing channels JSON: {0}", json);
116  await ioManager.WriteAllBytes(channelsPath, Encoding.UTF8.GetBytes(json), cancellationToken).ConfigureAwait(false);
117  }
118  }
119  }
120 }
+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 }
-
async Task SetChannels(IEnumerable< Channel > channels, CancellationToken cancellationToken)
Writes information about connected channels to the IJsonTrackingContext
- +
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
- + -
JsonTrackingContext(IIOManager ioManager, ICustomCommandHandler customCommandHandler, ILogger< JsonTrackingContext > logger, Action onDispose, string commandsPath, string channelsPath)
Construct a JsonTrackingContext
+
JsonTrackingContext(IIOManager ioManager, ICustomCommandHandler customCommandHandler, ILogger< JsonTrackingContext > logger, Action onDispose, string commandsPath, string channelsPath)
Construct a JsonTrackingContext
+
Task< bool > FileExists(string path, CancellationToken cancellationToken)
Check that the file at path exists
-
Represents a tracking of dynamic chat json files
+
Represents a tracking of dynamic chat json files
- + -
Handles Commands.ICommands that map to those defined in a IJsonTrackingContext
- -
Interface for using filesystems
Definition: IIOManager.cs:11
- -
static async Task< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore
- - +
Handles Commands.ICommands that map to those defined in a IJsonTrackingContext
+ +
Interface for using filesystems
Definition: IIOManager.cs:11
+
Task< byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
Returns all the contents of a file at path as a byte array
+ +
static async Task< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore
+ + -
async Task< IReadOnlyList< CustomCommand > > GetCustomCommands(CancellationToken cancellationToken)
Read CustomCommands from the IJsonTrackingContext
+
async Task< IReadOnlyList< CustomCommand > > GetCustomCommands(CancellationToken cancellationToken)
Read CustomCommands from the IJsonTrackingContext
diff --git a/_kek_command_8cs.html b/_kek_command_8cs.html index f1434f1dbc..a03c7ae50a 100644 --- a/_kek_command_8cs.html +++ b/_kek_command_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/KekCommand.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
namespace  Tgstation.Server.Host.Components.Chat.Commands
 
@@ -114,7 +103,7 @@ Namespaces diff --git a/_kek_command_8cs_source.html b/_kek_command_8cs_source.html index a32397dafd..bee27daf43 100644 --- a/_kek_command_8cs_source.html +++ b/_kek_command_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/KekCommand.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
KekCommand.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
4 namespace Tgstation.Server.Host.Components.Chat.Commands
5 {
9  sealed class KekCommand : ICommand
10  {
14  const string Kek = "kek";
15 
17  public string Name => Kek;
18 
20  public string HelpText => Kek;
21 
23  public bool AdminOnly => false;
24 
26  public Task<string> Invoke(string arguments, User user, CancellationToken cancellationToken) => Task.FromResult(Kek);
27  }
28 }
- - -
Represents a tgs_chat_user datum
Definition: User.cs:10
-
Represents a command that can be invoked by talking to chat bots
Definition: ICommand.cs:9
- +Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
5 {
9  sealed class KekCommand : ICommand
10  {
14  const string Kek = "kek";
15 
17  public string Name => Kek;
18 
20  public string HelpText => Kek;
21 
23  public bool AdminOnly => false;
24 
26  public Task<string> Invoke(string arguments, User user, CancellationToken cancellationToken) => Task.FromResult(Kek);
27  }
28 }
+ + +
Task< string > Invoke(string arguments, User user, CancellationToken cancellationToken)
Invoke the ICommand
+ + +
Represents a tgs_chat_user datum
Definition: User.cs:10
+ +
Represents a command that can be invoked by talking to chat bots
Definition: ICommand.cs:9
diff --git a/_launch_result_8cs.html b/_launch_result_8cs.html index 2218b84182..d6a1a76167 100644 --- a/_launch_result_8cs.html +++ b/_launch_result_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/LaunchResult.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Watchdog
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_launch_result_8cs_source.html b/_launch_result_8cs_source.html index 29e6166b8a..f66f974b01 100644 --- a/_launch_result_8cs_source.html +++ b/_launch_result_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/LaunchResult.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
LaunchResult.cs
-Go to the documentation of this file.
1 using System;
2 using System.Globalization;
3 
4 namespace Tgstation.Server.Host.Components.Watchdog
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
- - - +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
diff --git a/_message_8cs.html b/_message_8cs.html index 42cb368889..1f0c586ebf 100644 --- a/_message_8cs.html +++ b/_message_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Message.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Components.Chat.Providers.Message - Represents a message recieved by a IProvider More...
+ Represents a message recieved by a IProvider More...
  + + + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
namespace  Tgstation.Server.Host.Components.Chat.Providers
 
@@ -114,7 +103,7 @@ Namespaces diff --git a/_message_8cs_source.html b/_message_8cs_source.html index 4dbdda47a9..13b204b8fc 100644 --- a/_message_8cs_source.html +++ b/_message_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Message.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Message.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Host.Components.Chat.Providers
2 {
6  sealed class Message
7  {
11  public string Content { get; set; }
12 
16  public User User { get; set; }
17  }
18 }
-
Represents a message recieved by a IProvider
Definition: Message.cs:6
-
Represents a tgs_chat_user datum
Definition: User.cs:10
- - +Go to the documentation of this file.
2 {
6  sealed class Message
7  {
11  public string Content { get; set; }
12 
16  public User User { get; set; }
17  }
18 }
Represents a message recieved by a IProvider
Definition: Message.cs:6
+ + +
Represents a tgs_chat_user datum
Definition: User.cs:10
diff --git a/_method_not_supported_exception_8cs.html b/_method_not_supported_exception_8cs.html index e8d7fe8c24..0865f995ae 100644 --- a/_method_not_supported_exception_8cs.html +++ b/_method_not_supported_exception_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/MethodNotSupportedException.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_method_not_supported_exception_8cs_source.html b/_method_not_supported_exception_8cs_source.html index 3b2bfe8ad2..f41d02eb4b 100644 --- a/_method_not_supported_exception_8cs_source.html +++ b/_method_not_supported_exception_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/MethodNotSupportedException.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
MethodNotSupportedException.cs
-Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
5 namespace Tgstation.Server.Client
6 {
11  {
16  {
17  Message = "This method is not currently supported!",
18  SeverApiVersion = null
19  }, HttpStatusCode.NotImplemented)
20  { }
21 
26  public MethodNotSupportedException(string message) : base(message) { }
27 
33  public MethodNotSupportedException(string message, Exception innerException) : base(message, innerException) { }
34  }
35 }
MethodNotSupportedException()
Construct an MethodNotSupportedException
+Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
6 {
11  {
16  {
17  Message = "This method is not currently supported!",
18  SeverApiVersion = null
19  }, HttpStatusCode.NotImplemented)
20  { }
21 
26  public MethodNotSupportedException(string message) : base(message) { }
27 
33  public MethodNotSupportedException(string message, Exception innerException) : base(message, innerException) { }
34  }
35 }
MethodNotSupportedException()
Construct an MethodNotSupportedException
- - -
MethodNotSupportedException(string message, Exception innerException)
Construct an MethodNotSupportedException with a message and innerException
-
MethodNotSupportedException(string message)
Construct an MethodNotSupportedException with a message
+ +
MethodNotSupportedException(string message, Exception innerException)
Construct an MethodNotSupportedException with a message and innerException
+
MethodNotSupportedException(string message)
Construct an MethodNotSupportedException with a message
- -
Occurs when the client tries to use a currently unsupported API
-
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- -
Exceptions thrown by IServerClients
+ +
Occurs when the client tries to use a currently unsupported API
+
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+ +
Exceptions thrown by IServerClients
diff --git a/_model_controller_8cs.html b/_model_controller_8cs.html index 16d5edc530..31767f69f8 100644 --- a/_model_controller_8cs.html +++ b/_model_controller_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/ModelController.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Controllers.ModelController< TModel > - An ApiController representing a TModel More...
+ An ApiController representing a TModel More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Controllers
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_model_controller_8cs_source.html b/_model_controller_8cs_source.html index 2f5dd69573..ff52c73724 100644 --- a/_model_controller_8cs_source.html +++ b/_model_controller_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/ModelController.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ModelController.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.Extensions.Logging;
3 using System.Threading;
4 using System.Threading.Tasks;
7 
8 namespace Tgstation.Server.Host.Controllers
9 {
14  public abstract class ModelController<TModel> : ApiController where TModel : class
15  {
23  public ModelController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ILogger logger, bool requireInstance) : base(databaseContext, authenticationContextFactory, logger, requireInstance, true) { }
24 
31  [HttpPut]
32  public virtual Task<IActionResult> Create([FromBody]TModel model, CancellationToken cancellationToken) => Task.FromResult((IActionResult)NotFound());
33 
39  [HttpGet]
40  public virtual Task<IActionResult> Read(CancellationToken cancellationToken) => Task.FromResult((IActionResult)NotFound());
41 
48  [HttpGet("{id}")]
49  public virtual Task<IActionResult> GetId(long id, CancellationToken cancellationToken) => Task.FromResult((IActionResult)NotFound());
50 
57  [HttpPost]
58  public virtual Task<IActionResult> Update([FromBody]TModel model, CancellationToken cancellationToken) => Task.FromResult((IActionResult)NotFound());
59 
66  [HttpDelete("{id}")]
67  public virtual Task<IActionResult> Delete(long id, CancellationToken cancellationToken) => Task.FromResult((IActionResult)NotFound());
68 
74  [HttpGet("List")]
75  public virtual Task<IActionResult> List(CancellationToken cancellationToken) => Task.FromResult((IActionResult)NotFound());
76  }
77 }
- - -
ModelController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ILogger logger, bool requireInstance)
Construct a ModelController<TModel>
+Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.Extensions.Logging;
3 using System.Threading;
4 using System.Threading.Tasks;
7 
9 {
14  public abstract class ModelController<TModel> : ApiController where TModel : class
15  {
23  public ModelController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ILogger logger, bool requireInstance) : base(databaseContext, authenticationContextFactory, logger, requireInstance, true) { }
24 
31  [HttpPut]
32  public virtual Task<IActionResult> Create([FromBody]TModel model, CancellationToken cancellationToken) => Task.FromResult((IActionResult)NotFound());
33 
39  [HttpGet]
40  public virtual Task<IActionResult> Read(CancellationToken cancellationToken) => Task.FromResult((IActionResult)NotFound());
41 
48  [HttpGet("{id}")]
49  public virtual Task<IActionResult> GetId(long id, CancellationToken cancellationToken) => Task.FromResult((IActionResult)NotFound());
50 
57  [HttpPost]
58  public virtual Task<IActionResult> Update([FromBody]TModel model, CancellationToken cancellationToken) => Task.FromResult((IActionResult)NotFound());
59 
66  [HttpDelete("{id}")]
67  public virtual Task<IActionResult> Delete(long id, CancellationToken cancellationToken) => Task.FromResult((IActionResult)NotFound());
68 
74  [HttpGet("List")]
75  public virtual Task<IActionResult> List(CancellationToken cancellationToken) => Task.FromResult((IActionResult)NotFound());
76  }
77 }
+ + +
ModelController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ILogger logger, bool requireInstance)
Construct a ModelController<TModel>
- - -
An ApiController representing a TModel
+
virtual Task< IActionResult > Delete(long id, CancellationToken cancellationToken)
Attempt to delete a model with a particular id
+
virtual Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Attempt to get a specific a TModel
+
virtual Task< IActionResult > Create([FromBody]TModel model, CancellationToken cancellationToken)
Attempt to create a model
+ +
An ApiController representing a TModel
- - - +
readonly bool requireInstance
If IAuthenticationContext.InstanceUser permissions are required to access the ApiController
+
virtual Task< IActionResult > List(CancellationToken cancellationToken)
Attempt to list entries of the TModel
+ +
virtual Task< IActionResult > Read(CancellationToken cancellationToken)
Attempt to read a TModel
+ +
virtual Task< IActionResult > Update([FromBody]TModel model, CancellationToken cancellationToken)
Attempt to update a model
+
diff --git a/_models_2_reattach_information_8cs.html b/_models_2_reattach_information_8cs.html index 9223de5686..051952b22d 100644 --- a/_models_2_reattach_information_8cs.html +++ b/_models_2_reattach_information_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/ReattachInformation.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

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

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_models_2_reattach_information_8cs_source.html b/_models_2_reattach_information_8cs_source.html index 83505cbf0d..98487de226 100644 --- a/_models_2_reattach_information_8cs_source.html +++ b/_models_2_reattach_information_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/ReattachInformation.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ReattachInformation.cs
-Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
3 namespace Tgstation.Server.Host.Models
4 {
9  {
13  public long Id { get; set; }
14 
18  [Required]
19  public CompileJob CompileJob { get; set; }
20  }
21 }
-
Database representation of Components.Watchdog.ReattachInformation
- - - +Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
4 {
9  {
13  public long Id { get; set; }
14 
18  [Required]
19  public CompileJob CompileJob { get; set; }
20  }
21 }
+
Database representation of Components.Watchdog.ReattachInformation
+ +
diff --git a/_models_2_watchdog_reattach_information_8cs.html b/_models_2_watchdog_reattach_information_8cs.html index e503ecd0fc..d08d15007a 100644 --- a/_models_2_watchdog_reattach_information_8cs.html +++ b/_models_2_watchdog_reattach_information_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/WatchdogReattachInformation.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

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

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_models_2_watchdog_reattach_information_8cs_source.html b/_models_2_watchdog_reattach_information_8cs_source.html index 90c03c66d1..15429d09e8 100644 --- a/_models_2_watchdog_reattach_information_8cs_source.html +++ b/_models_2_watchdog_reattach_information_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/WatchdogReattachInformation.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
WatchdogReattachInformation.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Host.Models
2 {
7  {
11  public long Id { get; set; }
12 
16  public long InstanceId { get; set; }
17 
21  public ReattachInformation Alpha { get; set; }
22 
26  public ReattachInformation Bravo { get; set; }
27  }
28 }
Database representation of Components.Watchdog.WatchdogReattachInformation
- -
Database representation of Components.Watchdog.ReattachInformation
- - +Go to the documentation of this file.
2 {
7  {
11  public long Id { get; set; }
12 
16  public long InstanceId { get; set; }
17 
21  public ReattachInformation Alpha { get; set; }
22 
26  public ReattachInformation Bravo { get; set; }
27  }
28 }
Database representation of Components.Watchdog.WatchdogReattachInformation
+
ReattachInformation Alpha
The ReattachInformation for the Alpha server
+
Database representation of Components.Watchdog.ReattachInformation
+ + + +
long InstanceId
The Api.Models.Instance.Id of the Instance the WatchdogReattachInformation belongs to
+
ReattachInformation Bravo
The ReattachInformation for the Bravo server
diff --git a/_monitor_action_8cs.html b/_monitor_action_8cs.html index 6ce9edf593..c4d60d37a2 100644 --- a/_monitor_action_8cs.html +++ b/_monitor_action_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/MonitorAction.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Host +  +namespace  Tgstation.Server.Host.Components +  namespace  Tgstation.Server.Host.Components.Watchdog   @@ -113,8 +100,8 @@ Enumerations
  Tgstation.Server.Host.Components.Watchdog.MonitorAction.Exit
- } - + } +
 The action for the monitor loop to take when control is returned to it More...
 The action for the monitor loop to take when control is returned to it More...
 
@@ -122,7 +109,7 @@ Enumerations diff --git a/_monitor_action_8cs_source.html b/_monitor_action_8cs_source.html index e0c3aaf88f..df66ea6eff 100644 --- a/_monitor_action_8cs_source.html +++ b/_monitor_action_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/MonitorAction.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
MonitorAction.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Host.Components.Watchdog
2 {
7  {
11  Continue,
12 
16  Skip,
17 
21  Restart,
22 
26  Break,
27 
31  Exit
32  }
33 }
- -
Skips the next call to HandleMonitorWakeup action
-
The monitor should stop checking actions for this iteration and continue its loop ...
-
The monitor should exit. Does not kill servers
-
MonitorAction
The action for the monitor loop to take when control is returned to it
Definition: MonitorAction.cs:6
- +Go to the documentation of this file.
2 {
7  {
11  Continue,
12 
16  Skip,
17 
21  Restart,
22 
26  Break,
27 
31  Exit
32  }
33 }
+ +
Skips the next call to HandleMonitorWakeup action
+
The monitor should stop checking actions for this iteration and continue its loop
+
The monitor should exit. Does not kill servers
+
MonitorAction
The action for the monitor loop to take when control is returned to it
Definition: MonitorAction.cs:6
diff --git a/_monitor_activation_reason_8cs.html b/_monitor_activation_reason_8cs.html index 1f7cd474f7..e993cdc8d8 100644 --- a/_monitor_activation_reason_8cs.html +++ b/_monitor_activation_reason_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/MonitorActivationReason.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Host +  +namespace  Tgstation.Server.Host.Components +  namespace  Tgstation.Server.Host.Components.Watchdog   @@ -115,8 +102,8 @@ EnumerationsTgstation.Server.Host.Components.Watchdog.MonitorActivationReason.NewDmbAvailable, Tgstation.Server.Host.Components.Watchdog.MonitorActivationReason.ActiveLaunchParametersUpdated
- } - + } +
 Reasons for the monitor to wake up More...
 Reasons for the monitor to wake up More...
 
@@ -124,7 +111,7 @@ Enumerations diff --git a/_monitor_activation_reason_8cs_source.html b/_monitor_activation_reason_8cs_source.html index c65689af92..06c0bc4ba2 100644 --- a/_monitor_activation_reason_8cs_source.html +++ b/_monitor_activation_reason_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/MonitorActivationReason.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
MonitorActivationReason.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Host.Components.Watchdog
2 {
7  {
12 
17 
22 
27 
32 
37 
42  }
43 }
- - - - - -
MonitorActivationReason
Reasons for the monitor to wake up
- - -
The inactive server is past that point where DD hangs when you press "Go"
+Go to the documentation of this file.
2 {
7  {
12 
17 
22 
27 
32 
37 
42  }
43 }
+ + + + + +
MonitorActivationReason
Reasons for the monitor to wake up
+ +
The inactive server is past that point where DD hangs when you press "Go"
diff --git a/_monitor_state_8cs.html b/_monitor_state_8cs.html index 9a65ba8f95..c3e0068cdc 100644 --- a/_monitor_state_8cs.html +++ b/_monitor_state_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/MonitorState.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Watchdog
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_monitor_state_8cs_source.html b/_monitor_state_8cs_source.html index 95a7ac2891..43cfbaadb0 100644 --- a/_monitor_state_8cs_source.html +++ b/_monitor_state_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/MonitorState.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
MonitorState.cs
-Go to the documentation of this file.
1 using Newtonsoft.Json;
2 
3 namespace Tgstation.Server.Host.Components.Watchdog
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 }
-
Handles communication with a DreamDaemon IProcess
-
MonitorAction
The action for the monitor loop to take when control is returned to it
Definition: MonitorAction.cs:6
-
The (absolute) state of the Watchdog
Definition: MonitorState.cs:8
- +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 Watchdog.MonitorLifetimes(System.Threading.CancellationToken)
Definition: MonitorState.cs:23
+ +
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
+
MonitorAction
The action for the monitor loop to take when control is returned to it
Definition: MonitorAction.cs:6
+
The (absolute) state of the Watchdog
Definition: MonitorState.cs:8
diff --git a/_my_sql_database_context_8cs.html b/_my_sql_database_context_8cs.html index 59c4d0de8d..ce9955b129 100644 --- a/_my_sql_database_context_8cs.html +++ b/_my_sql_database_context_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/MySqlDatabaseContext.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.MySqlDatabaseContextDatabaseContext<TParentContext> for MySQL More...
DatabaseContext<TParentContext> for MySQL More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_my_sql_database_context_8cs_source.html b/_my_sql_database_context_8cs_source.html index 5828221b45..bf89bcf2ae 100644 --- a/_my_sql_database_context_8cs_source.html +++ b/_my_sql_database_context_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/MySqlDatabaseContext.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
9 namespace Tgstation.Server.Host.Models
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
- +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
-
DatabaseType DatabaseType
The Configuration.DatabaseType to create
+ +
For initially seeding a database
+
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>
-
DatabaseType
Type of database to user
Definition: DatabaseType.cs:6
- - -
DatabaseContext<TParentContext> for MySQL
- + +
string MySqlServerVersion
The string form of the System.Version of a target MySQL/MariaDB server
+
Configuration options for the Models.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
+ +
DatabaseContext<TParentContext> for MySQL
+
diff --git a/_my_sql_database_context_model_snapshot_8cs.html b/_my_sql_database_context_model_snapshot_8cs.html index ff99309916..712c1e8fd2 100644 --- a/_my_sql_database_context_model_snapshot_8cs.html +++ b/_my_sql_database_context_model_snapshot_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/MySqlDatabaseContextModelSnapshot.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_my_sql_database_context_model_snapshot_8cs_source.html b/_my_sql_database_context_model_snapshot_8cs_source.html index ee302e46f5..21a9952cbf 100644 --- a/_my_sql_database_context_model_snapshot_8cs_source.html +++ b/_my_sql_database_context_model_snapshot_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/MySqlDatabaseContextModelSnapshot.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
6 namespace Tgstation.Server.Host.Models.Migrations
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;
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 }
+ - -
diff --git a/_my_sql_design_time_db_context_factory_8cs.html b/_my_sql_design_time_db_context_factory_8cs.html index b91b9ad81a..36e34d5b12 100644 --- a/_my_sql_design_time_db_context_factory_8cs.html +++ b/_my_sql_design_time_db_context_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/MySqlDesignTimeDbContextFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -113,7 +100,7 @@ Namespaces 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 c91a91f440..a22c9e63f2 100644 --- a/_my_sql_design_time_db_context_factory_8cs_source.html +++ b/_my_sql_design_time_db_context_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/MySqlDesignTimeDbContextFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
7 namespace Tgstation.Server.Host.Models.Migrations
8 {
10  sealed class MySqlDesignTimeDbContextFactory : IDesignTimeDbContextFactory<MySqlDatabaseContext>
11  {
13  public MySqlDatabaseContext CreateDbContext(string[] args) => new MySqlDatabaseContext(new DbContextOptions<MySqlDatabaseContext>(), DesignTimeDbContextFactoryHelpers.GetDbContextOptions(), new DatabaseSeeder(new CryptographySuite(new PasswordHasher<User>())), new LoggerFactory().CreateLogger<MySqlDatabaseContext>());
14  }
15 }
static IOptions< DatabaseConfiguration > GetDbContextOptions()
Get the IOptions<TOptions> for the DatabaseConfiguration
- -
Contains helpers for creating design time Models.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;
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
- + - -
DatabaseContext<TParentContext> for MySQL
- + +
DatabaseContext<TParentContext> for MySQL
+
diff --git a/_native_methods_8cs.html b/_native_methods_8cs.html index f684b1e378..f7a4847996 100644 --- a/_native_methods_8cs.html +++ b/_native_methods_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/NativeMethods.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_native_methods_8cs_source.html b/_native_methods_8cs_source.html index 9ff412e519..4b5fa6c0bd 100644 --- a/_native_methods_8cs_source.html +++ b/_native_methods_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/NativeMethods.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 }
- +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
CreateSymbolicLinkFlags
See https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createsymboliclinka#param...
-
Native methods used by the code
- +
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
+
Native methods used by the code
+
static int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId)
See https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getwindowthreadprocessid
+
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/_platform_identifier_8cs.html b/_platform_identifier_8cs.html index e359b59492..11e3137a67 100644 --- a/_platform_identifier_8cs.html +++ b/_platform_identifier_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/PlatformIdentifier.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_platform_identifier_8cs_source.html b/_platform_identifier_8cs_source.html index 0c98d3f02a..64451f01aa 100644 --- a/_platform_identifier_8cs_source.html +++ b/_platform_identifier_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/PlatformIdentifier.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
PlatformIdentifier.cs
-Go to the documentation of this file.
1 using System.Runtime.InteropServices;
2 
3 namespace Tgstation.Server.Host.Core
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
+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
- + +
For identifying the current platform
diff --git a/_posix_byond_installer_8cs.html b/_posix_byond_installer_8cs.html index b0dac8f8ed..2d1b98f1c8 100644 --- a/_posix_byond_installer_8cs.html +++ b/_posix_byond_installer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Byond/PosixByondInstaller.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Components.Byond.PosixByondInstallerIByondInstaller for Posix systems More...
IByondInstaller for Posix systems More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Byond
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_posix_byond_installer_8cs_source.html b/_posix_byond_installer_8cs_source.html index c25ccc78fb..b8c0b1aa9e 100644 --- a/_posix_byond_installer_8cs_source.html +++ b/_posix_byond_installer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Byond/PosixByondInstaller.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
PosixByondInstaller.cs
-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 
9 namespace Tgstation.Server.Host.Components.Byond
10 {
15  {
19  const string ByondRevisionsURLTemplate = "https://secure.byond.com/download/build/{0}/{0}.{1}_byond_linux.zip";
20 
24  const string ByondCachePath = "~/.byond/cache";
25 
26  const string DreamDaemonExecutableName = "DreamDaemon";
27  const string DreamMakerExecutableName = "DreamMaker";
28  const string ShellScriptExtension = ".sh";
29 
31  public string DreamDaemonName => DreamDaemonExecutableName + ShellScriptExtension;
32 
34  public string DreamMakerName => DreamMakerExecutableName + ShellScriptExtension;
35 
40 
45 
49  readonly ILogger<PosixByondInstaller> logger;
50 
57  public PosixByondInstaller(IIOManager ioManager, IPostWriteHandler postWriteHandler, ILogger<PosixByondInstaller> logger)
58  {
59  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
60  this.postWriteHandler = postWriteHandler ?? throw new ArgumentNullException(nameof(postWriteHandler));
61  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
62  }
63 
65  public async Task CleanCache(CancellationToken cancellationToken)
66  {
67  try
68  {
69  await ioManager.DeleteDirectory(ByondCachePath, cancellationToken).ConfigureAwait(false);
70  }
71  catch (OperationCanceledException)
72  {
73  throw;
74  }
75  catch (Exception e)
76  {
77  logger.LogWarning("Error deleting BYOND cache! Exception: {0}", e);
78  }
79  }
80 
82  public async Task<byte[]> DownloadVersion(Version version, CancellationToken cancellationToken)
83  {
84  if (version == null)
85  throw new ArgumentNullException(nameof(version));
86 
87  var url = String.Format(CultureInfo.InvariantCulture, ByondRevisionsURLTemplate, version.Major, version.Minor);
88 
89  return await ioManager.DownloadFile(new Uri(url), cancellationToken).ConfigureAwait(false);
90  }
91 
93  public Task InstallByond(string path, Version version, CancellationToken cancellationToken)
94  {
95  if (path == null)
96  throw new ArgumentNullException(nameof(path));
97  if (version == null)
98  throw new ArgumentNullException(nameof(version));
99 
100  // write the scripts for running the ting
101  // need to add $ORIGIN to LD_LIBRARY_PATH
102  const string StandardScript = "#!/bin/sh\nexport LD_LIBRARY_PATH=\"\\$ORIGIN:$LD_LIBRARY_PATH\"\nBASEDIR=$(dirname \"$0\")\nexec \"$BASEDIR/{0}\" \"$@\"\n";
103 
104  var dreamDaemonScript = String.Format(CultureInfo.InvariantCulture, StandardScript, DreamDaemonExecutableName);
105  var dreamMakerScript = String.Format(CultureInfo.InvariantCulture, StandardScript, DreamMakerExecutableName);
106 
107  async Task WriteAndMakeExecutable(string fullPath, string script)
108  {
109  await ioManager.WriteAllBytes(fullPath, Encoding.ASCII.GetBytes(script), cancellationToken).ConfigureAwait(false);
110  postWriteHandler.HandleWrite(fullPath);
111  }
112 
113  var basePath = ioManager.ConcatPath(path, ByondManager.BinPath);
114 
115  var task = Task.WhenAll(WriteAndMakeExecutable(ioManager.ConcatPath(basePath, DreamDaemonName), dreamDaemonScript), WriteAndMakeExecutable(ioManager.ConcatPath(basePath, DreamMakerName), dreamMakerScript));
116 
117  postWriteHandler.HandleWrite(ioManager.ConcatPath(basePath, DreamDaemonExecutableName));
118  postWriteHandler.HandleWrite(ioManager.ConcatPath(basePath, DreamMakerExecutableName));
119 
120  return task;
121  }
122  }
123 }
PosixByondInstaller(IIOManager ioManager, IPostWriteHandler postWriteHandler, ILogger< PosixByondInstaller > logger)
Construct a WindowsByondInstaller
-
Handles changing file modes/permissions after writing
- - -
async Task< byte[]> DownloadVersion(Version version, CancellationToken cancellationToken)
Download a given BYOND version
- -
async Task CleanCache(CancellationToken cancellationToken)
Attempts to cleans the BYOND cache folder for the system
-
For downloading and installing BYOND extractions for a given system
- -
readonly ILogger< PosixByondInstaller > logger
The ILogger for the PosixByondInstaller
-
readonly IIOManager ioManager
The IIOManager for the PosixByondInstaller
-
Task InstallByond(string path, Version version, CancellationToken cancellationToken)
Does actions necessary to get an extracted BYOND installation working
-
readonly IPostWriteHandler postWriteHandler
The IPostWriteHandler for the PosixByondInstaller
+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 ByondRevisionsURLTemplate = "https://secure.byond.com/download/build/{0}/{0}.{1}_byond_linux.zip";
20 
24  const string ByondCachePath = "~/.byond/cache";
25 
26  const string DreamDaemonExecutableName = "DreamDaemon";
27  const string DreamMakerExecutableName = "DreamMaker";
28  const string ShellScriptExtension = ".sh";
29 
32 
35 
40 
45 
49  readonly ILogger<PosixByondInstaller> logger;
50 
58  {
59  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
60  this.postWriteHandler = postWriteHandler ?? throw new ArgumentNullException(nameof(postWriteHandler));
61  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
62  }
63 
65  public async Task CleanCache(CancellationToken cancellationToken)
66  {
67  try
68  {
69  await ioManager.DeleteDirectory(ByondCachePath, cancellationToken).ConfigureAwait(false);
70  }
71  catch (OperationCanceledException)
72  {
73  throw;
74  }
75  catch (Exception e)
76  {
77  logger.LogWarning("Error deleting BYOND cache! Exception: {0}", e);
78  }
79  }
80 
82  public async Task<byte[]> DownloadVersion(Version version, CancellationToken cancellationToken)
83  {
84  if (version == null)
85  throw new ArgumentNullException(nameof(version));
86 
87  var url = String.Format(CultureInfo.InvariantCulture, ByondRevisionsURLTemplate, version.Major, version.Minor);
88 
89  return await ioManager.DownloadFile(new Uri(url), cancellationToken).ConfigureAwait(false);
90  }
91 
93  public Task InstallByond(string path, Version version, CancellationToken cancellationToken)
94  {
95  if (path == null)
96  throw new ArgumentNullException(nameof(path));
97  if (version == null)
98  throw new ArgumentNullException(nameof(version));
99 
100  // write the scripts for running the ting
101  // need to add $ORIGIN to LD_LIBRARY_PATH
102  const string StandardScript = "#!/bin/sh\nexport LD_LIBRARY_PATH=\"\\$ORIGIN:$LD_LIBRARY_PATH\"\nBASEDIR=$(dirname \"$0\")\nexec \"$BASEDIR/{0}\" \"$@\"\n";
103 
104  var dreamDaemonScript = String.Format(CultureInfo.InvariantCulture, StandardScript, DreamDaemonExecutableName);
105  var dreamMakerScript = String.Format(CultureInfo.InvariantCulture, StandardScript, DreamMakerExecutableName);
106 
107  async Task WriteAndMakeExecutable(string fullPath, string script)
108  {
109  await ioManager.WriteAllBytes(fullPath, Encoding.ASCII.GetBytes(script), cancellationToken).ConfigureAwait(false);
110  postWriteHandler.HandleWrite(fullPath);
111  }
112 
113  var basePath = ioManager.ConcatPath(path, ByondManager.BinPath);
114 
115  var task = Task.WhenAll(WriteAndMakeExecutable(ioManager.ConcatPath(basePath, DreamDaemonName), dreamDaemonScript), WriteAndMakeExecutable(ioManager.ConcatPath(basePath, DreamMakerName), dreamMakerScript));
116 
119 
120  return task;
121  }
122  }
123 }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
+
PosixByondInstaller(IIOManager ioManager, IPostWriteHandler postWriteHandler, ILogger< PosixByondInstaller > logger)
Construct a WindowsByondInstaller
+ +
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
+
Task< byte[]> DownloadFile(Uri url, CancellationToken cancellationToken)
Downloads a file from url
+ +
const string ByondRevisionsURLTemplate
The URL format string for getting BYOND linux version {0}.{1} zipfile
+ +
void HandleWrite(string filePath)
For handling system specific necessities after a write
+
async Task< byte[]> DownloadVersion(Version version, CancellationToken cancellationToken)
Download a given BYOND version
+
async Task CleanCache(CancellationToken cancellationToken)
Attempts to cleans the BYOND cache folder for the system
+
For downloading and installing BYOND extractions for a given system
+ + + + +
readonly ILogger< PosixByondInstaller > logger
The ILogger for the PosixByondInstaller
+ +
readonly IIOManager ioManager
The IIOManager for the PosixByondInstaller
+
Task InstallByond(string path, Version version, CancellationToken cancellationToken)
Does actions necessary to get an extracted BYOND installation working
+
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
- - + +
Interface for using filesystems
Definition: IIOManager.cs:11
+
const string BinPath
The path to the BYOND bin folder
Definition: ByondManager.cs:21
+ +
string ConcatPath(params string[] paths)
Combines an array of strings into a path
+
diff --git a/_posix_network_prompt_reaper_8cs.html b/_posix_network_prompt_reaper_8cs.html index 06fb567cfb..da65ab3026 100644 --- a/_posix_network_prompt_reaper_8cs.html +++ b/_posix_network_prompt_reaper_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/PosixNetworkPromptReaper.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Watchdog
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_posix_network_prompt_reaper_8cs_source.html b/_posix_network_prompt_reaper_8cs_source.html index 9cd3a6d3ec..1a7217d9c1 100644 --- a/_posix_network_prompt_reaper_8cs_source.html +++ b/_posix_network_prompt_reaper_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/PosixNetworkPromptReaper.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
PosixNetworkPromptReaper.cs
-Go to the documentation of this file.
2 
3 namespace Tgstation.Server.Host.Components.Watchdog
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
+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
- -
On Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort(). This looks out for those prompts and immediately clicks "Yes" if the owning process has registered for it
- - +
Abstraction over a System.Diagnostics.Process
Definition: IProcess.cs:9
+ +
On Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort()....
+ +
diff --git a/_posix_post_write_handler_8cs.html b/_posix_post_write_handler_8cs.html index 9aaaaadfe0..2a571e2551 100644 --- a/_posix_post_write_handler_8cs.html +++ b/_posix_post_write_handler_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/PosixPostWriteHandler.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.IO.PosixPostWriteHandlerIPostWriteHandler for POSIX systems More...
IPostWriteHandler for POSIX systems More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.IO
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_posix_post_write_handler_8cs_source.html b/_posix_post_write_handler_8cs_source.html index 82549d6f27..c0df419f98 100644 --- a/_posix_post_write_handler_8cs_source.html +++ b/_posix_post_write_handler_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/PosixPostWriteHandler.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
PosixPostWriteHandler.cs
-Go to the documentation of this file.
1 using Mono.Unix;
2 using Mono.Unix.Native;
3 using System;
4 
5 namespace Tgstation.Server.Host.IO
6 {
11  {
13  public void HandleWrite(string filePath)
14  {
15  if (filePath == null)
16  throw new ArgumentNullException(nameof(filePath));
17 
18  // set executable bit every time, don't want people calling me when their uploaded "sl" binary doesn't work
19  if (Syscall.stat(filePath, out var stat) != 0)
20  throw new UnixIOException(Stdlib.GetLastError());
21 
22  if (stat.st_mode.HasFlag(FilePermissions.S_IXUSR))
23  return;
24 
25  if (Syscall.chmod(filePath, stat.st_mode | FilePermissions.S_IXUSR) != 0)
26  throw new UnixIOException(Stdlib.GetLastError());
27  }
28  }
29 }
void HandleWrite(string filePath)
For handling system specific necessities after a write
-
IPostWriteHandler for POSIX systems
-
Handles changing file modes/permissions after writing
- - - +Go to the documentation of this file.
1 using Mono.Unix;
2 using Mono.Unix.Native;
3 using System;
4 
6 {
11  {
13  public void HandleWrite(string filePath)
14  {
15  if (filePath == null)
16  throw new ArgumentNullException(nameof(filePath));
17 
18  // set executable bit every time, don't want people calling me when their uploaded "sl" binary doesn't work
19  if (Syscall.stat(filePath, out var stat) != 0)
20  throw new UnixIOException(Stdlib.GetLastError());
21 
22  if (stat.st_mode.HasFlag(FilePermissions.S_IXUSR))
23  return;
24 
25  if (Syscall.chmod(filePath, stat.st_mode | FilePermissions.S_IXUSR) != 0)
26  throw new UnixIOException(Stdlib.GetLastError());
27  }
28  }
29 }
void HandleWrite(string filePath)
For handling system specific necessities after a write
+
IPostWriteHandler for POSIX systems
+
Handles changing file modes/permissions after writing
+
diff --git a/_posix_symlink_factory_8cs.html b/_posix_symlink_factory_8cs.html index 08e19acac6..0073df7748 100644 --- a/_posix_symlink_factory_8cs.html +++ b/_posix_symlink_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/PosixSymlinkFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.IO.PosixSymlinkFactoryISymlinkFactory for posix systems More...
ISymlinkFactory for posix systems More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.IO
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_posix_symlink_factory_8cs_source.html b/_posix_symlink_factory_8cs_source.html index ca441608d3..db6680d613 100644 --- a/_posix_symlink_factory_8cs_source.html +++ b/_posix_symlink_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/PosixSymlinkFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
PosixSymlinkFactory.cs
-Go to the documentation of this file.
1 using Mono.Unix;
2 using System;
3 using System.IO;
4 using System.Threading;
5 using System.Threading.Tasks;
6 
7 namespace Tgstation.Server.Host.IO
8 {
13  {
15  public Task CreateSymbolicLink(string targetPath, string linkPath, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
16  {
17  if (targetPath == null)
18  throw new ArgumentNullException(nameof(targetPath));
19  if (linkPath == null)
20  throw new ArgumentNullException(nameof(linkPath));
21 
22  UnixFileSystemInfo fsInfo;
23  var isFile = File.Exists(targetPath);
24  cancellationToken.ThrowIfCancellationRequested();
25  if (isFile)
26  fsInfo = new UnixFileInfo(targetPath);
27  else
28  fsInfo = new UnixDirectoryInfo(targetPath);
29  cancellationToken.ThrowIfCancellationRequested();
30  fsInfo.CreateSymbolicLink(linkPath);
31  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
32  }
33 }
- - - - +Go to the documentation of this file.
1 using Mono.Unix;
2 using System;
3 using System.IO;
4 using System.Threading;
5 using System.Threading.Tasks;
6 
8 {
13  {
15  public Task CreateSymbolicLink(string targetPath, string linkPath, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
16  {
17  if (targetPath == null)
18  throw new ArgumentNullException(nameof(targetPath));
19  if (linkPath == null)
20  throw new ArgumentNullException(nameof(linkPath));
21 
22  UnixFileSystemInfo fsInfo;
23  var isFile = File.Exists(targetPath);
24  cancellationToken.ThrowIfCancellationRequested();
25  if (isFile)
26  fsInfo = new UnixFileInfo(targetPath);
27  else
28  fsInfo = new UnixDirectoryInfo(targetPath);
29  cancellationToken.ThrowIfCancellationRequested();
30  fsInfo.CreateSymbolicLink(linkPath);
31  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
32  }
33 }
+ + +
diff --git a/_posix_system_identity_factory_8cs.html b/_posix_system_identity_factory_8cs.html index aa929c74d7..ef719b2519 100644 --- a/_posix_system_identity_factory_8cs.html +++ b/_posix_system_identity_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/PosixSystemIdentityFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Security.PosixSystemIdentityFactoryISystemIdentityFactory for posix systems More...
ISystemIdentityFactory for posix systems More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_posix_system_identity_factory_8cs_source.html b/_posix_system_identity_factory_8cs_source.html index 61942b11ad..5afba328cf 100644 --- a/_posix_system_identity_factory_8cs_source.html +++ b/_posix_system_identity_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/PosixSystemIdentityFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
PosixSystemIdentityFactory.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Host.Security
7 {
13  {
15  public Task<ISystemIdentity> CreateSystemIdentity(User user, CancellationToken cancellationToken) => throw new NotImplementedException();
16 
18  public Task<ISystemIdentity> CreateSystemIdentity(string username, string password, CancellationToken cancellationToken) => throw new NotImplementedException();
19  }
20 }
+Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
13  {
15  public Task<ISystemIdentity> CreateSystemIdentity(User user, CancellationToken cancellationToken) => throw new NotImplementedException();
16 
18  public Task<ISystemIdentity> CreateSystemIdentity(string username, string password, CancellationToken cancellationToken) => throw new NotImplementedException();
19  }
20 }
Task< ISystemIdentity > CreateSystemIdentity(User user, CancellationToken cancellationToken)
Create a ISystemIdentity for a given user
- - - - - - + + + + + +
diff --git a/_process_8cs.html b/_process_8cs.html index 63044a1317..3e0e93a08f 100644 --- a/_process_8cs.html +++ b/_process_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/Process.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_process_8cs_source.html b/_process_8cs_source.html index dda59e64b5..830132d676 100644 --- a/_process_8cs_source.html +++ b/_process_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/Process.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
6 namespace Tgstation.Server.Host.Core
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
+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
+
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&#39;s the owned System.Diagnostics.Process.PriorityClass to System.Diagnostics.ProcessPriorityClass.AboveNormal
Definition: Process.cs:117
-
readonly ILogger< Process > logger
The ILogger for the Process
Definition: Process.cs:29
+ +
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
- +
void Terminate()
Terminates the process
Definition: Process.cs:100
diff --git a/_process_executor_8cs.html b/_process_executor_8cs.html index dce1b3bfd2..d6419a7ded 100644 --- a/_process_executor_8cs.html +++ b/_process_executor_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/ProcessExecutor.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_process_executor_8cs_source.html b/_process_executor_8cs_source.html index 92d0029ad8..5ca4edba64 100644 --- a/_process_executor_8cs_source.html +++ b/_process_executor_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/ProcessExecutor.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
6 namespace Tgstation.Server.Host.Core
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
+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
+
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
- +
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
diff --git a/_provider_8cs.html b/_provider_8cs.html index 493751130f..3e1bcdcbef 100644 --- a/_provider_8cs.html +++ b/_provider_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Providers/Provider.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
namespace  Tgstation.Server.Host.Components.Chat.Providers
 
@@ -113,7 +102,7 @@ Namespaces diff --git a/_provider_8cs_source.html b/_provider_8cs_source.html index 0617a05a07..2432bf4322 100644 --- a/_provider_8cs_source.html +++ b/_provider_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Providers/Provider.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Provider.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Host.Components.Chat.Providers
7 {
9  abstract class Provider : IProvider
10  {
14  readonly Queue<Message> messageQueue;
15 
19  TaskCompletionSource<object> nextMessage;
20 
24  protected Provider()
25  {
26  messageQueue = new Queue<Message>();
27  nextMessage = new TaskCompletionSource<object>();
28  }
29 
31  public abstract bool Connected { get; }
32 
34  public abstract string BotMention { get; }
35 
40  protected void EnqueueMessage(Message message)
41  {
42  lock (messageQueue)
43  {
44  messageQueue.Enqueue(message);
45  nextMessage.TrySetResult(null);
46  }
47  }
48 
50  public abstract void Dispose();
51 
53  public abstract Task<bool> Connect(CancellationToken cancellationToken);
54 
56  public abstract Task Disconnect(CancellationToken cancellationToken);
57 
59  public abstract Task<IReadOnlyList<Channel>> MapChannels(IEnumerable<ChatChannel> channels, CancellationToken cancellationToken);
60 
62  public async Task<Message> NextMessage(CancellationToken cancellationToken)
63  {
64  var cancelTcs = new TaskCompletionSource<object>();
65  using (cancellationToken.Register(() => cancelTcs.SetCanceled()))
66  await Task.WhenAny(nextMessage.Task, cancelTcs.Task).ConfigureAwait(false);
67  cancellationToken.ThrowIfCancellationRequested();
68  lock (messageQueue)
69  {
70  var result = messageQueue.Dequeue();
71  if (messageQueue.Count == 0)
72  nextMessage = new TaskCompletionSource<object>();
73  return result;
74  }
75  }
76 
78  public abstract Task SendMessage(ulong channelId, string message, CancellationToken cancellationToken);
79  }
80 }
- - +Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
9  abstract class Provider : IProvider
10  {
14  readonly Queue<Message> messageQueue;
15 
19  TaskCompletionSource<object> nextMessage;
20 
24  protected Provider()
25  {
26  messageQueue = new Queue<Message>();
27  nextMessage = new TaskCompletionSource<object>();
28  }
29 
31  public abstract bool Connected { get; }
32 
34  public abstract string BotMention { get; }
35 
40  protected void EnqueueMessage(Message message)
41  {
42  lock (messageQueue)
43  {
44  messageQueue.Enqueue(message);
45  nextMessage.TrySetResult(null);
46  }
47  }
48 
50  public abstract void Dispose();
51 
53  public abstract Task<bool> Connect(CancellationToken cancellationToken);
54 
56  public abstract Task Disconnect(CancellationToken cancellationToken);
57 
59  public abstract Task<IReadOnlyList<Channel>> MapChannels(IEnumerable<ChatChannel> channels, CancellationToken cancellationToken);
60 
62  public async Task<Message> NextMessage(CancellationToken cancellationToken)
63  {
64  var cancelTcs = new TaskCompletionSource<object>();
65  using (cancellationToken.Register(() => cancelTcs.SetCanceled()))
66  await Task.WhenAny(nextMessage.Task, cancelTcs.Task).ConfigureAwait(false);
67  cancellationToken.ThrowIfCancellationRequested();
68  lock (messageQueue)
69  {
70  var result = messageQueue.Dequeue();
71  if (messageQueue.Count == 0)
72  nextMessage = new TaskCompletionSource<object>();
73  return result;
74  }
75  }
76 
78  public abstract Task SendMessage(ulong channelId, string message, CancellationToken cancellationToken);
79  }
80 }
-
Represents a message recieved by a IProvider
Definition: Message.cs:6
-
For interacting with a chat service
Definition: IProvider.cs:11
+
Represents a message recieved by a IProvider
Definition: Message.cs:6
+ + -
async Task< Message > NextMessage(CancellationToken cancellationToken)
Get a Task<TResult> resulting in the next Message the IProvider recieves or on a disconnect ...
Definition: Provider.cs:62
-
TaskCompletionSource< object > nextMessage
TaskCompletionSource<TResult> that completes while messageQueue isn&#39;t empty
Definition: Provider.cs:19
- - -
readonly Queue< Message > messageQueue
Queue<T> of received Messages
Definition: Provider.cs:14
-
void EnqueueMessage(Message message)
Queues a message for NextMessage(CancellationToken)
Definition: Provider.cs:40
- +
abstract Task SendMessage(ulong channelId, string message, CancellationToken cancellationToken)
Send a message to the IProvider
+
async Task< Message > NextMessage(CancellationToken cancellationToken)
Get a Task<TResult> resulting in the next Message the IProvider recieves or null on a disconnect
Definition: Provider.cs:62
+
TaskCompletionSource< object > nextMessage
TaskCompletionSource<TResult> that completes while messageQueue isn't empty
Definition: Provider.cs:19
+
abstract Task< bool > Connect(CancellationToken cancellationToken)
Attempt to connect the IProvider
+ + + +
readonly Queue< Message > messageQueue
Queue<T> of received Messages
Definition: Provider.cs:14
+
abstract Task< IReadOnlyList< Channel > > MapChannels(IEnumerable< ChatChannel > channels, CancellationToken cancellationToken)
+ +
abstract Task Disconnect(CancellationToken cancellationToken)
Gracefully disconnects the provider. Implies a call to IDisposable.Dispose
+
void EnqueueMessage(Message message)
Queues a message for NextMessage(CancellationToken)
Definition: Provider.cs:40
+ +
diff --git a/_provider_factory_8cs.html b/_provider_factory_8cs.html index 58edaec3f9..82d9bc0c8c 100644 --- a/_provider_factory_8cs.html +++ b/_provider_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/ProviderFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_provider_factory_8cs_source.html b/_provider_factory_8cs_source.html index 18438276ca..36528fab53 100644 --- a/_provider_factory_8cs_source.html +++ b/_provider_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/ProviderFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ProviderFactory.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;
8 
9 namespace Tgstation.Server.Host.Components.Chat
10 {
13  {
18 
23 
27  readonly ILoggerFactory loggerFactory;
28 
35  public ProviderFactory(IApplication application, IAsyncDelayer asyncDelayer, ILoggerFactory loggerFactory)
36  {
37  this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
38  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
39  this.application = application ?? throw new ArgumentNullException(nameof(application));
40  }
41 
43  public IProvider CreateProvider(Api.Models.Internal.ChatBot settings)
44  {
45  if (settings == null)
46  throw new ArgumentNullException(nameof(settings));
47  var builder = settings.ConnectionStringBuilder;
48  if (builder == null || !builder.Valid)
49  throw new InvalidOperationException("Invalid ChatConnectionStringBuilder!");
50  switch (settings.Provider)
51  {
52  case ChatProvider.Irc:
53  var ircBuilder = (IrcConnectionStringBuilder)builder;
54  return new IrcProvider(application, asyncDelayer, loggerFactory.CreateLogger<IrcProvider>(), ircBuilder.Address, ircBuilder.Port.Value, ircBuilder.Nickname, ircBuilder.Password, ircBuilder.PasswordType, ircBuilder.UseSsl.Value);
55  case ChatProvider.Discord:
56  var discordBuilder = (DiscordConnectionStringBuilder)builder;
57  return new DiscordProvider(loggerFactory.CreateLogger<DiscordProvider>(), discordBuilder.BotToken);
58  default:
59  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid ChatProvider: {0}", settings.Provider));
60  }
61  }
62  }
63 }
+Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using System;
3 using System.Globalization;
7 
9 {
12  {
17 
22 
26  readonly ILoggerFactory loggerFactory;
27 
35  {
36  this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
37  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
38  this.application = application ?? throw new ArgumentNullException(nameof(application));
39  }
40 
42  public IProvider CreateProvider(Api.Models.Internal.ChatBot settings)
43  {
44  if (settings == null)
45  throw new ArgumentNullException(nameof(settings));
46  var builder = settings.CreateConnectionStringBuilder();
47  if (builder == null || !builder.Valid)
48  throw new InvalidOperationException("Invalid ChatConnectionStringBuilder!");
49  switch (settings.Provider)
50  {
51  case ChatProvider.Irc:
52  var ircBuilder = (IrcConnectionStringBuilder)builder;
53  return new IrcProvider(application, asyncDelayer, loggerFactory.CreateLogger<IrcProvider>(), ircBuilder.Address, ircBuilder.Port.Value, ircBuilder.Nickname, ircBuilder.Password, ircBuilder.PasswordType, ircBuilder.UseSsl.Value);
54  case ChatProvider.Discord:
55  var discordBuilder = (DiscordConnectionStringBuilder)builder;
56  return new DiscordProvider(loggerFactory.CreateLogger<DiscordProvider>(), discordBuilder.BotToken);
57  default:
58  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid ChatProvider: {0}", settings.Provider));
59  }
60  }
61  }
62 }
-
readonly IApplication application
The IApplication for the ProviderFactory
+
readonly IApplication application
The IApplication for the ProviderFactory
- -
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
- - -
ChatConnectionStringBuilder for ChatProvider.Discord
-
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the ProviderFactory
-
For interacting with a chat service
Definition: IProvider.cs:11
- + +
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
+
ChatConnectionStringBuilder for ChatProvider.Discord
+
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the ProviderFactory
+ + - -
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the ProviderFactory
- -
ProviderFactory(IApplication application, IAsyncDelayer asyncDelayer, ILoggerFactory loggerFactory)
Construct a ProviderFactory
- - -
ChatConnectionStringBuilder for ChatProvider.Irc
-
ChatProvider
Represents a chat service provider
Definition: ChatProvider.cs:6
- - -
IProvider CreateProvider(Api.Models.Internal.ChatBot settings)
+ +
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the ProviderFactory
+ +
ProviderFactory(IApplication application, IAsyncDelayer asyncDelayer, ILoggerFactory loggerFactory)
Construct a ProviderFactory
+ + +
ChatConnectionStringBuilder for ChatProvider.Irc
+
ChatProvider
Represents a chat service provider
Definition: ChatProvider.cs:6
+ + +
IProvider CreateProvider(Api.Models.Internal.ChatBot settings)
diff --git a/_pull_requests_command_8cs.html b/_pull_requests_command_8cs.html index 01d13d0a9e..d1e349f55e 100644 --- a/_pull_requests_command_8cs.html +++ b/_pull_requests_command_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/PullRequestsCommand.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
namespace  Tgstation.Server.Host.Components.Chat.Commands
 
@@ -114,7 +103,7 @@ Namespaces diff --git a/_pull_requests_command_8cs_source.html b/_pull_requests_command_8cs_source.html index 352e2c6853..412248f3fc 100644 --- a/_pull_requests_command_8cs_source.html +++ b/_pull_requests_command_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/PullRequestsCommand.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
PullRequestsCommand.cs
-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 
12 namespace Tgstation.Server.Host.Components.Chat.Commands
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 
55  public PullRequestsCommand(IWatchdog watchdog, IRepositoryManager repositoryManager, IDatabaseContextFactory databaseContextFactory, Models.Instance instance)
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
+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
- -
readonly IRepositoryManager repositoryManager
The IRepositoryManager 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
-
readonly IWatchdog watchdog
The IWatchdog for the PullRequestsCommand
-
Represents a tgs_chat_user datum
Definition: User.cs:10
- -
Factory for creating and loading IRepositorys
- -
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
+
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
+
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/_r_e_a_d_m_e_8md.html b/_r_e_a_d_m_e_8md.html index 01cf882bd5..c122e60121 100644 --- a/_r_e_a_d_m_e_8md.html +++ b/_r_e_a_d_m_e_8md.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: README.md File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
README.md File Reference
- -

Go to the source code of this file.

diff --git a/_r_e_a_d_m_e_8md_source.html b/_r_e_a_d_m_e_8md_source.html deleted file mode 100644 index 907c84c248..0000000000 --- a/_r_e_a_d_m_e_8md_source.html +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - -tgstation-server: README.md Source File - - - - - - - - - - -
-
- - - - - - - -
-
tgstation-server -
-
The /tg/station 13 server suite
-
-
- - - - - -
- -
-
- - -
- -
- -
-
-
README.md
-
-
-Go to the documentation of this file.
1 # tgstation-server v4:
2 
3 [![Build status](https://ci.appveyor.com/api/projects/status/7t1h7bvuha0p9j5f/branch/master?svg=true)](https://ci.appveyor.com/project/Cyberboss/tgstation-server-tools/branch/master) [![Build Status](https://travis-ci.org/tgstation/tgstation-server.svg?branch=master)](https://travis-ci.org/tgstation/tgstation-server) [![codecov](https://codecov.io/gh/tgstation/tgstation-server/branch/master/graph/badge.svg)](https://codecov.io/gh/tgstation/tgstation-server) [![Waffle.io - Columns and their card count](https://badge.waffle.io/tgstation/tgstation-server.png?columns=all)](https://waffle.io/tgstation/tgstation-server?utm_source=badge)
4 
5 [![GitHub license](https://img.shields.io/github/license/tgstation/tgstation-server.svg)](https://github.com/tgstation/tgstation-server/blob/master/LICENSE) [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/tgstation/tgstation-server.svg)](http://isitmaintained.com/project/tgstation/tgstation-server "Average time to resolve an issue") [![NuGet version](https://img.shields.io/nuget/v/Tgstation.Server.Api.svg)](https://www.nuget.org/packages/Tgstation.Server.Api) [![NuGet version](https://img.shields.io/nuget/v/Tgstation.Server.Client.svg)](https://www.nuget.org/packages/Tgstation.Server.Client)
6 
7 [![forthebadge](http://forthebadge.com/images/badges/made-with-c-sharp.svg)](http://forthebadge.com) [![forinfinityandbyond](https://user-images.githubusercontent.com/5211576/29499758-4efff304-85e6-11e7-8267-62919c3688a9.gif)](https://www.reddit.com/r/SS13/comments/5oplxp/what_is_the_main_problem_with_byond_as_an_engine/dclbu1a)
8 
9 [![forthebadge](http://forthebadge.com/images/badges/built-with-love.svg)](http://forthebadge.com) [![forthebadge](http://forthebadge.com/images/badges/60-percent-of-the-time-works-every-time.svg)](http://forthebadge.com)
10 
11 This is a toolset to manage production BYOND servers. It includes the ability to update the server without having to stop or shutdown the server (the update will take effect on a "reboot" of the server) the ability start the server and restart it if it crashes, as well as systems for managing code and game files, and merging GitHub Pull Requests for test deployments.
12 
13 ### Legacy Servers
14 
15 Older server versions can be found in the V# branches of this repository. Note that V4 is nearly fully incompatible with existing installations. Only some static files may be copied over: https://github.com/tgstation/tgstation-server#static-files
16 
17 ## Setup
18 
19 ### Pre-Requisites
20 
21 - [.NET Core Runtime (>= v2.1)](https://www.microsoft.com/net/download) If you plan to install tgstation-server as a Windows service, you should also ensure that your .NET Framework runtime version is >= v4.7.1 (Download can be found on same page). On Windows, ensure that the `dotnet` executable file is in your system's `PATH` variable (or the user's that will be running the server).
22 - A [MariaDB](https://downloads.mariadb.org/), MySQL, or [Microsoft SQL Server](https://www.microsoft.com/en-us/download/details.aspx?id=55994) database engine is required
23 
24 ### Installation
25 
26 1. [Download the latest V4 release .zip](https://github.com/tgstation/tgstation-server/releases/latest). The ServerService package will only work on Windows. Choose ServerConsole if that is not your target OS or you prefer not to use the Windows service.
27 2. Extract the .zip file to where you want the server to run from. Note the account running the server must have write and delete access to the `lib` subdirectory.
28 
29 #### Windows
30 
31 If you wish to install the TGS as a service, run `Tgstation.Server.Host.Service.exe`. It should prompt you to install it. Click `Yes` and accept a potential UAC elevation prompt and the setup wizard should run.
32 
33 #### REFER TO ISSUE [#798](https://github.com/tgstation/tgstation-server/issues/798) BEFORE DECIDING TO USE A LINUX DEPLOYMENT
34 
35 #### Linux (Native)
36 
37 We recommend using Docker for Linux installations, see below. The content of this parent section may be skipped if you choose to do so.
38 
39 The following dependencies are required to run tgstation-server on Linux alongside the .NET Core runtime
40 
41 - gcc-multilib (on 64-bit systems for running BYOND)
42 
43 Note that tgstation-server has only ever been tested on Linux via it's [docker environment](https://github.com/tgstation/tgstation-server/blob/master/build/Dockerfile#L22). If you are having trouble with something in a native installation, or figure out a required workaround, please contact project maintainers so this documentation may be better updated.
44 
45 #### Docker (Linux)
46 
47 tgstation-server supports running in a docker container and is the recommended deployment method for Linux systems. The official image repository is located at https://hub.docker.com/r/tgstation/server. It can also be built locally by running `docker build . -f build/Dockerfile -t <your tag name>` in the repository root.
48 
49 To create a container run
50 ```sh
51 docker run \
52  -ti \ #start interactive for manual configuration
53  --restart=always \ #if you want maximum uptime
54  --network="host" \ #if your sql server is on the same machine
55  --name="tgs" \ #or whatever else you wanna call it
56  --cap-add=sys_nice \ #allows tgs to schedule DreamDaemon as a higher priority process
57  --init \ #reaps potential zombie processes
58  -p <tgs port>:80 \
59  -p 0.0.0.0:<public game port>:<public game port> \
60  -v /path/to/your/configfile/directory:/config_data \ #only if you want to use manual configuration
61  -v /path/to/store/instances:/tgs4_instances \
62  -v /path/to/your/log/folder:/tgs_logs \
63  tgstation/server #replace this with <your tag name> if you built the image locally
64 ```
65 with any additional options you desire (i.e. You'll have to expose more game ports in order to host more than one instance).
66 
67 Note although `/app/lib` is specified as a volume mount point in the `Dockerfile`, unless you REALLY know what you're doing. Do not mount any volumes over this for fear of breaking your container.
68 
69 If using manual configuration, before starting your container make sure the aforemention `appsettings.Production.json` is setup properly. See below
70 
71 ### Configuring
72 
73 The first time you run TGS4 you should be prompted with a configuration wizard which will guide you through setting up your appsettings.Production.json
74 
75 This wizard will, generally, run whenever the server is launched without detecting the config json. Follow the instructions below to perform this process manually.
76 
77 #### Manual Configuration
78 
79 Create an `appsettings.Production.json` file next to `appsettings.json`. This will override the default settings in appsettings.json with your production settings. There are a few keys meant to be changed by hosts. Modifying any config files while the server is running will trigger a safe restart (Keeps DreamDaemon's running). Note these are all case-sensitive:
80 
81 - `General:MinimumPasswordLength`: Minimum password length requirement for database users
82 
83 - `General:GitHubAccessToken`: Specify a GitHub personal access token with no scopes here to highly mitigate the possiblity of 429 response codes from GitHub requests
84 
85 - `FileLogging:Directory`: Override the default directory where server logs are stored. Default is C:/ProgramData/tgstation-server/logs on Windows, /usr/share/tgstation-server/logs otherwise
86 
87 - `FileLogging:LogLevel`: Can be one of `Trace`, `Debug`, `Information`, `Warning`, `Error`, or `Critical`. Restricts what is put into the log files. Currently `Debug` is reccommended for help with error reporting.
88 
89 - `Kestrel:Endpoints:Http:Url`: The URL (i.e. interface and ports) your application should listen on. General use case should be `http://localhost:<port>` for restricted local connections. See the Remote Access section for configuring public access to the World Wide Web. This doesn't need to be changed using the docker setup and should be mapped with the `-p` option instead
90 
91 - `Database:DatabaseType`: Can be one of `SqlServer`, `MariaDB`, or `MySql`
92 
93 - `Database:MySqlServerVersion`: The version of MySql/MariaDB the database resides on, can be left as null for attempted auto detection. Used by the MySQL/MariaDB provider for selection of [certain features](https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql/blob/2.1.1/src/EFCore.MySql/Storage/Internal/ServerVersion.cs) ignore at your own risk. A string in the form `<major>.<minor>.<patch>`
94 
95 - `Database:ConnectionString`: Connection string for your database. Click [here](https://www.developerfusion.com/tools/sql-connection-string/) for an SQL Server generator or see [here](https://www.connectionstrings.com/mysql/) for a MySQL guide ([You should probably use '127.0.0.1' instead of 'localhost'](https://stackoverflow.com/questions/19712307/mysql-localhost-127-0-0-1)).
96 
97 - `ControlPanel:Enable`: Enable the javascript based control panel to be served from the server via /index.html
98 
99 - `ControlPanel:AllowAnyOrigin`: Set the Access-Control-Allow-Origin header to * for all responses (also enables all headers and methods)
100 
101 - `ControlPanel:AllowedOrigins`: Set the Access-Control-Allow-Origin headers to this list of origins for all responses (also enables all headers and methods). This is overridden by `ControlPanel:AllowAnyOrigin`
102 
103 ### Database Configuration
104 
105 If using a MariaDB/MySQL server, our client library [recommends you set 'utf8mb4' as your default charset](https://github.com/PomeloFoundation/Pomelo.EntityFrameworkCore.MySql#1-recommended-server-charset) disregard at your own risk.
106 
107 The user created for the application will need the privilege to create databases on the first run, do not create the database for it. Once the initial set of migrations is run, the create right may be revoked. The user should maintain DDL rights though for applying future migrations
108 
109 Note that the ratio of application installations to databases is 1:1. Do not attempt to share a database amongst multiple TGS installations. (We know SQLite would be perfect for this, but it does not handle the high level of concurrency the server uses)
110 
111 ### Starting
112 
113 For the Windows service version start the `tgstation-server-4` service. If it fails to start, check the Windows event log under Windows/Application for entries from tgstation-server-4 for errors.
114 
115 For the console version run `dotnet Tgstation.Server.Host.Console.dll` in the installation directory. The `tgs.bat` and `tgs.sh` shell scripts are shortcuts for this. If on Windows, you must do this as admin to give the server permission to install the required DirectX dependency for certain 512 BYOND versions as well as create symlinks.
116 
117 For the docker version run `docker start <your container name>`
118 
119 Test your server is running by visiting the local port in your browser. You should receive a 401 Unauthorized response (You may need to view the developer console). Otherwise an error page will be present.
120 
121 ### Stopping
122 
123 Note that the live detach for DreamDaemon servers is only supported for updates or restarts via the API at this time. Stopping tgstation-server will TERMINATE ALL CHILD DREAMDAEMON SERVERS.
124 
125 For the Windows service version stop the `tgstation-server-4` service
126 
127 For the console version press `Ctrl+C` or send a SIGQUIT to the ORIGINAL dotnet process
128 
129 For the docker version run `docker stop <your container name>`
130 
131 ## Integrating
132 
133 tgstation-server 4 now REQUIRES the DMAPI to be integrated into any BYOND codebase which plans on being used by it. The integration process is a fairly simple set of code changes.
134 
135 1. Copy the [DMAPI](https://github.com/tgstation/tgstation-server/tree/master/src/DMAPI) files anywhere in your code base. `tgs.dm` can be seperated from the `tgs` folder, but do not modify or move the contents of the `tgs` folder
136 2. Modify your `.dme`(s) to include the `tgs.dm` and `tgs/includes.dm` files (ORDER OF APPEARANCE IS MANDATORY)
137 3. Follow the instructions in `tgs.dm` to integrate the API with your codebase.
138 
139 The DMAPI is fully backwards compatible and should function with any tgstation-server version to date. Updates can be performed in the same manner. Using the `TGS_EXTERNAL_CONFIGURATION` is recommended in order to make the process as easy as replacing `tgs.dm` and the `tgs` folder with a newer version
140 
141 ### Example
142 
143 Here is a bare minimum example project that implements the essential code changes for integrating the DMAPI
144 
145 Before `tgs.dm`:
146 ```dm
147 //Remember, every codebase is different, you probably have better methods for these defines than the ones given here
148 #define TGS_EXTERNAL_CONFIGURATION
149 #define TGS_DEFINE_AND_SET_GLOBAL(Name, Value) var/global/##Name = ##Value
150 #define TGS_READ_GLOBAL(Name) global.##Name
151 #define TGS_WRITE_GLOBAL(Name, Value) global.##Name = ##Value
152 #define TGS_WORLD_ANNOUNCE(message) world << ##message
153 #define TGS_INFO_LOG(message) world.log << "TGS Info: [##message]"
154 #define TGS_ERROR_LOG(message) world.log << "TGS Error: [##message]"
155 #define TGS_NOTIFY_ADMINS(event) world.log << "TGS Admin Message: [##event]"
156 #define TGS_CLIENT_COUNT global.client_cout
157 #define TGS_PROTECT_DATUM(Path) // Leave blank if your codebase doesn't give administrators code reflection capabilities
158 ```
159 
160 Anywhere else:
161 ```dm
162 var/global/client_count = 0
163 
164 /world/New()
165  ..()
166  TgsNew()
167  TgsInitializationsComplete()
168 
169 /world/Reboot()
170  TgsReboot()
171  ..()
172 
173 /world/Topic()
174  TGS_TOPIC
175  ..()
176 
177 /client/New()
178  ..()
179  ++global.client_count
180 
181 /client/Del()
182  ..()
183  --global.client_count
184 
185 ```
186 
187 ## Remote Access
188 
189 tgstation-server is an [ASP.Net Core](https://docs.microsoft.com/en-us/aspnet/core/) app based on the Kestrel web server. This section is meant to serve as a general use case overview, but the entire Kestrel configuration can be modified to your liking with the configuration JSON. See [the official documentation](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel) for details.
190 
191 Exposing the builtin Kestrel server to the internet directly over HTTP is highly not reccommended due to the lack of security. The recommended way to expose tgstation-server to the internet is to host it through a reverse proxy with HTTPS support. Here are some step by step examples to achieve this for major web servers.
192 
193 System administrators will most likely have their own configuration plans, but here are some basic guides for beginners.
194 
195 Once complete, test that your configuration worked by visiting your proxy site from a browser on a different computer. You should recieve a 401 Unauthorized response.
196 
197 ### IIS (Reccommended for Windows)
198 
199 1. Acquire an HTTPS certificate. The easiet free way for Windows is [win-acme](https://github.com/PKISharp/win-acme) (requires you to set up the website first)
200 2. Install the [Web Platform Installer](https://www.microsoft.com/web/downloads/platform.aspx)
201 3. Open the web platform installer in the IIS Manager and install the Application Request Routing 3.0 module
202 4. Create a new website, bind it to HTTPS only with your chosen certificate and exposed port. The physical path won't matter since it won't be used. Use `Require Server Name Indication` if you want to limit requests to a specific URL prefix.
203 5. Close and reopen the IIS Manager
204 5. Open the site and navigate to the `URL Rewrite` module
205 6. In the `Actions` Pane on the right click `Add Rule(s)...`
206 7. For the rule template, select `Reverse Proxy` under `Inbound and Outbound Rules` and click `OK`
207 8. You may get a prompt about enabling proxy functionality. Click `OK`
208 9. In the window that appears set the `Inbound Rules` textbox to the URL of your tgstation-server i.e. `http://localhost:5000`. Ensure `Enable SSL Offloading` is checked, then click `OK`
209 
210 ### Caddy (Reccommended for Linux, or those unfamilar with configuring NGINX or Apache)
211 
212 1. Setup a basic website configuration. Instructions on how to do so are out of scope.
213 2. In your Caddyfile, under a server entry, add the following (replace 8080 with the port TGS is hosted on):
214 ```
215 proxy /tgs localhost:8080 {
216  transparent
217 }
218 ```
219 
220 See https://caddyserver.com/docs/proxy
221 
222 ### NGINX (Reccommended for Linux)
223 
224 1. Setup a basic website configuration. Instructions on how to do so are out of scope.
225 2. Acquire an HTTPS certificate, likely via Let's Encrypt, and configure NGINX to use it.
226 3. Setup a path under a server like the following (replace 8080 with the port TGS is hosted on):
227 ```
228 location /tgs {
229  proxy_pass http://127.0.0.1:8080;
230  break;
231 }
232 ```
233 
234 See https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
235 
236 ### Apache
237 
238 1. Ensure the `mod_proxy` extension is installed.
239 2. Setup a basic website configuration. Instructions on how to do so are out of scope.
240 3. Acquire an HTTPS certificate, likely via Let's Encrypt, and configure Apache to use it.
241 4. Under a VirtualHost entry, setup the following (replace 8080 with the port TGS is hosted on):
242 ```
243 ProxyPass / http://127.0.0.1:8080
244 ProxyPassReverse / http://127.0.0.1:8080
245 ```
246 
247 See https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html
248 
249 Example VirtualHost Entry
250 ```
251 <IfModule mod_ssl.c>
252 <VirtualHost *:443>
253  ServerName tgs_subdomain.example.com
254 
255  SSLEngine on
256  SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
257  SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
258 
259  ProxyPass / http://127.0.0.1:8080/
260  ProxyPassReverse / http://127.0.0.1:8080/
261 </VirtualHost>
262 </IfModule>
263 ```
264 
265 ## Usage
266 
267 tgstation-server v4 is controlled via a RESTful HTTP json API. Documentation on this API can be found [here](https://tgstation.github.io/tgstation-server/api.html). This section serves to document the concepts of the server.
268 
269 ### Users
270 
271 All actions apart from logging in must be taken by a user. TGS installs with one default user whose credentials can be found [here](https://github.com/tgstation/tgstation-server/blob/master/src/Tgstation.Server.Api/Models/User.cs). It is recommended to disable this user ASAP as it is used to create Jobs that are started by the system. If access to all users is lost, the default user can be reset using the `Database:ResetAdminPassword` configuration setting.
272 
273 Users can be enabled/disabled and have a very granular set of rights associated to them that determine the actions they are allowed to take (i.e. Modify the user list or create instances). Users can be _database based_ or _system based_. Database users are your standard web users with a username and password. System users, on the otherhand, are authenticated with the host OS. These users cannot have their password or names changed by TGS as they are managed by the system (and in reverse, login tokens don't expire when their password changes). The benefit to having these users is it allows the use of system ACLs for static file control. More on that later.
274 
275 ### Instances
276 
277 A TGS deployment is made up with a set of instances, which each represent a production BYOND server. As many instances as desired can be created. Be aware, however, due to the nature of BYOND, this will quickly result in system resource exhaustion.
278 
279 An instance is stored in a single folder anywhere on a system and is made up of several components: The source code git repository, the BYOND installations, the compiler, the watchdog, chat bots, and static file management systems.
280 
281 ##### Instance Users
282 
283 All users with access to an instance have an InstanceUser object associated with the two that defines more rights specific to that instance (i.e. Deploy code, modify bots, edit other InstanceUsers).
284 
285 #### Repository
286 
287 The `Repository` folder is a git repository containing the code of the game you wish to host. It can be cloned from any public or private remote repository and has capabilities to affect changes back to it. All the standard benefits of git are utilized (i.e. check out any revision or reference).
288 
289 Additional features become available if the remote repository is hosted on https://github.com/. Namely the Test Merge feature, which allows you to take a pull request opened on the repository and compile it into a game deployment for testing. Information about test merges is available in game via the DMAPI and via the main API as well.
290 
291 Manual operations on the repository while an instance is running may lead to git data corruption. Thankfully, it's simple enough to delete and reclone the repository via the API.
292 
293 #### Byond
294 
295 The `Byond` folder contains installations of [BYOND](https://secure.byond.com/) versions. The version which is used by your game code can be changed on a whim (Note that only versions >= 511.1385 have been thouroughly tested. Lower versions should work but if one doesn't function, please open an issue report) and the server will take care of installing it.
296 
297 #### Compiler
298 
299 The compiler deploys code from the `Repository` folder to the `Game` folder and compiles it either by autodetecting the `.dme` or having it set by configuration. Several other step are also run such as validating the DMAPI version and creating symlinks for static files are done at this point. The compiler also applies server side code modifications and duplicates compiled code for the watchdog as well (See following section).
300 
301 #### Watchdog
302 
303 The watchdog is responsible for starting and keeping your server running. It functions by launching two servers which are hot-swapped on `/world/Reboot`s and during crashes to prevent downtime. This hot swapping feature is also what allows TGS to deploy updates to live servers without bringing them down.
304 
305 DreamDaemon can be finicky and will crash with several high load games or bad DM code. The watchdog has several failure prevention methods to keep at least one server running while these issues are sorted out.
306 
307 #### Chat Bots
308 
309 TGS supports creating infinite chat bots for notifying staff or players of things like code deployments and uptime in. Currently the following providers are supported
310 
311 - Internet Relay Chat (IRC)
312 - Discord
313 
314 More can be added by providing a new implementation of the [IProvider](https://github.com/tgstation/tgstation-server/blob/master/src/Tgstation.Server.Host/Components/Chat/Providers/IProvider.cs) interface
315 
316 Bots have a set of built-in commands that can be triggered via `!tgs`, mentioning, or private messaging them. Along with these, custom commands can be defined using the DMAPI by creating a subtype of the `/datum/tgs_chat_command` type (See `tgs.dm` for details). Invocation for custom commands can be restricted to certain channels.
317 
318 #### Static Files
319 
320 All files in game code deployments are considered transient by default, meaning when new code is deployed, changes will be lost. Static files allow you to specify which files and folders stick around throughout all deployments.
321 
322 The `StaticFiles` folder contains 3 root folders which cannot be deleted and operate under special rules
323  - `CodeModifications`
324  - `EventScripts`
325  - `GameStaticFiles`
326 
327 These files can be modified either in host mode or system user mode. In host mode, TGS itself is responsible for reading and writing the files. In system user mode read and write actions are performed using the system account of the logged on User, enabling the use of ACLs to control access to files. Database users will not be able to use the static file system if this mode is configured for an instance.
328 
329 This folder may be freely modified manually just beware this may cause in-progress deployments to error if done on Windows systems.
330 
331 #### CodeModifications
332 
333 When a deployment is made by the compiler, all the contents of this folder are copied over the repository contents. Then one of two code change modes are selected based on the prescense of certain files.
334 
335 If `<target dme>.dm` is present, that .dme will be used instead of the repository's `.dme`
336 
337 Otherwise the files `HeadInclude.dm` and `TailInclude.dm` are searched for and added as include lines to the top and bottom of the target `.dme` repsectively if they exist. These files can contain any valid DreamMaker code (Including `#include`ing other `.dm` files!) allowing you to modify the a repository's code on a per instance basis
338 
339 #### EventScripts
340 
341 This folder can contain anything. But, when certain events occur in the instance, TGS will look here for `.bat` or `.sh` files with the same name and run those with corresponding arguments. List of supported events can be found [here](https://github.com/tgstation/tgstation-server/blob/master/src/Tgstation.Server.Host/Components/StaticFiles/Configuration.cs#L28) (subject to expansion) list of event parameters can be found [here](https://github.com/tgstation/tgstation-server/blob/master/src/Tgstation.Server.Host/Components/EventType.cs)
342 
343 #### GameStaticFiles
344 
345 Any files and folders contained in this root level of this folder will be symbolically linked to all deployments at the time they are created. This allows persistent game data (BYOND `.sav`s or code configuration files for example) to persist across all deployments. This folder contains a .tgsignore file which can be used to prevent symlinks from being generated by entering the names of files and folders (1 per line)
346 
347 ### Updating
348 
349 TGS 4 can self update without stopping your DreamDaemon servers. Any V4 release made to this repository is bound by a contract that allows changes of the runtime assemblies without stopping your servers. Database migrations are automatically applied as well. Because of this REVERTING TO LOWER VERSIONS IS NOT OFFICIALLY SUPPORTED, do so at your own risk (check changes made to `/src/Tgstation.Server.Host/Models/Migrations`).
350 
351 ### Clients
352 
353 Here are tools for interacting with the TGS 4 web API
354 
355 - [Tgstation.Server.ControlPanel](https://github.com/tgstation/Tgstation.Server.ControlPanel): Official client. A cross platform GUI for using tgstation-server
356 - [Tgstation.Server.Client](https://www.nuget.org/packages/Tgstation.Server.Client): A nuget .NET Standard 2.0 TAP based library for communicating with tgstation-server
357 - [Tgstation.Server.Api](https://www.nuget.org/packages/Tgstation.Server.Api): A nuget .NET Standard 2.0 library containing API definitions for tgstation-server
358 - [Postman](https://www.getpostman.com/): This repository contains [TGS.postman_collection.json](https://github.com/tgstation/tgstation-server/blob/master/tools/TGS.postman_collection.json) which is used during development for testing. Contains example requests for all endpoints but takes some knowledge to use (Note that the pre-request script is configured to login the default admin user for every request)
359 
360 Contact project maintainers to get your client added to this list
361 
362 ## Backup/Restore
363 
364 Note that tgstation-server is NOT a backup solution, the onus is on the server runners.
365 
366 The `Repository` folder should, by the nature of git, not need to be backed up or should be done so on the remote server if necessary.
367 
368 The `BYOND` and `Game` folders should never be backed up due.
369 
370 The `Configuration` folder should and database be fully backed up
371 
372 To restore an installation from backups, first restore the instance `Configuration` folders in their new homes. Then restore the database, modifying the `Path` column in the `Instances` table where necessary to point to the new instances. Then start the server pointed at the new database.
373 
374 Should you end up with a lost database for some reason or want to reattach a detached instance you can reattach an existing folder by creating an empty file named `TGS4_ALLOW_INSTANCE_ATTACH` inside it (This is automatically created when detaching instances). Then create a new instance with that path, this will bypass the empty folder check. Note that this will not restore things such as user permissions, server config options, or deployment metadata. Those must be reconfigured manually
375 
376 ## Troubleshooting
377 
378 Feel free to ask for help at the coderbus discord in #tooling-questions: https://discord.gg/Vh8TJp9. Cyberboss#8246 can answer most questions.
379 
380 ## Contributing
381 
382 * See [CONTRIBUTING.md](https://github.com/tgstation/tgstation-server/blob/master/.github/CONTRIBUTING.md)
383 
384 ## Licensing
385 
386 * The DMAPI for the project is licensed under the MIT license.
387 * The /tg/station 13 icon is licensed under [Creative Commons 3.0 BY-SA](http://creativecommons.org/licenses/by-sa/3.0/).
388 * The remainder of the project is licensed under [GNU AGPL v3](http://www.gnu.org/licenses/agpl-3.0.html)
389 
390 See the files in the `/src/DMAPI` tree for the MIT license
- - - - diff --git a/_rate_limit_exception_8cs.html b/_rate_limit_exception_8cs.html index 8919f8d83b..2aaa69f3b1 100644 --- a/_rate_limit_exception_8cs.html +++ b/_rate_limit_exception_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/RateLimitException.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_rate_limit_exception_8cs_source.html b/_rate_limit_exception_8cs_source.html index 91a52a3e45..b33adf71aa 100644 --- a/_rate_limit_exception_8cs_source.html +++ b/_rate_limit_exception_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/RateLimitException.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
RateLimitException.cs
-Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
5 namespace Tgstation.Server.Client
6 {
10  public sealed class RateLimitException : ClientException
11  {
12  DateTimeOffset RetryAfter { get; }
13 
17  public RateLimitException() { }
18 
23  public RateLimitException(string secondsString) : base(new ErrorMessage
24  {
25  Message = "GitHub rate limit reached!",
26  SeverApiVersion = null
27  }, (HttpStatusCode)429)
28  {
29  if (Int32.TryParse(secondsString, out var seconds) && seconds >= 0)
30  RetryAfter = DateTimeOffset.Now.AddSeconds(seconds);
31  else
32  RetryAfter = DateTimeOffset.Now;
33  }
34 
40  public RateLimitException(string message, Exception innerException) : base(message, innerException) { }
41  }
42 }
- -
Occurs when a GitHub rate limit occurs
- -
RateLimitException(string secondsString)
Construct an RateLimitException with a secondsString
+Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
6 {
10  public sealed class RateLimitException : ClientException
11  {
12  DateTimeOffset RetryAfter { get; }
13 
17  public RateLimitException() { }
18 
23  public RateLimitException(string secondsString) : base(new ErrorMessage
24  {
25  Message = "GitHub rate limit reached!",
26  SeverApiVersion = null
27  }, (HttpStatusCode)429)
28  {
29  if (Int32.TryParse(secondsString, out var seconds) && seconds >= 0)
30  RetryAfter = DateTimeOffset.Now.AddSeconds(seconds);
31  else
32  RetryAfter = DateTimeOffset.Now;
33  }
34 
40  public RateLimitException(string message, Exception innerException) : base(message, innerException) { }
41  }
42 }
+ +
Occurs when a GitHub rate limit occurs
+
RateLimitException(string secondsString)
Construct an RateLimitException with a secondsString
-
RateLimitException()
Construct an RateLimitException
- -
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- -
Exceptions thrown by IServerClients
-
RateLimitException(string message, Exception innerException)
Construct an RateLimitException with a message and innerException
+ +
RateLimitException()
Construct an RateLimitException
+ +
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+ +
Exceptions thrown by IServerClients
+
RateLimitException(string message, Exception innerException)
Construct an RateLimitException with a message and innerException
diff --git a/_reattach_info_handler_8cs.html b/_reattach_info_handler_8cs.html index fbdefb62f4..a8614f2d89 100644 --- a/_reattach_info_handler_8cs.html +++ b/_reattach_info_handler_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/ReattachInfoHandler.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_reattach_info_handler_8cs_source.html b/_reattach_info_handler_8cs_source.html index 978325a785..073013cb49 100644 --- a/_reattach_info_handler_8cs_source.html +++ b/_reattach_info_handler_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/ReattachInfoHandler.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
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 
12 namespace Tgstation.Server.Host.Components
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
+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
- - -
string ChatCommandsJson
Path to the chat commands json file
-
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
-
async Task< WatchdogReattachInformation > Load(CancellationToken cancellationToken)
Load a saved WatchdogReattachInformation
-
ReattachInformation Alpha
ReattachInformation for the Alpha session
- -
ushort Port
The port DreamDaemon was last listening on
-
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 ...
-
string ChatChannelsJson
Path to the chat channels json file
- - -
ReattachInformation Bravo
ReattachInformation for the Bravo session
- -
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
- -
string AccessIdentifier
Used to identify and authenticate the DreamDaemon instance
+ +
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
+
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
+
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< 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
+ +
string AccessIdentifier
Used to identify and authenticate the DreamDaemon instance
diff --git a/_reattach_information_base_8cs.html b/_reattach_information_base_8cs.html index 463ec4d147..a961d30ddd 100644 --- a/_reattach_information_base_8cs.html +++ b/_reattach_information_base_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/ReattachInformationBase.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.ReattachInformationBase - Base class for ReattachInformation More...
+ Base class for ReattachInformation More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_reattach_information_base_8cs_source.html b/_reattach_information_base_8cs_source.html index a3ab24010e..75e37f5e80 100644 --- a/_reattach_information_base_8cs_source.html +++ b/_reattach_information_base_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/ReattachInformationBase.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ReattachInformationBase.cs
-Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
3 using System.Globalization;
6 
7 namespace Tgstation.Server.Host.Models
8 {
12  public abstract class ReattachInformationBase : JsonSubFileList
13  {
17  [Required]
18  public string AccessIdentifier { get; set; }
19 
23  public int ProcessId { get; set; }
24 
28  public bool IsPrimary { get; set; }
29 
33  public ushort Port { get; set; }
34 
38  public RebootState RebootState { get; set; }
39 
43  protected ReattachInformationBase() { }
44 
49  protected ReattachInformationBase(ReattachInformationBase copy) : base(copy)
50  {
51  if (copy == null)
52  throw new ArgumentNullException(nameof(copy));
53  AccessIdentifier = copy.AccessIdentifier;
54  IsPrimary = copy.IsPrimary;
55  Port = copy.Port;
56  ProcessId = copy.ProcessId;
57  RebootState = copy.RebootState;
58  }
59 
61  public override string ToString() => String.Format(CultureInfo.InvariantCulture, "Process ID: {3}, Access Identifier {4}, Primary: {0}, RebootState: {1}, Port: {2}", IsPrimary, RebootState, Port, ProcessId, AccessIdentifier);
62  }
63 }
ReattachInformationBase()
Construct a ReattachInformationBase
+Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
3 using System.Globalization;
6 
8 {
12  public abstract class ReattachInformationBase : JsonSubFileList
13  {
17  [Required]
18  public string AccessIdentifier { get; set; }
19 
23  public int ProcessId { get; set; }
24 
28  public bool IsPrimary { get; set; }
29 
33  public ushort Port { get; set; }
34 
38  public RebootState RebootState { get; set; }
39 
43  protected ReattachInformationBase() { }
44 
49  protected ReattachInformationBase(ReattachInformationBase copy) : base(copy)
50  {
51  if (copy == null)
52  throw new ArgumentNullException(nameof(copy));
54  IsPrimary = copy.IsPrimary;
55  Port = copy.Port;
56  ProcessId = copy.ProcessId;
57  RebootState = copy.RebootState;
58  }
59 
61  public override string ToString() => String.Format(CultureInfo.InvariantCulture, "Process ID: {3}, Access Identifier {4}, Primary: {0}, RebootState: {1}, Port: {2}", IsPrimary, RebootState, Port, ProcessId, AccessIdentifier);
62  }
63 }
ReattachInformationBase()
Construct a ReattachInformationBase
-
ReattachInformationBase(ReattachInformationBase copy)
Construct a ReattachInformationBase from a given copy
- - -
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 ...
+
ReattachInformationBase(ReattachInformationBase copy)
Construct a ReattachInformationBase from a given copy
+ + +
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
- - - -
RebootState RebootState
The current DreamDaemon reboot state
- -
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
- -
string AccessIdentifier
Used to identify and authenticate the DreamDaemon instance
+ + + +
RebootState RebootState
The current DreamDaemon reboot state
+ +
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
+ +
string AccessIdentifier
Used to identify and authenticate the DreamDaemon instance
diff --git a/_reboot_state_8cs.html b/_reboot_state_8cs.html index 90034e5519..c2362a264e 100644 --- a/_reboot_state_8cs.html +++ b/_reboot_state_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/RebootState.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Host +  +namespace  Tgstation.Server.Host.Components +  namespace  Tgstation.Server.Host.Components.Watchdog   @@ -108,8 +95,8 @@ Enumerations - + } +
enum  Tgstation.Server.Host.Components.Watchdog.RebootState : int { Tgstation.Server.Host.Components.Watchdog.RebootState.Normal = 0, Tgstation.Server.Host.Components.Watchdog.RebootState.Shutdown = 1, Tgstation.Server.Host.Components.Watchdog.RebootState.Restart = 2 - }
 Represents the action to take when /world/Reboot() is called More...
 Represents the action to take when /world/Reboot() is called More...
 
@@ -117,7 +104,7 @@ Enumerations diff --git a/_reboot_state_8cs_source.html b/_reboot_state_8cs_source.html index 2a276e22e4..5c11f2c649 100644 --- a/_reboot_state_8cs_source.html +++ b/_reboot_state_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/RebootState.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
RebootState.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Host.Components.Watchdog
2 {
6  public enum RebootState : int
7  {
11  Normal = 0,
12 
16  Shutdown = 1,
17 
21  Restart = 2
22  }
23 }
Run DreamDaemon&#39;s normal reboot process
- -
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
- +Go to the documentation of this file.
2 {
6  public enum RebootState : int
7  {
11  Normal = 0,
12 
16  Shutdown = 1,
17 
21  Restart = 2
22  }
23 }
+ +
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
diff --git a/_release_notes_8_assembly_info_8cs.html b/_release_notes_8_assembly_info_8cs.html index 638a7353fc..90ae4f85dc 100644 --- a/_release_notes_8_assembly_info_8cs.html +++ b/_release_notes_8_assembly_info_8cs.html @@ -1,19 +1,17 @@ - + - -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 - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -99,7 +78,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_release_notes_8_assembly_info_8cs_source.html b/_release_notes_8_assembly_info_8cs_source.html index 2af530f94b..4cfe3e21d0 100644 --- a/_release_notes_8_assembly_info_8cs_source.html +++ b/_release_notes_8_assembly_info_8cs_source.html @@ -1,19 +1,17 @@ - + - -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 - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,13 +71,12 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
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 
diff --git a/_repository_client_8cs.html b/_repository_client_8cs.html index d6e426d02a..2c2fb428d3 100644 --- a/_repository_client_8cs.html +++ b/_repository_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/RepositoryClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_repository_client_8cs_source.html b/_repository_client_8cs_source.html index c43edc0441..1f3200ae9e 100644 --- a/_repository_client_8cs_source.html +++ b/_repository_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components/RepositoryClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
RepositoryClient.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 using Tgstation.Server.Api;
6 
7 namespace Tgstation.Server.Client.Components
8 {
11  {
16 
20  readonly Instance instance;
21 
27  public RepositoryClient(IApiClient apiClient, Instance instance)
28  {
29  this.apiClient = apiClient;
30  this.instance = instance;
31  }
32 
34  public Task<Repository> Clone(Repository repository, CancellationToken cancellationToken) => apiClient.Create<Repository, Repository>(Routes.Repository, repository, instance.Id, cancellationToken);
35 
37  public Task<Repository> Delete(CancellationToken cancellationToken) => apiClient.Delete<Repository>(Routes.Repository, instance.Id, cancellationToken);
38 
40  public Task<Repository> Read(CancellationToken cancellationToken) => apiClient.Read<Repository>(Routes.Repository, instance.Id, cancellationToken);
41 
43  public Task<Repository> Update(Repository repository, CancellationToken cancellationToken) => apiClient.Update<Repository, Repository>(Routes.Repository, repository ?? throw new ArgumentNullException(nameof(repository)), instance.Id, cancellationToken);
44  }
45 }
- - - -
readonly Instance instance
The Instance for the RepositoryClient
+Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 using Tgstation.Server.Api;
6 
8 {
11  {
16 
20  readonly Instance instance;
21 
28  {
29  this.apiClient = apiClient;
30  this.instance = instance;
31  }
32 
34  public Task<Repository> Clone(Repository repository, CancellationToken cancellationToken) => apiClient.Create<Repository, Repository>(Routes.Repository, repository, instance.Id, cancellationToken);
35 
37  public Task<Repository> Delete(CancellationToken cancellationToken) => apiClient.Delete<Repository>(Routes.Repository, instance.Id, cancellationToken);
38 
40  public Task<Repository> Read(CancellationToken cancellationToken) => apiClient.Read<Repository>(Routes.Repository, instance.Id, cancellationToken);
41 
43  public Task<Repository> Update(Repository repository, CancellationToken cancellationToken) => apiClient.Update<Repository, Repository>(Routes.Repository, repository ?? throw new ArgumentNullException(nameof(repository)), instance.Id, cancellationToken);
44  }
45 }
Task< Repository > Read(CancellationToken cancellationToken)
Get the Repository represented by the IRepositoryClient
+ + +
Task< Repository > Repository(Routes.Repository, repository, instance.Id, cancellationToken)
+
readonly Instance instance
The Instance for the RepositoryClient
+
Task< Repository > Delete(CancellationToken cancellationToken)
Deletes the Repository
-
Routes to a server actions
Definition: Routes.cs:9
+
Routes to a server actions
Definition: Routes.cs:9
+ -
Represents a git repository
Definition: Repository.cs:8
-
const string Repository
The Models.Repository controller
Definition: Routes.cs:39
-
Metadata about a server instance
Definition: Instance.cs:9
-
readonly IApiClient apiClient
The IApiClient for the RepositoryClient
- -
RepositoryClient(IApiClient apiClient, Instance instance)
Construct a RepositoryClient
-
Web interface for the API
Definition: IApiClient.cs:11
- +
Represents a git repository
Definition: Repository.cs:8
+
const string Repository
The Models.Repository controller
Definition: Routes.cs:39
+
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
+
Task< Repository > Clone(Repository repository, CancellationToken cancellationToken)
Clones a repository
+
Metadata about a server instance
Definition: Instance.cs:9
+
Task< Repository > Update(Repository repository, CancellationToken cancellationToken)
Update the Repository
+
readonly IApiClient apiClient
The IApiClient for the RepositoryClient
+
Task Delete(string route, CancellationToken cancellationToken)
Run an HTTP DELETE request
+ +
RepositoryClient(IApiClient apiClient, Instance instance)
Construct a RepositoryClient
+
Web interface for the API
Definition: IApiClient.cs:11
+
diff --git a/_repository_controller_8cs.html b/_repository_controller_8cs.html index 2afc6cb02e..b35029be86 100644 --- a/_repository_controller_8cs.html +++ b/_repository_controller_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/RepositoryController.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Controllers
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_repository_controller_8cs_source.html b/_repository_controller_8cs_source.html index bc0ca11fd6..6514b47fac 100644 --- a/_repository_controller_8cs_source.html +++ b/_repository_controller_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/RepositoryController.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
RepositoryController.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.EntityFrameworkCore;
3 using Microsoft.Extensions.Logging;
4 using Microsoft.Extensions.Options;
5 using System;
6 using System.Collections.Generic;
7 using System.Globalization;
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;
22 
23 namespace Tgstation.Server.Host.Controllers
24 {
28  [Route(Routes.Repository)]
29  #pragma warning disable CA1506 // TODO: Decomplexify
30  public sealed class RepositoryController : ModelController<Repository>
31  {
36 
41 
46 
51 
62  public RepositoryController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, IGitHubClientFactory gitHubClientFactory, IJobManager jobManager, ILogger<RepositoryController> logger, IOptions<GeneralConfiguration> generalConfigurationOptions) : base(databaseContext, authenticationContextFactory, logger, true)
63  {
64  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
65  this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
66  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
67  generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
68  }
69 
70  async Task<bool> LoadRevisionInformation(Components.Repository.IRepository repository, IDatabaseContext databaseContext, Models.Instance instance, string lastOriginCommitSha, Action<Models.RevisionInformation> revInfoSink, CancellationToken cancellationToken)
71  {
72  var repoSha = repository.Head;
73 
74  IQueryable<Models.RevisionInformation> ApplyQuery(IQueryable<Models.RevisionInformation> query) => query
75  .Where(x => x.CommitSha == repoSha && x.Instance.Id == instance.Id)
76  .Include(x => x.CompileJobs)
77  .Include(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).ThenInclude(x => x.MergedBy);
78 
79  var revisionInfo = await ApplyQuery(databaseContext.RevisionInformations).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
80 
81  if (revisionInfo == default)
82  revisionInfo = databaseContext.RevisionInformations.Local.Where(x => x.CommitSha == repoSha && x.Instance.Id == instance.Id).FirstOrDefault();
83 
84  var needsDbUpdate = revisionInfo == default;
85  if (needsDbUpdate)
86  {
87  // needs insertion
88  revisionInfo = new Models.RevisionInformation
89  {
90  Instance = instance,
91  CommitSha = repoSha,
92  CompileJobs = new List<Models.CompileJob>(),
93  ActiveTestMerges = new List<RevInfoTestMerge>() // non null vals for api returns
94  };
95 
96  lock (databaseContext) // cleaner this way
97  databaseContext.RevisionInformations.Add(revisionInfo);
98  }
99 
100  revisionInfo.OriginCommitSha = revisionInfo.OriginCommitSha ?? lastOriginCommitSha;
101  if (revisionInfo.OriginCommitSha == null)
102  {
103  revisionInfo.OriginCommitSha = repoSha;
104  Logger.LogWarning(Components.Repository.Repository.OriginTrackingErrorTemplate, repoSha);
105  }
106 
107  revInfoSink?.Invoke(revisionInfo);
108  return needsDbUpdate;
109  }
110 
111  async Task<bool> PopulateApi(Repository model, Components.Repository.IRepository repository, IDatabaseContext databaseContext, Models.Instance instance, CancellationToken cancellationToken)
112  {
113  if (repository.IsGitHubRepository)
114  {
115  model.GitHubOwner = repository.GitHubOwner;
116  model.GitHubName = repository.GitHubRepoName;
117  }
118 
119  model.Origin = repository.Origin;
120  model.Reference = repository.Reference;
121 
122  // rev info stuff
123  Models.RevisionInformation revisionInfo = null;
124  var needsDbUpdate = await LoadRevisionInformation(repository, databaseContext, instance, null, x => revisionInfo = x, cancellationToken).ConfigureAwait(false);
125  model.RevisionInformation = revisionInfo.ToApi();
126  return needsDbUpdate;
127  }
128 
130  [TgsAuthorize(RepositoryRights.SetOrigin)]
131  public override async Task<IActionResult> Create([FromBody] Repository model, CancellationToken cancellationToken)
132  {
133  if (model == null)
134  throw new ArgumentNullException(nameof(model));
135 
136  if (model.Origin == null)
137  return BadRequest(new ErrorMessage { Message = "Missing repo origin!" });
138 
139  if (model.AccessUser == null ^ model.AccessToken == null)
140  return BadRequest(new ErrorMessage { Message = "Either both accessToken and accessUser must be present or neither!" });
141 
142  var currentModel = await DatabaseContext.RepositorySettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
143 
144  if (currentModel == default)
145  return StatusCode((int)HttpStatusCode.Gone);
146 
147  // normalize github urls
148  const string BadGitHubUrl = "://www.github.com/";
149  var uiOrigin = model.Origin.ToUpperInvariant();
150  var uiBad = BadGitHubUrl.ToUpperInvariant();
151  var uiGitHub = Components.Repository.Repository.GitHubUrl.ToUpperInvariant();
152  if (uiOrigin.Contains(uiBad, StringComparison.Ordinal))
153  model.Origin = uiOrigin.Replace(uiBad, uiGitHub, StringComparison.Ordinal);
154 
155  currentModel.AccessToken = model.AccessToken;
156  currentModel.AccessUser = model.AccessUser; // intentionally only these fields, user not allowed to change anything else atm
157  var cloneBranch = model.Reference;
158  var origin = model.Origin;
159 
160  var repoManager = instanceManager.GetInstance(Instance).RepositoryManager;
161 
162  if (repoManager.CloneInProgress)
163  return Conflict(new ErrorMessage
164  {
165  Message = "A clone operation is in progress!"
166  });
167 
168  if(repoManager.InUse)
169  return Conflict(new ErrorMessage
170  {
171  Message = "The repo is busy!"
172  });
173 
174  using (var repo = await repoManager.LoadRepository(cancellationToken).ConfigureAwait(false))
175  {
176  // clone conflict
177  if (repo != null)
178  return Conflict(new ErrorMessage
179  {
180  Message = "The repository already exists!"
181  });
182 
183  var job = new Models.Job
184  {
185  Description = String.Format(CultureInfo.InvariantCulture, "Clone branch {1} of repository {0}", origin, cloneBranch ?? "master"),
186  StartedBy = AuthenticationContext.User,
187  CancelRightsType = RightsType.Repository,
188  CancelRight = (ulong)RepositoryRights.CancelClone,
190  };
191  var api = currentModel.ToApi();
192  await jobManager.RegisterOperation(job, async (paramJob, databaseContext, progressReporter, ct) =>
193  {
194  using (var repos = await repoManager.CloneRepository(new Uri(origin), cloneBranch, currentModel.AccessUser, currentModel.AccessToken, progressReporter, ct).ConfigureAwait(false))
195  {
196  if (repos == null)
197  throw new JobException("Filesystem conflict while cloning repository!");
198  var instance = new Models.Instance
199  {
200  Id = Instance.Id
201  };
202  databaseContext.Instances.Attach(instance);
203  if (await PopulateApi(api, repos, databaseContext, instance, ct).ConfigureAwait(false))
204  await databaseContext.Save(ct).ConfigureAwait(false);
205  }
206  }, cancellationToken).ConfigureAwait(false);
207 
208  api.Origin = model.Origin;
209  api.Reference = model.Reference;
210  api.ActiveJob = job.ToApi();
211 
212  return StatusCode((int)HttpStatusCode.Created, api);
213  }
214  }
215 
221  [TgsAuthorize(RepositoryRights.Delete)]
222  public async Task<IActionResult> Delete(CancellationToken cancellationToken)
223  {
224  var currentModel = await DatabaseContext.RepositorySettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
225 
226  if (currentModel == default)
227  return StatusCode((int)HttpStatusCode.Gone);
228 
229  currentModel.AccessToken = null;
230  currentModel.AccessUser = null;
231 
232  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
233 
234  Logger.LogInformation("Instance {0} repository delete initiated by user {1}", Instance.Id, AuthenticationContext.User.Id);
235 
236  var job = new Models.Job
237  {
238  Description = "Delete repository",
239  StartedBy = AuthenticationContext.User,
241  };
242  var api = currentModel.ToApi();
243  await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressReporter, ct) => instanceManager.GetInstance(Instance).RepositoryManager.DeleteRepository(cancellationToken), cancellationToken).ConfigureAwait(false);
244  api.ActiveJob = job.ToApi();
245  return Accepted(api);
246  }
247 
249  [TgsAuthorize(RepositoryRights.Read)]
250  public override async Task<IActionResult> Read(CancellationToken cancellationToken)
251  {
252  var currentModel = await DatabaseContext.RepositorySettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
253 
254  if (currentModel == default)
255  return StatusCode((int)HttpStatusCode.Gone);
256 
257  var api = currentModel.ToApi();
258  var repoManager = instanceManager.GetInstance(Instance).RepositoryManager;
259 
260  if (repoManager.CloneInProgress)
261  return Conflict(new ErrorMessage
262  {
263  Message = "A clone operation is in progress!"
264  });
265 
266  if (repoManager.InUse)
267  return Conflict(new ErrorMessage
268  {
269  Message = "The repo is busy!"
270  });
271 
272  using (var repo = await repoManager.LoadRepository(cancellationToken).ConfigureAwait(false))
273  {
274  if (repo != null && await PopulateApi(api, repo, DatabaseContext, Instance, cancellationToken).ConfigureAwait(false))
275  {
276  // user may have fucked with the repo without telling us, do what we can
277  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
278  return StatusCode((int)HttpStatusCode.Created, api);
279  }
280 
281  return Json(api);
282  }
283  }
284 
286  [TgsAuthorize(RepositoryRights.ChangeAutoUpdateSettings | RepositoryRights.ChangeCommitter | RepositoryRights.ChangeCredentials | RepositoryRights.ChangeTestMergeCommits | RepositoryRights.MergePullRequest | RepositoryRights.SetReference | RepositoryRights.SetSha | RepositoryRights.UpdateBranch)]
287  #pragma warning disable CA1502 // TODO: Decomplexify
288  #pragma warning disable CA1505
289  public override async Task<IActionResult> Update([FromBody]Repository model, CancellationToken cancellationToken)
290  {
291  if (model == null)
292  throw new ArgumentNullException(nameof(model));
293 
294  if (model.AccessUser == null ^ model.AccessToken == null)
295  return BadRequest(new ErrorMessage { Message = "Either both accessToken and accessUser must be present or neither!" });
296 
297  if (model.CheckoutSha != null && model.Reference != null)
298  return BadRequest(new ErrorMessage { Message = "Only one of sha or reference may be specified!" });
299 
300  if (model.CheckoutSha != null && model.UpdateFromOrigin == true)
301  return BadRequest(new ErrorMessage { Message = "Cannot update a reference when checking out a sha!" });
302 
303  if (model.Origin != null)
304  return BadRequest(new ErrorMessage { Message = "origin cannot be modified without deleting the repository!" });
305 
306  if (model.NewTestMerges?.Any(x => !x.Number.HasValue) == true)
307  return BadRequest(new ErrorMessage { Message = "All new test merges must provide a number!" });
308 
309  if (model.NewTestMerges?.Any(x => model.NewTestMerges.Any(y => x != y && x.Number == y.Number)) == true)
310  return BadRequest(new ErrorMessage { Message = "Cannot test merge the same PR twice in one job!" });
311 
312  if (model.CommitterName?.Length == 0)
313  return BadRequest(new ErrorMessage { Message = "Cannot set empty committer name!" });
314 
315  if (model.CommitterEmail?.Length == 0)
316  return BadRequest(new ErrorMessage { Message = "Cannot set empty committer e=mail!" });
317 
318  var newTestMerges = model.NewTestMerges != null && model.NewTestMerges.Count > 0;
319  var userRights = (RepositoryRights)AuthenticationContext.GetRight(RightsType.Repository);
320  if (newTestMerges && !userRights.HasFlag(RepositoryRights.MergePullRequest))
321  return Forbid();
322 
323  var currentModel = await DatabaseContext.RepositorySettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
324 
325  if (currentModel == default)
326  return StatusCode((int)HttpStatusCode.Gone);
327 
328  bool CheckModified<T>(Expression<Func<Api.Models.Internal.RepositorySettings, T>> expression, RepositoryRights requiredRight)
329  {
330  var memberSelectorExpression = (MemberExpression)expression.Body;
331  var property = (PropertyInfo)memberSelectorExpression.Member;
332 
333  var newVal = property.GetValue(model);
334  if (newVal == null)
335  return false;
336  if (!userRights.HasFlag(requiredRight) && property.GetValue(currentModel) != newVal)
337  return true;
338 
339  property.SetValue(currentModel, newVal);
340  return false;
341  }
342 
343  if (CheckModified(x => x.AccessToken, RepositoryRights.ChangeCredentials)
344  || CheckModified(x => x.AccessUser, RepositoryRights.ChangeCredentials)
345  || CheckModified(x => x.AutoUpdatesKeepTestMerges, RepositoryRights.ChangeAutoUpdateSettings)
346  || CheckModified(x => x.AutoUpdatesSynchronize, RepositoryRights.ChangeAutoUpdateSettings)
347  || CheckModified(x => x.CommitterEmail, RepositoryRights.ChangeCommitter)
348  || CheckModified(x => x.CommitterName, RepositoryRights.ChangeCommitter)
349  || CheckModified(x => x.PushTestMergeCommits, RepositoryRights.ChangeTestMergeCommits)
350  || CheckModified(x => x.ShowTestMergeCommitters, RepositoryRights.ChangeTestMergeCommits)
351  || CheckModified(x => x.PostTestMergeComment, RepositoryRights.ChangeTestMergeCommits)
352  || (model.UpdateFromOrigin == true && !userRights.HasFlag(RepositoryRights.UpdateBranch)))
353  return Forbid();
354 
355  if (currentModel.AccessToken?.Length == 0 && currentModel.AccessUser?.Length == 0)
356  {
357  // setting an empty string clears everything
358  currentModel.AccessUser = null;
359  currentModel.AccessToken = null;
360  }
361 
362  var canRead = userRights.HasFlag(RepositoryRights.Read);
363 
364  var api = canRead ? currentModel.ToApi() : new Repository();
365  var repoManager = instanceManager.GetInstance(Instance).RepositoryManager;
366 
367  if (canRead)
368  {
369  if (repoManager.CloneInProgress)
370  return Conflict(new ErrorMessage
371  {
372  Message = "A clone operation is in progress!"
373  });
374 
375  if (repoManager.InUse)
376  return Conflict(new ErrorMessage
377  {
378  Message = "The repo is busy!"
379  });
380 
381  using (var repo = await repoManager.LoadRepository(cancellationToken).ConfigureAwait(false))
382  {
383  if (repo == null)
384  return Conflict(new ErrorMessage
385  {
386  Message = "Repository could not be loaded!"
387  });
388  await PopulateApi(api, repo, DatabaseContext, Instance, cancellationToken).ConfigureAwait(false);
389  }
390  }
391 
392  // this is just db stuf so stow it away
393  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
394 
395  // format the job description
396  string description = null;
397  if (model.UpdateFromOrigin == true)
398  if (model.Reference != null)
399  description = String.Format(CultureInfo.InvariantCulture, "Fetch and hard reset repository to origin/{0}", model.Reference);
400  else if (model.CheckoutSha != null)
401  description = String.Format(CultureInfo.InvariantCulture, "Fetch and checkout {0} in repository", model.CheckoutSha);
402  else
403  description = "Pull current repository reference";
404  else if (model.Reference != null || model.CheckoutSha != null)
405  description = String.Format(CultureInfo.InvariantCulture, "Checkout repository {0} {1}", model.Reference != null ? "reference" : "SHA", model.Reference ?? model.CheckoutSha);
406 
407  if (newTestMerges)
408  description = String.Format(CultureInfo.InvariantCulture, "{0}est merge pull request(s) {1}{2}",
409  description != null ? String.Format(CultureInfo.InvariantCulture, "{0} and t", description) : "T",
410  String.Join(", ", model.NewTestMerges.Select(x =>
411  String.Format(CultureInfo.InvariantCulture, "#{0}{1}", x.Number,
412  x.PullRequestRevision != null ? String.Format(CultureInfo.InvariantCulture, " at {0}", x.PullRequestRevision.Substring(0, 7)) : String.Empty))),
413  description != null ? String.Empty : " in repository");
414 
415  if (description == null)
416  return Json(api); // no git changes
417 
418  var job = new Models.Job
419  {
420  Description = description,
421  StartedBy = AuthenticationContext.User,
422  Instance = Instance,
423  CancelRightsType = RightsType.Repository,
424  CancelRight = (ulong)RepositoryRights.CancelPendingChanges,
425  };
426 
427  await jobManager.RegisterOperation(job, async (paramJob, databaseContext, progressReporter, ct) =>
428  {
429  using (var repo = await repoManager.LoadRepository(ct).ConfigureAwait(false))
430  {
431  if (repo == null)
432  throw new JobException("Repository could not be loaded!");
433 
434  var modelHasShaOrReference = model.CheckoutSha != null || model.Reference != null;
435 
436  var startReference = repo.Reference;
437  var startSha = repo.Head;
438  string postUpdateSha = null;
439 
440  if (newTestMerges && !repo.IsGitHubRepository)
441  throw new JobException("Cannot test merge on a non GitHub based repository!");
442 
443  var committerName = currentModel.ShowTestMergeCommitters.Value ? AuthenticationContext.User.Name : currentModel.CommitterName;
444 
445  var hardResettingToOriginReference = model.UpdateFromOrigin == true && model.Reference != null;
446 
447  var numSteps = (model.NewTestMerges?.Count ?? 0) + (model.UpdateFromOrigin == true ? 1 : 0) + (!modelHasShaOrReference ? 2 : (hardResettingToOriginReference ? 3 : 1));
448  var doneSteps = 0;
449 
450  Action<int> NextProgressReporter()
451  {
452  var tmpDoneSteps = doneSteps;
453  ++doneSteps;
454  return progress => progressReporter((progress + (100 * tmpDoneSteps)) / numSteps);
455  }
456 
457  progressReporter(0);
458 
459  // get a base line for where we are
460  Models.RevisionInformation lastRevisionInfo = null;
461 
462  var attachedInstance = new Models.Instance
463  {
464  Id = Instance.Id
465  };
466  databaseContext.Instances.Attach(attachedInstance);
467 
468  await LoadRevisionInformation(repo, databaseContext, attachedInstance, null, x => lastRevisionInfo = x, ct).ConfigureAwait(false);
469 
470  // apply new rev info, tracking applied test merges
471  async Task UpdateRevInfo()
472  {
473  var last = lastRevisionInfo;
474  await LoadRevisionInformation(repo, databaseContext, attachedInstance, last.OriginCommitSha, x => lastRevisionInfo = x, ct).ConfigureAwait(false);
475  lastRevisionInfo.ActiveTestMerges.AddRange(last.ActiveTestMerges);
476  }
477 
478  try
479  {
480  // fetch/pull
481  if (model.UpdateFromOrigin == true)
482  {
483  if (!repo.Tracking)
484  throw new JobException("Not on an updatable reference!");
485  await repo.FetchOrigin(currentModel.AccessUser, currentModel.AccessToken, NextProgressReporter(), ct).ConfigureAwait(false);
486  doneSteps = 1;
487  if (!modelHasShaOrReference)
488  {
489  var fastForward = await repo.MergeOrigin(committerName, currentModel.CommitterEmail, NextProgressReporter(), ct).ConfigureAwait(false);
490  if (!fastForward.HasValue)
491  throw new JobException("Merge conflict occurred during origin update!");
492  await UpdateRevInfo().ConfigureAwait(false);
493  if (fastForward.Value)
494  {
495  lastRevisionInfo.OriginCommitSha = repo.Head;
496  await repo.Sychronize(currentModel.AccessUser, currentModel.AccessToken, currentModel.CommitterName, currentModel.CommitterEmail, NextProgressReporter(), true, ct).ConfigureAwait(false);
497  postUpdateSha = repo.Head;
498  }
499  else
500  NextProgressReporter()(100);
501  }
502  }
503 
504  // checkout/hard reset
505  if (modelHasShaOrReference)
506  {
507  if ((model.CheckoutSha != null && repo.Head.ToUpperInvariant().StartsWith(model.CheckoutSha.ToUpperInvariant(), StringComparison.Ordinal))
508  || (model.Reference != null && repo.Reference.ToUpperInvariant() != model.Reference.ToUpperInvariant()))
509  {
510  var committish = model.CheckoutSha ?? model.Reference;
511  var isSha = await repo.IsSha(committish, cancellationToken).ConfigureAwait(false);
512 
513  if ((isSha && model.Reference != null) || (!isSha && model.CheckoutSha != null))
514  throw new JobException("Attempted to checkout a SHA or reference that was actually the opposite!");
515 
516  await repo.CheckoutObject(committish, NextProgressReporter(), ct).ConfigureAwait(false);
517  await LoadRevisionInformation(repo, databaseContext, attachedInstance, null, x => lastRevisionInfo = x, ct).ConfigureAwait(false); // we've either seen origin before or what we're checking out is on origin
518  }
519  else
520  NextProgressReporter()(100);
521 
522  if (hardResettingToOriginReference)
523  {
524  if (!repo.Tracking)
525  throw new JobException("Checked out reference does not track a remote object!");
526  await repo.ResetToOrigin(NextProgressReporter(), ct).ConfigureAwait(false);
527  await repo.Sychronize(currentModel.AccessUser, currentModel.AccessToken, currentModel.CommitterName, currentModel.CommitterEmail, NextProgressReporter(), true, ct).ConfigureAwait(false);
528  await LoadRevisionInformation(repo, databaseContext, attachedInstance, null, x => lastRevisionInfo = x, ct).ConfigureAwait(false);
529 
530  // repo head is on origin so force this
531  // will update the db if necessary
532  lastRevisionInfo.OriginCommitSha = repo.Head;
533  }
534  }
535 
536  // test merging
537  Dictionary<int, Octokit.PullRequest> prMap = null;
538  if (newTestMerges)
539  {
540  // bit of sanitization
541  foreach (var I in model.NewTestMerges.Where(x => String.IsNullOrWhiteSpace(x.PullRequestRevision)))
542  I.PullRequestRevision = null;
543 
544  var gitHubClient = currentModel.AccessToken != null
545  ? gitHubClientFactory.CreateClient(currentModel.AccessToken)
546  : (String.IsNullOrEmpty(generalConfiguration.GitHubAccessToken)
547  ? gitHubClientFactory.CreateClient()
548  : gitHubClientFactory.CreateClient(generalConfiguration.GitHubAccessToken));
549 
550  var repoOwner = repo.GitHubOwner;
551  var repoName = repo.GitHubRepoName;
552 
553  // optimization: if we've already merged these exact same commits in this fashion before, just find the rev info for it and check it out
554  Models.RevisionInformation revInfoWereLookingFor = null;
555  bool needToApplyRemainingPrs = true;
556  if (lastRevisionInfo.OriginCommitSha == lastRevisionInfo.CommitSha)
557  {
558  // In order for this to work though we need the shas of all the commits
559  if (model.NewTestMerges.Any(x => x.PullRequestRevision == null))
560  prMap = new Dictionary<int, Octokit.PullRequest>();
561 
562  bool cantSearch = false;
563  foreach (var I in model.NewTestMerges)
564  {
565  if (I.PullRequestRevision != null)
566 #pragma warning disable CA1308 // Normalize strings to uppercase
567  I.PullRequestRevision = I.PullRequestRevision?.ToLowerInvariant(); // ala libgit2
568 #pragma warning restore CA1308 // Normalize strings to uppercase
569  else
570  try
571  {
572  // retrieve the latest sha
573  var pr = await gitHubClient.PullRequest.Get(repoOwner, repoName, I.Number.Value).ConfigureAwait(false);
574  prMap.Add(I.Number.Value, pr);
575  I.PullRequestRevision = pr.Head.Sha;
576  }
577  catch
578  {
579  cantSearch = true;
580  break;
581  }
582  }
583 
584  if (!cantSearch)
585  {
586  var dbPull = await databaseContext.RevisionInformations
587  .Where(x => x.Instance.Id == Instance.Id
588  && x.OriginCommitSha == lastRevisionInfo.OriginCommitSha
589  && x.ActiveTestMerges.Count <= model.NewTestMerges.Count
590  && x.ActiveTestMerges.Count > 0)
591  .Include(x => x.ActiveTestMerges)
592  .ThenInclude(x => x.TestMerge)
593  .ToListAsync(cancellationToken).ConfigureAwait(false);
594 
595  // split here cause this bit has to be done locally
596  revInfoWereLookingFor = dbPull
597  .Where(x => x.ActiveTestMerges.Count == model.NewTestMerges.Count
598  && x.ActiveTestMerges.Select(y => y.TestMerge)
599  .All(y => model.NewTestMerges.Any(z =>
600  y.Number == z.Number
601  && y.PullRequestRevision.StartsWith(z.PullRequestRevision, StringComparison.Ordinal)
602  && (y.Comment?.Trim().ToUpperInvariant() == z.Comment?.Trim().ToUpperInvariant() || z.Comment == null))))
603  .FirstOrDefault();
604 
605  if (revInfoWereLookingFor == null && model.NewTestMerges.Count > 1)
606  {
607  // okay try to add at least SOME prs we've seen before
608  var search = model.NewTestMerges.ToList();
609 
610  var appliedTestMergeIds = new List<long>();
611 
612  Models.RevisionInformation lastGoodRevInfo = null;
613  do
614  {
615  foreach (var I in search)
616  {
617  revInfoWereLookingFor = dbPull
618  .Where(x => model.NewTestMerges.Any(z =>
619  x.PrimaryTestMerge.Number == z.Number
620  && x.PrimaryTestMerge.PullRequestRevision.StartsWith(z.PullRequestRevision, StringComparison.Ordinal)
621  && (x.PrimaryTestMerge.Comment?.Trim().ToUpperInvariant() == z.Comment?.Trim().ToUpperInvariant() || z.Comment == null))
622  && x.ActiveTestMerges.Select(y => y.TestMerge).All(y => appliedTestMergeIds.Contains(y.Id)))
623  .FirstOrDefault();
624 
625  if (revInfoWereLookingFor != null)
626  {
627  lastGoodRevInfo = revInfoWereLookingFor;
628  appliedTestMergeIds.Add(revInfoWereLookingFor.PrimaryTestMerge.Id);
629  search.Remove(I);
630  break;
631  }
632  }
633  }
634  while (revInfoWereLookingFor != null && search.Count > 0);
635 
636  revInfoWereLookingFor = lastGoodRevInfo;
637  needToApplyRemainingPrs = search.Count != 0;
638  if (needToApplyRemainingPrs)
639  model.NewTestMerges = search;
640  }
641  else if (revInfoWereLookingFor != null)
642  needToApplyRemainingPrs = false;
643  }
644  }
645 
646  if (revInfoWereLookingFor != null)
647  {
648  // goteem
649  await repo.ResetToSha(revInfoWereLookingFor.CommitSha, NextProgressReporter(), cancellationToken).ConfigureAwait(false);
650  lastRevisionInfo = revInfoWereLookingFor;
651  }
652 
653  if (needToApplyRemainingPrs)
654  {
655  // an invocation of LoadRevisionInformation could have already loaded this user
656  var contextUser = databaseContext.Users.Local.Where(x => x.Id == AuthenticationContext.User.Id).FirstOrDefault();
657  if (contextUser == default)
658  {
659  contextUser = new Models.User
660  {
662  };
663  databaseContext.Users.Attach(contextUser);
664  }
665  else
666  Logger.LogTrace("Skipping attaching the user to the database context as it is already loaded!");
667 
668  foreach (var I in model.NewTestMerges)
669  {
670  Octokit.PullRequest pr = null;
671  string errorMessage = null;
672 
673  if (lastRevisionInfo.ActiveTestMerges.Any(x => x.TestMerge.Number == I.Number.Value))
674  throw new JobException("Cannot test merge the same PR twice in one HEAD!");
675 
676  try
677  {
678  // load from cache if possible
679  if (prMap == null || !prMap.TryGetValue(I.Number.Value, out pr))
680  pr = await gitHubClient.PullRequest.Get(repoOwner, repoName, I.Number.Value).ConfigureAwait(false);
681  }
682  catch (Octokit.RateLimitExceededException)
683  {
684  // you look at your anonymous access and sigh
685  errorMessage = "P.R.E. RATE LIMITED";
686  }
687  catch (Octokit.AuthorizationException)
688  {
689  errorMessage = "P.R.E. BAD CREDENTIALS";
690  }
691  catch (Octokit.NotFoundException)
692  {
693  // you look at your shithub and sigh
694  errorMessage = "P.R.E. NOT FOUND";
695  }
696 
697  // we want to take the earliest truth possible to prevent RCEs, if this fails AddTestMerge will set it
698  if (I.PullRequestRevision == null && pr != null)
699  I.PullRequestRevision = pr.Head.Sha;
700 
701  var mergeResult = await repo.AddTestMerge(I, committerName, currentModel.CommitterEmail, currentModel.AccessUser, currentModel.AccessToken, NextProgressReporter(), ct).ConfigureAwait(false);
702 
703  if (!mergeResult.HasValue)
704  throw new JobException(String.Format(CultureInfo.InvariantCulture, "Merge of PR #{0} at {1} conflicted!", I.Number, I.PullRequestRevision.Substring(0, 7)));
705 
706  ++doneSteps;
707 
708  var revInfoUpdateTask = UpdateRevInfo();
709 
710  var tm = new Models.TestMerge
711  {
712  Author = pr?.User.Login ?? errorMessage,
713  BodyAtMerge = pr?.Body ?? errorMessage ?? String.Empty,
714  MergedAt = DateTimeOffset.Now,
715  TitleAtMerge = pr?.Title ?? errorMessage ?? String.Empty,
716  Comment = I.Comment,
717  Number = I.Number,
718  MergedBy = contextUser,
719  PullRequestRevision = I.PullRequestRevision,
720  Url = pr?.HtmlUrl ?? errorMessage
721  };
722 
723  await revInfoUpdateTask.ConfigureAwait(false);
724 
725  lastRevisionInfo.PrimaryTestMerge = tm;
726  lastRevisionInfo.ActiveTestMerges.Add(new RevInfoTestMerge
727  {
728  TestMerge = tm
729  });
730  }
731  }
732  }
733 
734  var currentHead = repo.Head;
735  if (startSha != currentHead || (postUpdateSha != null && postUpdateSha != currentHead))
736  {
737  await repo.Sychronize(currentModel.AccessUser, currentModel.AccessToken, currentModel.CommitterName, currentModel.CommitterEmail, NextProgressReporter(), false, ct).ConfigureAwait(false);
738  await UpdateRevInfo().ConfigureAwait(false);
739  }
740 
741  await databaseContext.Save(ct).ConfigureAwait(false);
742  }
743  catch
744  {
745  doneSteps = 0;
746  numSteps = 2;
747 
748  // the stuff didn't make it into the db, forget what we've done and abort
749  await repo.CheckoutObject(startReference ?? startSha, NextProgressReporter(), default).ConfigureAwait(false);
750  if (startReference != null && repo.Head != startSha)
751  await repo.ResetToSha(startSha, NextProgressReporter(), default).ConfigureAwait(false);
752  else
753  progressReporter(100);
754  throw;
755  }
756  }
757  }, cancellationToken).ConfigureAwait(false);
758 
759  api.ActiveJob = job.ToApi();
760  return Accepted(api);
761  }
762  #pragma warning restore CA1502
763  #pragma warning restore CA1505
764  }
765 }
string Name
The name of the User
Definition: User.cs:38
- -
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 Microsoft.Extensions.Options;
5 using System;
6 using System.Collections.Generic;
7 using System.Globalization;
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;
22 
24 {
28  [Route(Routes.Repository)]
29  #pragma warning disable CA1506 // TODO: Decomplexify
30  public sealed class RepositoryController : ModelController<Repository>
31  {
36 
41 
46 
51 
62  public RepositoryController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, IGitHubClientFactory gitHubClientFactory, IJobManager jobManager, ILogger<RepositoryController> logger, IOptions<GeneralConfiguration> generalConfigurationOptions) : base(databaseContext, authenticationContextFactory, logger, true)
63  {
64  this.instanceManager = instanceManager ?? throw new ArgumentNullException(nameof(instanceManager));
65  this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
66  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
67  generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
68  }
69 
70  async Task<bool> LoadRevisionInformation(Components.Repository.IRepository repository, IDatabaseContext databaseContext, Models.Instance instance, string lastOriginCommitSha, Action<Models.RevisionInformation> revInfoSink, CancellationToken cancellationToken)
71  {
72  var repoSha = repository.Head;
73 
74  IQueryable<Models.RevisionInformation> ApplyQuery(IQueryable<Models.RevisionInformation> query) => query
75  .Where(x => x.CommitSha == repoSha && x.Instance.Id == instance.Id)
76  .Include(x => x.CompileJobs)
77  .Include(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).ThenInclude(x => x.MergedBy);
78 
79  var revisionInfo = await ApplyQuery(databaseContext.RevisionInformations).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
80 
81  if (revisionInfo == default)
82  revisionInfo = databaseContext.RevisionInformations.Local.Where(x => x.CommitSha == repoSha && x.Instance.Id == instance.Id).FirstOrDefault();
83 
84  var needsDbUpdate = revisionInfo == default;
85  if (needsDbUpdate)
86  {
87  // needs insertion
88  revisionInfo = new Models.RevisionInformation
89  {
90  Instance = instance,
91  CommitSha = repoSha,
92  CompileJobs = new List<Models.CompileJob>(),
93  ActiveTestMerges = new List<RevInfoTestMerge>() // non null vals for api returns
94  };
95 
96  lock (databaseContext) // cleaner this way
97  databaseContext.RevisionInformations.Add(revisionInfo);
98  }
99 
100  revisionInfo.OriginCommitSha = revisionInfo.OriginCommitSha ?? lastOriginCommitSha;
101  if (revisionInfo.OriginCommitSha == null)
102  {
103  revisionInfo.OriginCommitSha = repoSha;
104  Logger.LogWarning(Components.Repository.Repository.OriginTrackingErrorTemplate, repoSha);
105  }
106 
107  revInfoSink?.Invoke(revisionInfo);
108  return needsDbUpdate;
109  }
110 
111  async Task<bool> PopulateApi(Repository model, Components.Repository.IRepository repository, IDatabaseContext databaseContext, Models.Instance instance, CancellationToken cancellationToken)
112  {
113  if (repository.IsGitHubRepository)
114  {
115  model.GitHubOwner = repository.GitHubOwner;
116  model.GitHubName = repository.GitHubRepoName;
117  }
118 
119  model.Origin = repository.Origin;
120  model.Reference = repository.Reference;
121 
122  // rev info stuff
123  Models.RevisionInformation revisionInfo = null;
124  var needsDbUpdate = await LoadRevisionInformation(repository, databaseContext, instance, null, x => revisionInfo = x, cancellationToken).ConfigureAwait(false);
125  model.RevisionInformation = revisionInfo.ToApi();
126  return needsDbUpdate;
127  }
128 
130  [TgsAuthorize(RepositoryRights.SetOrigin)]
131  public override async Task<IActionResult> Create([FromBody] Repository model, CancellationToken cancellationToken)
132  {
133  if (model == null)
134  throw new ArgumentNullException(nameof(model));
135 
136  if (model.Origin == null)
137  return BadRequest(new ErrorMessage { Message = "Missing repo origin!" });
138 
139  if (model.AccessUser == null ^ model.AccessToken == null)
140  return BadRequest(new ErrorMessage { Message = "Either both accessToken and accessUser must be present or neither!" });
141 
142  var currentModel = await DatabaseContext.RepositorySettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
143 
144  if (currentModel == default)
145  return StatusCode((int)HttpStatusCode.Gone);
146 
147  // normalize github urls
148  const string BadGitHubUrl = "://www.github.com/";
149  var uiOrigin = model.Origin.ToUpperInvariant();
150  var uiBad = BadGitHubUrl.ToUpperInvariant();
151  var uiGitHub = Components.Repository.Repository.GitHubUrl.ToUpperInvariant();
152  if (uiOrigin.Contains(uiBad, StringComparison.Ordinal))
153  model.Origin = uiOrigin.Replace(uiBad, uiGitHub, StringComparison.Ordinal);
154 
155  currentModel.AccessToken = model.AccessToken;
156  currentModel.AccessUser = model.AccessUser; // intentionally only these fields, user not allowed to change anything else atm
157  var cloneBranch = model.Reference;
158  var origin = model.Origin;
159 
161 
162  if (repoManager.CloneInProgress)
163  return Conflict(new ErrorMessage
164  {
165  Message = "A clone operation is in progress!"
166  });
167 
168  if(repoManager.InUse)
169  return Conflict(new ErrorMessage
170  {
171  Message = "The repo is busy!"
172  });
173 
174  using (var repo = await repoManager.LoadRepository(cancellationToken).ConfigureAwait(false))
175  {
176  // clone conflict
177  if (repo != null)
178  return Conflict(new ErrorMessage
179  {
180  Message = "The repository already exists!"
181  });
182 
183  var job = new Models.Job
184  {
185  Description = String.Format(CultureInfo.InvariantCulture, "Clone branch {1} of repository {0}", origin, cloneBranch ?? "master"),
186  StartedBy = AuthenticationContext.User,
187  CancelRightsType = RightsType.Repository,
188  CancelRight = (ulong)RepositoryRights.CancelClone,
190  };
191  var api = currentModel.ToApi();
192  await jobManager.RegisterOperation(job, async (paramJob, databaseContext, progressReporter, ct) =>
193  {
194  using (var repos = await repoManager.CloneRepository(new Uri(origin), cloneBranch, currentModel.AccessUser, currentModel.AccessToken, progressReporter, ct).ConfigureAwait(false))
195  {
196  if (repos == null)
197  throw new JobException("Filesystem conflict while cloning repository!");
198  var instance = new Models.Instance
199  {
200  Id = Instance.Id
201  };
202  databaseContext.Instances.Attach(instance);
203  if (await PopulateApi(api, repos, databaseContext, instance, ct).ConfigureAwait(false))
204  await databaseContext.Save(ct).ConfigureAwait(false);
205  }
206  }, cancellationToken).ConfigureAwait(false);
207 
208  api.Origin = model.Origin;
209  api.Reference = model.Reference;
210  api.ActiveJob = job.ToApi();
211 
212  return StatusCode((int)HttpStatusCode.Created, api);
213  }
214  }
215 
221  [TgsAuthorize(RepositoryRights.Delete)]
222  public async Task<IActionResult> Delete(CancellationToken cancellationToken)
223  {
224  var currentModel = await DatabaseContext.RepositorySettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
225 
226  if (currentModel == default)
227  return StatusCode((int)HttpStatusCode.Gone);
228 
229  currentModel.AccessToken = null;
230  currentModel.AccessUser = null;
231 
232  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
233 
234  Logger.LogInformation("Instance {0} repository delete initiated by user {1}", Instance.Id, AuthenticationContext.User.Id);
235 
236  var job = new Models.Job
237  {
238  Description = "Delete repository",
239  StartedBy = AuthenticationContext.User,
241  };
242  var api = currentModel.ToApi();
243  await jobManager.RegisterOperation(job, (paramJob, databaseContext, progressReporter, ct) => instanceManager.GetInstance(Instance).RepositoryManager.DeleteRepository(cancellationToken), cancellationToken).ConfigureAwait(false);
244  api.ActiveJob = job.ToApi();
245  return Accepted(api);
246  }
247 
249  [TgsAuthorize(RepositoryRights.Read)]
250  public override async Task<IActionResult> Read(CancellationToken cancellationToken)
251  {
252  var currentModel = await DatabaseContext.RepositorySettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
253 
254  if (currentModel == default)
255  return StatusCode((int)HttpStatusCode.Gone);
256 
257  var api = currentModel.ToApi();
259 
260  if (repoManager.CloneInProgress)
261  return Conflict(new ErrorMessage
262  {
263  Message = "A clone operation is in progress!"
264  });
265 
266  if (repoManager.InUse)
267  return Conflict(new ErrorMessage
268  {
269  Message = "The repo is busy!"
270  });
271 
272  using (var repo = await repoManager.LoadRepository(cancellationToken).ConfigureAwait(false))
273  {
274  if (repo != null && await PopulateApi(api, repo, DatabaseContext, Instance, cancellationToken).ConfigureAwait(false))
275  {
276  // user may have fucked with the repo without telling us, do what we can
277  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
278  return StatusCode((int)HttpStatusCode.Created, api);
279  }
280 
281  return Json(api);
282  }
283  }
284 
286  [TgsAuthorize(RepositoryRights.ChangeAutoUpdateSettings | RepositoryRights.ChangeCommitter | RepositoryRights.ChangeCredentials | RepositoryRights.ChangeTestMergeCommits | RepositoryRights.MergePullRequest | RepositoryRights.SetReference | RepositoryRights.SetSha | RepositoryRights.UpdateBranch)]
287  #pragma warning disable CA1502 // TODO: Decomplexify
288  #pragma warning disable CA1505
289  public override async Task<IActionResult> Update([FromBody]Repository model, CancellationToken cancellationToken)
290  {
291  if (model == null)
292  throw new ArgumentNullException(nameof(model));
293 
294  if (model.AccessUser == null ^ model.AccessToken == null)
295  return BadRequest(new ErrorMessage { Message = "Either both accessToken and accessUser must be present or neither!" });
296 
297  if (model.CheckoutSha != null && model.Reference != null)
298  return BadRequest(new ErrorMessage { Message = "Only one of sha or reference may be specified!" });
299 
300  if (model.CheckoutSha != null && model.UpdateFromOrigin == true)
301  return BadRequest(new ErrorMessage { Message = "Cannot update a reference when checking out a sha!" });
302 
303  if (model.Origin != null)
304  return BadRequest(new ErrorMessage { Message = "origin cannot be modified without deleting the repository!" });
305 
306  if (model.NewTestMerges?.Any(x => !x.Number.HasValue) == true)
307  return BadRequest(new ErrorMessage { Message = "All new test merges must provide a number!" });
308 
309  if (model.NewTestMerges?.Any(x => model.NewTestMerges.Any(y => x != y && x.Number == y.Number)) == true)
310  return BadRequest(new ErrorMessage { Message = "Cannot test merge the same PR twice in one job!" });
311 
312  if (model.CommitterName?.Length == 0)
313  return BadRequest(new ErrorMessage { Message = "Cannot set empty committer name!" });
314 
315  if (model.CommitterEmail?.Length == 0)
316  return BadRequest(new ErrorMessage { Message = "Cannot set empty committer e=mail!" });
317 
318  var newTestMerges = model.NewTestMerges != null && model.NewTestMerges.Count > 0;
319  var userRights = (RepositoryRights)AuthenticationContext.GetRight(RightsType.Repository);
320  if (newTestMerges && !userRights.HasFlag(RepositoryRights.MergePullRequest))
321  return Forbid();
322 
323  var currentModel = await DatabaseContext.RepositorySettings.Where(x => x.InstanceId == Instance.Id).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
324 
325  if (currentModel == default)
326  return StatusCode((int)HttpStatusCode.Gone);
327 
328  bool CheckModified<T>(Expression<Func<Api.Models.Internal.RepositorySettings, T>> expression, RepositoryRights requiredRight)
329  {
330  var memberSelectorExpression = (MemberExpression)expression.Body;
331  var property = (PropertyInfo)memberSelectorExpression.Member;
332 
333  var newVal = property.GetValue(model);
334  if (newVal == null)
335  return false;
336  if (!userRights.HasFlag(requiredRight) && property.GetValue(currentModel) != newVal)
337  return true;
338 
339  property.SetValue(currentModel, newVal);
340  return false;
341  }
342 
343  if (CheckModified(x => x.AccessToken, RepositoryRights.ChangeCredentials)
344  || CheckModified(x => x.AccessUser, RepositoryRights.ChangeCredentials)
345  || CheckModified(x => x.AutoUpdatesKeepTestMerges, RepositoryRights.ChangeAutoUpdateSettings)
346  || CheckModified(x => x.AutoUpdatesSynchronize, RepositoryRights.ChangeAutoUpdateSettings)
347  || CheckModified(x => x.CommitterEmail, RepositoryRights.ChangeCommitter)
348  || CheckModified(x => x.CommitterName, RepositoryRights.ChangeCommitter)
349  || CheckModified(x => x.PushTestMergeCommits, RepositoryRights.ChangeTestMergeCommits)
350  || CheckModified(x => x.ShowTestMergeCommitters, RepositoryRights.ChangeTestMergeCommits)
351  || CheckModified(x => x.PostTestMergeComment, RepositoryRights.ChangeTestMergeCommits)
352  || (model.UpdateFromOrigin == true && !userRights.HasFlag(RepositoryRights.UpdateBranch)))
353  return Forbid();
354 
355  if (currentModel.AccessToken?.Length == 0 && currentModel.AccessUser?.Length == 0)
356  {
357  // setting an empty string clears everything
358  currentModel.AccessUser = null;
359  currentModel.AccessToken = null;
360  }
361 
362  var canRead = userRights.HasFlag(RepositoryRights.Read);
363 
364  var api = canRead ? currentModel.ToApi() : new Repository();
366 
367  if (canRead)
368  {
369  if (repoManager.CloneInProgress)
370  return Conflict(new ErrorMessage
371  {
372  Message = "A clone operation is in progress!"
373  });
374 
375  if (repoManager.InUse)
376  return Conflict(new ErrorMessage
377  {
378  Message = "The repo is busy!"
379  });
380 
381  using (var repo = await repoManager.LoadRepository(cancellationToken).ConfigureAwait(false))
382  {
383  if (repo == null)
384  return Conflict(new ErrorMessage
385  {
386  Message = "Repository could not be loaded!"
387  });
388  await PopulateApi(api, repo, DatabaseContext, Instance, cancellationToken).ConfigureAwait(false);
389  }
390  }
391 
392  // this is just db stuf so stow it away
393  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
394 
395  // format the job description
396  string description = null;
397  if (model.UpdateFromOrigin == true)
398  if (model.Reference != null)
399  description = String.Format(CultureInfo.InvariantCulture, "Fetch and hard reset repository to origin/{0}", model.Reference);
400  else if (model.CheckoutSha != null)
401  description = String.Format(CultureInfo.InvariantCulture, "Fetch and checkout {0} in repository", model.CheckoutSha);
402  else
403  description = "Pull current repository reference";
404  else if (model.Reference != null || model.CheckoutSha != null)
405  description = String.Format(CultureInfo.InvariantCulture, "Checkout repository {0} {1}", model.Reference != null ? "reference" : "SHA", model.Reference ?? model.CheckoutSha);
406 
407  if (newTestMerges)
408  description = String.Format(CultureInfo.InvariantCulture, "{0}est merge pull request(s) {1}{2}",
409  description != null ? String.Format(CultureInfo.InvariantCulture, "{0} and t", description) : "T",
410  String.Join(", ", model.NewTestMerges.Select(x =>
411  String.Format(CultureInfo.InvariantCulture, "#{0}{1}", x.Number,
412  x.PullRequestRevision != null ? String.Format(CultureInfo.InvariantCulture, " at {0}", x.PullRequestRevision.Substring(0, 7)) : String.Empty))),
413  description != null ? String.Empty : " in repository");
414 
415  if (description == null)
416  return Json(api); // no git changes
417 
418  var job = new Models.Job
419  {
420  Description = description,
421  StartedBy = AuthenticationContext.User,
422  Instance = Instance,
423  CancelRightsType = RightsType.Repository,
424  CancelRight = (ulong)RepositoryRights.CancelPendingChanges,
425  };
426 
427  await jobManager.RegisterOperation(job, async (paramJob, databaseContext, progressReporter, ct) =>
428  {
429  using (var repo = await repoManager.LoadRepository(ct).ConfigureAwait(false))
430  {
431  if (repo == null)
432  throw new JobException("Repository could not be loaded!");
433 
434  var modelHasShaOrReference = model.CheckoutSha != null || model.Reference != null;
435 
436  var startReference = repo.Reference;
437  var startSha = repo.Head;
438  string postUpdateSha = null;
439 
440  if (newTestMerges && !repo.IsGitHubRepository)
441  throw new JobException("Cannot test merge on a non GitHub based repository!");
442 
443  var committerName = currentModel.ShowTestMergeCommitters.Value ? AuthenticationContext.User.Name : currentModel.CommitterName;
444 
445  var hardResettingToOriginReference = model.UpdateFromOrigin == true && model.Reference != null;
446 
447  var numSteps = (model.NewTestMerges?.Count ?? 0) + (model.UpdateFromOrigin == true ? 1 : 0) + (!modelHasShaOrReference ? 2 : (hardResettingToOriginReference ? 3 : 1));
448  var doneSteps = 0;
449 
450  Action<int> NextProgressReporter()
451  {
452  var tmpDoneSteps = doneSteps;
453  ++doneSteps;
454  return progress => progressReporter((progress + (100 * tmpDoneSteps)) / numSteps);
455  }
456 
457  progressReporter(0);
458 
459  // get a base line for where we are
460  Models.RevisionInformation lastRevisionInfo = null;
461 
462  var attachedInstance = new Models.Instance
463  {
464  Id = Instance.Id
465  };
466  databaseContext.Instances.Attach(attachedInstance);
467 
468  await LoadRevisionInformation(repo, databaseContext, attachedInstance, null, x => lastRevisionInfo = x, ct).ConfigureAwait(false);
469 
470  // apply new rev info, tracking applied test merges
471  async Task UpdateRevInfo()
472  {
473  var last = lastRevisionInfo;
474  await LoadRevisionInformation(repo, databaseContext, attachedInstance, last.OriginCommitSha, x => lastRevisionInfo = x, ct).ConfigureAwait(false);
475  lastRevisionInfo.ActiveTestMerges.AddRange(last.ActiveTestMerges);
476  }
477 
478  try
479  {
480  // fetch/pull
481  if (model.UpdateFromOrigin == true)
482  {
483  if (!repo.Tracking)
484  throw new JobException("Not on an updatable reference!");
485  await repo.FetchOrigin(currentModel.AccessUser, currentModel.AccessToken, NextProgressReporter(), ct).ConfigureAwait(false);
486  doneSteps = 1;
487  if (!modelHasShaOrReference)
488  {
489  var fastForward = await repo.MergeOrigin(committerName, currentModel.CommitterEmail, NextProgressReporter(), ct).ConfigureAwait(false);
490  if (!fastForward.HasValue)
491  throw new JobException("Merge conflict occurred during origin update!");
492  await UpdateRevInfo().ConfigureAwait(false);
493  if (fastForward.Value)
494  {
495  lastRevisionInfo.OriginCommitSha = repo.Head;
496  await repo.Sychronize(currentModel.AccessUser, currentModel.AccessToken, currentModel.CommitterName, currentModel.CommitterEmail, NextProgressReporter(), true, ct).ConfigureAwait(false);
497  postUpdateSha = repo.Head;
498  }
499  else
500  NextProgressReporter()(100);
501  }
502  }
503 
504  // checkout/hard reset
505  if (modelHasShaOrReference)
506  {
507  if ((model.CheckoutSha != null && repo.Head.ToUpperInvariant().StartsWith(model.CheckoutSha.ToUpperInvariant(), StringComparison.Ordinal))
508  || (model.Reference != null && repo.Reference.ToUpperInvariant() != model.Reference.ToUpperInvariant()))
509  {
510  var committish = model.CheckoutSha ?? model.Reference;
511  var isSha = await repo.IsSha(committish, cancellationToken).ConfigureAwait(false);
512 
513  if ((isSha && model.Reference != null) || (!isSha && model.CheckoutSha != null))
514  throw new JobException("Attempted to checkout a SHA or reference that was actually the opposite!");
515 
516  await repo.CheckoutObject(committish, NextProgressReporter(), ct).ConfigureAwait(false);
517  await LoadRevisionInformation(repo, databaseContext, attachedInstance, null, x => lastRevisionInfo = x, ct).ConfigureAwait(false); // we've either seen origin before or what we're checking out is on origin
518  }
519  else
520  NextProgressReporter()(100);
521 
522  if (hardResettingToOriginReference)
523  {
524  if (!repo.Tracking)
525  throw new JobException("Checked out reference does not track a remote object!");
526  await repo.ResetToOrigin(NextProgressReporter(), ct).ConfigureAwait(false);
527  await repo.Sychronize(currentModel.AccessUser, currentModel.AccessToken, currentModel.CommitterName, currentModel.CommitterEmail, NextProgressReporter(), true, ct).ConfigureAwait(false);
528  await LoadRevisionInformation(repo, databaseContext, attachedInstance, null, x => lastRevisionInfo = x, ct).ConfigureAwait(false);
529 
530  // repo head is on origin so force this
531  // will update the db if necessary
532  lastRevisionInfo.OriginCommitSha = repo.Head;
533  }
534  }
535 
536  // test merging
537  Dictionary<int, Octokit.PullRequest> prMap = null;
538  if (newTestMerges)
539  {
540  // bit of sanitization
541  foreach (var I in model.NewTestMerges.Where(x => String.IsNullOrWhiteSpace(x.PullRequestRevision)))
542  I.PullRequestRevision = null;
543 
544  var gitHubClient = currentModel.AccessToken != null
545  ? gitHubClientFactory.CreateClient(currentModel.AccessToken)
546  : (String.IsNullOrEmpty(generalConfiguration.GitHubAccessToken)
549 
550  var repoOwner = repo.GitHubOwner;
551  var repoName = repo.GitHubRepoName;
552 
553  // optimization: if we've already merged these exact same commits in this fashion before, just find the rev info for it and check it out
554  Models.RevisionInformation revInfoWereLookingFor = null;
555  bool needToApplyRemainingPrs = true;
556  if (lastRevisionInfo.OriginCommitSha == lastRevisionInfo.CommitSha)
557  {
558  // In order for this to work though we need the shas of all the commits
559  if (model.NewTestMerges.Any(x => x.PullRequestRevision == null))
560  prMap = new Dictionary<int, Octokit.PullRequest>();
561 
562  bool cantSearch = false;
563  foreach (var I in model.NewTestMerges)
564  {
565  if (I.PullRequestRevision != null)
566 #pragma warning disable CA1308 // Normalize strings to uppercase
567  I.PullRequestRevision = I.PullRequestRevision?.ToLowerInvariant(); // ala libgit2
568 #pragma warning restore CA1308 // Normalize strings to uppercase
569  else
570  try
571  {
572  // retrieve the latest sha
573  var pr = await gitHubClient.PullRequest.Get(repoOwner, repoName, I.Number.Value).ConfigureAwait(false);
574  prMap.Add(I.Number.Value, pr);
575  I.PullRequestRevision = pr.Head.Sha;
576  }
577  catch
578  {
579  cantSearch = true;
580  break;
581  }
582  }
583 
584  if (!cantSearch)
585  {
586  var dbPull = await databaseContext.RevisionInformations
587  .Where(x => x.Instance.Id == Instance.Id
588  && x.OriginCommitSha == lastRevisionInfo.OriginCommitSha
589  && x.ActiveTestMerges.Count <= model.NewTestMerges.Count
590  && x.ActiveTestMerges.Count > 0)
591  .Include(x => x.ActiveTestMerges)
592  .ThenInclude(x => x.TestMerge)
593  .ToListAsync(cancellationToken).ConfigureAwait(false);
594 
595  // split here cause this bit has to be done locally
596  revInfoWereLookingFor = dbPull
597  .Where(x => x.ActiveTestMerges.Count == model.NewTestMerges.Count
598  && x.ActiveTestMerges.Select(y => y.TestMerge)
599  .All(y => model.NewTestMerges.Any(z =>
600  y.Number == z.Number
601  && y.PullRequestRevision.StartsWith(z.PullRequestRevision, StringComparison.Ordinal)
602  && (y.Comment?.Trim().ToUpperInvariant() == z.Comment?.Trim().ToUpperInvariant() || z.Comment == null))))
603  .FirstOrDefault();
604 
605  if (revInfoWereLookingFor == null && model.NewTestMerges.Count > 1)
606  {
607  // okay try to add at least SOME prs we've seen before
608  var search = model.NewTestMerges.ToList();
609 
610  var appliedTestMergeIds = new List<long>();
611 
612  Models.RevisionInformation lastGoodRevInfo = null;
613  do
614  {
615  foreach (var I in search)
616  {
617  revInfoWereLookingFor = dbPull
618  .Where(x => model.NewTestMerges.Any(z =>
619  x.PrimaryTestMerge.Number == z.Number
620  && x.PrimaryTestMerge.PullRequestRevision.StartsWith(z.PullRequestRevision, StringComparison.Ordinal)
621  && (x.PrimaryTestMerge.Comment?.Trim().ToUpperInvariant() == z.Comment?.Trim().ToUpperInvariant() || z.Comment == null))
622  && x.ActiveTestMerges.Select(y => y.TestMerge).All(y => appliedTestMergeIds.Contains(y.Id)))
623  .FirstOrDefault();
624 
625  if (revInfoWereLookingFor != null)
626  {
627  lastGoodRevInfo = revInfoWereLookingFor;
628  appliedTestMergeIds.Add(revInfoWereLookingFor.PrimaryTestMerge.Id);
629  search.Remove(I);
630  break;
631  }
632  }
633  }
634  while (revInfoWereLookingFor != null && search.Count > 0);
635 
636  revInfoWereLookingFor = lastGoodRevInfo;
637  needToApplyRemainingPrs = search.Count != 0;
638  if (needToApplyRemainingPrs)
639  model.NewTestMerges = search;
640  }
641  else if (revInfoWereLookingFor != null)
642  needToApplyRemainingPrs = false;
643  }
644  }
645 
646  if (revInfoWereLookingFor != null)
647  {
648  // goteem
649  await repo.ResetToSha(revInfoWereLookingFor.CommitSha, NextProgressReporter(), cancellationToken).ConfigureAwait(false);
650  lastRevisionInfo = revInfoWereLookingFor;
651  }
652 
653  if (needToApplyRemainingPrs)
654  {
655  // an invocation of LoadRevisionInformation could have already loaded this user
656  var contextUser = databaseContext.Users.Local.Where(x => x.Id == AuthenticationContext.User.Id).FirstOrDefault();
657  if (contextUser == default)
658  {
659  contextUser = new Models.User
660  {
662  };
663  databaseContext.Users.Attach(contextUser);
664  }
665  else
666  Logger.LogTrace("Skipping attaching the user to the database context as it is already loaded!");
667 
668  foreach (var I in model.NewTestMerges)
669  {
670  Octokit.PullRequest pr = null;
671  string errorMessage = null;
672 
673  if (lastRevisionInfo.ActiveTestMerges.Any(x => x.TestMerge.Number == I.Number.Value))
674  throw new JobException("Cannot test merge the same PR twice in one HEAD!");
675 
676  try
677  {
678  // load from cache if possible
679  if (prMap == null || !prMap.TryGetValue(I.Number.Value, out pr))
680  pr = await gitHubClient.PullRequest.Get(repoOwner, repoName, I.Number.Value).ConfigureAwait(false);
681  }
682  catch (Octokit.RateLimitExceededException)
683  {
684  // you look at your anonymous access and sigh
685  errorMessage = "P.R.E. RATE LIMITED";
686  }
687  catch (Octokit.AuthorizationException)
688  {
689  errorMessage = "P.R.E. BAD CREDENTIALS";
690  }
691  catch (Octokit.NotFoundException)
692  {
693  // you look at your shithub and sigh
694  errorMessage = "P.R.E. NOT FOUND";
695  }
696 
697  // we want to take the earliest truth possible to prevent RCEs, if this fails AddTestMerge will set it
698  if (I.PullRequestRevision == null && pr != null)
699  I.PullRequestRevision = pr.Head.Sha;
700 
701  var mergeResult = await repo.AddTestMerge(I, committerName, currentModel.CommitterEmail, currentModel.AccessUser, currentModel.AccessToken, NextProgressReporter(), ct).ConfigureAwait(false);
702 
703  if (!mergeResult.HasValue)
704  throw new JobException(String.Format(CultureInfo.InvariantCulture, "Merge of PR #{0} at {1} conflicted!", I.Number, I.PullRequestRevision.Substring(0, 7)));
705 
706  ++doneSteps;
707 
708  var revInfoUpdateTask = UpdateRevInfo();
709 
710  var tm = new Models.TestMerge
711  {
712  Author = pr?.User.Login ?? errorMessage,
713  BodyAtMerge = pr?.Body ?? errorMessage ?? String.Empty,
714  MergedAt = DateTimeOffset.Now,
715  TitleAtMerge = pr?.Title ?? errorMessage ?? String.Empty,
716  Comment = I.Comment,
717  Number = I.Number,
718  MergedBy = contextUser,
719  PullRequestRevision = I.PullRequestRevision,
720  Url = pr?.HtmlUrl ?? errorMessage
721  };
722 
723  await revInfoUpdateTask.ConfigureAwait(false);
724 
725  lastRevisionInfo.PrimaryTestMerge = tm;
726  lastRevisionInfo.ActiveTestMerges.Add(new RevInfoTestMerge
727  {
728  TestMerge = tm
729  });
730  }
731  }
732  }
733 
734  var currentHead = repo.Head;
735  if (startSha != currentHead || (postUpdateSha != null && postUpdateSha != currentHead))
736  {
737  await repo.Sychronize(currentModel.AccessUser, currentModel.AccessToken, currentModel.CommitterName, currentModel.CommitterEmail, NextProgressReporter(), false, ct).ConfigureAwait(false);
738  await UpdateRevInfo().ConfigureAwait(false);
739  }
740 
741  await databaseContext.Save(ct).ConfigureAwait(false);
742  }
743  catch
744  {
745  doneSteps = 0;
746  numSteps = 2;
747 
748  // the stuff didn't make it into the db, forget what we've done and abort
749  await repo.CheckoutObject(startReference ?? startSha, NextProgressReporter(), default).ConfigureAwait(false);
750  if (startReference != null && repo.Head != startSha)
751  await repo.ResetToSha(startSha, NextProgressReporter(), default).ConfigureAwait(false);
752  else
753  progressReporter(100);
754  throw;
755  }
756  }
757  }, cancellationToken).ConfigureAwait(false);
758 
759  api.ActiveJob = job.ToApi();
760  return Accepted(api);
761  }
762  #pragma warning restore CA1502
763  #pragma warning restore CA1505
764  }
765 }
string Name
The name of the User
Definition: User.cs:38
+ +
Manages the runtime of Jobs
Definition: IJobManager.cs:12
+ + + -
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
+
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
+
string GitHubAccessToken
A GitHub personal access token to use for bypassing rate limits on requests. Requires no scopes
-
string GitHubOwner
If the repository was cloned from GitHub.com this will be set with the owner of the repository ...
Definition: Repository.cs:28
- - +
string GitHubOwner
If the repository was cloned from GitHub.com this will be set with the owner of the repository
Definition: Repository.cs:28
+
IInstance GetInstance(Models.Instance metadata)
Get the IInstance associated with given metadata
- - -
Many to many relationship for Models.RevisionInformation and Models.TestMerge
-
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
-
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
+
Many to many relationship for Models.RevisionInformation and Models.TestMerge
+
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
+
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
async Task< bool > PopulateApi(Repository model, Components.Repository.IRepository repository, IDatabaseContext databaseContext, Models.Instance instance, CancellationToken cancellationToken)
- -
User may list and read all Models.CompileJobs
-
readonly IInstanceManager instanceManager
The IInstanceManager for the RepositoryController
+
Task RegisterOperation(Job job, Func< Job, IDatabaseContext, Action< int >, CancellationToken, Task > operation, CancellationToken cancellationToken)
Registers a given Job and begins running it
+ +
User may list and read all Models.CompileJobs
+
readonly IInstanceManager instanceManager
The IInstanceManager for the RepositoryController
-
Routes to a server actions
Definition: Routes.cs:9
+
Routes to a server actions
Definition: Routes.cs:9
async Task< bool > LoadRevisionInformation(Components.Repository.IRepository repository, IDatabaseContext databaseContext, Models.Instance instance, string lastOriginCommitSha, Action< Models.RevisionInformation > revInfoSink, CancellationToken cancellationToken)
- + -
Represents a git repository
Definition: Repository.cs:8
-
const string Repository
The Models.Repository controller
Definition: Routes.cs:39
-
RevisionInformation RevisionInformation
The current Models.RevisionInformation for the Repository
Definition: Repository.cs:23
+
Represents a git repository
Definition: Repository.cs:8
+
const string Repository
The Models.Repository controller
Definition: Routes.cs:39
+
IRepositoryManager RepositoryManager
The IRepositoryManager for the IInstance
Definition: IInstance.cs:22
+
RevisionInformation RevisionInformation
The current Models.RevisionInformation for the Repository
Definition: Repository.cs:23
DbSet< RepositorySettings > RepositorySettings
-
RepositoryRights
Rights for a Models.Repository
-
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
-
readonly IGitHubClientFactory gitHubClientFactory
The IGitHubClientFactory for the RepositoryController
-
string Reference
The branch or tag HEAD points to
Definition: Repository.cs:48
-
An ApiController representing a TModel
+
RepositoryRights
Rights for a Models.Repository
+
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
+
IGitHubClient CreateClient()
Create a client with anonymous authentication. Low rate limit
+
readonly IGitHubClientFactory gitHubClientFactory
The IGitHubClientFactory for the RepositoryController
+
string Reference
The branch or tag HEAD points to
Definition: Repository.cs:48
+
An ApiController representing a TModel
override async Task< IActionResult > Update([FromBody]Repository model, CancellationToken cancellationToken)
-
RepositoryController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, IGitHubClientFactory gitHubClientFactory, IJobManager jobManager, ILogger< RepositoryController > logger, IOptions< GeneralConfiguration > generalConfigurationOptions)
Construct a RepositoryController
- -
long Id
The ID of the User
Definition: User.cs:15
-
Metadata about a server instance
Definition: Instance.cs:9
-
DbSet< RevisionInformation > RevisionInformations
The RevisionInformations in the IDatabaseContext
- - +
RepositoryController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, IInstanceManager instanceManager, IGitHubClientFactory gitHubClientFactory, IJobManager jobManager, ILogger< RepositoryController > logger, IOptions< GeneralConfiguration > generalConfigurationOptions)
Construct a RepositoryController
+ +
long Id
The ID of the User
Definition: User.cs:15
+
Metadata about a server instance
Definition: Instance.cs:9
+
DbSet< RevisionInformation > RevisionInformations
The RevisionInformations in the IDatabaseContext
+ + +
virtual Task< IActionResult > List(CancellationToken cancellationToken)
Attempt to list entries of the TModel
override async Task< IActionResult > Create([FromBody] Repository model, CancellationToken cancellationToken)
-
string Origin
The origin URL. If , the Repository does not exist
Definition: Repository.cs:13
- -
string GitHubName
If the repository was cloned from GitHub.com this will be set with the name of the repository ...
Definition: Repository.cs:33
-
override async Task< IActionResult > Read(CancellationToken cancellationToken)
Attempt to read a TModel
-
readonly IJobManager jobManager
The IJobManager for the RepositoryController
-
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+
string Origin
The origin URL. If null, the Repository does not exist
Definition: Repository.cs:13
+ +
string GitHubName
If the repository was cloned from GitHub.com this will be set with the name of the repository
Definition: Repository.cs:33
+
override async Task< IActionResult > Read(CancellationToken cancellationToken)
Attempt to read a TModel
+
readonly IJobManager jobManager
The IJobManager for the RepositoryController
+
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- -
async Task< IActionResult > Delete(CancellationToken cancellationToken)
Delete the Repository
-
readonly GeneralConfiguration generalConfiguration
The GeneralConfiguration for the RepositoryController
-
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
- + +
async Task< IActionResult > Delete(CancellationToken cancellationToken)
Delete the Repository
+
readonly GeneralConfiguration generalConfiguration
The GeneralConfiguration for the RepositoryController
+
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
+
diff --git a/_repository_manager_8cs.html b/_repository_manager_8cs.html index 52c9e80195..2fb2e7d1f7 100644 --- a/_repository_manager_8cs.html +++ b/_repository_manager_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Repository/RepositoryManager.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Repository
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_repository_manager_8cs_source.html b/_repository_manager_8cs_source.html index b3a9dcbd7c..44ad27d2d3 100644 --- a/_repository_manager_8cs_source.html +++ b/_repository_manager_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Repository/RepositoryManager.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
RepositoryManager.cs
-Go to the documentation of this file.
1 using LibGit2Sharp;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Threading;
5 using System.Threading.Tasks;
8 using Tgstation.Server.Host.IO;
9 
10 namespace Tgstation.Server.Host.Components.Repository
11 {
14  {
16  public bool InUse => semaphore.CurrentCount == 0;
17 
19  public bool CloneInProgress { get; private set; }
20 
25 
30 
35 
39  readonly ILogger<Repository> repositoryLogger;
40 
44  readonly ILogger<RepositoryManager> logger;
45 
50 
54  readonly SemaphoreSlim semaphore;
55 
65  public RepositoryManager(RepositorySettings repositorySettings, IIOManager ioManager, IEventConsumer eventConsumer, ICredentialsProvider credentialsProvider, ILogger<Repository> repositoryLogger, ILogger<RepositoryManager> logger)
66  {
67  this.repositorySettings = repositorySettings ?? throw new ArgumentNullException(nameof(repositorySettings));
68  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
69  this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
70  this.credentialsProvider = credentialsProvider ?? throw new ArgumentNullException(nameof(credentialsProvider));
71  this.repositoryLogger = repositoryLogger ?? throw new ArgumentNullException(nameof(repositoryLogger));
72  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
73  semaphore = new SemaphoreSlim(1);
74  }
75 
77  public void Dispose()
78  {
79  logger.LogTrace("Disposing...");
80  semaphore.Dispose();
81  }
82 
84  public async Task<IRepository> CloneRepository(Uri url, string initialBranch, string username, string password, Action<int> progressReporter, CancellationToken cancellationToken)
85  {
86  if (url == null)
87  throw new ArgumentNullException(nameof(url));
88  if (progressReporter == null)
89  throw new ArgumentNullException(nameof(progressReporter));
90 
91  logger.LogInformation("Begin clone {0} (Branch: {1})", url, initialBranch);
92  lock (this)
93  {
94  if (CloneInProgress)
95  throw new InvalidOperationException("The repository is already being cloned!");
96  CloneInProgress = true;
97  }
98 
99  try
100  {
101  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
102  {
103  logger.LogTrace("Semaphore acquired");
104  if (!await ioManager.DirectoryExists(".", cancellationToken).ConfigureAwait(false))
105  try
106  {
107  await Task.Factory.StartNew(() =>
108  {
109  string path = null;
110  try
111  {
112  path = LibGit2Sharp.Repository.Clone(url.ToString(), ioManager.ResolvePath("."), new CloneOptions
113  {
114  OnProgress = (a) => !cancellationToken.IsCancellationRequested,
115  OnTransferProgress = (a) =>
116  {
117  var percentage = 100 * (((float)a.IndexedObjects + a.ReceivedObjects) / (a.TotalObjects * 2));
118  progressReporter((int)percentage);
119  return !cancellationToken.IsCancellationRequested;
120  },
121  RecurseSubmodules = true,
122  OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
123  RepositoryOperationStarting = (a) => !cancellationToken.IsCancellationRequested,
124  BranchName = initialBranch,
125  CredentialsProvider = credentialsProvider.GenerateHandler(username, password)
126  });
127  }
128  catch (UserCancelledException) { }
129  cancellationToken.ThrowIfCancellationRequested();
130  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
131  }
132  catch
133  {
134  try
135  {
136  logger.LogTrace("Deleting partially cloned repository...");
137  await ioManager.DeleteDirectory(".", default).ConfigureAwait(false);
138  }
139  catch (Exception e)
140  {
141  logger.LogDebug("Error deleting partially cloned repository! Exception: {0}", e);
142  }
143 
144  throw;
145  }
146  else
147  {
148  logger.LogDebug("Repository exists, clone aborted!");
149  return null;
150  }
151  }
152 
153  logger.LogInformation("Clone complete!");
154  }
155  finally
156  {
157  CloneInProgress = false;
158  }
159 
160  return await LoadRepository(cancellationToken).ConfigureAwait(false);
161  }
162 
164  public async Task<IRepository> LoadRepository(CancellationToken cancellationToken)
165  {
166  logger.LogTrace("Begin LoadRepository...");
167  lock (this)
168  if (CloneInProgress)
169  throw new InvalidOperationException("The repository is being cloned!");
170  await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
171  LibGit2Sharp.Repository repo = null;
172  await Task.Factory.StartNew(() =>
173  {
174  try
175  {
176  logger.LogTrace("Creating LibGit2Sharp.Repository...");
177  repo = new LibGit2Sharp.Repository(ioManager.ResolvePath("."));
178  }
179  catch (RepositoryNotFoundException e)
180  {
181  logger.LogDebug("Repository not found!");
182  logger.LogTrace("Exception: {0}", e);
183  }
184  catch
185  {
186  semaphore.Release();
187  throw;
188  }
189  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
190  if (repo == null)
191  {
192  semaphore.Release();
193  return null;
194  }
195 
196  return new Repository(repo, ioManager, eventConsumer, credentialsProvider, repositoryLogger, () =>
197  {
198  logger.LogTrace("Releasing semaphore due to Repository disposal...");
199  semaphore.Release();
200  });
201  }
202 
204  public async Task DeleteRepository(CancellationToken cancellationToken)
205  {
206  logger.LogInformation("Deleting repository...");
207  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
208  {
209  logger.LogTrace("Semaphore acquired, deleting Repository directory...");
210  await ioManager.DeleteDirectory(".", cancellationToken).ConfigureAwait(false);
211  }
212  }
213  }
214 }
Represents configurable settings for a Repository
-
Consumes EventTypes and takes the appropriate actions
+Go to the documentation of this file.
1 using LibGit2Sharp;
2 using Microsoft.Extensions.Logging;
3 using System;
4 using System.Threading;
5 using System.Threading.Tasks;
8 using Tgstation.Server.Host.IO;
9 
11 {
14  {
16  public bool InUse => semaphore.CurrentCount == 0;
17 
19  public bool CloneInProgress { get; private set; }
20 
25 
30 
35 
39  readonly ILogger<Repository> repositoryLogger;
40 
44  readonly ILogger<RepositoryManager> logger;
45 
50 
54  readonly SemaphoreSlim semaphore;
55 
66  {
67  this.repositorySettings = repositorySettings ?? throw new ArgumentNullException(nameof(repositorySettings));
68  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
69  this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
70  this.credentialsProvider = credentialsProvider ?? throw new ArgumentNullException(nameof(credentialsProvider));
71  this.repositoryLogger = repositoryLogger ?? throw new ArgumentNullException(nameof(repositoryLogger));
72  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
73  semaphore = new SemaphoreSlim(1);
74  }
75 
77  public void Dispose()
78  {
79  logger.LogTrace("Disposing...");
80  semaphore.Dispose();
81  }
82 
84  public async Task<IRepository> CloneRepository(Uri url, string initialBranch, string username, string password, Action<int> progressReporter, CancellationToken cancellationToken)
85  {
86  if (url == null)
87  throw new ArgumentNullException(nameof(url));
88  if (progressReporter == null)
89  throw new ArgumentNullException(nameof(progressReporter));
90 
91  logger.LogInformation("Begin clone {0} (Branch: {1})", url, initialBranch);
92  lock (this)
93  {
94  if (CloneInProgress)
95  throw new InvalidOperationException("The repository is already being cloned!");
96  CloneInProgress = true;
97  }
98 
99  try
100  {
101  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
102  {
103  logger.LogTrace("Semaphore acquired");
104  if (!await ioManager.DirectoryExists(".", cancellationToken).ConfigureAwait(false))
105  try
106  {
107  await Task.Factory.StartNew(() =>
108  {
109  string path = null;
110  try
111  {
112  path = LibGit2Sharp.Repository.Clone(url.ToString(), ioManager.ResolvePath("."), new CloneOptions
113  {
114  OnProgress = (a) => !cancellationToken.IsCancellationRequested,
115  OnTransferProgress = (a) =>
116  {
117  var percentage = 100 * (((float)a.IndexedObjects + a.ReceivedObjects) / (a.TotalObjects * 2));
118  progressReporter((int)percentage);
119  return !cancellationToken.IsCancellationRequested;
120  },
121  RecurseSubmodules = true,
122  OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
123  RepositoryOperationStarting = (a) => !cancellationToken.IsCancellationRequested,
124  BranchName = initialBranch,
126  });
127  }
128  catch (UserCancelledException) { }
129  cancellationToken.ThrowIfCancellationRequested();
130  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
131  }
132  catch
133  {
134  try
135  {
136  logger.LogTrace("Deleting partially cloned repository...");
137  await ioManager.DeleteDirectory(".", default).ConfigureAwait(false);
138  }
139  catch (Exception e)
140  {
141  logger.LogDebug("Error deleting partially cloned repository! Exception: {0}", e);
142  }
143 
144  throw;
145  }
146  else
147  {
148  logger.LogDebug("Repository exists, clone aborted!");
149  return null;
150  }
151  }
152 
153  logger.LogInformation("Clone complete!");
154  }
155  finally
156  {
157  CloneInProgress = false;
158  }
159 
160  return await LoadRepository(cancellationToken).ConfigureAwait(false);
161  }
162 
164  public async Task<IRepository> LoadRepository(CancellationToken cancellationToken)
165  {
166  logger.LogTrace("Begin LoadRepository...");
167  lock (this)
168  if (CloneInProgress)
169  throw new InvalidOperationException("The repository is being cloned!");
170  await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
171  LibGit2Sharp.Repository repo = null;
172  await Task.Factory.StartNew(() =>
173  {
174  try
175  {
176  logger.LogTrace("Creating LibGit2Sharp.Repository...");
177  repo = new LibGit2Sharp.Repository(ioManager.ResolvePath("."));
178  }
179  catch (RepositoryNotFoundException e)
180  {
181  logger.LogDebug("Repository not found!");
182  logger.LogTrace("Exception: {0}", e);
183  }
184  catch
185  {
186  semaphore.Release();
187  throw;
188  }
189  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
190  if (repo == null)
191  {
192  semaphore.Release();
193  return null;
194  }
195 
197  {
198  logger.LogTrace("Releasing semaphore due to Repository disposal...");
199  semaphore.Release();
200  });
201  }
202 
204  public async Task DeleteRepository(CancellationToken cancellationToken)
205  {
206  logger.LogInformation("Deleting repository...");
207  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
208  {
209  logger.LogTrace("Semaphore acquired, deleting Repository directory...");
210  await ioManager.DeleteDirectory(".", cancellationToken).ConfigureAwait(false);
211  }
212  }
213  }
214 }
Represents configurable settings for a Repository
+
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
+
Consumes EventTypes and takes the appropriate actions
- -
RepositoryManager(RepositorySettings repositorySettings, IIOManager ioManager, IEventConsumer eventConsumer, ICredentialsProvider credentialsProvider, ILogger< Repository > repositoryLogger, ILogger< RepositoryManager > logger)
Construct a RepositoryManager
-
CredentialsHandler GenerateHandler(string username, string password)
Generate a CredentialsHandler from a given username and password
-
readonly ILogger< RepositoryManager > logger
The ILogger for the RepositoryManager
- -
readonly ILogger< Repository > repositoryLogger
The ILogger created Repositorys
-
readonly SemaphoreSlim semaphore
Used for controlling single access to the IRepository
- +
RepositoryManager(RepositorySettings repositorySettings, IIOManager ioManager, IEventConsumer eventConsumer, ICredentialsProvider credentialsProvider, ILogger< Repository > repositoryLogger, ILogger< RepositoryManager > logger)
Construct a RepositoryManager
+
readonly ILogger< RepositoryManager > logger
The ILogger for the RepositoryManager
+
readonly ILogger< Repository > repositoryLogger
The ILogger created Repositorys
+
readonly SemaphoreSlim semaphore
Used for controlling single access to the IRepository
+
string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
- -
readonly ICredentialsProvider credentialsProvider
The ICredentialsProvider for the RepositoryManager
+ +
CredentialsHandler GenerateHandler(string username, string password)
Generate a CredentialsHandler from a given username and password
+ +
readonly ICredentialsProvider credentialsProvider
The ICredentialsProvider for the RepositoryManager
+ -
readonly IIOManager ioManager
The IIOManager for the RepositoryManager
- -
Factory for creating and loading IRepositorys
+
readonly IIOManager ioManager
The IIOManager for the RepositoryManager
+ + + - - -
readonly IEventConsumer eventConsumer
The IEventConsumer for the RepositoryManager
-
async Task< IRepository > CloneRepository(Uri url, string initialBranch, string username, string password, Action< int > progressReporter, CancellationToken cancellationToken)
Clone the repository at url
-
Interface for using filesystems
Definition: IIOManager.cs:11
-
async Task< IRepository > LoadRepository(CancellationToken cancellationToken)
Attempt to load the IRepository from the default location
+ +
readonly IEventConsumer eventConsumer
The IEventConsumer for the RepositoryManager
+
async Task< IRepository > CloneRepository(Uri url, string initialBranch, string username, string password, Action< int > progressReporter, CancellationToken cancellationToken)
Clone the repository at url
+
Interface for using filesystems
Definition: IIOManager.cs:11
+
async Task< IRepository > LoadRepository(CancellationToken cancellationToken)
Attempt to load the IRepository from the default location
-
async Task DeleteRepository(CancellationToken cancellationToken)
Delete the current repository
- -
static async Task< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore
-
readonly RepositorySettings repositorySettings
The RepositorySettings for the RepositoryManager
- - +
async Task DeleteRepository(CancellationToken cancellationToken)
Delete the current repository
+
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
+
readonly RepositorySettings repositorySettings
The RepositorySettings for the RepositoryManager
+ +
@@ -132,7 +113,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_repository_rights_8cs.html b/_repository_rights_8cs.html index 11a03b326d..32032ae1de 100644 --- a/_repository_rights_8cs.html +++ b/_repository_rights_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/RepositoryRights.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Api +  namespace  Tgstation.Server.Api.Rights   @@ -124,8 +109,8 @@ Enumerations   Tgstation.Server.Api.Rights.RepositoryRights.Delete = 2048, Tgstation.Server.Api.Rights.RepositoryRights.CancelClone = 4096
- } - + } +
 Rights for a Models.Repository More...
 Rights for a Models.Repository More...
 
@@ -133,7 +118,7 @@ Enumerations diff --git a/_repository_rights_8cs_source.html b/_repository_rights_8cs_source.html index b79c56c617..52cc7f16b7 100644 --- a/_repository_rights_8cs_source.html +++ b/_repository_rights_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/RepositoryRights.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
RepositoryRights.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Api.Rights
4 {
8  [Flags]
9  public enum RepositoryRights : ulong
10  {
14  None = 0,
15 
20 
24  SetOrigin = 2,
25 
29  SetSha = 4,
30 
34  MergePullRequest = 8,
35 
39  UpdateBranch = 16,
40 
44  ChangeCommitter = 32,
45 
50 
54  ChangeCredentials = 128,
55 
59  SetReference = 256,
60 
64  Read = 512,
65 
70 
74  Delete = 2048,
75 
79  CancelClone = 4096
80  }
81 }
-
User may change Models.Internal.RepositorySettings.AutoUpdatesKeepTestMerges and Models.Internal.RepositorySettings.AutoUpdatesSynchronize
- - -
User may fetch and merge GitHub pull requests
-
User may change Models.Internal.RepositorySettings.PushTestMergeCommits and Models.Internal.RepositorySettings.PostTestMergeComment
- - - -
RepositoryRights
Rights for a Models.Repository
-
User may directly set the sha the Models.Repository&#39;s HEAD points to
-
User may set Models.Repository.Reference to another git reference (not a SHA)
- -
User may create the Models.Repository if it does not exist
-
User may read and change Models.Internal.RepositorySettings.AccessUser and Models.Internal.RepositorySettings.AccessToken
-
User can read all chat settings except Models.Internal.ChatBot.ConnectionString
- -
User may change Models.Internal.RepositorySettings.CommitterName and Models.Internal.RepositorySettings.CommitterEmail
+Go to the documentation of this file.
1 using System;
2 
4 {
8  [Flags]
9  public enum RepositoryRights : ulong
10  {
14  None = 0,
15 
20 
24  SetOrigin = 2,
25 
29  SetSha = 4,
30 
34  MergePullRequest = 8,
35 
39  UpdateBranch = 16,
40 
44  ChangeCommitter = 32,
45 
50 
54  ChangeCredentials = 128,
55 
59  SetReference = 256,
60 
64  Read = 512,
65 
70 
74  Delete = 2048,
75 
79  CancelClone = 4096
80  }
81 }
+
User may change Models.Internal.RepositorySettings.AutoUpdatesKeepTestMerges and Models....
+
User may fetch and merge GitHub pull requests
+
User may change Models.Internal.RepositorySettings.PushTestMergeCommits and Models....
+ + + +
RepositoryRights
Rights for a Models.Repository
+
User may directly set the sha the Models.Repository's HEAD points to
+ +
User may set Models.Repository.Reference to another git reference (not a SHA)
+ +
User may create the Models.Repository if it does not exist
+
User may read and change Models.Internal.RepositorySettings.AccessUser and Models....
+
User can read all chat settings except Models.Internal.ChatBot.ConnectionString
+
User may change Models.Internal.RepositorySettings.CommitterName and Models.Internal....
diff --git a/_request_timeout_exception_8cs.html b/_request_timeout_exception_8cs.html index 37184c968c..b108448f04 100644 --- a/_request_timeout_exception_8cs.html +++ b/_request_timeout_exception_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/RequestTimeoutException.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_request_timeout_exception_8cs_source.html b/_request_timeout_exception_8cs_source.html index 4fe6d43046..c5717cea88 100644 --- a/_request_timeout_exception_8cs_source.html +++ b/_request_timeout_exception_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/RequestTimeoutException.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
RequestTimeoutException.cs
-Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
5 namespace Tgstation.Server.Client
6 {
11  {
16  {
17  Message = "The request timed out!",
18  SeverApiVersion = null
19  }, HttpStatusCode.RequestTimeout)
20  { }
21 
26  public RequestTimeoutException(string message) : base(message) { }
27 
33  public RequestTimeoutException(string message, Exception innerException) : base(message, innerException) { }
34  }
35 }
RequestTimeoutException()
Construct an RequestTimeoutException
+Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
6 {
11  {
16  {
17  Message = "The request timed out!",
18  SeverApiVersion = null
19  }, HttpStatusCode.RequestTimeout)
20  { }
21 
26  public RequestTimeoutException(string message) : base(message) { }
27 
33  public RequestTimeoutException(string message, Exception innerException) : base(message, innerException) { }
34  }
35 }
RequestTimeoutException()
Construct an RequestTimeoutException
- - + -
RequestTimeoutException(string message, Exception innerException)
Construct an RequestTimeoutException with a message and innerException
-
Occurs when the client provides invalid credentials
- -
RequestTimeoutException(string message)
Construct an RequestTimeoutException with a message
-
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- -
Exceptions thrown by IServerClients
+
RequestTimeoutException(string message, Exception innerException)
Construct an RequestTimeoutException with a message and innerException
+
Occurs when the client provides invalid credentials
+ +
RequestTimeoutException(string message)
Construct an RequestTimeoutException with a message
+
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+ +
Exceptions thrown by IServerClients
diff --git a/_resolving_i_o_manager_8cs.html b/_resolving_i_o_manager_8cs.html index bd306b900d..4cbab0875b 100644 --- a/_resolving_i_o_manager_8cs.html +++ b/_resolving_i_o_manager_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/ResolvingIOManager.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.IO.ResolvingIOManager - An IIOManager that resolve relative paths from another IIOManager to a subdirectory of that More...
+ An IIOManager that resolve relative paths from another IIOManager to a subdirectory of that More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.IO
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_resolving_i_o_manager_8cs_source.html b/_resolving_i_o_manager_8cs_source.html index f585a7a1d3..183274d51e 100644 --- a/_resolving_i_o_manager_8cs_source.html +++ b/_resolving_i_o_manager_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/ResolvingIOManager.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ResolvingIOManager.cs
-Go to the documentation of this file.
1 using System;
2 using System.IO;
3 
4 namespace Tgstation.Server.Host.IO
5 {
10  {
14  readonly string subdirectory;
15 
21  public ResolvingIOManager(IIOManager parent, string subdirectory)
22  {
23  if (parent == null)
24  throw new ArgumentNullException(nameof(parent));
25  if (subdirectory == null)
26  throw new ArgumentNullException(nameof(subdirectory));
27 
28  this.subdirectory = ConcatPath(parent.ResolvePath("."), subdirectory);
29  }
30 
32  public override string ResolvePath(string path)
33  {
34  if (!Path.IsPathRooted(path))
35  return base.ResolvePath(ConcatPath(subdirectory, path));
36  return path;
37  }
38  }
39 }
An IIOManager that resolve relative paths from another IIOManager to a subdirectory of that ...
- - +Go to the documentation of this file.
1 using System;
2 using System.IO;
3 
5 {
10  {
14  readonly string subdirectory;
15 
22  {
23  if (parent == null)
24  throw new ArgumentNullException(nameof(parent));
25  if (subdirectory == null)
26  throw new ArgumentNullException(nameof(subdirectory));
27 
28  this.subdirectory = ConcatPath(parent.ResolvePath("."), subdirectory);
29  }
30 
32  public override string ResolvePath(string path)
33  {
34  if (!Path.IsPathRooted(path))
35  return base.ResolvePath(ConcatPath(subdirectory, path));
36  return path;
37  }
38  }
39 }
string ConcatPath(params string[] paths)
Combines an array of strings into a path
+
An IIOManager that resolve relative paths from another IIOManager to a subdirectory of that
string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
-
ResolvingIOManager(IIOManager parent, string subdirectory)
Construct a ResolvingIOManager
+
ResolvingIOManager(IIOManager parent, string subdirectory)
Construct a ResolvingIOManager
override string ResolvePath(string path)
Retrieve the full path of some path given a relative path. Must be used before passing relative path...
-
IIOManager that resolves paths to Environment.CurrentDirectory
-
Interface for using filesystems
Definition: IIOManager.cs:11
-
readonly string subdirectory
Path to the subdirectory attached to path resolutions
- +
IIOManager that resolves paths to Environment.CurrentDirectory
+
Interface for using filesystems
Definition: IIOManager.cs:11
+
readonly string subdirectory
Path to the subdirectory attached to path resolutions
+
diff --git a/_response_8cs.html b/_response_8cs.html index 4b8a7d02b6..a418304111 100644 --- a/_response_8cs.html +++ b/_response_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Response.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_response_8cs_source.html b/_response_8cs_source.html index 04f23dd36c..f32d9b74ba 100644 --- a/_response_8cs_source.html +++ b/_response_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Response.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Response.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 
3 namespace Tgstation.Server.Host.Components.Chat
4 {
8  sealed class Response
9  {
13  public string Message { get; set; }
14 
18  public List<ulong> ChannelIds { get; set; }
19  }
20 }
- - -
Represents a chat message requested by DD
Definition: Response.cs:8
+Go to the documentation of this file.
1 using System.Collections.Generic;
2 
4 {
8  sealed class Response
9  {
13  public string Message { get; set; }
14 
18  public List<ulong> ChannelIds { get; set; }
19  }
20 }
+ +
List< ulong > ChannelIds
The list of internal channel ids to send Message to
Definition: Response.cs:18
+
Represents a chat message requested by DD
Definition: Response.cs:8
diff --git a/_restart_registration_8cs.html b/_restart_registration_8cs.html index c241f991da..57feab1a10 100644 --- a/_restart_registration_8cs.html +++ b/_restart_registration_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/RestartRegistration.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_restart_registration_8cs_source.html b/_restart_registration_8cs_source.html index 075e864128..8c5f2428dc 100644 --- a/_restart_registration_8cs_source.html +++ b/_restart_registration_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/RestartRegistration.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
RestartRegistration.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Host.Core
4 {
7  {
11  readonly Action onDispose;
12 
17  public RestartRegistration(Action onDispose)
18  {
19  this.onDispose = onDispose ?? throw new ArgumentNullException(nameof(onDispose));
20  }
21 
23  public void Dispose() => onDispose();
24  }
25 }
- +Go to the documentation of this file.
1 using System;
2 
4 {
7  {
11  readonly Action onDispose;
12 
18  {
19  this.onDispose = onDispose ?? throw new ArgumentNullException(nameof(onDispose));
20  }
21 
23  public void Dispose() => onDispose();
24  }
25 }
-
readonly Action onDispose
The Dispose Action
-
Represents the lifetime of a IRestartHandler registration
-
RestartRegistration(Action onDispose)
Construct a RestartRegistration
- + +
readonly Action onDispose
The Dispose Action
+
Represents the lifetime of a IRestartHandler registration
+
RestartRegistration(Action onDispose)
Construct a RestartRegistration
diff --git a/_rev_info_test_merge_8cs.html b/_rev_info_test_merge_8cs.html index ec6438c052..673a36c601 100644 --- a/_rev_info_test_merge_8cs.html +++ b/_rev_info_test_merge_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/RevInfoTestMerge.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_rev_info_test_merge_8cs_source.html b/_rev_info_test_merge_8cs_source.html index caffe4db2d..91f52a2fb2 100644 --- a/_rev_info_test_merge_8cs_source.html +++ b/_rev_info_test_merge_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/RevInfoTestMerge.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
RevInfoTestMerge.cs
-Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
3 namespace Tgstation.Server.Host.Models
4 {
8  public sealed class RevInfoTestMerge
9  {
13  public long Id { get; set; }
14 
18  [Required]
19  public TestMerge TestMerge { get; set; }
20 
24  [Required]
26  }
27 }
- -
Many to many relationship for Models.RevisionInformation and Models.TestMerge
+Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
4 {
8  public sealed class RevInfoTestMerge
9  {
13  public long Id { get; set; }
14 
18  [Required]
19  public TestMerge TestMerge { get; set; }
20 
24  [Required]
26  }
27 }
+
Many to many relationship for Models.RevisionInformation and Models.TestMerge
+ -
diff --git a/_revision_command_8cs.html b/_revision_command_8cs.html index 397bc8a15c..e8dc258731 100644 --- a/_revision_command_8cs.html +++ b/_revision_command_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/RevisionCommand.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Components.Chat.Commands.RevisionCommand - For displaying Api.Models.Internal.RevisionInformation More...
+ For displaying Api.Models.Internal.RevisionInformation More...
  + + + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
namespace  Tgstation.Server.Host.Components.Chat.Commands
 
@@ -114,7 +103,7 @@ Namespaces diff --git a/_revision_command_8cs_source.html b/_revision_command_8cs_source.html index efd6f09fbb..27e1891bc1 100644 --- a/_revision_command_8cs_source.html +++ b/_revision_command_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/RevisionCommand.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
RevisionCommand.cs
-Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Globalization;
4 using System.Linq;
5 using System.Threading;
6 using System.Threading.Tasks;
9 
10 namespace Tgstation.Server.Host.Components.Chat.Commands
11 {
15  sealed class RevisionCommand : ICommand
16  {
18  public string Name => "revision";
19 
21  public string HelpText => "Display live commit sha. Add --repo to view repository revision";
22 
24  public bool AdminOnly => false;
25 
29  readonly IWatchdog watchdog;
30 
35 
39  readonly Models.Instance instance;
40 
47  public RevisionCommand(IWatchdog watchdog, IRepositoryManager repositoryManager, Models.Instance instance)
48  {
49  this.watchdog = watchdog ?? throw new ArgumentNullException(nameof(watchdog));
50  this.repositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager));
51  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
52  }
53 
55  public async Task<string> Invoke(string arguments, User user, CancellationToken cancellationToken)
56  {
57  string result;
58  if (arguments.Split(' ').Any(x => x.ToUpperInvariant() == "--REPO"))
59  using (var repo = await repositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false))
60  {
61  if (repo == null)
62  return "Repository unavailable!";
63  result = repo.Head;
64  }
65  else
66  {
67  if (!watchdog.Running)
68  return "Server offline!";
69  result = watchdog.ActiveCompileJob?.RevisionInformation.CommitSha;
70  }
71 
72  return String.Format(CultureInfo.InvariantCulture, "^{0}", result);
73  }
74  }
75 }
- -
readonly IRepositoryManager repositoryManager
The IRepositoryManager for the PullRequestsCommand
- +Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Globalization;
4 using System.Linq;
5 using System.Threading;
6 using System.Threading.Tasks;
9 
11 {
15  sealed class RevisionCommand : ICommand
16  {
18  public string Name => "revision";
19 
21  public string HelpText => "Display live commit sha. Add --repo to view repository revision";
22 
24  public bool AdminOnly => false;
25 
29  readonly IWatchdog watchdog;
30 
35 
39  readonly Models.Instance instance;
40 
48  {
49  this.watchdog = watchdog ?? throw new ArgumentNullException(nameof(watchdog));
50  this.repositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager));
51  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
52  }
53 
55  public async Task<string> Invoke(string arguments, User user, CancellationToken cancellationToken)
56  {
57  string result;
58  if (arguments.Split(' ').Any(x => x.ToUpperInvariant() == "--REPO"))
59  using (var repo = await repositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false))
60  {
61  if (repo == null)
62  return "Repository unavailable!";
63  result = repo.Head;
64  }
65  else
66  {
67  if (!watchdog.Running)
68  return "Server offline!";
69  result = watchdog.ActiveCompileJob?.RevisionInformation.CommitSha;
70  }
71 
72  return String.Format(CultureInfo.InvariantCulture, "^{0}", result);
73  }
74  }
75 }
+ +
readonly IRepositoryManager repositoryManager
The IRepositoryManager for the PullRequestsCommand
+ +
Models.CompileJob ActiveCompileJob
The CompileJob currently running on the server
Definition: IWatchdog.cs:27
-
async Task< string > Invoke(string arguments, User user, CancellationToken cancellationToken)
Invoke the ICommand
-
readonly IWatchdog watchdog
The IWatchdog for the PullRequestsCommand
-
readonly Models.Instance instance
The Models.Instance for the PullRequestsCommand
-
RevisionCommand(IWatchdog watchdog, IRepositoryManager repositoryManager, Models.Instance instance)
Construct a RevisionCommand
-
For displaying Api.Models.Internal.RevisionInformation
-
Represents a tgs_chat_user datum
Definition: User.cs:10
- -
Factory for creating and loading IRepositorys
- - -
Represents a command that can be invoked by talking to chat bots
Definition: ICommand.cs:9
- -
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
+
async Task< string > Invoke(string arguments, User user, CancellationToken cancellationToken)
Invoke the ICommand
+
readonly IWatchdog watchdog
The IWatchdog for the PullRequestsCommand
+ +
readonly Models.Instance instance
The Models.Instance for the PullRequestsCommand
+
Task< IRepository > LoadRepository(CancellationToken cancellationToken)
Attempt to load the IRepository from the default location
+
RevisionCommand(IWatchdog watchdog, IRepositoryManager repositoryManager, Models.Instance instance)
Construct a RevisionCommand
+ +
For displaying Api.Models.Internal.RevisionInformation
+
Represents a tgs_chat_user datum
Definition: User.cs:10
+ + + +
bool Running
If the watchdog is running
Definition: IWatchdog.cs:17
+ +
Represents a command that can be invoked by talking to chat bots
Definition: ICommand.cs:9
+ +
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
diff --git a/_rights_helper_8cs.html b/_rights_helper_8cs.html index d89b2fee5f..dc2201a64e 100644 --- a/_rights_helper_8cs.html +++ b/_rights_helper_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/RightsHelper.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Api.Rights.RightsHelper - Helper for RightsTypes More...
+ Helper for RightsTypes More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Rights
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_rights_helper_8cs_source.html b/_rights_helper_8cs_source.html index c41c17bfc2..29a4ffbd8f 100644 --- a/_rights_helper_8cs_source.html +++ b/_rights_helper_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/RightsHelper.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
RightsHelper.cs
-Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Globalization;
4 
5 namespace Tgstation.Server.Api.Rights
6 {
10  public static class RightsHelper
11  {
15  static readonly IReadOnlyDictionary<RightsType, Type> TypeMap = new Dictionary<RightsType, Type>
16  {
17  { RightsType.Administration, typeof(AdministrationRights) },
18  { RightsType.InstanceManager, typeof(InstanceManagerRights) },
19  { RightsType.Repository, typeof(RepositoryRights) },
20  { RightsType.Byond, typeof(ByondRights) },
21  { RightsType.DreamMaker, typeof(DreamMakerRights) },
22  { RightsType.DreamDaemon, typeof(DreamDaemonRights) },
23  { RightsType.ChatBots, typeof(ChatBotRights) },
24  { RightsType.Configuration, typeof(ConfigurationRights) },
25  { RightsType.InstanceUser, typeof(InstanceUserRights) }
26  };
27 
33  public static Type RightToType(RightsType rightsType) => TypeMap[rightsType];
34 
41  public static string RoleNames<TRight>(TRight right) where TRight : Enum
42  {
43  var flags = new List<string>();
44  IEnumerable<string> GetRoleNames()
45  {
46  foreach (Enum J in Enum.GetValues(right.GetType()))
47  if (Convert.ToInt32(J, CultureInfo.InvariantCulture) != 0 && right.HasFlag(J))
48  yield return String.Concat(typeof(TRight).Name, '.', J.ToString());
49  }
50 
51  var names = GetRoleNames();
52  return String.Join(",", names);
53  }
54 
61  public static string RoleName(RightsType rightsType, Enum right)
62  {
63  var enumType = TypeMap[rightsType];
64  return String.Concat(enumType.Name, '.', Enum.GetName(enumType, right));
65  }
66 
72  public static bool IsInstanceRight(RightsType rightsType) => !(rightsType == RightsType.Administration || rightsType == RightsType.InstanceManager);
73  }
74 }
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
-
InstanceUserRights
Rights for an Models.Instance
- - -
AdministrationRights
Rights for Models.Administration
-
DreamDaemonRights
Rights for Models.DreamDaemon
-
InstanceManagerRights
Rights for managing Models.Instances
-
DreamMakerRights
Rights for Models.DreamMaker
-
RepositoryRights
Rights for a Models.Repository
-
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
-
static string RoleName(RightsType rightsType, Enum right)
Gets the role claim name used for a given rightsType and right
Definition: RightsHelper.cs:61
- +Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Globalization;
4 
6 {
10  public static class RightsHelper
11  {
15  static readonly IReadOnlyDictionary<RightsType, Type> TypeMap = new Dictionary<RightsType, Type>
16  {
17  { RightsType.Administration, typeof(AdministrationRights) },
18  { RightsType.InstanceManager, typeof(InstanceManagerRights) },
19  { RightsType.Repository, typeof(RepositoryRights) },
20  { RightsType.Byond, typeof(ByondRights) },
21  { RightsType.DreamMaker, typeof(DreamMakerRights) },
22  { RightsType.DreamDaemon, typeof(DreamDaemonRights) },
23  { RightsType.ChatBots, typeof(ChatBotRights) },
24  { RightsType.Configuration, typeof(ConfigurationRights) },
25  { RightsType.InstanceUser, typeof(InstanceUserRights) }
26  };
27 
33  public static Type RightToType(RightsType rightsType) => TypeMap[rightsType];
34 
41  public static string RoleNames<TRight>(TRight right) where TRight : Enum
42  {
43  var flags = new List<string>();
44  IEnumerable<string> GetRoleNames()
45  {
46  foreach (Enum J in Enum.GetValues(right.GetType()))
47  if (Convert.ToInt32(J, CultureInfo.InvariantCulture) != 0 && right.HasFlag(J))
48  yield return String.Concat(typeof(TRight).Name, '.', J.ToString());
49  }
50 
51  var names = GetRoleNames();
52  return String.Join(",", names);
53  }
54 
61  public static string RoleName(RightsType rightsType, Enum right)
62  {
63  var enumType = TypeMap[rightsType];
64  return String.Concat(enumType.Name, '.', Enum.GetName(enumType, right));
65  }
66 
72  public static bool IsInstanceRight(RightsType rightsType) => !(rightsType == RightsType.Administration || rightsType == RightsType.InstanceManager);
73  }
74 }
static bool IsInstanceRight(RightsType rightsType)
Check if a given rightsType is meant for an Models.Instance
+
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
+
InstanceUserRights
Rights for an Models.Instance
+
AdministrationRights
Rights for Models.Administration
+
DreamDaemonRights
Rights for Models.DreamDaemon
+
InstanceManagerRights
Rights for managing Models.Instances
+
static string RoleNames< TRight >(TRight right)
Gets the role claim name used for a given right
Definition: RightsHelper.cs:41
+
DreamMakerRights
Rights for Models.DreamMaker
+
RepositoryRights
Rights for a Models.Repository
+ +
static Type RightToType(RightsType rightsType)
Map a given rightsType to its respective Enum Type
+
static readonly IReadOnlyDictionary< RightsType, Type > TypeMap
Map of RightsTypes to their respective flag Enums
Definition: RightsHelper.cs:15
+
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
+
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/_rights_type_8cs.html b/_rights_type_8cs.html index edd26cca09..0a3fe36b67 100644 --- a/_rights_type_8cs.html +++ b/_rights_type_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/RightsType.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Api +  namespace  Tgstation.Server.Api.Rights   @@ -118,8 +103,8 @@ Enumerations
  Tgstation.Server.Api.Rights.RightsType.InstanceUser
- } - + } +
 The type of rights a model uses More...
 The type of rights a model uses More...
 
@@ -127,7 +112,7 @@ Enumerations diff --git a/_rights_type_8cs_source.html b/_rights_type_8cs_source.html index f4aa042ece..07e707fd3f 100644 --- a/_rights_type_8cs_source.html +++ b/_rights_type_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights/RightsType.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
RightsType.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Api.Rights
2 {
6  public enum RightsType : ulong
7  {
12 
17 
21  Repository,
22 
26  Byond,
27 
31  DreamMaker,
32 
37 
41  ChatBots,
42 
47 
52  }
53 }
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
- - - - - - - - - - - +Go to the documentation of this file.
diff --git a/_routes_8cs.html b/_routes_8cs.html index 3f26c0121a..aa0beba876 100644 --- a/_routes_8cs.html +++ b/_routes_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Routes.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Api.RoutesRoutes to a server actions More...
Routes to a server actions More...
  + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_routes_8cs_source.html b/_routes_8cs_source.html index 6e4befd909..96993efc9f 100644 --- a/_routes_8cs_source.html +++ b/_routes_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Routes.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Routes.cs
-Go to the documentation of this file.
1 using System;
2 using System.Globalization;
3 
4 namespace Tgstation.Server.Api
5 {
9  public static class Routes
10  {
14  public const string Root = "/";
15 
19  public const string Administration = Root + nameof(Models.Administration);
20 
24  public const string User = Root + nameof(Models.User);
25 
29  public const string InstanceManager = Root + nameof(Models.Instance);
30 
34  public const string Byond = Root + nameof(Models.Byond);
35 
39  public const string Repository = Root + nameof(Models.Repository);
40 
44  public const string DreamDaemon = Root + nameof(Models.DreamDaemon);
45 
49  public const string Configuration = Root + "Config";
50 
54  public const string File = "File";
55 
59  public const string ConfigurationFile = Configuration + "/" + File;
60 
64  public const string InstanceUser = Root + nameof(Models.InstanceUser);
65 
69  public const string Chat = Root + "Chat";
70 
74  public const string DreamMaker = Root + nameof(Models.DreamMaker);
75 
79  public const string Jobs = Root + nameof(Models.Job);
80 
87  public static string SetID(string route, long id) => String.Format(CultureInfo.InvariantCulture, "{0}/{1}", route, id);
88 
94  public static string List(string route) => String.Format(CultureInfo.InvariantCulture, "{0}/List", route);
95  }
96 }
- -
Routes to a server actions
Definition: Routes.cs:9
- +Go to the documentation of this file.
1 using System;
2 using System.Globalization;
3 
4 namespace Tgstation.Server.Api
5 {
9  public static class Routes
10  {
14  public const string Root = "/";
15 
19  public const string Administration = Root + nameof(Models.Administration);
20 
24  public const string User = Root + nameof(Models.User);
25 
29  public const string InstanceManager = Root + nameof(Models.Instance);
30 
34  public const string Byond = Root + nameof(Models.Byond);
35 
39  public const string Repository = Root + nameof(Models.Repository);
40 
44  public const string DreamDaemon = Root + nameof(Models.DreamDaemon);
45 
49  public const string Configuration = Root + "Config";
50 
54  public const string File = "File";
55 
59  public const string ConfigurationFile = Configuration + "/" + File;
60 
64  public const string InstanceUser = Root + nameof(Models.InstanceUser);
65 
69  public const string Chat = Root + "Chat";
70 
74  public const string DreamMaker = Root + nameof(Models.DreamMaker);
75 
79  public const string Jobs = Root + nameof(Models.Job);
80 
87  public static string SetID(string route, long id) => String.Format(CultureInfo.InvariantCulture, "{0}/{1}", route, id);
88 
94  public static string List(string route) => String.Format(CultureInfo.InvariantCulture, "{0}/List", route);
95  }
96 }
const string Byond
The Models.Byond controller
Definition: Routes.cs:34
+
const string Configuration
The Models.ConfigurationFile controller
Definition: Routes.cs:49
+
const string User
The Models.User controller
Definition: Routes.cs:24
+ +
const string InstanceUser
The Models.InstanceUser controller
Definition: Routes.cs:64
+
const string File
To be paired with Configuration for accessing Models.ConfigurationFiles
Definition: Routes.cs:54
+
const string Administration
The Models.Administration controller
Definition: Routes.cs:19
+
Routes to a server actions
Definition: Routes.cs:9
+
const string Repository
The Models.Repository controller
Definition: Routes.cs:39
+
const string Chat
The Models.ChatBot controller
Definition: Routes.cs:69
+
const string DreamMaker
The Models.DreamMaker controller
Definition: Routes.cs:74
+
const string Root
The root controller
Definition: Routes.cs:14
+
const string Jobs
The Models.Job controller
Definition: Routes.cs:79
+
const string DreamDaemon
The Models.DreamDaemon controller
Definition: Routes.cs:44
+
const string InstanceManager
The Models.Instance controller
Definition: Routes.cs:29
+
static string SetID(string route, long id)
Apply an id postfix to a route
+
static string List(string route)
Get the /List postfix for a route
+
const string ConfigurationFile
Full combination of Configuration and File
Definition: Routes.cs:59
diff --git a/_semaphore_slim_context_8cs.html b/_semaphore_slim_context_8cs.html index fe2b37222d..54ddde86db 100644 --- a/_semaphore_slim_context_8cs.html +++ b/_semaphore_slim_context_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/SemaphoreSlimContext.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_semaphore_slim_context_8cs_source.html b/_semaphore_slim_context_8cs_source.html index 1f8721bf74..a360b72c42 100644 --- a/_semaphore_slim_context_8cs_source.html +++ b/_semaphore_slim_context_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/SemaphoreSlimContext.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
SemaphoreSlimContext.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
5 namespace Tgstation.Server.Host.Core
6 {
10  public sealed class SemaphoreSlimContext : IDisposable
11  {
18  public static async Task<SemaphoreSlimContext> Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
19  {
20  if (semaphore == null)
21  throw new ArgumentNullException(nameof(semaphore));
22  await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
23  cancellationToken.ThrowIfCancellationRequested();
24  return new SemaphoreSlimContext(semaphore);
25  }
26 
30  readonly SemaphoreSlim lockedSemaphore;
31 
35  bool disposed;
36 
41  SemaphoreSlimContext(SemaphoreSlim lockedSemaphore)
42  {
43  this.lockedSemaphore = lockedSemaphore;
44  }
45 
49 #pragma warning disable CA1821 // Remove empty Finalizers //TODO remove this when https://github.com/dotnet/roslyn-analyzers/issues/1241 is fixed
50  ~SemaphoreSlimContext() => Dispose();
51 #pragma warning restore CA1821 // Remove empty Finalizers
52 
56  public void Dispose()
57  {
58  lock (this)
59  {
60  if (disposed)
61  return;
62  disposed = true;
63  }
64 
65  GC.SuppressFinalize(this);
66  lockedSemaphore.Release();
67  }
68  }
69 }
- -
readonly SemaphoreSlim lockedSemaphore
The locked SemaphoreSlim
-
SemaphoreSlimContext(SemaphoreSlim lockedSemaphore)
Construct a SemaphoreSlimContext
- -
void Dispose()
Release the lock on lockedSemaphore
+Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
6 {
10  public sealed class SemaphoreSlimContext : IDisposable
11  {
18  public static async Task<SemaphoreSlimContext> Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
19  {
20  if (semaphore == null)
21  throw new ArgumentNullException(nameof(semaphore));
22  await semaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
23  cancellationToken.ThrowIfCancellationRequested();
24  return new SemaphoreSlimContext(semaphore);
25  }
26 
30  readonly SemaphoreSlim lockedSemaphore;
31 
35  bool disposed;
36 
42  {
43  this.lockedSemaphore = lockedSemaphore;
44  }
45 
49 #pragma warning disable CA1821 // Remove empty Finalizers //TODO remove this when https://github.com/dotnet/roslyn-analyzers/issues/1241 is fixed
51 #pragma warning restore CA1821 // Remove empty Finalizers
52 
56  public void Dispose()
57  {
58  lock (this)
59  {
60  if (disposed)
61  return;
62  disposed = true;
63  }
64 
65  GC.SuppressFinalize(this);
66  lockedSemaphore.Release();
67  }
68  }
69 }
~SemaphoreSlimContext()
Finalizes an instance of the SemaphoreSlimContext class.
+
readonly SemaphoreSlim lockedSemaphore
The locked SemaphoreSlim
+
SemaphoreSlimContext(SemaphoreSlim lockedSemaphore)
Construct a SemaphoreSlimContext
+ + +
void Dispose()
Release the lock on lockedSemaphore
-
static async Task< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore
- - +
static async Task< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore
+
diff --git a/_server_8cs.html b/_server_8cs.html index bad8ff54df..b8f0c54059 100644 --- a/_server_8cs.html +++ b/_server_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Server.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
@@ -113,7 +96,7 @@ Namespaces diff --git a/_server_8cs_source.html b/_server_8cs_source.html index 5036acc7fa..6fc7d514a7 100644 --- a/_server_8cs_source.html +++ b/_server_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Server.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Server.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Hosting;
2 using Microsoft.Extensions.DependencyInjection;
3 using Microsoft.Extensions.Logging;
4 using Microsoft.Extensions.Options;
5 using System;
6 using System.Collections.Generic;
7 using System.IO;
8 using System.Linq;
9 using System.Threading;
10 using System.Threading.Tasks;
13 using Tgstation.Server.Host.IO;
14 
15 namespace Tgstation.Server.Host
16 {
18 #pragma warning disable CA1001 // Types that own disposable fields should be disposable
19  sealed class Server : IServer, IServerControl
20 #pragma warning restore CA1001 // Types that own disposable fields should be disposable
21  {
23  public bool RestartRequested { get; private set; }
24 
26  public bool WatchdogPresent => updatePath != null;
27 
31  readonly IWebHostBuilder webHostBuilder;
32 
36  readonly List<IRestartHandler> restartHandlers;
37 
41  readonly string updatePath;
42 
46  ILogger<Server> logger;
47 
52 
56  CancellationTokenSource cancellationTokenSource;
57 
62 
66  bool updating;
67 
73  public Server(IWebHostBuilder webHostBuilder, string updatePath)
74  {
75  this.webHostBuilder = webHostBuilder ?? throw new ArgumentNullException(nameof(webHostBuilder));
76  this.updatePath = updatePath;
77 
78  webHostBuilder.ConfigureServices(serviceCollection => serviceCollection.AddSingleton<IServerControl>(this));
79 
80  restartHandlers = new List<IRestartHandler>();
81  }
82 
87  void CheckSanity(bool checkWatchdog)
88  {
89  if (checkWatchdog && !WatchdogPresent && propagatedException == null)
90  throw new InvalidOperationException("Server restarts are not supported");
91 
92  if (cancellationTokenSource == null || logger == null)
93  throw new InvalidOperationException("Tried to control a non-running Server!");
94  }
95 
100  {
101  if (propagatedException != null)
102  throw propagatedException;
103  }
104 
106  public async Task RunAsync(CancellationToken cancellationToken)
107  {
108  using (cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
109  using (var fsWatcher = updatePath != null ? new FileSystemWatcher(Path.GetDirectoryName(updatePath)) : null)
110  {
111  if (fsWatcher != null)
112  {
113  fsWatcher.Created += (a, b) =>
114  {
115  if (b.FullPath == updatePath && File.Exists(b.FullPath))
116  cancellationTokenSource.Cancel();
117  };
118  fsWatcher.EnableRaisingEvents = true;
119  }
120 
121  using (var webHost = webHostBuilder.Build())
122  try
123  {
124  logger = webHost.Services.GetRequiredService<ILogger<Server>>();
125  var generalConfigurationOptions = webHost.Services.GetRequiredService<IOptions<GeneralConfiguration>>();
126  generalConfiguration = generalConfigurationOptions.Value;
127  await webHost.RunAsync(cancellationTokenSource.Token).ConfigureAwait(false);
128  }
129  catch (OperationCanceledException)
130  {
131  CheckExceptionPropagation();
132  throw;
133  }
134  }
135 
136  CheckExceptionPropagation();
137  }
138 
140  public bool ApplyUpdate(Version version, Uri updateZipUrl, IIOManager ioManager)
141  {
142  if (version == null)
143  throw new ArgumentNullException(nameof(version));
144  if (updateZipUrl == null)
145  throw new ArgumentNullException(nameof(updateZipUrl));
146  if (ioManager == null)
147  throw new ArgumentNullException(nameof(ioManager));
148 
149  CheckSanity(true);
150 
151  logger.LogTrace("Begin ApplyUpdate...");
152 
153  lock (this)
154  {
155  if (updating || RestartRequested)
156  {
157  logger.LogTrace("Aborted due to concurrency conflict!");
158  return false;
159  }
160 
161  updating = true;
162  }
163 
164  async void RunUpdate()
165  {
166  try
167  {
168  logger.LogInformation("Updating server to version {0} ({1})...", version, updateZipUrl);
169 
170  if (cancellationTokenSource == null)
171  throw new InvalidOperationException("Tried to update a non-running Server!");
172  var cancellationToken = cancellationTokenSource.Token;
173 
174  logger.LogTrace("Downloading zip package...");
175  var updateZipData = await ioManager.DownloadFile(updateZipUrl, cancellationToken).ConfigureAwait(false);
176 
177  try
178  {
179  logger.LogTrace("Exctracting zip package to {0}...", updatePath);
180  await ioManager.ZipToDirectory(updatePath, updateZipData, cancellationToken).ConfigureAwait(false);
181  }
182  catch (Exception e)
183  {
184  updating = false;
185  try
186  {
187  // important to not leave this directory around if possible
188  await ioManager.DeleteDirectory(updatePath, default).ConfigureAwait(false);
189  }
190  catch (Exception e2)
191  {
192  throw new AggregateException(e, e2);
193  }
194 
195  throw;
196  }
197 
198  await Restart(version, null).ConfigureAwait(false);
199  }
200  catch (OperationCanceledException)
201  {
202  logger.LogInformation("Server update cancelled!");
203  }
204  catch (Exception e)
205  {
206  logger.LogError("Error updating server! Exception: {0}", e);
207  }
208  finally
209  {
210  updating = false;
211  }
212  }
213 
214  RunUpdate();
215  return true;
216  }
217 
220  {
221  if (handler == null)
222  throw new ArgumentNullException(nameof(handler));
223 
224  CheckSanity(false);
225 
226  lock (this)
227  if (!RestartRequested)
228  {
229  logger.LogTrace("Registering restart handler {0}...", handler);
230  restartHandlers.Add(handler);
231  return new RestartRegistration(() =>
232  {
233  lock (this)
234  if (!RestartRequested)
235  restartHandlers.Remove(handler);
236  });
237  }
238 
239  return new RestartRegistration(() => { });
240  }
241 
243  public Task Restart() => Restart(null, null);
244 
251  async Task Restart(Version newVersion, Exception exception)
252  {
253  CheckSanity(true);
254 
255  logger.LogTrace("Begin Restart...");
256 
257  lock (this)
258  {
259  if ((updating && newVersion == null) || RestartRequested)
260  {
261  logger.LogTrace("Aborted due to concurrency conflict!");
262  return;
263  }
264 
265  RestartRequested = true;
266  propagatedException = exception;
267  }
268 
269  if (exception == null)
270  using (var cts = new CancellationTokenSource())
271  {
272  logger.LogInformation("Restarting server...");
273  var cancellationToken = cts.Token;
274  var eventsTask = Task.WhenAll(restartHandlers.Select(x => x.HandleRestart(newVersion, cancellationToken)).ToList());
275 
276  var expiryTask = Task.Delay(TimeSpan.FromMilliseconds(generalConfiguration.RestartTimeout));
277  await Task.WhenAny(eventsTask, expiryTask).ConfigureAwait(false);
278  logger.LogTrace("Joining restart handlers...");
279  cts.Cancel();
280  try
281  {
282  await eventsTask.ConfigureAwait(false);
283  }
284  catch (OperationCanceledException) { }
285  catch (Exception e)
286  {
287  logger.LogError("Restart handlers error! Exception: {0}", e);
288  }
289  }
290 
291  logger.LogTrace("Stopping host...");
292  cancellationTokenSource.Cancel();
293  }
294 
296  public Task Die(Exception exception) => Restart(null, exception);
297  }
298 }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
-
ILogger< Server > logger
The ILogger for the Server
Definition: Server.cs:46
-
async Task RunAsync(CancellationToken cancellationToken)
Runs the IServer
Definition: Server.cs:106
+Go to the documentation of this file.
1 using Microsoft.AspNetCore.Hosting;
2 using Microsoft.Extensions.DependencyInjection;
3 using Microsoft.Extensions.Logging;
4 using Microsoft.Extensions.Options;
5 using System;
6 using System.Collections.Generic;
7 using System.IO;
8 using System.Linq;
9 using System.Threading;
10 using System.Threading.Tasks;
13 using Tgstation.Server.Host.IO;
14 
15 namespace Tgstation.Server.Host
16 {
18 #pragma warning disable CA1001 // Types that own disposable fields should be disposable
19  sealed class Server : IServer, IServerControl
20 #pragma warning restore CA1001 // Types that own disposable fields should be disposable
21  {
23  public bool RestartRequested { get; private set; }
24 
26  public bool WatchdogPresent => updatePath != null;
27 
31  readonly IWebHostBuilder webHostBuilder;
32 
36  readonly List<IRestartHandler> restartHandlers;
37 
41  readonly string updatePath;
42 
46  ILogger<Server> logger;
47 
52 
56  CancellationTokenSource cancellationTokenSource;
57 
62 
66  bool updating;
67 
73  public Server(IWebHostBuilder webHostBuilder, string updatePath)
74  {
75  this.webHostBuilder = webHostBuilder ?? throw new ArgumentNullException(nameof(webHostBuilder));
76  this.updatePath = updatePath;
77 
78  webHostBuilder.ConfigureServices(serviceCollection => serviceCollection.AddSingleton<IServerControl>(this));
79 
80  restartHandlers = new List<IRestartHandler>();
81  }
82 
87  void CheckSanity(bool checkWatchdog)
88  {
89  if (checkWatchdog && !WatchdogPresent && propagatedException == null)
90  throw new InvalidOperationException("Server restarts are not supported");
91 
92  if (cancellationTokenSource == null || logger == null)
93  throw new InvalidOperationException("Tried to control a non-running Server!");
94  }
95 
100  {
101  if (propagatedException != null)
102  throw propagatedException;
103  }
104 
106  public async Task RunAsync(CancellationToken cancellationToken)
107  {
108  using (cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
109  using (var fsWatcher = updatePath != null ? new FileSystemWatcher(Path.GetDirectoryName(updatePath)) : null)
110  {
111  if (fsWatcher != null)
112  {
113  fsWatcher.Created += (a, b) =>
114  {
115  if (b.FullPath == updatePath && File.Exists(b.FullPath))
116  cancellationTokenSource.Cancel();
117  };
118  fsWatcher.EnableRaisingEvents = true;
119  }
120 
121  using (var webHost = webHostBuilder.Build())
122  try
123  {
124  logger = webHost.Services.GetRequiredService<ILogger<Server>>();
125  var generalConfigurationOptions = webHost.Services.GetRequiredService<IOptions<GeneralConfiguration>>();
126  generalConfiguration = generalConfigurationOptions.Value;
127  await webHost.RunAsync(cancellationTokenSource.Token).ConfigureAwait(false);
128  }
129  catch (OperationCanceledException)
130  {
132  throw;
133  }
134  }
135 
137  }
138 
140  public bool ApplyUpdate(Version version, Uri updateZipUrl, IIOManager ioManager)
141  {
142  if (version == null)
143  throw new ArgumentNullException(nameof(version));
144  if (updateZipUrl == null)
145  throw new ArgumentNullException(nameof(updateZipUrl));
146  if (ioManager == null)
147  throw new ArgumentNullException(nameof(ioManager));
148 
149  CheckSanity(true);
150 
151  logger.LogTrace("Begin ApplyUpdate...");
152 
153  lock (this)
154  {
155  if (updating || RestartRequested)
156  {
157  logger.LogTrace("Aborted due to concurrency conflict!");
158  return false;
159  }
160 
161  updating = true;
162  }
163 
164  async void RunUpdate()
165  {
166  try
167  {
168  logger.LogInformation("Updating server to version {0} ({1})...", version, updateZipUrl);
169 
170  if (cancellationTokenSource == null)
171  throw new InvalidOperationException("Tried to update a non-running Server!");
172  var cancellationToken = cancellationTokenSource.Token;
173 
174  logger.LogTrace("Downloading zip package...");
175  var updateZipData = await ioManager.DownloadFile(updateZipUrl, cancellationToken).ConfigureAwait(false);
176 
177  try
178  {
179  logger.LogTrace("Exctracting zip package to {0}...", updatePath);
180  await ioManager.ZipToDirectory(updatePath, updateZipData, cancellationToken).ConfigureAwait(false);
181  }
182  catch (Exception e)
183  {
184  updating = false;
185  try
186  {
187  // important to not leave this directory around if possible
188  await ioManager.DeleteDirectory(updatePath, default).ConfigureAwait(false);
189  }
190  catch (Exception e2)
191  {
192  throw new AggregateException(e, e2);
193  }
194 
195  throw;
196  }
197 
198  await Restart(version, null).ConfigureAwait(false);
199  }
200  catch (OperationCanceledException)
201  {
202  logger.LogInformation("Server update cancelled!");
203  }
204  catch (Exception e)
205  {
206  logger.LogError("Error updating server! Exception: {0}", e);
207  }
208  finally
209  {
210  updating = false;
211  }
212  }
213 
214  RunUpdate();
215  return true;
216  }
217 
220  {
221  if (handler == null)
222  throw new ArgumentNullException(nameof(handler));
223 
224  CheckSanity(false);
225 
226  lock (this)
227  if (!RestartRequested)
228  {
229  logger.LogTrace("Registering restart handler {0}...", handler);
230  restartHandlers.Add(handler);
231  return new RestartRegistration(() =>
232  {
233  lock (this)
234  if (!RestartRequested)
235  restartHandlers.Remove(handler);
236  });
237  }
238 
239  return new RestartRegistration(() => { });
240  }
241 
243  public Task Restart() => Restart(null, null);
244 
251  async Task Restart(Version newVersion, Exception exception)
252  {
253  CheckSanity(true);
254 
255  logger.LogTrace("Begin Restart...");
256 
257  lock (this)
258  {
259  if ((updating && newVersion == null) || RestartRequested)
260  {
261  logger.LogTrace("Aborted due to concurrency conflict!");
262  return;
263  }
264 
265  RestartRequested = true;
266  propagatedException = exception;
267  }
268 
269  if (exception == null)
270  using (var cts = new CancellationTokenSource())
271  {
272  logger.LogInformation("Restarting server...");
273  var cancellationToken = cts.Token;
274  var eventsTask = Task.WhenAll(restartHandlers.Select(x => x.HandleRestart(newVersion, cancellationToken)).ToList());
275 
276  var expiryTask = Task.Delay(TimeSpan.FromMilliseconds(generalConfiguration.RestartTimeout));
277  await Task.WhenAny(eventsTask, expiryTask).ConfigureAwait(false);
278  logger.LogTrace("Joining restart handlers...");
279  cts.Cancel();
280  try
281  {
282  await eventsTask.ConfigureAwait(false);
283  }
284  catch (OperationCanceledException) { }
285  catch (Exception e)
286  {
287  logger.LogError("Restart handlers error! Exception: {0}", e);
288  }
289  }
290 
291  logger.LogTrace("Stopping host...");
292  cancellationTokenSource.Cancel();
293  }
294 
296  public Task Die(Exception exception) => Restart(null, exception);
297  }
298 }
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
+
ILogger< Server > logger
The ILogger for the Server
Definition: Server.cs:46
+ +
async Task RunAsync(CancellationToken cancellationToken)
Runs the IServer
Definition: Server.cs:106
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...
Definition: Server.cs:140
-
readonly List< IRestartHandler > restartHandlers
The IRestartHandlers to run when the Server restarts
Definition: Server.cs:36
-
async Task Restart(Version newVersion, Exception exception)
Implements Restart()
Definition: Server.cs:251
- -
Task< byte[]> DownloadFile(Uri url, CancellationToken cancellationToken)
Downloads a file from url
-
IRestartRegistration RegisterForRestart(IRestartHandler handler)
Register a given handler to run before stopping the server for a restart
Definition: Server.cs:219
-
Task ZipToDirectory(string path, byte[] zipFileBytes, CancellationToken cancellationToken)
Extract a set of zipFileBytes to a given path
- +
readonly List< IRestartHandler > restartHandlers
The IRestartHandlers to run when the Server restarts
Definition: Server.cs:36
+
async Task Restart(Version newVersion, Exception exception)
Implements Restart()
Definition: Server.cs:251
+
Task< byte[]> DownloadFile(Uri url, CancellationToken cancellationToken)
Downloads a file from url
+
IRestartRegistration RegisterForRestart(IRestartHandler handler)
Register a given handler to run before stopping the server for a restart
Definition: Server.cs:219
+
Task ZipToDirectory(string path, byte[] zipFileBytes, CancellationToken cancellationToken)
Extract a set of zipFileBytes to a given path
-
GeneralConfiguration generalConfiguration
The GeneralConfiguration for the Server
Definition: Server.cs:51
-
int RestartTimeout
The timeout milliseconds for restarting the server
- -
void CheckExceptionPropagation()
Re-throw propagatedException if it exists
Definition: Server.cs:99
-
readonly string updatePath
The absolute path to install updates to
Definition: Server.cs:41
-
Represents the host
Definition: IServer.cs:9
+
GeneralConfiguration generalConfiguration
The GeneralConfiguration for the Server
Definition: Server.cs:51
+ +
int RestartTimeout
The timeout milliseconds for restarting the server
+ +
void CheckExceptionPropagation()
Re-throw propagatedException if it exists
Definition: Server.cs:99
+
readonly string updatePath
The absolute path to install updates to
Definition: Server.cs:41
+
Represents the host
Definition: IServer.cs:9
-
Server(IWebHostBuilder webHostBuilder, string updatePath)
Construct a Server
Definition: Server.cs:73
-
CancellationTokenSource cancellationTokenSource
The cancellationTokenSource for the Server
Definition: Server.cs:56
- -
bool updating
If a server update has been or is being applied
Definition: Server.cs:66
-
Exception propagatedException
The Exception to propagate when the server terminates
Definition: Server.cs:61
- +
Task Die(Exception exception)
Kill the server with a fatal exception
+
Server(IWebHostBuilder webHostBuilder, string updatePath)
Construct a Server
Definition: Server.cs:73
+
CancellationTokenSource cancellationTokenSource
The cancellationTokenSource for the Server
Definition: Server.cs:56
+
Task Restart()
Restarts the Host
+ +
bool updating
If a server update has been or is being applied
Definition: Server.cs:66
+
Exception propagatedException
The Exception to propagate when the server terminates
Definition: Server.cs:61
+ -
Interface for using filesystems
Definition: IIOManager.cs:11
-
Represents the lifetime of a IRestartHandler registration
- -
readonly IWebHostBuilder webHostBuilder
The IWebHostBuilder for the Server
Definition: Server.cs:31
- +
Interface for using filesystems
Definition: IIOManager.cs:11
+
Represents the lifetime of a IRestartHandler registration
+ +
readonly IWebHostBuilder webHostBuilder
The IWebHostBuilder for the Server
Definition: Server.cs:31
+
Represents a service that may take an updated Host assembly and run it, stopping the current assembly...
-
void CheckSanity(bool checkWatchdog)
Throws an InvalidOperationException if the IServerControl cannot be used
Definition: Server.cs:87
+
void CheckSanity(bool checkWatchdog)
Throws an InvalidOperationException if the IServerControl cannot be used
Definition: Server.cs:87
diff --git a/_server_client_8cs.html b/_server_client_8cs.html index 2428b9f16d..85fcf07761 100644 --- a/_server_client_8cs.html +++ b/_server_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ServerClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -113,7 +96,7 @@ Namespaces diff --git a/_server_client_8cs_source.html b/_server_client_8cs_source.html index 4e24ac789b..4beb7e31d1 100644 --- a/_server_client_8cs_source.html +++ b/_server_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ServerClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ServerClient.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 using Tgstation.Server.Api;
6 
7 namespace Tgstation.Server.Client
8 {
10  sealed class ServerClient : IServerClient
11  {
13  public Uri Url => apiClient.Url;
14 
16  public Token Token
17  {
18  get => token;
19  set
20  {
21  token = value ?? throw new InvalidOperationException("Cannot set a null Token!");
22  apiClient.Headers = new ApiHeaders(apiClient.Headers.UserAgent, token.Bearer);
23  }
24  }
25 
27  public TimeSpan Timeout
28  {
29  get => apiClient.Timeout;
30  set => apiClient.Timeout = value;
31  }
32 
34  public IInstanceManagerClient Instances { get; }
35 
38 
40  public IUsersClient Users { get; }
41 
46 
51 
57  public ServerClient(IApiClient apiClient, Token token)
58  {
59  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
60  this.token = token ?? throw new ArgumentNullException(nameof(token));
61 
62  if (Token.Bearer != apiClient.Headers.Token)
63  throw new ArgumentOutOfRangeException(nameof(token), token, "Provided token does not match apiClient headers!");
64 
65  Instances = new InstanceManagerClient(apiClient);
66  Users = new UsersClient(apiClient);
67  Administration = new AdministrationClient(apiClient);
68  }
69 
71  public void Dispose() => apiClient.Dispose();
72 
74  public Task<ServerInformation> Version(CancellationToken cancellationToken) => apiClient.Read<ServerInformation>(Routes.Root, cancellationToken);
75 
77  public void AddRequestLogger(IRequestLogger requestLogger) => apiClient.AddRequestLogger(requestLogger);
78  }
79 }
ServerClient(IApiClient apiClient, Token token)
Construct a ServerClient
Definition: ServerClient.cs:57
-
ApiHeaders Headers
The ApiHeaders the IApiClient uses
Definition: IApiClient.cs:16
- -
Token token
Backing field for Token
Definition: ServerClient.cs:50
+Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 using Tgstation.Server.Api;
6 
8 {
10  sealed class ServerClient : IServerClient
11  {
13  public Uri Url => apiClient.Url;
14 
16  public Token Token
17  {
18  get => token;
19  set
20  {
21  token = value ?? throw new InvalidOperationException("Cannot set a null Token!");
23  }
24  }
25 
27  public TimeSpan Timeout
28  {
29  get => apiClient.Timeout;
30  set => apiClient.Timeout = value;
31  }
32 
35 
38 
40  public IUsersClient Users { get; }
41 
46 
51 
58  {
59  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
60  this.token = token ?? throw new ArgumentNullException(nameof(token));
61 
63  throw new ArgumentOutOfRangeException(nameof(token), token, "Provided token does not match apiClient headers!");
64 
68  }
69 
71  public void Dispose() => apiClient.Dispose();
72 
74  public Task<ServerInformation> Version(CancellationToken cancellationToken) => apiClient.Read<ServerInformation>(Routes.Root, cancellationToken);
75 
77  public void AddRequestLogger(IRequestLogger requestLogger) => apiClient.AddRequestLogger(requestLogger);
78  }
79 }
+ +
ServerClient(IApiClient apiClient, Token token)
Construct a ServerClient
Definition: ServerClient.cs:57
+ +
ApiHeaders Headers
The ApiHeaders the IApiClient uses
Definition: IApiClient.cs:16
+ +
Token token
Backing field for Token
Definition: ServerClient.cs:50
- - + +
TimeSpan Timeout
The request timeout
Definition: IApiClient.cs:26
+
Task< ServerInformation > Version(CancellationToken cancellationToken)
The ServerInformation of the IServerClient
+
ProductHeaderValue UserAgent
The client's user agent as a ProductHeaderValue if valid
Definition: ApiHeaders.cs:66
-
readonly IApiClient apiClient
The IApiClient for the ServerClient
Definition: ServerClient.cs:45
-
Represents basic server information
-
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
-
Uri Url
The connected server Uri
-
Represents administrative server information
-
Routes to a server actions
Definition: Routes.cs:9
+
readonly IApiClient apiClient
The IApiClient for the ServerClient
Definition: ServerClient.cs:45
+
Represents basic server information
+
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
+
Represents administrative server information
+
Routes to a server actions
Definition: Routes.cs:9
-
Main client for communicating with a server
- +
Main client for communicating with a server
+ -
const string Root
The root controller
Definition: Routes.cs:14
-
Represents a JWT returned by the API
Definition: Token.cs:8
- -
For logging HTTP requests and responses
+
const string Root
The root controller
Definition: Routes.cs:14
+
Represents a JWT returned by the API
Definition: Token.cs:8
+ +
For logging HTTP requests and responses
- -
Web interface for the API
Definition: IApiClient.cs:11
-
string Token
The client&#39;s JWT
Definition: ApiHeaders.cs:81
-
string Bearer
The value of the JWT
Definition: Token.cs:13
- +
Uri Url
The Uri pointing the tgstation-server
Definition: IApiClient.cs:21
+
void AddRequestLogger(IRequestLogger requestLogger)
Adds a requestLogger to the request pipeline
+ +
Web interface for the API
Definition: IApiClient.cs:11
+
string Token
The client's JWT
Definition: ApiHeaders.cs:81
+ +
string Bearer
The value of the JWT
Definition: Token.cs:13
+
IInstanceManagerClient Instances
Definition: ServerClient.cs:34
+
void AddRequestLogger(IRequestLogger requestLogger)
Adds a requestLogger to the request pipeline
+
diff --git a/_server_client_factory_8cs.html b/_server_client_factory_8cs.html index b3bac5a504..3681e670bc 100644 --- a/_server_client_factory_8cs.html +++ b/_server_client_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ServerClientFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -113,7 +96,7 @@ Namespaces diff --git a/_server_client_factory_8cs_source.html b/_server_client_factory_8cs_source.html index 788cac46ec..c8cb6e938f 100644 --- a/_server_client_factory_8cs_source.html +++ b/_server_client_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ServerClientFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ServerClientFactory.cs
-Go to the documentation of this file.
1 using System;
2 using System.Net.Http.Headers;
3 using System.Threading;
4 using System.Threading.Tasks;
5 using Tgstation.Server.Api;
7 
8 namespace Tgstation.Server.Client
9 {
12  {
17 
21  readonly ProductHeaderValue productHeaderValue;
22 
27  public ServerClientFactory(ProductHeaderValue productHeaderValue)
28  {
29  this.productHeaderValue = productHeaderValue ?? throw new ArgumentNullException(nameof(productHeaderValue));
30  }
31 
33  public async Task<IServerClient> CreateServerClient(Uri host, string username, string password, TimeSpan timeout, CancellationToken cancellationToken)
34  {
35  if (host == null)
36  throw new ArgumentNullException(nameof(host));
37  if (username == null)
38  throw new ArgumentNullException(nameof(username));
39  if (password == null)
40  throw new ArgumentNullException(nameof(password));
41 
42  Token token;
43  using (var api = ApiClientFactory.CreateApiClient(host, new ApiHeaders(productHeaderValue, username, password)))
44  {
45  if (timeout != default)
46  api.Timeout = timeout;
47  token = await api.Update<Token>(Routes.Root, cancellationToken).ConfigureAwait(false);
48  }
49 
50  return CreateServerClient(host, token, timeout);
51  }
52 
54  public IServerClient CreateServerClient(Uri host, Token token, TimeSpan timeout)
55  {
56  if (host == null)
57  throw new ArgumentNullException(nameof(host));
58  if (token == null)
59  throw new ArgumentNullException(nameof(token));
60  var result = new ServerClient(ApiClientFactory.CreateApiClient(host, new ApiHeaders(productHeaderValue, token.Bearer)), token);
61  if (timeout != default)
62  result.Timeout = timeout;
63  return result;
64  }
65  }
66 }
+Go to the documentation of this file.
1 using System;
2 using System.Net.Http.Headers;
3 using System.Threading;
4 using System.Threading.Tasks;
5 using Tgstation.Server.Api;
7 
9 {
12  {
17 
21  readonly ProductHeaderValue productHeaderValue;
22 
27  public ServerClientFactory(ProductHeaderValue productHeaderValue)
28  {
29  this.productHeaderValue = productHeaderValue ?? throw new ArgumentNullException(nameof(productHeaderValue));
30  }
31 
33  public async Task<IServerClient> CreateServerClient(Uri host, string username, string password, TimeSpan timeout, CancellationToken cancellationToken)
34  {
35  if (host == null)
36  throw new ArgumentNullException(nameof(host));
37  if (username == null)
38  throw new ArgumentNullException(nameof(username));
39  if (password == null)
40  throw new ArgumentNullException(nameof(password));
41 
42  Token token;
43  using (var api = ApiClientFactory.CreateApiClient(host, new ApiHeaders(productHeaderValue, username, password)))
44  {
45  if (timeout != default)
46  api.Timeout = timeout;
47  token = await api.Update<Token>(Routes.Root, cancellationToken).ConfigureAwait(false);
48  }
49 
50  return CreateServerClient(host, token, timeout);
51  }
52 
54  public IServerClient CreateServerClient(Uri host, Token token, TimeSpan timeout)
55  {
56  if (host == null)
57  throw new ArgumentNullException(nameof(host));
58  if (token == null)
59  throw new ArgumentNullException(nameof(token));
60  var result = new ServerClient(ApiClientFactory.CreateApiClient(host, new ApiHeaders(productHeaderValue, token.Bearer)), token);
61  if (timeout != default)
62  result.Timeout = timeout;
63  return result;
64  }
65  }
66 }
- - + -
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
-
Routes to a server actions
Definition: Routes.cs:9
+
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
+
Routes to a server actions
Definition: Routes.cs:9
-
Main client for communicating with a server
-
const string Root
The root controller
Definition: Routes.cs:14
-
Represents a JWT returned by the API
Definition: Token.cs:8
-
Factory for creating IServerClients
+
Main client for communicating with a server
+
IApiClient CreateApiClient(Uri url, ApiHeaders apiHeaders)
Create an IApiClient
+
const string Root
The root controller
Definition: Routes.cs:14
+
Represents a JWT returned by the API
Definition: Token.cs:8
+
Factory for creating IServerClients
-
readonly ProductHeaderValue productHeaderValue
The ProductHeaderValue for the ServerClientFactory
-
static readonly IApiClientFactory ApiClientFactory
The IApiClientFactory for the ServerClientFactory
- -
async Task< IServerClient > CreateServerClient(Uri host, string username, string password, TimeSpan timeout, CancellationToken cancellationToken)
Create a IServerClient
-
IServerClient CreateServerClient(Uri host, Token token, TimeSpan timeout)
Create a IServerClient
- -
string Bearer
The value of the JWT
Definition: Token.cs:13
-
ServerClientFactory(ProductHeaderValue productHeaderValue)
Construct a ServerClientFactory
- +
readonly ProductHeaderValue productHeaderValue
The ProductHeaderValue for the ServerClientFactory
+
static readonly IApiClientFactory ApiClientFactory
The IApiClientFactory for the ServerClientFactory
+ +
async Task< IServerClient > CreateServerClient(Uri host, string username, string password, TimeSpan timeout, CancellationToken cancellationToken)
Create a IServerClient
+
IServerClient CreateServerClient(Uri host, Token token, TimeSpan timeout)
Create a IServerClient
+ +
string Bearer
The value of the JWT
Definition: Token.cs:13
+
ServerClientFactory(ProductHeaderValue productHeaderValue)
Construct a ServerClientFactory
+
diff --git a/_server_error_exception_8cs.html b/_server_error_exception_8cs.html index a63ba16ffa..465291faae 100644 --- a/_server_error_exception_8cs.html +++ b/_server_error_exception_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ServerErrorException.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_server_error_exception_8cs_source.html b/_server_error_exception_8cs_source.html index 414629c949..5392c4cd22 100644 --- a/_server_error_exception_8cs_source.html +++ b/_server_error_exception_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ServerErrorException.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ServerErrorException.cs
-Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
5 namespace Tgstation.Server.Client
6 {
10  public sealed class ServerErrorException : ClientException
11  {
15  public string Html { get; }
16 
20  public ServerErrorException() { }
21 
26  public ServerErrorException(string html) : base(new ErrorMessage
27  {
28  Message = "An internal server error occurred!",
29  SeverApiVersion = null
30  }, HttpStatusCode.InternalServerError)
31  {
32  Html = html;
33  }
34 
40  public ServerErrorException(string message, Exception innerException) : base(message, innerException) { }
41  }
42 }
- -
ServerErrorException(string message, Exception innerException)
Construct an ServerErrorException with a message and innerException
- -
Occurs when an error occurs in the server
+Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
6 {
10  public sealed class ServerErrorException : ClientException
11  {
15  public string Html { get; }
16 
20  public ServerErrorException() { }
21 
26  public ServerErrorException(string html) : base(new ErrorMessage
27  {
28  Message = "An internal server error occurred!",
29  SeverApiVersion = null
30  }, HttpStatusCode.InternalServerError)
31  {
32  Html = html;
33  }
34 
40  public ServerErrorException(string message, Exception innerException) : base(message, innerException) { }
41  }
42 }
+
ServerErrorException(string message, Exception innerException)
Construct an ServerErrorException with a message and innerException
+ +
Occurs when an error occurs in the server
+ - -
ServerErrorException(string html)
Construct an ServerErrorException with html
-
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
-
ServerErrorException()
Construct an ServerErrorException
- -
Exceptions thrown by IServerClients
+ +
ServerErrorException(string html)
Construct an ServerErrorException with html
+
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+
ServerErrorException()
Construct an ServerErrorException
+ +
Exceptions thrown by IServerClients
diff --git a/_server_factory_8cs.html b/_server_factory_8cs.html index 6d12c87011..dfe2bf72f4 100644 --- a/_server_factory_8cs.html +++ b/_server_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/ServerFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
@@ -113,7 +96,7 @@ Namespaces diff --git a/_server_factory_8cs_source.html b/_server_factory_8cs_source.html index c23ff1d02b..fd59d292f1 100644 --- a/_server_factory_8cs_source.html +++ b/_server_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/ServerFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ServerFactory.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore;
2 using Microsoft.AspNetCore.Hosting;
3 using Microsoft.Extensions.Configuration;
4 using System;
5 using System.IO;
6 using System.Reflection;
8 
9 namespace Tgstation.Server.Host
10 {
12  public sealed class ServerFactory : IServerFactory
13  {
15  public IServer CreateServer(string[] args, string updatePath)
16  {
17  var webHost = WebHost.CreateDefaultBuilder(args ?? throw new ArgumentNullException(nameof(args)))
18  .ConfigureAppConfiguration((context, configurationBuilder) => configurationBuilder.SetBasePath(Directory.GetCurrentDirectory()))
19  .UseStartup<Application>()
20  .SuppressStatusMessages(true)
21  .UseShutdownTimeout(TimeSpan.FromMinutes(1));
22 
23  if(updatePath != null)
24  webHost.UseContentRoot(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
25 
26  return new Server(webHost, updatePath);
27  }
28  }
29 }
- - +Go to the documentation of this file.
1 using Microsoft.AspNetCore;
2 using Microsoft.AspNetCore.Hosting;
3 using Microsoft.Extensions.Configuration;
4 using System;
5 using System.IO;
6 using System.Reflection;
8 
9 namespace Tgstation.Server.Host
10 {
12  public sealed class ServerFactory : IServerFactory
13  {
15  public IServer CreateServer(string[] args, string updatePath)
16  {
17  var webHost = WebHost.CreateDefaultBuilder(args ?? throw new ArgumentNullException(nameof(args)))
18  .ConfigureAppConfiguration((context, configurationBuilder) => configurationBuilder.SetBasePath(Directory.GetCurrentDirectory()))
19  .UseStartup<Application>()
20  .SuppressStatusMessages(true)
21  .UseShutdownTimeout(TimeSpan.FromMinutes(1));
22 
23  if(updatePath != null)
24  webHost.UseContentRoot(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
25 
26  return new Server(webHost, updatePath);
27  }
28  }
29 }
-
Represents the host
Definition: IServer.cs:9
-
IServer CreateServer(string[] args, string updatePath)
Create a IServer
- +
Represents the host
Definition: IServer.cs:9
+
IServer CreateServer(string[] args, string updatePath)
Create a IServer
+ - - + +
diff --git a/_server_information_8cs.html b/_server_information_8cs.html index 96351a766d..942cc82639 100644 --- a/_server_information_8cs.html +++ b/_server_information_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/ServerInformation.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_server_information_8cs_source.html b/_server_information_8cs_source.html index b7ba37a7c3..5cf3371b92 100644 --- a/_server_information_8cs_source.html +++ b/_server_information_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/ServerInformation.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ServerInformation.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Api.Models
4 {
8  public sealed class ServerInformation
9  {
13  public Version Version { get; set; }
14 
18  public Version ApiVersion { get; set; }
19  }
20 }
- -
Represents basic server information
- +Go to the documentation of this file.
1 using System;
2 
4 {
8  public sealed class ServerInformation
9  {
13  public Version Version { get; set; }
14 
18  public Version ApiVersion { get; set; }
19  }
20 }
+ +
Represents basic server information
+
Version ApiVersion
The Api version of the host
diff --git a/_server_service_8cs.html b/_server_service_8cs.html index 55c77418b8..1bcc9e1f33 100644 --- a/_server_service_8cs.html +++ b/_server_service_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Service/ServerService.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Service
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_server_service_8cs_source.html b/_server_service_8cs_source.html index 439aed0c5c..a65d3fe388 100644 --- a/_server_service_8cs_source.html +++ b/_server_service_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Service/ServerService.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ServerService.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Microsoft.Extensions.Logging.EventLog;
3 using Microsoft.Extensions.Logging.EventLog.Internal;
4 using System;
5 using System.Diagnostics;
6 using System.Diagnostics.CodeAnalysis;
7 using System.Globalization;
8 using System.ServiceProcess;
9 using System.Threading;
10 using System.Threading.Tasks;
12 
13 namespace Tgstation.Server.Host.Service
14 {
19  {
23  public const string Name = "tgstation-server-4";
24 
28  readonly IWatchdog watchdog;
29 
34 
38  CancellationTokenSource cancellationTokenSource;
39 
46  public ServerService(IWatchdogFactory watchdogFactory, ILoggerFactory loggerFactory, LogLevel minumumLogLevel)
47  {
48  if (watchdogFactory == null)
49  throw new ArgumentNullException(nameof(watchdogFactory));
50  if (loggerFactory == null)
51  throw new ArgumentNullException(nameof(loggerFactory));
52 
53  loggerFactory.AddEventLog(new EventLogSettings
54  {
55  EventLog = this,
56  Filter = (message, logLevel) => logLevel >= minumumLogLevel
57  });
58 
59  ServiceName = Name;
60  watchdog = watchdogFactory.CreateWatchdog(loggerFactory);
61  }
62 
64  public int MaxMessageSize => (int)EventLog.MaximumKilobytes * 1024;
65 
67  public void WriteEntry(string message, EventLogEntryType type, int eventID, short category) => EventLog.WriteEntry(message, type, eventID, category);
68 
75  async Task RunWatchdog(string[] args, CancellationToken cancellationToken)
76  {
77  await watchdog.RunAsync(false, args, cancellationToken).ConfigureAwait(false);
78 
79  void StopServiceAsync()
80  {
81  try
82  {
83  Task.Run(Stop, cancellationToken);
84  }
85  catch (OperationCanceledException) { }
86  catch (Exception e)
87  {
88  EventLog.WriteEntry(String.Format(CultureInfo.InvariantCulture, "Error stopping service! Exception: {0}", e));
89  }
90  }
91 
92  StopServiceAsync();
93  }
94 
96  [SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "cancellationTokenSource", Justification = "IT'S DISPOSED RIGHT THERE YOU FUCCBOI!")]
97  protected override void Dispose(bool disposing)
98  {
99  cancellationTokenSource?.Dispose();
100  base.Dispose(disposing);
101  }
102 
104  protected override void OnStart(string[] args)
105  {
106  cancellationTokenSource?.Dispose();
107  cancellationTokenSource = new CancellationTokenSource();
108  watchdogTask = RunWatchdog(args, cancellationTokenSource.Token);
109  }
110 
112  protected override void OnStop()
113  {
114  cancellationTokenSource.Cancel();
115  watchdogTask.GetAwaiter().GetResult();
116  }
117  }
118 }
async Task RunWatchdog(string[] args, CancellationToken cancellationToken)
Executes the watchdog, stopping the service if it exits
-
IWatchdog CreateWatchdog(ILoggerFactory loggerFactory)
Create a IWatchdog
- -
override void OnStart(string[] args)
- -
Task watchdogTask
The Task recieved from IWatchdog.RunAsync(bool, string[], CancellationToken) of watchdog ...
-
override void Dispose(bool disposing)
-
ServerService(IWatchdogFactory watchdogFactory, ILoggerFactory loggerFactory, LogLevel minumumLogLevel)
Construct a ServerService
+Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Microsoft.Extensions.Logging.EventLog;
3 using System;
4 using System.Diagnostics;
5 using System.Globalization;
6 using System.ServiceProcess;
7 using System.Threading;
8 using System.Threading.Tasks;
10 
12 {
16  sealed class ServerService : ServiceBase
17  {
21  public const string Name = "tgstation-server-4";
22 
26  readonly IWatchdog watchdog;
27 
32 
36  CancellationTokenSource cancellationTokenSource;
37 
44  public ServerService(IWatchdogFactory watchdogFactory, ILoggerFactory loggerFactory, LogLevel minumumLogLevel)
45  {
46  if (watchdogFactory == null)
47  throw new ArgumentNullException(nameof(watchdogFactory));
48  if (loggerFactory == null)
49  throw new ArgumentNullException(nameof(loggerFactory));
50 
51 #pragma warning disable CS0618 // Type or member is obsolete
52  loggerFactory.AddEventLog(new EventLogSettings
53  {
54  LogName = EventLog.Log,
55  MachineName = EventLog.MachineName,
56  SourceName = EventLog.Source,
57  Filter = (message, logLevel) => logLevel >= minumumLogLevel
58  });
59 #pragma warning restore CS0618 // Type or member is obsolete
60 
61  ServiceName = Name;
62  watchdog = watchdogFactory.CreateWatchdog(loggerFactory);
63  }
64 
71  async Task RunWatchdog(string[] args, CancellationToken cancellationToken)
72  {
73  await watchdog.RunAsync(false, args, cancellationTokenSource.Token).ConfigureAwait(false);
74 
75  void StopServiceAsync()
76  {
77  try
78  {
79  Task.Run(Stop, cancellationToken);
80  }
81  catch (OperationCanceledException) { }
82  catch (Exception e)
83  {
84  EventLog.WriteEntry(String.Format(CultureInfo.InvariantCulture, "Error stopping service! Exception: {0}", e));
85  }
86  }
87 
88  StopServiceAsync();
89  }
90 
92  protected override void Dispose(bool disposing)
93  {
94  cancellationTokenSource?.Dispose();
95  base.Dispose(disposing);
96  }
97 
99  protected override void OnStart(string[] args)
100  {
101  cancellationTokenSource?.Dispose();
102  cancellationTokenSource = new CancellationTokenSource();
104  }
105 
107  protected override void OnStop()
108  {
109  cancellationTokenSource.Cancel();
110  watchdogTask.GetAwaiter().GetResult();
111  }
112  }
113 }
async Task RunWatchdog(string[] args, CancellationToken cancellationToken)
Executes the watchdog, stopping the service if it exits
+
IWatchdog CreateWatchdog(ILoggerFactory loggerFactory)
Create a IWatchdog
+
override void OnStart(string[] args)
+
Task watchdogTask
The Task recieved from IWatchdog.RunAsync(bool, string[], CancellationToken) of watchdog
+
override void Dispose(bool disposing)
+
ServerService(IWatchdogFactory watchdogFactory, ILoggerFactory loggerFactory, LogLevel minumumLogLevel)
Construct a ServerService
-
The watchdog for a Host
Definition: IWatchdog.cs:9
- -
readonly IWatchdog watchdog
The IWatchdog for the ServerService
-
Represents a IWatchdog as a ServiceBase
- - - - - -
CancellationTokenSource cancellationTokenSource
The cancellationTokenSource for the ServerService
+
Task RunAsync(bool runConfigure, string[] args, CancellationToken cancellationToken)
Run the IWatchdog
+ + +
readonly IWatchdog watchdog
The IWatchdog for the ServerService
+
const string Name
The canonical windows service name
+ +
Represents a IWatchdog as a ServiceBase
+ + + + +
CancellationTokenSource cancellationTokenSource
The cancellationTokenSource for the ServerService
diff --git a/_server_side_modifications_8cs.html b/_server_side_modifications_8cs.html index c2aadd2546..1d3d3fa212 100644 --- a/_server_side_modifications_8cs.html +++ b/_server_side_modifications_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/StaticFiles/ServerSideModifications.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.StaticFiles
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_server_side_modifications_8cs_source.html b/_server_side_modifications_8cs_source.html index 0ff960c596..3f002360c8 100644 --- a/_server_side_modifications_8cs_source.html +++ b/_server_side_modifications_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/StaticFiles/ServerSideModifications.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ServerSideModifications.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Host.Components.StaticFiles
2 {
6  public sealed class ServerSideModifications
7  {
11  public bool TotalDmeOverwrite { get; }
12 
16  public string HeadIncludeLine { get; }
17 
21  public string TailIncludeLine { get; }
22 
29  public ServerSideModifications(string headIncludeLine, string tailIncludeLine, bool totalDmeOverwrite)
30  {
31  HeadIncludeLine = headIncludeLine;
32  TailIncludeLine = tailIncludeLine;
33  TotalDmeOverwrite = totalDmeOverwrite;
34  }
35  }
36 }
-
ServerSideModifications(string headIncludeLine, string tailIncludeLine, bool totalDmeOverwrite)
Construct ServerSideModifications
- - +Go to the documentation of this file.
2 {
6  public sealed class ServerSideModifications
7  {
11  public bool TotalDmeOverwrite { get; }
12 
16  public string HeadIncludeLine { get; }
17 
21  public string TailIncludeLine { get; }
22 
29  public ServerSideModifications(string headIncludeLine, string tailIncludeLine, bool totalDmeOverwrite)
30  {
31  HeadIncludeLine = headIncludeLine;
32  TailIncludeLine = tailIncludeLine;
33  TotalDmeOverwrite = totalDmeOverwrite;
34  }
35  }
36 }
bool TotalDmeOverwrite
If the target dme was completely overwitten
+
ServerSideModifications(string headIncludeLine, string tailIncludeLine, bool totalDmeOverwrite)
Construct ServerSideModifications
+
string TailIncludeLine
The #include line which should be added to the end of the .dme if any
+ + +
string HeadIncludeLine
The #include line which should be added to the beginning of the .dme if any
diff --git a/_service_collection_extensions_8cs.html b/_service_collection_extensions_8cs.html index 61261d6947..f14b107b2f 100644 --- a/_service_collection_extensions_8cs.html +++ b/_service_collection_extensions_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/ServiceCollectionExtensions.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_service_collection_extensions_8cs_source.html b/_service_collection_extensions_8cs_source.html index eba7d6bd3c..3da56da43d 100644 --- a/_service_collection_extensions_8cs_source.html +++ b/_service_collection_extensions_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/ServiceCollectionExtensions.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ServiceCollectionExtensions.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Configuration;
2 using Microsoft.Extensions.DependencyInjection;
3 using System;
4 using System.Globalization;
6 
7 namespace Tgstation.Server.Host.Core
8 {
13  {
21  public static IServiceCollection UseStandardConfig<TConfig>(this IServiceCollection serviceCollection, IConfiguration configuration) where TConfig : class
22  {
23  if (serviceCollection == null)
24  throw new ArgumentNullException(nameof(serviceCollection));
25  if (configuration == null)
26  throw new ArgumentNullException(nameof(configuration));
27 
28  const string SectionFieldName = nameof(GeneralConfiguration.Section);
29 
30  var configType = typeof(TConfig);
31  var sectionField = configType.GetField(SectionFieldName);
32  if (sectionField == null)
33  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "{0} has no {1} field!", configType, SectionFieldName));
34 
35  var stringType = typeof(string);
36  if (sectionField.FieldType != stringType)
37  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "{0} has invalid {1} field type, must be {2}!", configType, SectionFieldName, stringType));
38 
39  var sectionName = (string)sectionField.GetValue(null);
40 
41  return serviceCollection.Configure<TConfig>(configuration.GetSection(sectionName));
42  }
43  }
44 }
- -
const string Section
The key for the Microsoft.Extensions.Configuration.IConfigurationSection the GeneralConfiguration res...
+Go to the documentation of this file.
1 using Microsoft.Extensions.Configuration;
2 using Microsoft.Extensions.DependencyInjection;
3 using System;
4 using System.Globalization;
6 
8 {
13  {
21  public static IServiceCollection UseStandardConfig<TConfig>(this IServiceCollection serviceCollection, IConfiguration configuration) where TConfig : class
22  {
23  if (serviceCollection == null)
24  throw new ArgumentNullException(nameof(serviceCollection));
25  if (configuration == null)
26  throw new ArgumentNullException(nameof(configuration));
27 
28  const string SectionFieldName = nameof(GeneralConfiguration.Section);
29 
30  var configType = typeof(TConfig);
31  var sectionField = configType.GetField(SectionFieldName);
32  if (sectionField == null)
33  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "{0} has no {1} field!", configType, SectionFieldName));
34 
35  var stringType = typeof(string);
36  if (sectionField.FieldType != stringType)
37  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "{0} has invalid {1} field type, must be {2}!", configType, SectionFieldName, stringType));
38 
39  var sectionName = (string)sectionField.GetValue(null);
40 
41  return serviceCollection.Configure<TConfig>(configuration.GetSection(sectionName));
42  }
43  }
44 }
const string Section
The key for the Microsoft.Extensions.Configuration.IConfigurationSection the GeneralConfiguration res...
+ - - - - - + + +
static IServiceCollection UseStandardConfig< TConfig >(this IServiceCollection serviceCollection, IConfiguration configuration)
Add a standard TConfig binding
+ + +
diff --git a/_service_unavailable_exception_8cs.html b/_service_unavailable_exception_8cs.html index be69f00a80..b0410f4f03 100644 --- a/_service_unavailable_exception_8cs.html +++ b/_service_unavailable_exception_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ServiceUnavailableException.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_service_unavailable_exception_8cs_source.html b/_service_unavailable_exception_8cs_source.html index 1dcd155763..b9b44ed508 100644 --- a/_service_unavailable_exception_8cs_source.html +++ b/_service_unavailable_exception_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/ServiceUnavailableException.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ServiceUnavailableException.cs
-Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
5 namespace Tgstation.Server.Client
6 {
11  {
16  {
17  Message = "The server is currently starting or stopping and is unable to process the request!",
18  SeverApiVersion = null
19  }, HttpStatusCode.ServiceUnavailable)
20  { }
21 
26  public ServiceUnavailableException(string message) : base(message) { }
27 
33  public ServiceUnavailableException(string message, Exception innerException) : base(message, innerException) { }
34  }
35 }
- - +Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
6 {
11  {
16  {
17  Message = "The server is currently starting or stopping and is unable to process the request!",
18  SeverApiVersion = null
19  }, HttpStatusCode.ServiceUnavailable)
20  { }
21 
26  public ServiceUnavailableException(string message) : base(message) { }
27 
33  public ServiceUnavailableException(string message, Exception innerException) : base(message, innerException) { }
34  }
35 }
+ -
Occurs when the client makes a request while the server is starting or stopping
-
ServiceUnavailableException(string message)
Construct an ServiceUnavailableException with a message
-
ServiceUnavailableException(string message, Exception innerException)
Construct an ServiceUnavailableException with a message and innerException
- -
ServiceUnavailableException()
Construct an ServiceUnavailableException
-
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- -
Exceptions thrown by IServerClients
+
Occurs when the client makes a request while the server is starting or stopping
+
ServiceUnavailableException(string message)
Construct an ServiceUnavailableException with a message
+
ServiceUnavailableException(string message, Exception innerException)
Construct an ServiceUnavailableException with a message and innerException
+ +
ServiceUnavailableException()
Construct an ServiceUnavailableException
+
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+ +
Exceptions thrown by IServerClients
diff --git a/_session_controller_8cs.html b/_session_controller_8cs.html index bce362748d..197b59ea19 100644 --- a/_session_controller_8cs.html +++ b/_session_controller_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/SessionController.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Watchdog
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_session_controller_8cs_source.html b/_session_controller_8cs_source.html index c671d91f1e..04e47be469 100644 --- a/_session_controller_8cs_source.html +++ b/_session_controller_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/SessionController.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
SessionController.cs
-Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Microsoft.Extensions.Logging;
3 using Newtonsoft.Json;
4 using Newtonsoft.Json.Serialization;
5 using System;
6 using System.Collections.Generic;
7 using System.Globalization;
8 using System.Net;
9 using System.Threading;
10 using System.Threading.Tasks;
16 
17 namespace Tgstation.Server.Host.Components.Watchdog
18 {
21  {
23  public bool IsPrimary
24  {
25  get
26  {
27  CheckDisposed();
28  return reattachInformation.IsPrimary;
29  }
30  }
31 
34  {
35  get
36  {
37  if (!Lifetime.IsCompleted)
38  throw new InvalidOperationException("ApiValidated cannot be checked while Lifetime is incomplete!");
39  return apiValidationStatus;
40  }
41  }
42 
44  public IDmbProvider Dmb
45  {
46  get
47  {
48  CheckDisposed();
49  return reattachInformation.Dmb;
50  }
51  }
52 
54  public ushort? Port
55  {
56  get
57  {
58  CheckDisposed();
59  if (portClosedForReboot)
60  return null;
61  return reattachInformation.Port;
62  }
63  }
64 
67  {
68  get
69  {
70  CheckDisposed();
71  return reattachInformation.RebootState;
72  }
73  }
74 
76  public bool ClosePortOnReboot { get; set; }
77 
79  public bool TerminationWasRequested { get; private set; }
80 
82  public Task<LaunchResult> LaunchResult { get; }
83 
85  public Task<int> Lifetime => process.Lifetime;
86 
88  public Task OnReboot => rebootTcs.Task;
89 
94 
98  readonly IByondTopicSender byondTopicSender;
99 
104 
108  readonly IProcess process;
109 
114 
119 
123  readonly IChat chat;
124 
128  readonly ILogger<SessionController> logger;
129 
134 
138  TaskCompletionSource<bool> portAssignmentTcs;
139 
143  ushort? nextPort;
144 
148  TaskCompletionSource<object> rebootTcs;
149 
154 
158  bool disposed;
159 
164 
168  bool released;
169 
183  public SessionController(ReattachInformation reattachInformation, IProcess process, IByondExecutableLock byondLock, IByondTopicSender byondTopicSender, IJsonTrackingContext chatJsonTrackingContext, ICommContext interopContext, IChat chat, ILogger<SessionController> logger, DreamDaemonSecurity? launchSecurityLevel, uint? startupTimeout)
184  {
185  this.chatJsonTrackingContext = chatJsonTrackingContext; // null valid
186  this.reattachInformation = reattachInformation ?? throw new ArgumentNullException(nameof(reattachInformation));
187  this.byondTopicSender = byondTopicSender ?? throw new ArgumentNullException(nameof(byondTopicSender));
188  this.process = process ?? throw new ArgumentNullException(nameof(process));
189  this.byondLock = byondLock ?? throw new ArgumentNullException(nameof(byondLock));
190  this.interopContext = interopContext ?? throw new ArgumentNullException(nameof(interopContext));
191  this.chat = chat ?? throw new ArgumentNullException(nameof(chat));
192  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
193 
194  this.launchSecurityLevel = launchSecurityLevel;
195 
196  interopContext.RegisterHandler(this);
197 
198  portClosedForReboot = false;
199  disposed = false;
200  apiValidationStatus = ApiValidationStatus.NeverValidated;
201  released = false;
202 
203  rebootTcs = new TaskCompletionSource<object>();
204 
205  process.Lifetime.ContinueWith(x => chatJsonTrackingContext.Active = false, TaskScheduler.Current);
206 
207  async Task<LaunchResult> GetLaunchResult()
208  {
209  var startTime = DateTimeOffset.Now;
210  Task toAwait = process.Startup;
211 
212  if (startupTimeout.HasValue)
213  toAwait = Task.WhenAny(process.Startup, Task.Delay(startTime.AddSeconds(startupTimeout.Value) - startTime));
214 
215  await toAwait.ConfigureAwait(false);
216 
217  var result = new LaunchResult
218  {
219  ExitCode = process.Lifetime.IsCompleted ? (int?)await process.Lifetime.ConfigureAwait(false) : null,
220  StartupTime = process.Startup.IsCompleted ? (TimeSpan?)(DateTimeOffset.Now - startTime) : null
221  };
222  return result;
223  }
224 
225  LaunchResult = GetLaunchResult();
226 
227  logger.LogDebug("Created session controller. Primary: {0}, CommsKey: {1}, Port: {2}", IsPrimary, reattachInformation.AccessIdentifier, Port);
228  }
229 
234 #pragma warning disable CA1821 // Remove empty Finalizers TODO: remove this when https://github.com/dotnet/roslyn-analyzers/issues/1241 is fixed
235  ~SessionController() => Dispose(false);
236 #pragma warning restore CA1821 // Remove empty Finalizers
237 
239  public void Dispose()
240  {
241  Dispose(true);
242  GC.SuppressFinalize(this);
243  }
244 
249  void Dispose(bool disposing)
250  {
251  lock (this)
252  {
253  if (disposed)
254  return;
255  if (disposing)
256  {
257  if (!released)
258  {
259  process.Terminate();
260  byondLock.Dispose();
261  }
262 
263  process.Dispose();
264  interopContext.Dispose();
265  Dmb?.Dispose(); // will be null when released
266  chatJsonTrackingContext.Dispose();
267  disposed = true;
268  }
269  else
270  {
271  if (logger != null)
272  logger.LogError("Being disposed via finalizer!");
273  if (!released)
274  if (process != null)
275  process.Terminate();
276  else if (logger != null)
277  logger.LogCritical("Unable to terminate active DreamDaemon session due to finalizer ordering!");
278  }
279  }
280  }
281 
283  #pragma warning disable CA1502 // TODO: Decomplexify
284  public async Task HandleInterop(CommCommand command, CancellationToken cancellationToken)
285  {
286  if (command == null)
287  throw new ArgumentNullException(nameof(command));
288 
289  var query = command.Parameters;
290 
291  object content;
292  Action postRespond = null;
293  ushort? overrideResponsePort = null;
294  if (query.TryGetValue(Constants.DMParameterCommand, out var method))
295  {
296  content = new object();
297  switch (method)
298  {
300  try
301  {
302  var message = JsonConvert.DeserializeObject<Response>(command.RawJson, new JsonSerializerSettings
303  {
304  ContractResolver = new CamelCasePropertyNamesContractResolver()
305  });
306  if (message.ChannelIds == null)
307  throw new InvalidOperationException("Missing ChannelIds field!");
308  if (message.Message == null)
309  throw new InvalidOperationException("Missing Message field!");
310  await chat.SendMessage(message.Message, message.ChannelIds, cancellationToken).ConfigureAwait(false);
311  }
312  catch (Exception e)
313  {
314  logger.LogDebug("Exception while decoding chat message! Exception: {0}", e);
315  goto default;
316  }
317 
318  break;
320  // currently unused, maybe in the future
321  break;
323  TerminationWasRequested = true;
324  process.Terminate();
325  return;
327  lock (this)
328  {
329  if (!query.TryGetValue(Constants.DMParameterData, out var stringPortObject) || !UInt16.TryParse(stringPortObject as string, out var currentPort))
330  {
332  logger.LogWarning("DreamDaemon sent new port command without providing it's own!");
333  content = new ErrorMessage { Message = "Missing stringified port as data parameter!" };
334  break;
335  }
336 
337  if (!nextPort.HasValue)
338  reattachInformation.Port = currentPort; // not ready yet, so what we'll do is accept the random port DD opened on for now and change it later when we decide to
339  else
340  {
341  // nextPort is ready, tell DD to switch to that
342  // if it fails it'll kill itself
343  content = new Dictionary<string, ushort> { { Constants.DMParameterData, nextPort.Value } };
344  reattachInformation.Port = nextPort.Value;
345  overrideResponsePort = currentPort;
346  nextPort = null;
347 
348  // we'll also get here from SetPort so complete that task
349  var tmpTcs = portAssignmentTcs;
350  portAssignmentTcs = null;
351  if (tmpTcs != null)
352  postRespond = () => tmpTcs.SetResult(true);
353  }
354 
355  portClosedForReboot = false;
356  }
357 
358  break;
360  if (!launchSecurityLevel.HasValue)
361  {
362  logger.LogWarning("DreamDaemon requested API validation but no intial security level was passed to the session controller!");
363  apiValidationStatus = ApiValidationStatus.UnaskedValidationRequest;
364  content = new ErrorMessage { Message = "Invalid API validation request!" };
365  break;
366  }
367 
368  if (!query.TryGetValue(Constants.DMParameterData, out var stringMinimumSecurityLevelObject) || !Enum.TryParse<DreamDaemonSecurity>(stringMinimumSecurityLevelObject as string, out var minimumSecurityLevel))
369  apiValidationStatus = ApiValidationStatus.BadValidationRequest;
370  else
371  switch (minimumSecurityLevel)
372  {
373  case DreamDaemonSecurity.Safe:
374  apiValidationStatus = ApiValidationStatus.RequiresSafe;
375  break;
376  case DreamDaemonSecurity.Ultrasafe:
377  apiValidationStatus = ApiValidationStatus.RequiresUltrasafe;
378  break;
379  case DreamDaemonSecurity.Trusted:
380  apiValidationStatus = ApiValidationStatus.RequiresTrusted;
381  break;
382  default:
383  throw new InvalidOperationException("Enum.TryParse failed to validate the DreamDaemonSecurity range!");
384  }
385 
386  break;
388  if (ClosePortOnReboot)
389  {
390  chatJsonTrackingContext.Active = false;
391  content = new Dictionary<string, int> { { Constants.DMParameterData, 0 } };
392  portClosedForReboot = true;
393  }
394 
395  var oldTcs = rebootTcs;
396  rebootTcs = new TaskCompletionSource<object>();
397  postRespond = () => oldTcs.SetResult(null);
398  break;
399  default:
400  content = new ErrorMessage { Message = "Requested command not supported!" };
401  break;
402  }
403  }
404  else
405  content = new ErrorMessage { Message = "Missing command parameter!" };
406 
407  var json = JsonConvert.SerializeObject(content);
408  var response = await SendCommand(String.Format(CultureInfo.InvariantCulture, "{0}&{1}={2}", byondTopicSender.SanitizeString(Constants.DMTopicInteropResponse), byondTopicSender.SanitizeString(Constants.DMParameterData), byondTopicSender.SanitizeString(json)), overrideResponsePort, cancellationToken).ConfigureAwait(false);
409 
410  if (response != Constants.DMResponseSuccess)
411  logger.LogWarning("Received error response while responding to interop: {0}", response);
412 
413  postRespond?.Invoke();
414  }
415  #pragma warning restore CA1502
416 
421  {
422  if (disposed)
423  throw new ObjectDisposedException(nameof(SessionController));
424  }
425 
427  public void EnableCustomChatCommands() => chatJsonTrackingContext.Active = true;
428 
431  {
432  CheckDisposed();
433 
434  // we still don't want to dispose the dmb yet, even though we're keeping it alive
435  var tmpProvider = reattachInformation.Dmb;
436  reattachInformation.Dmb = null;
437  released = true;
438  Dispose();
439  byondLock.DoNotDeleteThisSession();
440  tmpProvider.KeepAlive();
441  reattachInformation.Dmb = tmpProvider;
442  return reattachInformation;
443  }
444 
446  public Task<string> SendCommand(string command, CancellationToken cancellationToken) => SendCommand(command, null, cancellationToken);
447 
448  async Task<string> SendCommand(string command, ushort? overridePort, CancellationToken cancellationToken)
449  {
450  try
451  {
452  var commandString = String.Format(CultureInfo.InvariantCulture,
453  "?{0}={1}&{2}={3}",
454  byondTopicSender.SanitizeString(Constants.DMInteropAccessIdentifier),
455  byondTopicSender.SanitizeString(reattachInformation.AccessIdentifier),
456  byondTopicSender.SanitizeString(Constants.DMParameterCommand),
457  command); // intentionally don't sanitize command, that's up to the caller
458 
459  var targetPort = overridePort ?? reattachInformation.Port;
460  logger.LogTrace("Export to :{0}. Query: {1}", targetPort, commandString);
461 
462  return await byondTopicSender.SendTopic(
463  new IPEndPoint(IPAddress.Loopback, targetPort),
464  commandString,
465  cancellationToken).ConfigureAwait(false);
466  }
467  catch (OperationCanceledException)
468  {
469  throw;
470  }
471  catch (Exception e)
472  {
473  logger.LogInformation("Send command exception:{0}{1}", Environment.NewLine, e.Message);
474  return null;
475  }
476  }
477 
479  public Task<bool> SetPort(ushort port, CancellationToken cancellationToken)
480  {
481  CheckDisposed();
482 
483  if (port == 0)
484  throw new ArgumentOutOfRangeException(nameof(port), port, "port must not be zero!");
485 
486  async Task<bool> ImmediateTopicPortChange()
487  {
488  var commandResult = await SendCommand(String.Format(CultureInfo.InvariantCulture, "{0}&{1}={2}", byondTopicSender.SanitizeString(Constants.DMTopicChangePort), byondTopicSender.SanitizeString(Constants.DMParameterData), byondTopicSender.SanitizeString(port.ToString(CultureInfo.InvariantCulture))), cancellationToken).ConfigureAwait(false);
489 
490  if (commandResult != Constants.DMResponseSuccess)
491  {
492  logger.LogWarning("Failed port change! DD says: {0}", commandResult);
493  return false;
494  }
495 
496  reattachInformation.Port = port;
497  return true;
498  }
499 
500  lock (this)
501  if (portClosedForReboot)
502  {
503  if (portAssignmentTcs != null)
504  throw new InvalidOperationException("A port change operation is already in progress!");
505  nextPort = port;
506  portAssignmentTcs = new TaskCompletionSource<bool>();
507  return portAssignmentTcs.Task;
508  }
509  else
510  return ImmediateTopicPortChange();
511  }
512 
514  public async Task<bool> SetRebootState(RebootState newRebootState, CancellationToken cancellationToken)
515  {
516  if (RebootState == newRebootState)
517  return true;
518  reattachInformation.RebootState = newRebootState;
519  return await SendCommand(String.Format(CultureInfo.InvariantCulture, "{0}&{1}={2}", byondTopicSender.SanitizeString(Constants.DMTopicChangeReboot), byondTopicSender.SanitizeString(Constants.DMParameterData), (int)newRebootState), cancellationToken).ConfigureAwait(false) == Constants.DMResponseSuccess;
520  }
521 
523  public void ResetRebootState()
524  {
525  CheckDisposed();
526  reattachInformation.RebootState = RebootState.Normal;
527  }
528 
530  public void SetHighPriority() => process.SetHighPriority();
531  }
532 }
bool disposed
If the SessionController has been disposed
-
const string DMCommandWorldReboot
World reboot command
Definition: Constants.cs:71
+Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Microsoft.Extensions.Logging;
3 using Newtonsoft.Json;
4 using Newtonsoft.Json.Serialization;
5 using System;
6 using System.Collections.Generic;
7 using System.Globalization;
8 using System.Net;
9 using System.Threading;
10 using System.Threading.Tasks;
16 
18 {
21  {
23  public bool IsPrimary
24  {
25  get
26  {
27  CheckDisposed();
29  }
30  }
31 
34  {
35  get
36  {
37  if (!Lifetime.IsCompleted)
38  throw new InvalidOperationException("ApiValidated cannot be checked while Lifetime is incomplete!");
39  return apiValidationStatus;
40  }
41  }
42 
44  public IDmbProvider Dmb
45  {
46  get
47  {
48  CheckDisposed();
49  return reattachInformation.Dmb;
50  }
51  }
52 
54  public ushort? Port
55  {
56  get
57  {
58  CheckDisposed();
60  return null;
62  }
63  }
64 
67  {
68  get
69  {
70  CheckDisposed();
72  }
73  }
74 
76  public bool ClosePortOnReboot { get; set; }
77 
79  public bool TerminationWasRequested { get; private set; }
80 
82  public Task<LaunchResult> LaunchResult { get; }
83 
85  public Task<int> Lifetime => process.Lifetime;
86 
88  public Task OnReboot => rebootTcs.Task;
89 
94 
98  readonly IByondTopicSender byondTopicSender;
99 
104 
108  readonly IProcess process;
109 
114 
119 
123  readonly IChat chat;
124 
128  readonly ILogger<SessionController> logger;
129 
134 
138  TaskCompletionSource<bool> portAssignmentTcs;
139 
143  ushort? nextPort;
144 
148  TaskCompletionSource<object> rebootTcs;
149 
154 
158  bool disposed;
159 
164 
168  bool released;
169 
184  {
185  this.chatJsonTrackingContext = chatJsonTrackingContext; // null valid
186  this.reattachInformation = reattachInformation ?? throw new ArgumentNullException(nameof(reattachInformation));
187  this.byondTopicSender = byondTopicSender ?? throw new ArgumentNullException(nameof(byondTopicSender));
188  this.process = process ?? throw new ArgumentNullException(nameof(process));
189  this.byondLock = byondLock ?? throw new ArgumentNullException(nameof(byondLock));
190  this.interopContext = interopContext ?? throw new ArgumentNullException(nameof(interopContext));
191  this.chat = chat ?? throw new ArgumentNullException(nameof(chat));
192  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
193 
194  this.launchSecurityLevel = launchSecurityLevel;
195 
197 
198  portClosedForReboot = false;
199  disposed = false;
200  apiValidationStatus = ApiValidationStatus.NeverValidated;
201  released = false;
202 
203  rebootTcs = new TaskCompletionSource<object>();
204 
205  process.Lifetime.ContinueWith(x => chatJsonTrackingContext.Active = false, TaskScheduler.Current);
206 
207  async Task<LaunchResult> GetLaunchResult()
208  {
209  var startTime = DateTimeOffset.Now;
210  Task toAwait = process.Startup;
211 
212  if (startupTimeout.HasValue)
213  toAwait = Task.WhenAny(process.Startup, Task.Delay(startTime.AddSeconds(startupTimeout.Value) - startTime));
214 
215  await toAwait.ConfigureAwait(false);
216 
217  var result = new LaunchResult
218  {
219  ExitCode = process.Lifetime.IsCompleted ? (int?)await process.Lifetime.ConfigureAwait(false) : null,
220  StartupTime = process.Startup.IsCompleted ? (TimeSpan?)(DateTimeOffset.Now - startTime) : null
221  };
222  return result;
223  }
224 
225  LaunchResult = GetLaunchResult();
226 
227  logger.LogDebug("Created session controller. Primary: {0}, CommsKey: {1}, Port: {2}", IsPrimary, reattachInformation.AccessIdentifier, Port);
228  }
229 
234 #pragma warning disable CA1821 // Remove empty Finalizers TODO: remove this when https://github.com/dotnet/roslyn-analyzers/issues/1241 is fixed
235  ~SessionController() => Dispose(false);
236 #pragma warning restore CA1821 // Remove empty Finalizers
237 
239  public void Dispose()
240  {
241  Dispose(true);
242  GC.SuppressFinalize(this);
243  }
244 
249  void Dispose(bool disposing)
250  {
251  lock (this)
252  {
253  if (disposed)
254  return;
255  if (disposing)
256  {
257  if (!released)
258  {
259  process.Terminate();
260  byondLock.Dispose();
261  }
262 
263  process.Dispose();
264  interopContext.Dispose();
265  Dmb?.Dispose(); // will be null when released
266  chatJsonTrackingContext.Dispose();
267  disposed = true;
268  }
269  else
270  {
271  if (logger != null)
272  logger.LogError("Being disposed via finalizer!");
273  if (!released)
274  if (process != null)
275  process.Terminate();
276  else if (logger != null)
277  logger.LogCritical("Unable to terminate active DreamDaemon session due to finalizer ordering!");
278  }
279  }
280  }
281 
283  #pragma warning disable CA1502 // TODO: Decomplexify
284  public async Task HandleInterop(CommCommand command, CancellationToken cancellationToken)
285  {
286  if (command == null)
287  throw new ArgumentNullException(nameof(command));
288 
289  var query = command.Parameters;
290 
291  object content;
292  Action postRespond = null;
293  ushort? overrideResponsePort = null;
294  if (query.TryGetValue(Constants.DMParameterCommand, out var method))
295  {
296  content = new object();
297  switch (method)
298  {
300  try
301  {
302  var message = JsonConvert.DeserializeObject<Response>(command.RawJson, new JsonSerializerSettings
303  {
304  ContractResolver = new CamelCasePropertyNamesContractResolver()
305  });
306  if (message.ChannelIds == null)
307  throw new InvalidOperationException("Missing ChannelIds field!");
308  if (message.Message == null)
309  throw new InvalidOperationException("Missing Message field!");
310  await chat.SendMessage(message.Message, message.ChannelIds, cancellationToken).ConfigureAwait(false);
311  }
312  catch (Exception e)
313  {
314  logger.LogDebug("Exception while decoding chat message! Exception: {0}", e);
315  goto default;
316  }
317 
318  break;
320  // currently unused, maybe in the future
321  break;
324  process.Terminate();
325  return;
327  lock (this)
328  {
329  if (!query.TryGetValue(Constants.DMParameterData, out var stringPortObject) || !UInt16.TryParse(stringPortObject as string, out var currentPort))
330  {
332  logger.LogWarning("DreamDaemon sent new port command without providing it's own!");
333  content = new ErrorMessage { Message = "Missing stringified port as data parameter!" };
334  break;
335  }
336 
337  if (!nextPort.HasValue)
338  reattachInformation.Port = currentPort; // not ready yet, so what we'll do is accept the random port DD opened on for now and change it later when we decide to
339  else
340  {
341  // nextPort is ready, tell DD to switch to that
342  // if it fails it'll kill itself
343  content = new Dictionary<string, ushort> { { Constants.DMParameterData, nextPort.Value } };
345  overrideResponsePort = currentPort;
346  nextPort = null;
347 
348  // we'll also get here from SetPort so complete that task
349  var tmpTcs = portAssignmentTcs;
350  portAssignmentTcs = null;
351  if (tmpTcs != null)
352  postRespond = () => tmpTcs.SetResult(true);
353  }
354 
355  portClosedForReboot = false;
356  }
357 
358  break;
360  if (!launchSecurityLevel.HasValue)
361  {
362  logger.LogWarning("DreamDaemon requested API validation but no intial security level was passed to the session controller!");
363  apiValidationStatus = ApiValidationStatus.UnaskedValidationRequest;
364  content = new ErrorMessage { Message = "Invalid API validation request!" };
365  break;
366  }
367 
368  if (!query.TryGetValue(Constants.DMParameterData, out var stringMinimumSecurityLevelObject) || !Enum.TryParse<DreamDaemonSecurity>(stringMinimumSecurityLevelObject as string, out var minimumSecurityLevel))
369  apiValidationStatus = ApiValidationStatus.BadValidationRequest;
370  else
371  switch (minimumSecurityLevel)
372  {
373  case DreamDaemonSecurity.Safe:
375  break;
376  case DreamDaemonSecurity.Ultrasafe:
377  apiValidationStatus = ApiValidationStatus.RequiresUltrasafe;
378  break;
379  case DreamDaemonSecurity.Trusted:
380  apiValidationStatus = ApiValidationStatus.RequiresTrusted;
381  break;
382  default:
383  throw new InvalidOperationException("Enum.TryParse failed to validate the DreamDaemonSecurity range!");
384  }
385 
386  break;
388  if (ClosePortOnReboot)
389  {
391  content = new Dictionary<string, int> { { Constants.DMParameterData, 0 } };
392  portClosedForReboot = true;
393  }
394 
395  var oldTcs = rebootTcs;
396  rebootTcs = new TaskCompletionSource<object>();
397  postRespond = () => oldTcs.SetResult(null);
398  break;
399  default:
400  content = new ErrorMessage { Message = "Requested command not supported!" };
401  break;
402  }
403  }
404  else
405  content = new ErrorMessage { Message = "Missing command parameter!" };
406 
407  var json = JsonConvert.SerializeObject(content);
408  var response = await SendCommand(String.Format(CultureInfo.InvariantCulture, "{0}&{1}={2}", byondTopicSender.SanitizeString(Constants.DMTopicInteropResponse), byondTopicSender.SanitizeString(Constants.DMParameterData), byondTopicSender.SanitizeString(json)), overrideResponsePort, cancellationToken).ConfigureAwait(false);
409 
410  if (response != Constants.DMResponseSuccess)
411  logger.LogWarning("Received error response while responding to interop: {0}", response);
412 
413  postRespond?.Invoke();
414  }
415  #pragma warning restore CA1502
416 
421  {
422  if (disposed)
423  throw new ObjectDisposedException(nameof(SessionController));
424  }
425 
428 
431  {
432  CheckDisposed();
433 
434  // we still don't want to dispose the dmb yet, even though we're keeping it alive
435  var tmpProvider = reattachInformation.Dmb;
436  reattachInformation.Dmb = null;
437  released = true;
438  Dispose();
440  tmpProvider.KeepAlive();
441  reattachInformation.Dmb = tmpProvider;
442  return reattachInformation;
443  }
444 
446  public Task<string> SendCommand(string command, CancellationToken cancellationToken) => SendCommand(command, null, cancellationToken);
447 
448  async Task<string> SendCommand(string command, ushort? overridePort, CancellationToken cancellationToken)
449  {
450  try
451  {
452  var commandString = String.Format(CultureInfo.InvariantCulture,
453  "?{0}={1}&{2}={3}",
457  command); // intentionally don't sanitize command, that's up to the caller
458 
459  var targetPort = overridePort ?? reattachInformation.Port;
460  logger.LogTrace("Export to :{0}. Query: {1}", targetPort, commandString);
461 
462  return await byondTopicSender.SendTopic(
463  new IPEndPoint(IPAddress.Loopback, targetPort),
464  commandString,
465  cancellationToken).ConfigureAwait(false);
466  }
467  catch (OperationCanceledException)
468  {
469  throw;
470  }
471  catch (Exception e)
472  {
473  logger.LogInformation("Send command exception:{0}{1}", Environment.NewLine, e.Message);
474  return null;
475  }
476  }
477 
479  public Task<bool> SetPort(ushort port, CancellationToken cancellationToken)
480  {
481  CheckDisposed();
482 
483  if (port == 0)
484  throw new ArgumentOutOfRangeException(nameof(port), port, "port must not be zero!");
485 
486  async Task<bool> ImmediateTopicPortChange()
487  {
488  var commandResult = await SendCommand(String.Format(CultureInfo.InvariantCulture, "{0}&{1}={2}", byondTopicSender.SanitizeString(Constants.DMTopicChangePort), byondTopicSender.SanitizeString(Constants.DMParameterData), byondTopicSender.SanitizeString(port.ToString(CultureInfo.InvariantCulture))), cancellationToken).ConfigureAwait(false);
489 
490  if (commandResult != Constants.DMResponseSuccess)
491  {
492  logger.LogWarning("Failed port change! DD says: {0}", commandResult);
493  return false;
494  }
495 
496  reattachInformation.Port = port;
497  return true;
498  }
499 
500  lock (this)
502  {
503  if (portAssignmentTcs != null)
504  throw new InvalidOperationException("A port change operation is already in progress!");
505  nextPort = port;
506  portAssignmentTcs = new TaskCompletionSource<bool>();
507  return portAssignmentTcs.Task;
508  }
509  else
510  return ImmediateTopicPortChange();
511  }
512 
514  public async Task<bool> SetRebootState(RebootState newRebootState, CancellationToken cancellationToken)
515  {
516  if (RebootState == newRebootState)
517  return true;
518  reattachInformation.RebootState = newRebootState;
519  return await SendCommand(String.Format(CultureInfo.InvariantCulture, "{0}&{1}={2}", byondTopicSender.SanitizeString(Constants.DMTopicChangeReboot), byondTopicSender.SanitizeString(Constants.DMParameterData), (int)newRebootState), cancellationToken).ConfigureAwait(false) == Constants.DMResponseSuccess;
520  }
521 
523  public void ResetRebootState()
524  {
525  CheckDisposed();
527  }
528 
530  public void SetHighPriority() => process.SetHighPriority();
531  }
532 }
bool disposed
If the SessionController has been disposed
+
const string DMCommandWorldReboot
World reboot command
Definition: Constants.cs:71
-
readonly ICommContext interopContext
The ICommContext for the SessionController
-
Task< int > Lifetime
The Task<TResult> resulting in the exit code of the process
Definition: IProcessBase.cs:14
-
IReadOnlyDictionary< string, object > Parameters
The dictionary of the CommCommand
Definition: CommCommand.cs:13
-
Represents the result of trying to start a DD process
Definition: LaunchResult.cs:9
-
readonly ReattachInformation reattachInformation
The up to date ReattachInformation
-
Task< bool > SetPort(ushort port, CancellationToken cancellationToken)
Causes the world to start listening on a newPort
+
readonly ICommContext interopContext
The ICommContext for the SessionController
+
Task< int > Lifetime
The Task<TResult> resulting in the exit code of the process
Definition: IProcessBase.cs:14
+
IReadOnlyDictionary< string, object > Parameters
The dictionary of the CommCommand
Definition: CommCommand.cs:13
+ +
Represents the result of trying to start a DD process
Definition: LaunchResult.cs:9
+
readonly ReattachInformation reattachInformation
The up to date ReattachInformation
+
Task< bool > SetPort(ushort port, CancellationToken cancellationToken)
Causes the world to start listening on a newPort
- - -
readonly IProcess process
The IProcess for the SessionController
-
ReattachInformation Release()
Releases the IProcess without terminating it. Also calls System.IDisposable.Dispose ...
-
Represents a registration of an interop session
Definition: ICommContext.cs:8
-
readonly IJsonTrackingContext chatJsonTrackingContext
The IJsonTrackingContext for the SessionController
-
async Task< bool > SetRebootState(RebootState newRebootState, CancellationToken cancellationToken)
Attempts to change the current RebootState to newRebootState
-
bool Active
If the IJsonTrackingContext should be used for GetCustomCommands(CancellationToken) ...
+ +
ushort? nextPort
The port to assign DreamDaemon when it queries for it
+ +
readonly IProcess process
The IProcess for the SessionController
+
ReattachInformation Release()
Releases the IProcess without terminating it. Also calls System.IDisposable.Dispose
+
Represents a registration of an interop session
Definition: ICommContext.cs:8
+
readonly IJsonTrackingContext chatJsonTrackingContext
The IJsonTrackingContext for the SessionController
+
async Task< bool > SetRebootState(RebootState newRebootState, CancellationToken cancellationToken)
Attempts to change the current RebootState to newRebootState
+
bool Active
If the IJsonTrackingContext should be used for GetCustomCommands(CancellationToken)
-
readonly IByondExecutableLock byondLock
The IByondExecutableLock for the SessionController
+
readonly IByondExecutableLock byondLock
The IByondExecutableLock for the SessionController
-
void Dispose(bool disposing)
Implements the IDisposable pattern
-
readonly IChat chat
The IChat for the SessionController
-
Task Startup
The Task representing the time until the IProcess becomes "idle"
Definition: IProcess.cs:19
-
For managing connected chat services
Definition: IChat.cs:13
+
void Dispose(bool disposing)
Implements the IDisposable pattern
+
~SessionController()
Finalizes an instance of the SessionController class.
+
readonly IChat chat
The IChat for the SessionController
+
Task Startup
The Task representing the time until the IProcess becomes "idle"
Definition: IProcess.cs:19
+
For managing connected chat services
Definition: IChat.cs:13
-
void RegisterHandler(ICommHandler handler)
Register a handler with the ICommContext
-
SessionController(ReattachInformation reattachInformation, IProcess process, IByondExecutableLock byondLock, IByondTopicSender byondTopicSender, IJsonTrackingContext chatJsonTrackingContext, ICommContext interopContext, IChat chat, ILogger< SessionController > logger, DreamDaemonSecurity?launchSecurityLevel, uint?startupTimeout)
Construct a SessionController
-
Handles communication with a DreamDaemon IProcess
-
string RawJson
The raw JSON of the CommCommand
Definition: CommCommand.cs:18
-
readonly DreamDaemonSecurity launchSecurityLevel
The DreamDaemonSecurity level the process was launched with
+
void RegisterHandler(ICommHandler handler)
Register a handler with the ICommContext
+
Handles communication with a DreamDaemon IProcess
+
void SetHighPriority()
Set's the owned System.Diagnostics.Process.PriorityClass to System.Diagnostics.ProcessPriorityClass....
+
string RawJson
The raw JSON of the CommCommand
Definition: CommCommand.cs:18
+ +
TaskCompletionSource< bool > portAssignmentTcs
The TaskCompletionSource<TResult> SetPort(ushort, CancellationToken) waits on when DreamDaemon curren...
-
const string DMCommandEndProcess
Terminate process command
Definition: Constants.cs:76
-
void CheckDisposed()
Throws an ObjectDisposedException if Dispose(bool) has been called
-
const string DMCommandApiValidate
API validation command
Definition: Constants.cs:61
-
async Task< string > SendCommand(string command, ushort?overridePort, CancellationToken cancellationToken)
- -
const string DMTopicInteropResponse
Response to an interop export from DM
Definition: Constants.cs:51
-
ushort nextPort
The port to assign DreamDaemon when it queries for it
- -
readonly ILogger< SessionController > logger
The ILogger for the SessionController
-
TaskCompletionSource< object > rebootTcs
The TaskCompletionSource<TResult> that completes when DD tells us about a reboot
-
const string DMCommandServerPrimed
Server primed command
Definition: Constants.cs:66
-
Abstraction over a System.Diagnostics.Process
Definition: IProcess.cs:9
-
Represents a tracking of dynamic chat json files
- -
Constants used for communication with the DMAPI
Definition: Constants.cs:6
+
const string DMCommandEndProcess
Terminate process command
Definition: Constants.cs:76
+
void CheckDisposed()
Throws an ObjectDisposedException if Dispose(bool) has been called
+
const string DMCommandApiValidate
API validation command
Definition: Constants.cs:61
+ +
ushort Port
The port DreamDaemon was last listening on
+ +
void Terminate()
Terminates the process
+
const string DMTopicInteropResponse
Response to an interop export from DM
Definition: Constants.cs:51
+ +
IDmbProvider Dmb
The IDmbProvider used by DreamDaemon
+
readonly ILogger< SessionController > logger
The ILogger for the SessionController
+
TaskCompletionSource< object > rebootTcs
The TaskCompletionSource<TResult> that completes when DD tells us about a reboot
+
const string DMCommandServerPrimed
Server primed command
Definition: Constants.cs:66
+
Abstraction over a System.Diagnostics.Process
Definition: IProcess.cs:9
+
Represents a tracking of dynamic chat json files
+ + +
bool IsPrimary
If the Components.IDmbProvider.PrimaryDirectory of the associated dmb is being used
+
async Task< string > SendCommand(string command, ushort? overridePort, CancellationToken cancellationToken)
+
Task SendMessage(string message, IEnumerable< ulong > channelIds, CancellationToken cancellationToken)
Send a chat message to a given set of channelIds
+
Constants used for communication with the DMAPI
Definition: Constants.cs:6
+
readonly? DreamDaemonSecurity launchSecurityLevel
The DreamDaemonSecurity level the process was launched with
-
const string DMResponseSuccess
Generic OK response
Definition: Constants.cs:26
-
Represents usage of the two primary BYOND server executables
-
const string DMParameterCommand
Topic command parameter
Definition: Constants.cs:86
-
ApiValidationStatus apiValidationStatus
The ApiValidationStatus for the SessionController
-
const string DMCommandNewPort
Set port command
Definition: Constants.cs:56
- -
void ResetRebootState()
Changes RebootState to Components.Watchdog.RebootState.Normal without telling the DMAPI ...
-
Represents a BYOND installation
Definition: Byond.cs:8
- -
const string DMInteropAccessIdentifier
The JsonFile.AccessIdentifier
Definition: Constants.cs:21
-
DreamDaemonSecurity
DreamDaemon&#39;s security level
-
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
-
bool portClosedForReboot
If we know DreamDaemon currently has it&#39;s port closed
-
const string DMTopicChangeReboot
Change reboot mode
Definition: Constants.cs:36
-
readonly IByondTopicSender byondTopicSender
The IByondTopicSender for the SessionController
-
const string DMCommandChat
Chat send command
Definition: Constants.cs:81
-
async Task HandleInterop(CommCommand command, CancellationToken cancellationToken)
Handle a command
- -
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- -
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
-
Parameters necessary for duplicating a ISessionController session
- -
ApiValidationStatus
Status of DMAPI validation
-
string AccessIdentifier
Used to identify and authenticate the DreamDaemon instance
-
bool released
If process should be kept alive instead
-
Represents a chat message requested by DD
Definition: Response.cs:8
+
const string DMResponseSuccess
Generic OK response
Definition: Constants.cs:26
+
void SetHighPriority()
Set's the owned System.Diagnostics.Process.PriorityClass to System.Diagnostics.ProcessPriorityClass....
+
Represents usage of the two primary BYOND server executables
+
const string DMParameterCommand
Topic command parameter
Definition: Constants.cs:86
+
ApiValidationStatus apiValidationStatus
The ApiValidationStatus for the SessionController
+
const string DMCommandNewPort
Set port command
Definition: Constants.cs:56
+ +
Task< string > SendCommand(string command, CancellationToken cancellationToken)
Sends a command to DreamDaemon through /world/Topic()
+
void EnableCustomChatCommands()
Enables the reading of custom chat commands from the ISessionController
+
void ResetRebootState()
Changes RebootState to Components.Watchdog.RebootState.Normal without telling the DMAPI
+
Represents a BYOND installation
Definition: Byond.cs:8
+
void DoNotDeleteThisSession()
Call if, during a detach, this version should not be deleted
+ +
const string DMInteropAccessIdentifier
The JsonFile.AccessIdentifier
Definition: Constants.cs:21
+
DreamDaemonSecurity
DreamDaemon's security level
+
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
+
bool portClosedForReboot
If we know DreamDaemon currently has it's port closed
+
const string DMTopicChangeReboot
Change reboot mode
Definition: Constants.cs:36
+
SessionController(ReattachInformation reattachInformation, IProcess process, IByondExecutableLock byondLock, IByondTopicSender byondTopicSender, IJsonTrackingContext chatJsonTrackingContext, ICommContext interopContext, IChat chat, ILogger< SessionController > logger, DreamDaemonSecurity? launchSecurityLevel, uint? startupTimeout)
Construct a SessionController
+
readonly IByondTopicSender byondTopicSender
The IByondTopicSender for the SessionController
+
const string DMCommandChat
Chat send command
Definition: Constants.cs:81
+
async Task HandleInterop(CommCommand command, CancellationToken cancellationToken)
Handle a command
+ +
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+ +
RebootState RebootState
The current DreamDaemon reboot state
+ +
RebootState
Represents the action to take when /world/Reboot() is called
Definition: RebootState.cs:6
+
Parameters necessary for duplicating a ISessionController session
+ +
ApiValidationStatus
Status of DMAPI validation
+
string AccessIdentifier
Used to identify and authenticate the DreamDaemon instance
+
bool released
If process should be kept alive instead
+
Represents a chat message requested by DD
Definition: Response.cs:8
diff --git a/_session_controller_factory_8cs.html b/_session_controller_factory_8cs.html index a6c91d5512..4c456f115e 100644 --- a/_session_controller_factory_8cs.html +++ b/_session_controller_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/SessionControllerFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Watchdog
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_session_controller_factory_8cs_source.html b/_session_controller_factory_8cs_source.html index f71050e5cc..c38cd08489 100644 --- a/_session_controller_factory_8cs_source.html +++ b/_session_controller_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/SessionControllerFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
SessionControllerFactory.cs
-Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Microsoft.Extensions.Logging;
3 using Newtonsoft.Json;
4 using Newtonsoft.Json.Serialization;
5 using System;
6 using System.Globalization;
7 using System.Linq;
8 using System.Text;
9 using System.Threading;
10 using System.Threading.Tasks;
17 using Tgstation.Server.Host.IO;
19 
20 namespace Tgstation.Server.Host.Components.Watchdog
21 {
24  {
29 
33  readonly IByondManager byond;
34 
38  readonly IByondTopicSender byondTopicSender;
39 
44 
49 
54 
58  readonly IChat chat;
59 
64 
69 
73  readonly ILoggerFactory loggerFactory;
74 
78  readonly Api.Models.Instance instance;
79 
85  static string SecurityWord(DreamDaemonSecurity securityLevel)
86  {
87  switch (securityLevel)
88  {
89  case DreamDaemonSecurity.Safe:
90  return "safe";
91  case DreamDaemonSecurity.Trusted:
92  return "trusted";
93  case DreamDaemonSecurity.Ultrasafe:
94  return "ultrasafe";
95  default:
96  throw new ArgumentOutOfRangeException(nameof(securityLevel), securityLevel, String.Format(CultureInfo.InvariantCulture, "Bad DreamDaemon security level: {0}", securityLevel));
97  }
98  }
99 
114  public SessionControllerFactory(IProcessExecutor processExecutor, IByondManager byond, IByondTopicSender byondTopicSender, ICryptographySuite cryptographySuite, IApplication application, IIOManager ioManager, IChat chat, INetworkPromptReaper networkPromptReaper, IPlatformIdentifier platformIdentifier, ILoggerFactory loggerFactory, Api.Models.Instance instance)
115  {
116  this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor));
117  this.byond = byond ?? throw new ArgumentNullException(nameof(byond));
118  this.byondTopicSender = byondTopicSender ?? throw new ArgumentNullException(nameof(byondTopicSender));
119  this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite));
120  this.application = application ?? throw new ArgumentNullException(nameof(application));
121  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
122  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
123  this.chat = chat ?? throw new ArgumentNullException(nameof(chat));
124  this.networkPromptReaper = networkPromptReaper ?? throw new ArgumentNullException(nameof(networkPromptReaper));
125  this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
126  this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
127  }
128 
130  #pragma warning disable CA1506 // TODO: Decomplexify
131  public async Task<ISessionController> LaunchNew(DreamDaemonLaunchParameters launchParameters, IDmbProvider dmbProvider, IByondExecutableLock currentByondLock, bool primaryPort, bool primaryDirectory, bool apiValidate, CancellationToken cancellationToken)
132  {
133  var portToUse = primaryPort ? launchParameters.PrimaryPort : launchParameters.SecondaryPort;
134  if (!portToUse.HasValue)
135  throw new InvalidOperationException("Given port is null!");
136  var accessIdentifier = cryptographySuite.GetSecureString();
137 
138  const string JsonPostfix = "tgs.json";
139 
140  var basePath = primaryDirectory ? dmbProvider.PrimaryDirectory : dmbProvider.SecondaryDirectory;
141 
142  // delete all previous tgs json files
143  var files = await ioManager.GetFilesWithExtension(basePath, JsonPostfix, cancellationToken).ConfigureAwait(false);
144  await Task.WhenAll(files.Select(x => ioManager.DeleteFile(x, cancellationToken))).ConfigureAwait(false);
145 
146  // i changed this back from guids, hopefully i don't regret that
147  string JsonFile(string name) => String.Format(CultureInfo.InvariantCulture, "{0}.{1}", name, JsonPostfix);
148 
149  var securityLevelToUse = launchParameters.SecurityLevel.Value;
150  switch (dmbProvider.CompileJob.MinimumSecurityLevel)
151  {
152  case DreamDaemonSecurity.Ultrasafe:
153  break;
154  case DreamDaemonSecurity.Safe:
155  if (securityLevelToUse == DreamDaemonSecurity.Ultrasafe)
156  securityLevelToUse = DreamDaemonSecurity.Safe;
157  break;
158  case DreamDaemonSecurity.Trusted:
159  securityLevelToUse = DreamDaemonSecurity.Trusted;
160  break;
161  default:
162  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid DreamDaemonSecurity value: {0}", dmbProvider.CompileJob.MinimumSecurityLevel));
163  }
164 
165  // setup interop files
166  var interopInfo = new JsonFile
167  {
168  AccessIdentifier = accessIdentifier,
169  ApiValidateOnly = apiValidate,
170  ChatChannelsJson = JsonFile("chat_channels"),
171  ChatCommandsJson = JsonFile("chat_commands"),
172  ServerCommandsJson = JsonFile("server_commands"),
173  InstanceName = instance.Name,
174  SecurityLevel = securityLevelToUse,
175  Revision = new Api.Models.Internal.RevisionInformation
176  {
177  CommitSha = dmbProvider.CompileJob.RevisionInformation.CommitSha,
178  OriginCommitSha = dmbProvider.CompileJob.RevisionInformation.OriginCommitSha
179  }
180  };
181 
182  interopInfo.TestMerges.AddRange(dmbProvider.CompileJob.RevisionInformation.ActiveTestMerges.Select(x => x.TestMerge).Select(x => new Interop.TestMerge(x, interopInfo.Revision)));
183 
184  var interopJsonFile = JsonFile("interop");
185 
186  var interopJson = JsonConvert.SerializeObject(interopInfo, new JsonSerializerSettings
187  {
188  ContractResolver = new CamelCasePropertyNamesContractResolver(),
189  ReferenceLoopHandling = ReferenceLoopHandling.Ignore
190  });
191 
192  var chatJsonTrackingTask = chat.TrackJsons(basePath, interopInfo.ChatChannelsJson, interopInfo.ChatCommandsJson, cancellationToken);
193 
194  await ioManager.WriteAllBytes(ioManager.ConcatPath(basePath, interopJsonFile), Encoding.UTF8.GetBytes(interopJson), cancellationToken).ConfigureAwait(false);
195  var chatJsonTrackingContext = await chatJsonTrackingTask.ConfigureAwait(false);
196  try
197  {
198  // get the byond lock
199  var byondLock = currentByondLock ?? await byond.UseExecutables(Version.Parse(dmbProvider.CompileJob.ByondVersion), cancellationToken).ConfigureAwait(false);
200  try
201  {
202  // create interop context
203  var context = new CommContext(ioManager, loggerFactory.CreateLogger<CommContext>(), basePath, interopInfo.ServerCommandsJson);
204  try
205  {
206  // set command line options
207  // more sanitization here cause it uses the same scheme
208  var parameters = String.Format(CultureInfo.InvariantCulture, "{2}={0}&{3}={1}", byondTopicSender.SanitizeString(application.Version.ToString()), byondTopicSender.SanitizeString(interopJsonFile), byondTopicSender.SanitizeString(Constants.DMParamHostVersion), byondTopicSender.SanitizeString(Constants.DMParamInfoJson));
209 
210  var visibility = apiValidate ? "invisible" : "public";
211 
212  // important to run on all ports to allow port changing
213  var arguments = String.Format(CultureInfo.InvariantCulture, "{0} -port {1} -ports 1-65535 {2}-close -{3} -{5} -public -params \"{4}\"",
214  dmbProvider.DmbName,
215  primaryPort ? launchParameters.PrimaryPort : launchParameters.SecondaryPort,
216  launchParameters.AllowWebClient.Value ? "-webclient " : String.Empty,
217  SecurityWord(securityLevelToUse),
218  parameters,
219  visibility);
220 
221  // See https://github.com/tgstation/tgstation-server/issues/719
222  var noShellExecute = !platformIdentifier.IsWindows;
223 
224  // launch dd
225  var process = processExecutor.LaunchProcess(byondLock.DreamDaemonPath, basePath, arguments, noShellExecute: noShellExecute);
226  try
227  {
228  networkPromptReaper.RegisterProcess(process);
229 
230  // return the session controller for it
231  var result = new SessionController(new ReattachInformation
232  {
233  AccessIdentifier = accessIdentifier,
234  Dmb = dmbProvider,
235  IsPrimary = primaryDirectory,
236  Port = portToUse.Value,
237  ProcessId = process.Id,
238  ChatChannelsJson = interopInfo.ChatChannelsJson,
239  ChatCommandsJson = interopInfo.ChatCommandsJson,
240  ServerCommandsJson = interopInfo.ServerCommandsJson,
241  }, process, byondLock, byondTopicSender, chatJsonTrackingContext, context, chat, loggerFactory.CreateLogger<SessionController>(), launchParameters.SecurityLevel, launchParameters.StartupTimeout);
242 
243  // writeback launch parameter's fixed security level
244  launchParameters.SecurityLevel = securityLevelToUse;
245 
246  return result;
247  }
248  catch
249  {
250  process.Dispose();
251  throw;
252  }
253  }
254  catch
255  {
256  context.Dispose();
257  throw;
258  }
259  }
260  catch
261  {
262  if (currentByondLock == null)
263  byondLock.Dispose();
264  throw;
265  }
266  }
267  catch
268  {
269  chatJsonTrackingContext.Dispose();
270  throw;
271  }
272  }
273  #pragma warning restore CA1506
274 
276  public async Task<ISessionController> Reattach(ReattachInformation reattachInformation, CancellationToken cancellationToken)
277  {
278  if (reattachInformation == null)
279  throw new ArgumentNullException(nameof(reattachInformation));
280 
281  SessionController result = null;
282  var basePath = reattachInformation.IsPrimary ? reattachInformation.Dmb.PrimaryDirectory : reattachInformation.Dmb.SecondaryDirectory;
283  var chatJsonTrackingContext = await chat.TrackJsons(basePath, reattachInformation.ChatChannelsJson, reattachInformation.ChatCommandsJson, cancellationToken).ConfigureAwait(false);
284  try
285  {
286  var byondLock = await byond.UseExecutables(Version.Parse(reattachInformation.Dmb.CompileJob.ByondVersion), cancellationToken).ConfigureAwait(false);
287  try
288  {
289  var context = new CommContext(ioManager, loggerFactory.CreateLogger<CommContext>(), basePath, reattachInformation.ServerCommandsJson);
290  try
291  {
292  var process = processExecutor.GetProcess(reattachInformation.ProcessId);
293 
294  if (process != null)
295  try
296  {
297  networkPromptReaper.RegisterProcess(process);
298  result = new SessionController(reattachInformation, process, byondLock, byondTopicSender, chatJsonTrackingContext, context, chat, loggerFactory.CreateLogger<SessionController>(), null, null);
299  }
300  finally
301  {
302  if (result == null)
303  process.Dispose();
304  }
305  }
306  finally
307  {
308  if (result == null)
309  context.Dispose();
310  }
311  }
312  finally
313  {
314  if (result == null)
315  byondLock.Dispose();
316  }
317  }
318  finally
319  {
320  if (result == null)
321  chatJsonTrackingContext.Dispose();
322  }
323 
324  return result;
325  }
326 
328  public ISessionController CreateDeadSession(IDmbProvider dmbProvider) => new DeadSessionController(dmbProvider);
329  }
330 }
string ServerCommandsJson
Path to the server commands json file
-
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the SessionControllerFactory
+Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Microsoft.Extensions.Logging;
3 using Newtonsoft.Json;
4 using Newtonsoft.Json.Serialization;
5 using System;
6 using System.Globalization;
7 using System.Linq;
8 using System.Text;
9 using System.Threading;
10 using System.Threading.Tasks;
17 using Tgstation.Server.Host.IO;
19 
21 {
24  {
29 
33  readonly IByondManager byond;
34 
38  readonly IByondTopicSender byondTopicSender;
39 
44 
49 
54 
58  readonly IChat chat;
59 
64 
69 
73  readonly ILoggerFactory loggerFactory;
74 
78  readonly Api.Models.Instance instance;
79 
85  static string SecurityWord(DreamDaemonSecurity securityLevel)
86  {
87  switch (securityLevel)
88  {
89  case DreamDaemonSecurity.Safe:
90  return "safe";
91  case DreamDaemonSecurity.Trusted:
92  return "trusted";
93  case DreamDaemonSecurity.Ultrasafe:
94  return "ultrasafe";
95  default:
96  throw new ArgumentOutOfRangeException(nameof(securityLevel), securityLevel, String.Format(CultureInfo.InvariantCulture, "Bad DreamDaemon security level: {0}", securityLevel));
97  }
98  }
99 
115  {
116  this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor));
117  this.byond = byond ?? throw new ArgumentNullException(nameof(byond));
118  this.byondTopicSender = byondTopicSender ?? throw new ArgumentNullException(nameof(byondTopicSender));
119  this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite));
120  this.application = application ?? throw new ArgumentNullException(nameof(application));
121  this.instance = instance ?? throw new ArgumentNullException(nameof(instance));
122  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
123  this.chat = chat ?? throw new ArgumentNullException(nameof(chat));
124  this.networkPromptReaper = networkPromptReaper ?? throw new ArgumentNullException(nameof(networkPromptReaper));
125  this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
126  this.loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
127  }
128 
130  #pragma warning disable CA1506 // TODO: Decomplexify
131  public async Task<ISessionController> LaunchNew(DreamDaemonLaunchParameters launchParameters, IDmbProvider dmbProvider, IByondExecutableLock currentByondLock, bool primaryPort, bool primaryDirectory, bool apiValidate, CancellationToken cancellationToken)
132  {
133  var portToUse = primaryPort ? launchParameters.PrimaryPort : launchParameters.SecondaryPort;
134  if (!portToUse.HasValue)
135  throw new InvalidOperationException("Given port is null!");
136  var accessIdentifier = cryptographySuite.GetSecureString();
137 
138  const string JsonPostfix = "tgs.json";
139 
140  var basePath = primaryDirectory ? dmbProvider.PrimaryDirectory : dmbProvider.SecondaryDirectory;
141 
142  // delete all previous tgs json files
143  var files = await ioManager.GetFilesWithExtension(basePath, JsonPostfix, cancellationToken).ConfigureAwait(false);
144  await Task.WhenAll(files.Select(x => ioManager.DeleteFile(x, cancellationToken))).ConfigureAwait(false);
145 
146  // i changed this back from guids, hopefully i don't regret that
147  string JsonFile(string name) => String.Format(CultureInfo.InvariantCulture, "{0}.{1}", name, JsonPostfix);
148 
149  var securityLevelToUse = launchParameters.SecurityLevel.Value;
150  switch (dmbProvider.CompileJob.MinimumSecurityLevel)
151  {
152  case DreamDaemonSecurity.Ultrasafe:
153  break;
154  case DreamDaemonSecurity.Safe:
155  if (securityLevelToUse == DreamDaemonSecurity.Ultrasafe)
156  securityLevelToUse = DreamDaemonSecurity.Safe;
157  break;
158  case DreamDaemonSecurity.Trusted:
159  securityLevelToUse = DreamDaemonSecurity.Trusted;
160  break;
161  default:
162  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Invalid DreamDaemonSecurity value: {0}", dmbProvider.CompileJob.MinimumSecurityLevel));
163  }
164 
165  // setup interop files
166  var interopInfo = new JsonFile
167  {
168  AccessIdentifier = accessIdentifier,
169  ApiValidateOnly = apiValidate,
170  ChatChannelsJson = JsonFile("chat_channels"),
171  ChatCommandsJson = JsonFile("chat_commands"),
172  ServerCommandsJson = JsonFile("server_commands"),
173  InstanceName = instance.Name,
174  SecurityLevel = securityLevelToUse,
175  Revision = new Api.Models.Internal.RevisionInformation
176  {
177  CommitSha = dmbProvider.CompileJob.RevisionInformation.CommitSha,
178  OriginCommitSha = dmbProvider.CompileJob.RevisionInformation.OriginCommitSha
179  }
180  };
181 
182  interopInfo.TestMerges.AddRange(dmbProvider.CompileJob.RevisionInformation.ActiveTestMerges.Select(x => x.TestMerge).Select(x => new Interop.TestMerge(x, interopInfo.Revision)));
183 
184  var interopJsonFile = JsonFile("interop");
185 
186  var interopJson = JsonConvert.SerializeObject(interopInfo, new JsonSerializerSettings
187  {
188  ContractResolver = new CamelCasePropertyNamesContractResolver(),
189  ReferenceLoopHandling = ReferenceLoopHandling.Ignore
190  });
191 
192  var chatJsonTrackingTask = chat.TrackJsons(basePath, interopInfo.ChatChannelsJson, interopInfo.ChatCommandsJson, cancellationToken);
193 
194  await ioManager.WriteAllBytes(ioManager.ConcatPath(basePath, interopJsonFile), Encoding.UTF8.GetBytes(interopJson), cancellationToken).ConfigureAwait(false);
195  var chatJsonTrackingContext = await chatJsonTrackingTask.ConfigureAwait(false);
196  try
197  {
198  // get the byond lock
199  var byondLock = currentByondLock ?? await byond.UseExecutables(Version.Parse(dmbProvider.CompileJob.ByondVersion), cancellationToken).ConfigureAwait(false);
200  try
201  {
202  // create interop context
203  var context = new CommContext(ioManager, loggerFactory.CreateLogger<CommContext>(), basePath, interopInfo.ServerCommandsJson);
204  try
205  {
206  // set command line options
207  // more sanitization here cause it uses the same scheme
208  var parameters = String.Format(CultureInfo.InvariantCulture, "{2}={0}&{3}={1}", byondTopicSender.SanitizeString(application.Version.ToString()), byondTopicSender.SanitizeString(interopJsonFile), byondTopicSender.SanitizeString(Constants.DMParamHostVersion), byondTopicSender.SanitizeString(Constants.DMParamInfoJson));
209 
210  var visibility = apiValidate ? "invisible" : "public";
211 
212  // important to run on all ports to allow port changing
213  var arguments = String.Format(CultureInfo.InvariantCulture, "{0} -port {1} -ports 1-65535 {2}-close -{3} -{5} -public -params \"{4}\"",
214  dmbProvider.DmbName,
215  primaryPort ? launchParameters.PrimaryPort : launchParameters.SecondaryPort,
216  launchParameters.AllowWebClient.Value ? "-webclient " : String.Empty,
217  SecurityWord(securityLevelToUse),
218  parameters,
219  visibility);
220 
221  // See https://github.com/tgstation/tgstation-server/issues/719
222  var noShellExecute = !platformIdentifier.IsWindows;
223 
224  // launch dd
225  var process = processExecutor.LaunchProcess(byondLock.DreamDaemonPath, basePath, arguments, noShellExecute: noShellExecute);
226  try
227  {
229 
230  // return the session controller for it
231  var result = new SessionController(new ReattachInformation
232  {
233  AccessIdentifier = accessIdentifier,
234  Dmb = dmbProvider,
235  IsPrimary = primaryDirectory,
236  Port = portToUse.Value,
237  ProcessId = process.Id,
238  ChatChannelsJson = interopInfo.ChatChannelsJson,
239  ChatCommandsJson = interopInfo.ChatCommandsJson,
240  ServerCommandsJson = interopInfo.ServerCommandsJson,
241  }, process, byondLock, byondTopicSender, chatJsonTrackingContext, context, chat, loggerFactory.CreateLogger<SessionController>(), launchParameters.SecurityLevel, launchParameters.StartupTimeout);
242 
243  // writeback launch parameter's fixed security level
244  launchParameters.SecurityLevel = securityLevelToUse;
245 
246  return result;
247  }
248  catch
249  {
250  process.Dispose();
251  throw;
252  }
253  }
254  catch
255  {
256  context.Dispose();
257  throw;
258  }
259  }
260  catch
261  {
262  if (currentByondLock == null)
263  byondLock.Dispose();
264  throw;
265  }
266  }
267  catch
268  {
269  chatJsonTrackingContext.Dispose();
270  throw;
271  }
272  }
273  #pragma warning restore CA1506
274 
276  public async Task<ISessionController> Reattach(ReattachInformation reattachInformation, CancellationToken cancellationToken)
277  {
278  if (reattachInformation == null)
279  throw new ArgumentNullException(nameof(reattachInformation));
280 
281  SessionController result = null;
282  var basePath = reattachInformation.IsPrimary ? reattachInformation.Dmb.PrimaryDirectory : reattachInformation.Dmb.SecondaryDirectory;
283  var chatJsonTrackingContext = await chat.TrackJsons(basePath, reattachInformation.ChatChannelsJson, reattachInformation.ChatCommandsJson, cancellationToken).ConfigureAwait(false);
284  try
285  {
286  var byondLock = await byond.UseExecutables(Version.Parse(reattachInformation.Dmb.CompileJob.ByondVersion), cancellationToken).ConfigureAwait(false);
287  try
288  {
289  var context = new CommContext(ioManager, loggerFactory.CreateLogger<CommContext>(), basePath, reattachInformation.ServerCommandsJson);
290  try
291  {
292  var process = processExecutor.GetProcess(reattachInformation.ProcessId);
293 
294  if (process != null)
295  try
296  {
298  result = new SessionController(reattachInformation, process, byondLock, byondTopicSender, chatJsonTrackingContext, context, chat, loggerFactory.CreateLogger<SessionController>(), null, null);
299 
300  process = null;
301  context = null;
302  byondLock = null;
303  chatJsonTrackingContext = null;
304  }
305  finally
306  {
307  process?.Dispose();
308  }
309  }
310  finally
311  {
312  context?.Dispose();
313  }
314  }
315  finally
316  {
317  byondLock?.Dispose();
318  }
319  }
320  finally
321  {
322  chatJsonTrackingContext?.Dispose();
323  }
324 
325  return result;
326  }
327 
329  public ISessionController CreateDeadSession(IDmbProvider dmbProvider) => new DeadSessionController(dmbProvider);
330  }
331 }
string ServerCommandsJson
Path to the server commands json file
+
DreamDaemonSecurity? MinimumSecurityLevel
The minimum DreamDaemonSecurity required to run the CompileJob's output
Definition: CompileJob.cs:38
+
readonly ILoggerFactory loggerFactory
The ILoggerFactory for the SessionControllerFactory
-
readonly IIOManager ioManager
The IIOManager for the SessionControllerFactory
-
const string DMParamInfoJson
Path to the JsonFile
Definition: Constants.cs:16
-
CompileJob CompileJob
The CompileJob of the .dmb
Definition: IDmbProvider.cs:29
-
string DmbName
The file name of the .dmb
Definition: IDmbProvider.cs:14
-
readonly IProcessExecutor processExecutor
The IProcessExecutor for the SessionControllerFactory
+
readonly IIOManager ioManager
The IIOManager for the SessionControllerFactory
+
Task< List< string > > GetFilesWithExtension(string path, string extension, CancellationToken cancellationToken)
Gets a list of files in path with the given extension
+
ushort? PrimaryPort
The first port DreamDaemon uses. This should be the publically advertised port
+
const string DMParamInfoJson
Path to the JsonFile
Definition: Constants.cs:16
+
CompileJob CompileJob
The CompileJob of the .dmb
Definition: IDmbProvider.cs:29
+
string DmbName
The file name of the .dmb
Definition: IDmbProvider.cs:14
+ +
readonly IProcessExecutor processExecutor
The IProcessExecutor for the SessionControllerFactory
+
Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content
-
readonly Api.Models.Instance instance
The Api.Models.Instance for the SessionControllerFactory
-
readonly ICryptographySuite cryptographySuite
The ICryptographySuite for the SessionControllerFactory
-
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
- -
string SecondaryDirectory
The secondary game directory with a trailing directory separator
Definition: IDmbProvider.cs:24
-
RevisionInformation RevisionInformation
Git revision the compiler ran on. Not modifiable
Definition: CompileJob.cs:16
- -
string ChatCommandsJson
Path to the chat commands json file
- - -
readonly INetworkPromptReaper networkPromptReaper
The INetworkPromptReaper for the SessionControllerFactory
+
readonly Api.Models.Instance instance
The Api.Models.Instance for the SessionControllerFactory
+
readonly ICryptographySuite cryptographySuite
The ICryptographySuite for the SessionControllerFactory
+
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
+
string SecondaryDirectory
The secondary game directory with a trailing directory separator
Definition: IDmbProvider.cs:24
+
RevisionInformation RevisionInformation
Git revision the compiler ran on. Not modifiable
Definition: CompileJob.cs:16
+
string ChatCommandsJson
Path to the chat commands json file
+ + +
readonly INetworkPromptReaper networkPromptReaper
The INetworkPromptReaper for the SessionControllerFactory
-
DreamDaemonSecurity SecurityLevel
The DreamDaemonSecurity level of DreamDaemon
-
string PrimaryDirectory
The primary game directory with a trailing directory separator
Definition: IDmbProvider.cs:19
-
Representation of the initial json passed to DreamDaemon
Definition: JsonFile.cs:10
-
List< TestMerge > ActiveTestMerges
The TestMerges active in the RevisionInformation
-
For managing connected chat services
Definition: IChat.cs:13
-
Contains various cryptographic functions
+
string PrimaryDirectory
The primary game directory with a trailing directory separator
Definition: IDmbProvider.cs:19
+
Representation of the initial json passed to DreamDaemon
Definition: JsonFile.cs:10
+
List< TestMerge > ActiveTestMerges
The TestMerges active in the RevisionInformation
+
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
+ +
Contains various cryptographic functions
-
Handles communication with a DreamDaemon IProcess
-
readonly IApplication application
The IApplication for the SessionControllerFactory
+ +
Handles communication with a DreamDaemon IProcess
+
readonly IApplication application
The IApplication for the SessionControllerFactory
- -
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
-
DreamDaemonSecurity MinimumSecurityLevel
The minimum DreamDaemonSecurity required to run the CompileJob&#39;s output
Definition: CompileJob.cs:38
-
Version ByondVersion
The Byond.Version the CompileJob was made with
Definition: CompileJob.cs:21
- -
readonly IByondTopicSender byondTopicSender
The IByondTopicSender for the SessionControllerFactory
-
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for the SessionControllerFactory
-
async Task< ISessionController > Reattach(ReattachInformation reattachInformation, CancellationToken cancellationToken)
Create a ISessionController from an existing DreamDaemon instance
-
IDmbProvider Dmb
The IDmbProvider used by DreamDaemon
+
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
+
Task< IJsonTrackingContext > TrackJsons(string basePath, string channelsJsonName, string commandsJsonName, CancellationToken cancellationToken)
Start tracking json files for commands and channels
+
Version ByondVersion
The Byond.Version the CompileJob was made with
Definition: CompileJob.cs:21
+ +
readonly IByondTopicSender byondTopicSender
The IByondTopicSender for the SessionControllerFactory
+
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for the SessionControllerFactory
+
IProcess LaunchProcess(string fileName, string workingDirectory, string arguments=null, bool readOutput=false, bool readError=false, bool noShellExecute=false)
Launch a IProcess
+
async Task< ISessionController > Reattach(ReattachInformation reattachInformation, CancellationToken cancellationToken)
Create a ISessionController from an existing DreamDaemon instance
+
bool IsWindows
If the current platform is a Windows platform
+
IDmbProvider Dmb
The IDmbProvider used by DreamDaemon
- -
For managing the BYOND installation
-
bool IsPrimary
If the Components.IDmbProvider.PrimaryDirectory of the associated dmb is being used ...
-
const string DMParamHostVersion
Identifies a TGS execution. The server version
Definition: Constants.cs:11
- -
string ChatChannelsJson
Path to the chat channels json file
-
Constants used for communication with the DMAPI
Definition: Constants.cs:6
-
readonly IChat chat
The IChat for the SessionControllerFactory
+ + +
bool IsPrimary
If the Components.IDmbProvider.PrimaryDirectory of the associated dmb is being used
+
IProcess GetProcess(int id)
Get a IProcess by id
+
const string DMParamHostVersion
Identifies a TGS execution. The server version
Definition: Constants.cs:11
+ +
string ChatChannelsJson
Path to the chat channels json file
+
Constants used for communication with the DMAPI
Definition: Constants.cs:6
+
readonly IChat chat
The IChat for the SessionControllerFactory
-
SessionControllerFactory(IProcessExecutor processExecutor, IByondManager byond, IByondTopicSender byondTopicSender, ICryptographySuite cryptographySuite, IApplication application, IIOManager ioManager, IChat chat, INetworkPromptReaper networkPromptReaper, IPlatformIdentifier platformIdentifier, ILoggerFactory loggerFactory, Api.Models.Instance instance)
Construct a SessionControllerFactory
-
Represents usage of the two primary BYOND server executables
- -
Represents a BYOND installation
Definition: Byond.cs:8
- -
DreamDaemonSecurity
DreamDaemon&#39;s security level
-
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
- -
Interface for using filesystems
Definition: IIOManager.cs:11
-
readonly IByondManager byond
The IByondManager for the SessionControllerFactory
-
On Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort(). This looks out for those prompts and immediately clicks "Yes" if the owning process has registered for it
-
For identifying the current platform
-
static string SecurityWord(DreamDaemonSecurity securityLevel)
Change a given securityLevel into the appropriate DreamDaemon command line word
- - -
string OriginCommitSha
The sha of the most recent remote commit
-
ushort PrimaryPort
The first port DreamDaemon uses. This should be the publically advertised port
-
Parameters necessary for duplicating a ISessionController session
+
SessionControllerFactory(IProcessExecutor processExecutor, IByondManager byond, IByondTopicSender byondTopicSender, ICryptographySuite cryptographySuite, IApplication application, IIOManager ioManager, IChat chat, INetworkPromptReaper networkPromptReaper, IPlatformIdentifier platformIdentifier, ILoggerFactory loggerFactory, Api.Models.Instance instance)
Construct a SessionControllerFactory
+
Represents usage of the two primary BYOND server executables
+ +
Represents a BYOND installation
Definition: Byond.cs:8
+
string GetSecureString()
Generates a 40-length secure ascii string
+ +
DreamDaemonSecurity
DreamDaemon's security level
+
void RegisterProcess(IProcess process)
Register a given process for network prompt reaping
+
Task< IByondExecutableLock > UseExecutables(Version requiredVersion, CancellationToken cancellationToken)
Lock the current installation's location and return a IByondExecutableLock
+
Provides absolute paths to the latest compiled .dmbs
Definition: IDmbProvider.cs:9
+ +
Interface for using filesystems
Definition: IIOManager.cs:11
+
readonly IByondManager byond
The IByondManager for the SessionControllerFactory
+
bool? AllowWebClient
If the BYOND web client can be used to connect to the game server
+
On Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort()....
+
For identifying the current platform
+
static string SecurityWord(DreamDaemonSecurity securityLevel)
Change a given securityLevel into the appropriate DreamDaemon command line word
+ +
Task DeleteFile(string path, CancellationToken cancellationToken)
Deletes a file at path
+ +
Version Version
The version of the Application
Definition: IApplication.cs:23
+
string OriginCommitSha
The sha of the most recent remote commit
+
string ConcatPath(params string[] paths)
Combines an array of strings into a path
+
Parameters necessary for duplicating a ISessionController session
- - + +
DreamDaemonSecurity? SecurityLevel
The DreamDaemonSecurity level of DreamDaemon
-
bool AllowWebClient
If the BYOND web client can be used to connect to the game server
diff --git a/_setup_wizard_8cs.html b/_setup_wizard_8cs.html index 3927f59fae..13a01128ba 100644 --- a/_setup_wizard_8cs.html +++ b/_setup_wizard_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/SetupWizard.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_setup_wizard_8cs_source.html b/_setup_wizard_8cs_source.html index 4a8a972bca..c37e854ab0 100644 --- a/_setup_wizard_8cs_source.html +++ b/_setup_wizard_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core/SetupWizard.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
SetupWizard.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Hosting;
2 using Microsoft.Extensions.Logging;
3 using Microsoft.Extensions.Options;
4 using MySql.Data.MySqlClient;
5 using Newtonsoft.Json;
6 using System;
7 using System.Collections.Generic;
8 using System.Data.Common;
9 using System.Data.SqlClient;
10 using System.Globalization;
11 using System.Linq;
12 using System.Text;
13 using System.Threading;
14 using System.Threading.Tasks;
16 using Tgstation.Server.Host.IO;
17 
18 namespace Tgstation.Server.Host.Core
19 {
21  sealed class SetupWizard : ISetupWizard
22  {
27 
31  readonly IConsole console;
32 
36  readonly IHostingEnvironment hostingEnvironment;
37 
42 
47 
52 
57 
61  readonly ILogger<SetupWizard> logger;
62 
67 
80  public SetupWizard(IIOManager ioManager, IConsole console, IHostingEnvironment hostingEnvironment, IApplication application, IDBConnectionFactory dbConnectionFactory, IPlatformIdentifier platformIdentifier, IAsyncDelayer asyncDelayer, ILogger<SetupWizard> logger, IOptions<GeneralConfiguration> generalConfigurationOptions)
81  {
82  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
83  this.console = console ?? throw new ArgumentNullException(nameof(console));
84  this.hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
85  this.application = application ?? throw new ArgumentNullException(nameof(application));
86  this.dbConnectionFactory = dbConnectionFactory ?? throw new ArgumentNullException(nameof(dbConnectionFactory));
87  this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
88  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
89  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
90  generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
91  }
92 
99  async Task<bool> PromptYesNo(string question, CancellationToken cancellationToken)
100  {
101  do
102  {
103  await console.WriteAsync(question, false, cancellationToken).ConfigureAwait(false);
104  var responseString = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
105  var upperResponse = responseString.ToUpperInvariant();
106  if (upperResponse == "Y" || upperResponse == "YES")
107  return true;
108  else if (upperResponse == "N" || upperResponse == "NO")
109  return false;
110  await console.WriteAsync("Invalid response!", true, cancellationToken).ConfigureAwait(false);
111  }
112  while (true);
113  }
114 
120  async Task<ushort?> PromptForHostingPort(CancellationToken cancellationToken)
121  {
122  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
123  await console.WriteAsync("What port would you like to connect to TGS on?", true, cancellationToken).ConfigureAwait(false);
124  await console.WriteAsync("Note: If this is a docker container with the default port already mapped, use the default.", true, cancellationToken).ConfigureAwait(false);
125 
126  do
127  {
128  await console.WriteAsync("API Port (leave blank for default): ", false, cancellationToken).ConfigureAwait(false);
129  var portString = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
130  if (String.IsNullOrWhiteSpace(portString))
131  return null;
132  if (UInt16.TryParse(portString, out var port) && port != 0)
133  return port;
134  await console.WriteAsync("Invalid port! Please enter a value between 1 and 65535", true, cancellationToken).ConfigureAwait(false);
135  }
136  while (true);
137  }
138 
144  async Task<DatabaseConfiguration> ConfigureDatabase(CancellationToken cancellationToken)
145  {
146  do
147  {
148  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
149  await console.WriteAsync("What SQL database type will you be using?", true, cancellationToken).ConfigureAwait(false);
150 
151  var databaseConfiguration = new DatabaseConfiguration();
152  do
153  {
154  await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Please enter one of {0}, {1}, or {2}: ", DatabaseType.MariaDB, DatabaseType.SqlServer, DatabaseType.MySql), false, cancellationToken).ConfigureAwait(false);
155  var databaseTypeString = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
156  if (Enum.TryParse<DatabaseType>(databaseTypeString, out var databaseType))
157  {
158  databaseConfiguration.DatabaseType = databaseType;
159  break;
160  }
161 
162  await console.WriteAsync("Invalid database type!", true, cancellationToken).ConfigureAwait(false);
163  }
164  while (true);
165 
166  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
167  await console.WriteAsync("Enter the server's address and port (blank for local): ", false, cancellationToken).ConfigureAwait(false);
168  var serverAddress = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
169  if (String.IsNullOrWhiteSpace(serverAddress))
170  serverAddress = null;
171 
172  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
173  await console.WriteAsync("Enter the database name (Can be from previous installation. Otherwise, should not exist): ", false, cancellationToken).ConfigureAwait(false);
174  string databaseName;
175  do
176  {
177  databaseName = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
178  if (!String.IsNullOrWhiteSpace(databaseName))
179  break;
180  await console.WriteAsync("Invalid database name!", true, cancellationToken).ConfigureAwait(false);
181  }
182  while (true);
183 
184  var dbExists = await PromptYesNo("Does this database already exist? (y/n): ", cancellationToken).ConfigureAwait(false);
185 
186  bool useWinAuth;
187  if (databaseConfiguration.DatabaseType == DatabaseType.SqlServer && platformIdentifier.IsWindows)
188  useWinAuth = await PromptYesNo("Use Windows Authentication? (y/n): ", cancellationToken).ConfigureAwait(false);
189  else
190  useWinAuth = false;
191 
192  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
193 
194  string username = null;
195  string password = null;
196  if (!useWinAuth)
197  {
198  await console.WriteAsync("Enter username: ", false, cancellationToken).ConfigureAwait(false);
199  username = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
200  await console.WriteAsync("Enter password: ", false, cancellationToken).ConfigureAwait(false);
201  password = await console.ReadLineAsync(true, cancellationToken).ConfigureAwait(false);
202  }
203  else
204  {
205  await console.WriteAsync("IMPORTANT: If using the service runner, ensure this computer's LocalSystem account has CREATE DATABASE permissions on the target server!", true, cancellationToken).ConfigureAwait(false);
206  await console.WriteAsync("The account it uses in MSSQL is usually \"NT AUTHORITY\\SYSTEM\" and the role it needs is usually \"dbcreator\".", true, cancellationToken).ConfigureAwait(false);
207  await console.WriteAsync("We'll run a sanity test here, but it won't be indicative of the service's permissions if that is the case", true, cancellationToken).ConfigureAwait(false);
208  }
209 
210  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
211 
212  DbConnection testConnection;
213  void CreateTestConnection(string connectionString)
214  {
215  testConnection = dbConnectionFactory.CreateConnection(connectionString, databaseConfiguration.DatabaseType);
216  }
217 
218  if (databaseConfiguration.DatabaseType == DatabaseType.SqlServer)
219  {
220  var csb = new SqlConnectionStringBuilder
221  {
222  ApplicationName = application.VersionPrefix,
223  DataSource = serverAddress ?? "(local)"
224  };
225  if (useWinAuth)
226  csb.IntegratedSecurity = true;
227  else
228  {
229  csb.UserID = username;
230  csb.Password = password;
231  }
232 
233  CreateTestConnection(csb.ConnectionString);
234  csb.InitialCatalog = databaseName;
235  databaseConfiguration.ConnectionString = csb.ConnectionString;
236  }
237  else
238  {
239  var csb = new MySqlConnectionStringBuilder
240  {
241  Server = serverAddress ?? "127.0.0.1",
242  UserID = username,
243  Password = password
244  };
245 
246  CreateTestConnection(csb.ConnectionString);
247  csb.Database = databaseName;
248  databaseConfiguration.ConnectionString = csb.ConnectionString;
249  }
250 
251  try
252  {
253  using (testConnection)
254  {
255  await console.WriteAsync("Testing connection...", true, cancellationToken).ConfigureAwait(false);
256  await testConnection.OpenAsync(cancellationToken).ConfigureAwait(false);
257  await console.WriteAsync("Connection successful!", true, cancellationToken).ConfigureAwait(false);
258 
259  if (databaseConfiguration.DatabaseType != DatabaseType.SqlServer)
260  {
261  await console.WriteAsync("Checking MySQL/MariaDB version...", true, cancellationToken).ConfigureAwait(false);
262  using (var command = testConnection.CreateCommand())
263  {
264  command.CommandText = "SELECT VERSION()";
265  var fullVersion = (string)await command.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false);
266  await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Found {0}", fullVersion), true, cancellationToken).ConfigureAwait(false);
267  var splits = fullVersion.Split('-');
268  databaseConfiguration.MySqlServerVersion = splits[0];
269  }
270  }
271 
272  if (!dbExists)
273  {
274  await console.WriteAsync("Testing create DB permission...", true, cancellationToken).ConfigureAwait(false);
275  using (var command = testConnection.CreateCommand())
276  {
277  command.CommandText = String.Format(CultureInfo.InvariantCulture, "CREATE DATABASE {0}", databaseName);
278  await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
279  }
280 
281  await console.WriteAsync("Success!", true, cancellationToken).ConfigureAwait(false);
282  await console.WriteAsync("Dropping test database...", true, cancellationToken).ConfigureAwait(false);
283  using (var command = testConnection.CreateCommand())
284  {
285  command.CommandText = String.Format(CultureInfo.InvariantCulture, "DROP DATABASE {0}", databaseName);
286  try
287  {
288  await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
289  }
290  catch (OperationCanceledException)
291  {
292  throw;
293  }
294  catch (Exception e)
295  {
296  await console.WriteAsync(e.Message, true, cancellationToken).ConfigureAwait(false);
297  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
298  await console.WriteAsync("This should be okay, but you may want to manually drop the database before continuing!", true, cancellationToken).ConfigureAwait(false);
299  await console.WriteAsync("Press any key to continue...", true, cancellationToken).ConfigureAwait(false);
300  await console.PressAnyKeyAsync(cancellationToken).ConfigureAwait(false);
301  }
302  }
303  }
304  }
305 
306  return databaseConfiguration;
307  }
308  catch (OperationCanceledException)
309  {
310  throw;
311  }
312  catch (Exception e)
313  {
314  await console.WriteAsync(e.Message, true, cancellationToken).ConfigureAwait(false);
315  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
316  await console.WriteAsync("Retrying database configuration...", true, cancellationToken).ConfigureAwait(false);
317  }
318  }
319  while (true);
320  }
321 
327  async Task<GeneralConfiguration> ConfigureGeneral(CancellationToken cancellationToken)
328  {
329  var newGeneralConfiguration = new GeneralConfiguration
330  {
332  };
333 
334  do
335  {
336  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
337  await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Minimum database user password length (leave blank for default of {0}): ", newGeneralConfiguration.MinimumPasswordLength), false, cancellationToken).ConfigureAwait(false);
338  var passwordLengthString = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
339  if (String.IsNullOrWhiteSpace(passwordLengthString))
340  break;
341  if (UInt32.TryParse(passwordLengthString, out var passwordLength) && passwordLength >= 0)
342  {
343  newGeneralConfiguration.MinimumPasswordLength = passwordLength;
344  break;
345  }
346 
347  await console.WriteAsync("Please enter a positive integer!", true, cancellationToken).ConfigureAwait(false);
348  }
349  while (true);
350 
351  do
352  {
353  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
354  await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Timeout for sending and receiving BYOND topics (ms, 0 for infinite, leave blank for default of {0}): ", newGeneralConfiguration.ByondTopicTimeout), false, cancellationToken).ConfigureAwait(false);
355  var topicTimeoutString = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
356  if (String.IsNullOrWhiteSpace(topicTimeoutString))
357  break;
358  if (Int32.TryParse(topicTimeoutString, out var topicTimeout) && topicTimeout >= 0)
359  {
360  newGeneralConfiguration.ByondTopicTimeout = topicTimeout;
361  break;
362  }
363 
364  await console.WriteAsync("Please enter a positive integer!", true, cancellationToken).ConfigureAwait(false);
365  }
366  while (true);
367 
368  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
369  await console.WriteAsync("Enter a GitHub personal access token to bypass some rate limits (this is optional and does not require any scopes)", true, cancellationToken).ConfigureAwait(false);
370  await console.WriteAsync("GitHub personal access token: ", false, cancellationToken).ConfigureAwait(false);
371  newGeneralConfiguration.GitHubAccessToken = await console.ReadLineAsync(true, cancellationToken).ConfigureAwait(false);
372  if (String.IsNullOrWhiteSpace(newGeneralConfiguration.GitHubAccessToken))
373  newGeneralConfiguration.GitHubAccessToken = null;
374  return newGeneralConfiguration;
375  }
376 
382  async Task<FileLoggingConfiguration> ConfigureLogging(CancellationToken cancellationToken)
383  {
384  var fileLoggingConfiguration = new FileLoggingConfiguration();
385  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
386  fileLoggingConfiguration.Disable = !await PromptYesNo("Enable file logging? (y/n): ", cancellationToken).ConfigureAwait(false);
387 
388  if (!fileLoggingConfiguration.Disable)
389  {
390  do
391  {
392  await console.WriteAsync("Log file directory path (leave blank for default): ", false, cancellationToken).ConfigureAwait(false);
393  fileLoggingConfiguration.Directory = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
394  if (String.IsNullOrWhiteSpace(fileLoggingConfiguration.Directory))
395  {
396  fileLoggingConfiguration.Directory = null;
397  break;
398  }
399 
400  // test a write of it
401  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
402  await console.WriteAsync("Testing directory access...", true, cancellationToken).ConfigureAwait(false);
403  try
404  {
405  await ioManager.CreateDirectory(fileLoggingConfiguration.Directory, cancellationToken).ConfigureAwait(false);
406  var testFile = ioManager.ConcatPath(fileLoggingConfiguration.Directory, String.Format(CultureInfo.InvariantCulture, "WizardAccesTest.{0}.deleteme", Guid.NewGuid()));
407  await ioManager.WriteAllBytes(testFile, Array.Empty<byte>(), cancellationToken).ConfigureAwait(false);
408  try
409  {
410  await ioManager.DeleteFile(testFile, cancellationToken).ConfigureAwait(false);
411  }
412  catch (OperationCanceledException)
413  {
414  throw;
415  }
416  catch (Exception e)
417  {
418  await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Error deleting test log file: {0}", testFile), true, cancellationToken).ConfigureAwait(false);
419  await console.WriteAsync(e.Message, true, cancellationToken).ConfigureAwait(false);
420  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
421  }
422 
423  break;
424  }
425  catch (OperationCanceledException)
426  {
427  throw;
428  }
429  catch (Exception e)
430  {
431  await console.WriteAsync(e.Message, true, cancellationToken).ConfigureAwait(false);
432  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
433  await console.WriteAsync("Please verify the path is valid and you have access to it!", true, cancellationToken).ConfigureAwait(false);
434  }
435  }
436  while (true);
437 
438  async Task<LogLevel?> PromptLogLevel(string question)
439  {
440  do
441  {
442  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
443  await console.WriteAsync(question, true, cancellationToken).ConfigureAwait(false);
444  await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Enter one of {0}/{1}/{2}/{3}/{4}/{5} (leave blank for default): ", nameof(LogLevel.Trace), nameof(LogLevel.Debug), nameof(LogLevel.Information), nameof(LogLevel.Warning), nameof(LogLevel.Error), nameof(LogLevel.Critical)), false, cancellationToken).ConfigureAwait(false);
445  var responseString = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
446  if (String.IsNullOrWhiteSpace(responseString))
447  return null;
448  if (Enum.TryParse<LogLevel>(responseString, out var logLevel) && logLevel != LogLevel.None)
449  return logLevel;
450  await console.WriteAsync("Invalid log level!", true, cancellationToken).ConfigureAwait(false);
451  }
452  while (true);
453  }
454 
455  fileLoggingConfiguration.LogLevel = await PromptLogLevel(String.Format(CultureInfo.InvariantCulture, "Enter the level limit for normal logs (default {0}).", fileLoggingConfiguration.LogLevel)).ConfigureAwait(false) ?? fileLoggingConfiguration.LogLevel;
456  fileLoggingConfiguration.MicrosoftLogLevel = await PromptLogLevel(String.Format(CultureInfo.InvariantCulture, "Enter the level limit for Microsoft logs (VERY verbose, default {0}).", fileLoggingConfiguration.MicrosoftLogLevel)).ConfigureAwait(false) ?? fileLoggingConfiguration.MicrosoftLogLevel;
457  }
458 
459  return fileLoggingConfiguration;
460  }
461 
467  async Task<ControlPanelConfiguration> ConfigureControlPanel(CancellationToken cancellationToken)
468  {
469  var config = new ControlPanelConfiguration
470  {
471  Enable = await PromptYesNo("Enable the web control panel? (y/n): ", cancellationToken).ConfigureAwait(false),
472  AllowAnyOrigin = await PromptYesNo("Allow web control panels hosted elsewhere to access the server? (Access-Control-Allow-Origin: *) (y/n): ", cancellationToken).ConfigureAwait(false)
473  };
474 
475  if (!config.AllowAnyOrigin)
476  {
477  await console.WriteAsync("Enter a comma seperated list of CORS allowed origins (optional): ", false, cancellationToken).ConfigureAwait(false);
478  var commaSeperatedOrigins = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
479  if (!String.IsNullOrWhiteSpace(commaSeperatedOrigins))
480  {
481  var splits = commaSeperatedOrigins.Split(',');
482  config.AllowedOrigins = new List<string>(splits.Select(x => x.Trim()));
483  }
484  }
485 
486  return config;
487  }
488 
500  async Task SaveConfiguration(string userConfigFileName, ushort? hostingPort, DatabaseConfiguration databaseConfiguration, GeneralConfiguration newGeneralConfiguration, FileLoggingConfiguration fileLoggingConfiguration, ControlPanelConfiguration controlPanelConfiguration, CancellationToken cancellationToken)
501  {
502  await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Configuration complete! Saving to {0}", userConfigFileName), true, cancellationToken).ConfigureAwait(false);
503 
504  var map = new Dictionary<string, object>()
505  {
506  { DatabaseConfiguration.Section, databaseConfiguration },
507  { GeneralConfiguration.Section, newGeneralConfiguration },
508  { FileLoggingConfiguration.Section, fileLoggingConfiguration },
509  { ControlPanelConfiguration.Section, controlPanelConfiguration }
510  };
511 
512  if (hostingPort.HasValue)
513  map.Add("Kestrel", new
514  {
515  EndPoints = new
516  {
517  Http = new
518  {
519  Url = String.Format(CultureInfo.InvariantCulture, "http://0.0.0.0:{0}", hostingPort)
520  }
521  }
522  });
523 
524  var json = JsonConvert.SerializeObject(map, Formatting.Indented);
525  var configBytes = Encoding.UTF8.GetBytes(json);
526 
527  try
528  {
529  await ioManager.WriteAllBytes(userConfigFileName, configBytes, cancellationToken).ConfigureAwait(false);
530  }
531  catch (OperationCanceledException)
532  {
533  throw;
534  }
535  catch (Exception e)
536  {
537  await console.WriteAsync(e.Message, true, cancellationToken).ConfigureAwait(false);
538  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
539  await console.WriteAsync("For your convienence, here's the json we tried to write out:", true, cancellationToken).ConfigureAwait(false);
540  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
541  await console.WriteAsync(json, true, cancellationToken).ConfigureAwait(false);
542  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
543  await console.WriteAsync("Press any key to exit...", true, cancellationToken).ConfigureAwait(false);
544  await console.PressAnyKeyAsync(cancellationToken).ConfigureAwait(false);
545  throw new OperationCanceledException();
546  }
547 
548  await console.WriteAsync("Waiting for configuration changes to reload...", true, cancellationToken).ConfigureAwait(false);
549 
550  // we need to wait for the configuration's file system watcher to read and reload the changes
551  await asyncDelayer.Delay(TimeSpan.FromSeconds(5), cancellationToken).ConfigureAwait(false);
552  }
553 
560  async Task RunWizard(string userConfigFileName, CancellationToken cancellationToken)
561  {
562  // welcome message
563  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
564  await console.WriteAsync("Welcome to tgstation-server 4!", true, cancellationToken).ConfigureAwait(false);
565  await console.WriteAsync("This wizard will help you configure your server.", true, cancellationToken).ConfigureAwait(false);
566 
567  var hostingPort = await PromptForHostingPort(cancellationToken).ConfigureAwait(false);
568 
569  var databaseConfiguration = await ConfigureDatabase(cancellationToken).ConfigureAwait(false);
570 
571  var newGeneralConfiguration = await ConfigureGeneral(cancellationToken).ConfigureAwait(false);
572 
573  var fileLoggingConfiguration = await ConfigureLogging(cancellationToken).ConfigureAwait(false);
574 
575  var controlPanelConfiguration = await ConfigureControlPanel(cancellationToken).ConfigureAwait(false);
576 
577  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
578 
579  await SaveConfiguration(userConfigFileName, hostingPort, databaseConfiguration, newGeneralConfiguration, fileLoggingConfiguration, controlPanelConfiguration, cancellationToken).ConfigureAwait(false);
580  }
581 
583  public async Task<bool> CheckRunWizard(CancellationToken cancellationToken)
584  {
585  var setupWizardMode = generalConfiguration.SetupWizardMode;
586  logger.LogTrace("Checking if setup wizard should run. SetupWizardMode: {0}", setupWizardMode);
587 
588  if (setupWizardMode == SetupWizardMode.Never)
589  {
590  logger.LogTrace("Skipping due to configuration...");
591  return false;
592  }
593 
594  var forceRun = setupWizardMode == SetupWizardMode.Force || setupWizardMode == SetupWizardMode.Only;
595  if (!console.Available)
596  {
597  if (forceRun)
598  throw new InvalidOperationException("Asked to run setup wizard with no console avaliable!");
599  logger.LogTrace("Skipping due to console not being available...");
600  return false;
601  }
602 
603  var userConfigFileName = String.Format(CultureInfo.InvariantCulture, "appsettings.{0}.json", hostingEnvironment.EnvironmentName);
604  var exists = await ioManager.FileExists(userConfigFileName, cancellationToken).ConfigureAwait(false);
605 
606  bool shouldRunBasedOnAutodetect;
607  if (exists)
608  {
609  var bytes = await ioManager.ReadAllBytes(userConfigFileName, cancellationToken).ConfigureAwait(false);
610  var contents = Encoding.UTF8.GetString(bytes);
611  var existingConfigIsEmpty = String.IsNullOrWhiteSpace(contents) || contents.Trim() == "{}";
612  logger.LogTrace("Configuration json detected. Empty: {0}", existingConfigIsEmpty);
613  shouldRunBasedOnAutodetect = existingConfigIsEmpty;
614  }
615  else
616  {
617  shouldRunBasedOnAutodetect = true;
618  logger.LogTrace("No configuration json detected");
619  }
620 
621  if (!shouldRunBasedOnAutodetect)
622  {
623  if (forceRun)
624  {
625  logger.LogTrace("Asking user to bypass due to force run request...");
626  await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "The configuration settings are requesting the setup wizard be run, but you already appear to have a configuration file ({0})!", userConfigFileName), true, cancellationToken).ConfigureAwait(false);
627 
628  forceRun = await PromptYesNo("Continue running setup wizard? (y/n): ", cancellationToken).ConfigureAwait(false);
629  }
630 
631  if (!forceRun)
632  return false;
633  }
634 
635  // flush the logs to prevent console conflicts
636  await asyncDelayer.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
637 
638  await RunWizard(userConfigFileName, cancellationToken).ConfigureAwait(false);
639  return true;
640  }
641  }
642 }
readonly IConsole console
The IConsole for the SetupWizard
Definition: SetupWizard.cs:31
-
List< string > AllowedOrigins
Origins allowed for CORS requests
-
async Task< ControlPanelConfiguration > ConfigureControlPanel(CancellationToken cancellationToken)
Prompts the user to create a ControlPanelConfiguration
Definition: SetupWizard.cs:467
-
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
- -
SetupWizardMode
Determines if the Core.ISetupWizard will run
-
Abstraction for System.Console
Definition: IConsole.cs:9
- - +Go to the documentation of this file.
1 using Microsoft.AspNetCore.Hosting;
2 using Microsoft.Extensions.Logging;
3 using Microsoft.Extensions.Options;
4 using MySql.Data.MySqlClient;
5 using Newtonsoft.Json;
6 using System;
7 using System.Collections.Generic;
8 using System.Data.Common;
9 using System.Data.SqlClient;
10 using System.Globalization;
11 using System.Linq;
12 using System.Text;
13 using System.Threading;
14 using System.Threading.Tasks;
16 using Tgstation.Server.Host.IO;
17 
19 {
21  sealed class SetupWizard : ISetupWizard
22  {
27 
31  readonly IConsole console;
32 
36  readonly IHostingEnvironment hostingEnvironment;
37 
42 
47 
52 
57 
61  readonly ILogger<SetupWizard> logger;
62 
67 
80  public SetupWizard(IIOManager ioManager, IConsole console, IHostingEnvironment hostingEnvironment, IApplication application, IDBConnectionFactory dbConnectionFactory, IPlatformIdentifier platformIdentifier, IAsyncDelayer asyncDelayer, ILogger<SetupWizard> logger, IOptions<GeneralConfiguration> generalConfigurationOptions)
81  {
82  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
83  this.console = console ?? throw new ArgumentNullException(nameof(console));
84  this.hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
85  this.application = application ?? throw new ArgumentNullException(nameof(application));
86  this.dbConnectionFactory = dbConnectionFactory ?? throw new ArgumentNullException(nameof(dbConnectionFactory));
87  this.platformIdentifier = platformIdentifier ?? throw new ArgumentNullException(nameof(platformIdentifier));
88  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
89  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
90  generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
91  }
92 
99  async Task<bool> PromptYesNo(string question, CancellationToken cancellationToken)
100  {
101  do
102  {
103  await console.WriteAsync(question, false, cancellationToken).ConfigureAwait(false);
104  var responseString = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
105  var upperResponse = responseString.ToUpperInvariant();
106  if (upperResponse == "Y" || upperResponse == "YES")
107  return true;
108  else if (upperResponse == "N" || upperResponse == "NO")
109  return false;
110  await console.WriteAsync("Invalid response!", true, cancellationToken).ConfigureAwait(false);
111  }
112  while (true);
113  }
114 
120  async Task<ushort?> PromptForHostingPort(CancellationToken cancellationToken)
121  {
122  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
123  await console.WriteAsync("What port would you like to connect to TGS on?", true, cancellationToken).ConfigureAwait(false);
124  await console.WriteAsync("Note: If this is a docker container with the default port already mapped, use the default.", true, cancellationToken).ConfigureAwait(false);
125 
126  do
127  {
128  await console.WriteAsync("API Port (leave blank for default): ", false, cancellationToken).ConfigureAwait(false);
129  var portString = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
130  if (String.IsNullOrWhiteSpace(portString))
131  return null;
132  if (UInt16.TryParse(portString, out var port) && port != 0)
133  return port;
134  await console.WriteAsync("Invalid port! Please enter a value between 1 and 65535", true, cancellationToken).ConfigureAwait(false);
135  }
136  while (true);
137  }
138 
144  async Task<DatabaseConfiguration> ConfigureDatabase(CancellationToken cancellationToken)
145  {
146  do
147  {
148  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
149  await console.WriteAsync("What SQL database type will you be using?", true, cancellationToken).ConfigureAwait(false);
150 
151  var databaseConfiguration = new DatabaseConfiguration();
152  do
153  {
154  await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Please enter one of {0}, {1}, or {2}: ", DatabaseType.MariaDB, DatabaseType.SqlServer, DatabaseType.MySql), false, cancellationToken).ConfigureAwait(false);
155  var databaseTypeString = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
156  if (Enum.TryParse<DatabaseType>(databaseTypeString, out var databaseType))
157  {
158  databaseConfiguration.DatabaseType = databaseType;
159  break;
160  }
161 
162  await console.WriteAsync("Invalid database type!", true, cancellationToken).ConfigureAwait(false);
163  }
164  while (true);
165 
166  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
167  await console.WriteAsync("Enter the server's address and port (blank for local): ", false, cancellationToken).ConfigureAwait(false);
168  var serverAddress = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
169  if (String.IsNullOrWhiteSpace(serverAddress))
170  serverAddress = null;
171 
172  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
173  await console.WriteAsync("Enter the database name (Can be from previous installation. Otherwise, should not exist): ", false, cancellationToken).ConfigureAwait(false);
174  string databaseName;
175  do
176  {
177  databaseName = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
178  if (!String.IsNullOrWhiteSpace(databaseName))
179  break;
180  await console.WriteAsync("Invalid database name!", true, cancellationToken).ConfigureAwait(false);
181  }
182  while (true);
183 
184  var dbExists = await PromptYesNo("Does this database already exist? (y/n): ", cancellationToken).ConfigureAwait(false);
185 
186  bool useWinAuth;
187  if (databaseConfiguration.DatabaseType == DatabaseType.SqlServer && platformIdentifier.IsWindows)
188  useWinAuth = await PromptYesNo("Use Windows Authentication? (y/n): ", cancellationToken).ConfigureAwait(false);
189  else
190  useWinAuth = false;
191 
192  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
193 
194  string username = null;
195  string password = null;
196  if (!useWinAuth)
197  {
198  await console.WriteAsync("Enter username: ", false, cancellationToken).ConfigureAwait(false);
199  username = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
200  await console.WriteAsync("Enter password: ", false, cancellationToken).ConfigureAwait(false);
201  password = await console.ReadLineAsync(true, cancellationToken).ConfigureAwait(false);
202  }
203  else
204  {
205  await console.WriteAsync("IMPORTANT: If using the service runner, ensure this computer's LocalSystem account has CREATE DATABASE permissions on the target server!", true, cancellationToken).ConfigureAwait(false);
206  await console.WriteAsync("The account it uses in MSSQL is usually \"NT AUTHORITY\\SYSTEM\" and the role it needs is usually \"dbcreator\".", true, cancellationToken).ConfigureAwait(false);
207  await console.WriteAsync("We'll run a sanity test here, but it won't be indicative of the service's permissions if that is the case", true, cancellationToken).ConfigureAwait(false);
208  }
209 
210  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
211 
212  DbConnection testConnection;
213  void CreateTestConnection(string connectionString)
214  {
215  testConnection = dbConnectionFactory.CreateConnection(connectionString, databaseConfiguration.DatabaseType);
216  }
217 
218  if (databaseConfiguration.DatabaseType == DatabaseType.SqlServer)
219  {
220  var csb = new SqlConnectionStringBuilder
221  {
222  ApplicationName = application.VersionPrefix,
223  DataSource = serverAddress ?? "(local)"
224  };
225  if (useWinAuth)
226  csb.IntegratedSecurity = true;
227  else
228  {
229  csb.UserID = username;
230  csb.Password = password;
231  }
232 
233  CreateTestConnection(csb.ConnectionString);
234  csb.InitialCatalog = databaseName;
235  databaseConfiguration.ConnectionString = csb.ConnectionString;
236  }
237  else
238  {
239  var csb = new MySqlConnectionStringBuilder
240  {
241  Server = serverAddress ?? "127.0.0.1",
242  UserID = username,
243  Password = password
244  };
245 
246  CreateTestConnection(csb.ConnectionString);
247  csb.Database = databaseName;
248  databaseConfiguration.ConnectionString = csb.ConnectionString;
249  }
250 
251  try
252  {
253  using (testConnection)
254  {
255  await console.WriteAsync("Testing connection...", true, cancellationToken).ConfigureAwait(false);
256  await testConnection.OpenAsync(cancellationToken).ConfigureAwait(false);
257  await console.WriteAsync("Connection successful!", true, cancellationToken).ConfigureAwait(false);
258 
259  if (databaseConfiguration.DatabaseType != DatabaseType.SqlServer)
260  {
261  await console.WriteAsync("Checking MySQL/MariaDB version...", true, cancellationToken).ConfigureAwait(false);
262  using (var command = testConnection.CreateCommand())
263  {
264  command.CommandText = "SELECT VERSION()";
265  var fullVersion = (string)await command.ExecuteScalarAsync(cancellationToken).ConfigureAwait(false);
266  await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Found {0}", fullVersion), true, cancellationToken).ConfigureAwait(false);
267  var splits = fullVersion.Split('-');
268  databaseConfiguration.MySqlServerVersion = splits[0];
269  }
270  }
271 
272  if (!dbExists)
273  {
274  await console.WriteAsync("Testing create DB permission...", true, cancellationToken).ConfigureAwait(false);
275  using (var command = testConnection.CreateCommand())
276  {
277  // I really don't care about user sanitization here, they want to fuck their own DB? so be it
278 #pragma warning disable CA2100 // Review SQL queries for security vulnerabilities
279  command.CommandText = $"CREATE DATABASE {databaseName}";
280 #pragma warning restore CA2100 // Review SQL queries for security vulnerabilities
281  await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
282  }
283 
284  await console.WriteAsync("Success!", true, cancellationToken).ConfigureAwait(false);
285  await console.WriteAsync("Dropping test database...", true, cancellationToken).ConfigureAwait(false);
286  using (var command = testConnection.CreateCommand())
287  {
288 #pragma warning disable CA2100 // Review SQL queries for security vulnerabilities
289  command.CommandText = $"DROP DATABASE {databaseName}";
290 #pragma warning restore CA2100 // Review SQL queries for security vulnerabilities
291  try
292  {
293  await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false);
294  }
295  catch (OperationCanceledException)
296  {
297  throw;
298  }
299  catch (Exception e)
300  {
301  await console.WriteAsync(e.Message, true, cancellationToken).ConfigureAwait(false);
302  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
303  await console.WriteAsync("This should be okay, but you may want to manually drop the database before continuing!", true, cancellationToken).ConfigureAwait(false);
304  await console.WriteAsync("Press any key to continue...", true, cancellationToken).ConfigureAwait(false);
305  await console.PressAnyKeyAsync(cancellationToken).ConfigureAwait(false);
306  }
307  }
308  }
309  }
310 
311  return databaseConfiguration;
312  }
313  catch (OperationCanceledException)
314  {
315  throw;
316  }
317  catch (Exception e)
318  {
319  await console.WriteAsync(e.Message, true, cancellationToken).ConfigureAwait(false);
320  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
321  await console.WriteAsync("Retrying database configuration...", true, cancellationToken).ConfigureAwait(false);
322  }
323  }
324  while (true);
325  }
326 
332  async Task<GeneralConfiguration> ConfigureGeneral(CancellationToken cancellationToken)
333  {
334  var newGeneralConfiguration = new GeneralConfiguration
335  {
337  };
338 
339  do
340  {
341  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
342  await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Minimum database user password length (leave blank for default of {0}): ", newGeneralConfiguration.MinimumPasswordLength), false, cancellationToken).ConfigureAwait(false);
343  var passwordLengthString = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
344  if (String.IsNullOrWhiteSpace(passwordLengthString))
345  break;
346  if (UInt32.TryParse(passwordLengthString, out var passwordLength) && passwordLength >= 0)
347  {
348  newGeneralConfiguration.MinimumPasswordLength = passwordLength;
349  break;
350  }
351 
352  await console.WriteAsync("Please enter a positive integer!", true, cancellationToken).ConfigureAwait(false);
353  }
354  while (true);
355 
356  do
357  {
358  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
359  await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Timeout for sending and receiving BYOND topics (ms, 0 for infinite, leave blank for default of {0}): ", newGeneralConfiguration.ByondTopicTimeout), false, cancellationToken).ConfigureAwait(false);
360  var topicTimeoutString = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
361  if (String.IsNullOrWhiteSpace(topicTimeoutString))
362  break;
363  if (Int32.TryParse(topicTimeoutString, out var topicTimeout) && topicTimeout >= 0)
364  {
365  newGeneralConfiguration.ByondTopicTimeout = topicTimeout;
366  break;
367  }
368 
369  await console.WriteAsync("Please enter a positive integer!", true, cancellationToken).ConfigureAwait(false);
370  }
371  while (true);
372 
373  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
374  await console.WriteAsync("Enter a GitHub personal access token to bypass some rate limits (this is optional and does not require any scopes)", true, cancellationToken).ConfigureAwait(false);
375  await console.WriteAsync("GitHub personal access token: ", false, cancellationToken).ConfigureAwait(false);
376  newGeneralConfiguration.GitHubAccessToken = await console.ReadLineAsync(true, cancellationToken).ConfigureAwait(false);
377  if (String.IsNullOrWhiteSpace(newGeneralConfiguration.GitHubAccessToken))
378  newGeneralConfiguration.GitHubAccessToken = null;
379  return newGeneralConfiguration;
380  }
381 
387  async Task<FileLoggingConfiguration> ConfigureLogging(CancellationToken cancellationToken)
388  {
389  var fileLoggingConfiguration = new FileLoggingConfiguration();
390  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
391  fileLoggingConfiguration.Disable = !await PromptYesNo("Enable file logging? (y/n): ", cancellationToken).ConfigureAwait(false);
392 
393  if (!fileLoggingConfiguration.Disable)
394  {
395  do
396  {
397  await console.WriteAsync("Log file directory path (leave blank for default): ", false, cancellationToken).ConfigureAwait(false);
398  fileLoggingConfiguration.Directory = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
399  if (String.IsNullOrWhiteSpace(fileLoggingConfiguration.Directory))
400  {
401  fileLoggingConfiguration.Directory = null;
402  break;
403  }
404 
405  // test a write of it
406  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
407  await console.WriteAsync("Testing directory access...", true, cancellationToken).ConfigureAwait(false);
408  try
409  {
410  await ioManager.CreateDirectory(fileLoggingConfiguration.Directory, cancellationToken).ConfigureAwait(false);
411  var testFile = ioManager.ConcatPath(fileLoggingConfiguration.Directory, String.Format(CultureInfo.InvariantCulture, "WizardAccesTest.{0}.deleteme", Guid.NewGuid()));
412  await ioManager.WriteAllBytes(testFile, Array.Empty<byte>(), cancellationToken).ConfigureAwait(false);
413  try
414  {
415  await ioManager.DeleteFile(testFile, cancellationToken).ConfigureAwait(false);
416  }
417  catch (OperationCanceledException)
418  {
419  throw;
420  }
421  catch (Exception e)
422  {
423  await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Error deleting test log file: {0}", testFile), true, cancellationToken).ConfigureAwait(false);
424  await console.WriteAsync(e.Message, true, cancellationToken).ConfigureAwait(false);
425  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
426  }
427 
428  break;
429  }
430  catch (OperationCanceledException)
431  {
432  throw;
433  }
434  catch (Exception e)
435  {
436  await console.WriteAsync(e.Message, true, cancellationToken).ConfigureAwait(false);
437  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
438  await console.WriteAsync("Please verify the path is valid and you have access to it!", true, cancellationToken).ConfigureAwait(false);
439  }
440  }
441  while (true);
442 
443  async Task<LogLevel?> PromptLogLevel(string question)
444  {
445  do
446  {
447  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
448  await console.WriteAsync(question, true, cancellationToken).ConfigureAwait(false);
449  await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Enter one of {0}/{1}/{2}/{3}/{4}/{5} (leave blank for default): ", nameof(LogLevel.Trace), nameof(LogLevel.Debug), nameof(LogLevel.Information), nameof(LogLevel.Warning), nameof(LogLevel.Error), nameof(LogLevel.Critical)), false, cancellationToken).ConfigureAwait(false);
450  var responseString = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
451  if (String.IsNullOrWhiteSpace(responseString))
452  return null;
453  if (Enum.TryParse<LogLevel>(responseString, out var logLevel) && logLevel != LogLevel.None)
454  return logLevel;
455  await console.WriteAsync("Invalid log level!", true, cancellationToken).ConfigureAwait(false);
456  }
457  while (true);
458  }
459 
460  fileLoggingConfiguration.LogLevel = await PromptLogLevel(String.Format(CultureInfo.InvariantCulture, "Enter the level limit for normal logs (default {0}).", fileLoggingConfiguration.LogLevel)).ConfigureAwait(false) ?? fileLoggingConfiguration.LogLevel;
461  fileLoggingConfiguration.MicrosoftLogLevel = await PromptLogLevel(String.Format(CultureInfo.InvariantCulture, "Enter the level limit for Microsoft logs (VERY verbose, default {0}).", fileLoggingConfiguration.MicrosoftLogLevel)).ConfigureAwait(false) ?? fileLoggingConfiguration.MicrosoftLogLevel;
462  }
463 
464  return fileLoggingConfiguration;
465  }
466 
472  async Task<ControlPanelConfiguration> ConfigureControlPanel(CancellationToken cancellationToken)
473  {
474  var config = new ControlPanelConfiguration
475  {
476  Enable = await PromptYesNo("Enable the web control panel? (y/n): ", cancellationToken).ConfigureAwait(false),
477  AllowAnyOrigin = await PromptYesNo("Allow web control panels hosted elsewhere to access the server? (Access-Control-Allow-Origin: *) (y/n): ", cancellationToken).ConfigureAwait(false)
478  };
479 
480  if (!config.AllowAnyOrigin)
481  {
482  await console.WriteAsync("Enter a comma seperated list of CORS allowed origins (optional): ", false, cancellationToken).ConfigureAwait(false);
483  var commaSeperatedOrigins = await console.ReadLineAsync(false, cancellationToken).ConfigureAwait(false);
484  if (!String.IsNullOrWhiteSpace(commaSeperatedOrigins))
485  {
486  var splits = commaSeperatedOrigins.Split(',');
487  config.AllowedOrigins = new List<string>(splits.Select(x => x.Trim()));
488  }
489  }
490 
491  return config;
492  }
493 
505  async Task SaveConfiguration(string userConfigFileName, ushort? hostingPort, DatabaseConfiguration databaseConfiguration, GeneralConfiguration newGeneralConfiguration, FileLoggingConfiguration fileLoggingConfiguration, ControlPanelConfiguration controlPanelConfiguration, CancellationToken cancellationToken)
506  {
507  await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "Configuration complete! Saving to {0}", userConfigFileName), true, cancellationToken).ConfigureAwait(false);
508 
509  var map = new Dictionary<string, object>()
510  {
511  { DatabaseConfiguration.Section, databaseConfiguration },
512  { GeneralConfiguration.Section, newGeneralConfiguration },
513  { FileLoggingConfiguration.Section, fileLoggingConfiguration },
514  { ControlPanelConfiguration.Section, controlPanelConfiguration }
515  };
516 
517  if (hostingPort.HasValue)
518  map.Add("Kestrel", new
519  {
520  EndPoints = new
521  {
522  Http = new
523  {
524  Url = String.Format(CultureInfo.InvariantCulture, "http://0.0.0.0:{0}", hostingPort)
525  }
526  }
527  });
528 
529  var json = JsonConvert.SerializeObject(map, Formatting.Indented);
530  var configBytes = Encoding.UTF8.GetBytes(json);
531 
532  try
533  {
534  await ioManager.WriteAllBytes(userConfigFileName, configBytes, cancellationToken).ConfigureAwait(false);
535  }
536  catch (OperationCanceledException)
537  {
538  throw;
539  }
540  catch (Exception e)
541  {
542  await console.WriteAsync(e.Message, true, cancellationToken).ConfigureAwait(false);
543  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
544  await console.WriteAsync("For your convienence, here's the json we tried to write out:", true, cancellationToken).ConfigureAwait(false);
545  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
546  await console.WriteAsync(json, true, cancellationToken).ConfigureAwait(false);
547  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
548  await console.WriteAsync("Press any key to exit...", true, cancellationToken).ConfigureAwait(false);
549  await console.PressAnyKeyAsync(cancellationToken).ConfigureAwait(false);
550  throw new OperationCanceledException();
551  }
552 
553  await console.WriteAsync("Waiting for configuration changes to reload...", true, cancellationToken).ConfigureAwait(false);
554 
555  // we need to wait for the configuration's file system watcher to read and reload the changes
556  await asyncDelayer.Delay(TimeSpan.FromSeconds(5), cancellationToken).ConfigureAwait(false);
557  }
558 
565  async Task RunWizard(string userConfigFileName, CancellationToken cancellationToken)
566  {
567  // welcome message
568  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
569  await console.WriteAsync("Welcome to tgstation-server 4!", true, cancellationToken).ConfigureAwait(false);
570  await console.WriteAsync("This wizard will help you configure your server.", true, cancellationToken).ConfigureAwait(false);
571 
572  var hostingPort = await PromptForHostingPort(cancellationToken).ConfigureAwait(false);
573 
574  var databaseConfiguration = await ConfigureDatabase(cancellationToken).ConfigureAwait(false);
575 
576  var newGeneralConfiguration = await ConfigureGeneral(cancellationToken).ConfigureAwait(false);
577 
578  var fileLoggingConfiguration = await ConfigureLogging(cancellationToken).ConfigureAwait(false);
579 
580  var controlPanelConfiguration = await ConfigureControlPanel(cancellationToken).ConfigureAwait(false);
581 
582  await console.WriteAsync(null, true, cancellationToken).ConfigureAwait(false);
583 
584  await SaveConfiguration(userConfigFileName, hostingPort, databaseConfiguration, newGeneralConfiguration, fileLoggingConfiguration, controlPanelConfiguration, cancellationToken).ConfigureAwait(false);
585  }
586 
588  public async Task<bool> CheckRunWizard(CancellationToken cancellationToken)
589  {
590  var setupWizardMode = generalConfiguration.SetupWizardMode;
591  logger.LogTrace("Checking if setup wizard should run. SetupWizardMode: {0}", setupWizardMode);
592 
593  if (setupWizardMode == SetupWizardMode.Never)
594  {
595  logger.LogTrace("Skipping due to configuration...");
596  return false;
597  }
598 
599  var forceRun = setupWizardMode == SetupWizardMode.Force || setupWizardMode == SetupWizardMode.Only;
600  if (!console.Available)
601  {
602  if (forceRun)
603  throw new InvalidOperationException("Asked to run setup wizard with no console avaliable!");
604  logger.LogTrace("Skipping due to console not being available...");
605  return false;
606  }
607 
608  var userConfigFileName = String.Format(CultureInfo.InvariantCulture, "appsettings.{0}.json", hostingEnvironment.EnvironmentName);
609  var exists = await ioManager.FileExists(userConfigFileName, cancellationToken).ConfigureAwait(false);
610 
611  bool shouldRunBasedOnAutodetect;
612  if (exists)
613  {
614  var bytes = await ioManager.ReadAllBytes(userConfigFileName, cancellationToken).ConfigureAwait(false);
615  var contents = Encoding.UTF8.GetString(bytes);
616  var existingConfigIsEmpty = String.IsNullOrWhiteSpace(contents) || contents.Trim() == "{}";
617  logger.LogTrace("Configuration json detected. Empty: {0}", existingConfigIsEmpty);
618  shouldRunBasedOnAutodetect = existingConfigIsEmpty;
619  }
620  else
621  {
622  shouldRunBasedOnAutodetect = true;
623  logger.LogTrace("No configuration json detected");
624  }
625 
626  if (!shouldRunBasedOnAutodetect)
627  {
628  if (forceRun)
629  {
630  logger.LogTrace("Asking user to bypass due to force run request...");
631  await console.WriteAsync(String.Format(CultureInfo.InvariantCulture, "The configuration settings are requesting the setup wizard be run, but you already appear to have a configuration file ({0})!", userConfigFileName), true, cancellationToken).ConfigureAwait(false);
632 
633  forceRun = await PromptYesNo("Continue running setup wizard? (y/n): ", cancellationToken).ConfigureAwait(false);
634  }
635 
636  if (!forceRun)
637  return false;
638  }
639 
640  // flush the logs to prevent console conflicts
641  await asyncDelayer.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
642 
643  await RunWizard(userConfigFileName, cancellationToken).ConfigureAwait(false);
644  return true;
645  }
646  }
647 }
readonly IConsole console
The IConsole for the SetupWizard
Definition: SetupWizard.cs:31
+
Task WriteAllBytes(string path, byte[] contents, CancellationToken cancellationToken)
Writes some contents to a file at path overwriting previous content
+
async Task< ControlPanelConfiguration > ConfigureControlPanel(CancellationToken cancellationToken)
Prompts the user to create a ControlPanelConfiguration
Definition: SetupWizard.cs:472
+
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
+
SetupWizardMode
Determines if the Core.ISetupWizard will run
+
Abstraction for System.Console
Definition: IConsole.cs:9
+ +
bool Available
If the IConsole is visible to the user
Definition: IConsole.cs:14
+
string VersionPrefix
Prefix to VersionString
Definition: IApplication.cs:13
const string Section
The key for the Microsoft.Extensions.Configuration.IConfigurationSection the GeneralConfiguration res...
-
readonly IApplication application
The IApplication for the SetupWizard
Definition: SetupWizard.cs:41
- +
DbConnection CreateConnection(string connectionString, DatabaseType databaseType)
Create a DbConnection
+
readonly IApplication application
The IApplication for the SetupWizard
Definition: SetupWizard.cs:41
+
Task CreateDirectory(string path, CancellationToken cancellationToken)
Create a directory at path
+
const string Section
The key for the Microsoft.Extensions.Configuration.IConfigurationSection the DatabaseConfiguration re...
-
readonly IIOManager ioManager
The IIOManager for the SetupWizard
Definition: SetupWizard.cs:26
-
readonly IDBConnectionFactory dbConnectionFactory
The IDBConnectionFactory for the SetupWizard
Definition: SetupWizard.cs:46
-
readonly GeneralConfiguration generalConfiguration
The GeneralConfiguration for the SetupWizard
Definition: SetupWizard.cs:66
-
SetupWizard(IIOManager ioManager, IConsole console, IHostingEnvironment hostingEnvironment, IApplication application, IDBConnectionFactory dbConnectionFactory, IPlatformIdentifier platformIdentifier, IAsyncDelayer asyncDelayer, ILogger< SetupWizard > logger, IOptions< GeneralConfiguration > generalConfigurationOptions)
Construct a SetupWizard
Definition: SetupWizard.cs:80
-
async Task< bool > PromptYesNo(string question, CancellationToken cancellationToken)
A prompt for a yes or no value
Definition: SetupWizard.cs:99
+
readonly IIOManager ioManager
The IIOManager for the SetupWizard
Definition: SetupWizard.cs:26
+
readonly IDBConnectionFactory dbConnectionFactory
The IDBConnectionFactory for the SetupWizard
Definition: SetupWizard.cs:46
+ +
readonly GeneralConfiguration generalConfiguration
The GeneralConfiguration for the SetupWizard
Definition: SetupWizard.cs:66
+
SetupWizard(IIOManager ioManager, IConsole console, IHostingEnvironment hostingEnvironment, IApplication application, IDBConnectionFactory dbConnectionFactory, IPlatformIdentifier platformIdentifier, IAsyncDelayer asyncDelayer, ILogger< SetupWizard > logger, IOptions< GeneralConfiguration > generalConfigurationOptions)
Construct a SetupWizard
Definition: SetupWizard.cs:80
+
Task< bool > FileExists(string path, CancellationToken cancellationToken)
Check that the file at path exists
+
async Task< bool > PromptYesNo(string question, CancellationToken cancellationToken)
A prompt for a yes or no value
Definition: SetupWizard.cs:99
const string Section
The key for the Microsoft.Extensions.Configuration.IConfigurationSection the ControlPanelConfiguratio...
+
Task< string > ReadLineAsync(bool usePasswordChar, CancellationToken cancellationToken)
Read a line from the IConsole
- -
async Task< DatabaseConfiguration > ConfigureDatabase(CancellationToken cancellationToken)
Prompts the user to create a DatabaseConfiguration
Definition: SetupWizard.cs:144
- -
async Task< GeneralConfiguration > ConfigureGeneral(CancellationToken cancellationToken)
Prompts the user to create a GeneralConfiguration
Definition: SetupWizard.cs:327
- -
async Task SaveConfiguration(string userConfigFileName, ushort?hostingPort, DatabaseConfiguration databaseConfiguration, GeneralConfiguration newGeneralConfiguration, FileLoggingConfiguration fileLoggingConfiguration, ControlPanelConfiguration controlPanelConfiguration, CancellationToken cancellationToken)
Saves a given Configuration set to userConfigFileName
Definition: SetupWizard.cs:500
-
readonly IHostingEnvironment hostingEnvironment
The IHostingEnvironment for the SetupWizard
Definition: SetupWizard.cs:36
-
async Task< ushort?> PromptForHostingPort(CancellationToken cancellationToken)
Prompts the user to enter the port to host TGS on
Definition: SetupWizard.cs:120
-
Configuration options for the Models.DatabaseContext<TParentContext>
-
async Task< FileLoggingConfiguration > ConfigureLogging(CancellationToken cancellationToken)
Prompts the user to create a FileLoggingConfiguration
Definition: SetupWizard.cs:382
- -
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the SetupWizard
Definition: SetupWizard.cs:56
-
async Task< bool > CheckRunWizard(CancellationToken cancellationToken)
Run the setup wizard if necessary
Definition: SetupWizard.cs:583
-
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for the SetupWizard
Definition: SetupWizard.cs:51
-
DatabaseType
Type of database to user
Definition: DatabaseType.cs:6
- -
The command line Configuration setup wizard
Definition: ISetupWizard.cs:9
+
Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan
+ +
async Task< DatabaseConfiguration > ConfigureDatabase(CancellationToken cancellationToken)
Prompts the user to create a DatabaseConfiguration
Definition: SetupWizard.cs:144
+ + +
bool IsWindows
If the current platform is a Windows platform
+
Task WriteAsync(string text, bool newLine, CancellationToken cancellationToken)
Write some text to the IConsole
+
async Task< GeneralConfiguration > ConfigureGeneral(CancellationToken cancellationToken)
Prompts the user to create a GeneralConfiguration
Definition: SetupWizard.cs:332
+ +
async Task SaveConfiguration(string userConfigFileName, ushort? hostingPort, DatabaseConfiguration databaseConfiguration, GeneralConfiguration newGeneralConfiguration, FileLoggingConfiguration fileLoggingConfiguration, ControlPanelConfiguration controlPanelConfiguration, CancellationToken cancellationToken)
Saves a given Configuration set to userConfigFileName
Definition: SetupWizard.cs:505
+
readonly IHostingEnvironment hostingEnvironment
The IHostingEnvironment for the SetupWizard
Definition: SetupWizard.cs:36
+
async Task< ushort?> PromptForHostingPort(CancellationToken cancellationToken)
Prompts the user to enter the port to host TGS on
Definition: SetupWizard.cs:120
+
Configuration options for the Models.DatabaseContext<TParentContext>
+
async Task< FileLoggingConfiguration > ConfigureLogging(CancellationToken cancellationToken)
Prompts the user to create a FileLoggingConfiguration
Definition: SetupWizard.cs:387
+ +
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the SetupWizard
Definition: SetupWizard.cs:56
+
async Task< bool > CheckRunWizard(CancellationToken cancellationToken)
Run the setup wizard if necessary
Definition: SetupWizard.cs:588
+
readonly IPlatformIdentifier platformIdentifier
The IPlatformIdentifier for the SetupWizard
Definition: SetupWizard.cs:51
+
DatabaseType
Type of database to user
Definition: DatabaseType.cs:6
+ +
The command line Configuration setup wizard
Definition: ISetupWizard.cs:9
const string Section
The key for the Microsoft.Extensions.Configuration.IConfigurationSection the FileLoggingConfiguration...
-
Interface for using filesystems
Definition: IIOManager.cs:11
-
For identifying the current platform
-
readonly ILogger< SetupWizard > logger
The ILogger for the SetupWizard
Definition: SetupWizard.cs:61
-
async Task RunWizard(string userConfigFileName, CancellationToken cancellationToken)
Runs the SetupWizard
Definition: SetupWizard.cs:560
- -
uint MinimumPasswordLength
Minimum length of database user passwords
- +
Interface for using filesystems
Definition: IIOManager.cs:11
+
For identifying the current platform
+
readonly ILogger< SetupWizard > logger
The ILogger for the SetupWizard
Definition: SetupWizard.cs:61
+
Task PressAnyKeyAsync(CancellationToken cancellationToken)
Wait for a key press on the IConsole
+
Task< byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
Returns all the contents of a file at path as a byte array
+
async Task RunWizard(string userConfigFileName, CancellationToken cancellationToken)
Runs the SetupWizard
Definition: SetupWizard.cs:565
+
Task DeleteFile(string path, CancellationToken cancellationToken)
Deletes a file at path
+ +
string ConcatPath(params string[] paths)
Combines an array of strings into a path
+
diff --git a/_setup_wizard_mode_8cs.html b/_setup_wizard_mode_8cs.html index 3ed6e1ae18..fb217519cc 100644 --- a/_setup_wizard_mode_8cs.html +++ b/_setup_wizard_mode_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Configuration/SetupWizardMode.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Namespaces

+namespace  Tgstation +  +namespace  Tgstation.Server +  +namespace  Tgstation.Server.Host +  namespace  Tgstation.Server.Host.Configuration   @@ -109,8 +94,8 @@ EnumerationsTgstation.Server.Host.Configuration.SetupWizardMode.Force, Tgstation.Server.Host.Configuration.SetupWizardMode.Only, Tgstation.Server.Host.Configuration.SetupWizardMode.Never - } - + } +
 Determines if the Core.ISetupWizard will run More...
 Determines if the Core.ISetupWizard will run More...
 
@@ -118,7 +103,7 @@ Enumerations diff --git a/_setup_wizard_mode_8cs_source.html b/_setup_wizard_mode_8cs_source.html index 9384f95e30..d390acd1cd 100644 --- a/_setup_wizard_mode_8cs_source.html +++ b/_setup_wizard_mode_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Configuration/SetupWizardMode.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
SetupWizardMode.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Host.Configuration
2 {
6  public enum SetupWizardMode
7  {
11  Autodetect,
12 
16  Force,
17 
21  Only,
22 
26  Never
27  }
28 }
- -
SetupWizardMode
Determines if the Core.ISetupWizard will run
- -
Run the wizard if the appsettings.{Environment}.json is not present or empty
- - - +Go to the documentation of this file.
2 {
6  public enum SetupWizardMode
7  {
11  Autodetect,
12 
16  Force,
17 
21  Only,
22 
26  Never
27  }
28 }
+
SetupWizardMode
Determines if the Core.ISetupWizard will run
+ + +
Run the wizard if the appsettings.{Environment}.json is not present or empty
+
diff --git a/_sql_server_database_context_8cs.html b/_sql_server_database_context_8cs.html index 01ffefa67e..ff0f73429f 100644 --- a/_sql_server_database_context_8cs.html +++ b/_sql_server_database_context_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/SqlServerDatabaseContext.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.SqlServerDatabaseContextDatabaseContext<TParentContext> for Sqlserver More...
DatabaseContext<TParentContext> for Sqlserver More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_sql_server_database_context_8cs_source.html b/_sql_server_database_context_8cs_source.html index a4e7d5e31c..d56b769288 100644 --- a/_sql_server_database_context_8cs_source.html +++ b/_sql_server_database_context_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/SqlServerDatabaseContext.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
SqlServerDatabaseContext.cs
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using Microsoft.Extensions.Logging;
3 using Microsoft.Extensions.Options;
5 
6 namespace Tgstation.Server.Host.Models
7 {
11  sealed class SqlServerDatabaseContext : DatabaseContext<SqlServerDatabaseContext>
12  {
20  public SqlServerDatabaseContext(DbContextOptions<SqlServerDatabaseContext> dbContextOptions, IOptions<DatabaseConfiguration> databaseConfiguration, IDatabaseSeeder databaseSeeder, ILogger<SqlServerDatabaseContext> logger) : base(dbContextOptions, databaseConfiguration, databaseSeeder, logger)
21  { }
22 
24  protected override void OnConfiguring(DbContextOptionsBuilder options)
25  {
26  base.OnConfiguring(options);
27  options.UseSqlServer(DatabaseConfiguration.ConnectionString);
28  }
29 
31  protected override bool UseMySQLMigrations() => false;
32  }
33 }
string ConnectionString
The connection string for the database
+Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using Microsoft.Extensions.Logging;
3 using Microsoft.Extensions.Options;
5 
7 {
11  sealed class SqlServerDatabaseContext : DatabaseContext<SqlServerDatabaseContext>
12  {
20  public SqlServerDatabaseContext(DbContextOptions<SqlServerDatabaseContext> dbContextOptions, IOptions<DatabaseConfiguration> databaseConfiguration, IDatabaseSeeder databaseSeeder, ILogger<SqlServerDatabaseContext> logger) : base(dbContextOptions, databaseConfiguration, databaseSeeder, logger)
21  { }
22 
24  protected override void OnConfiguring(DbContextOptionsBuilder options)
25  {
26  base.OnConfiguring(options);
27  options.UseSqlServer(DatabaseConfiguration.ConnectionString);
28  }
29 
31  protected override bool UseMySQLMigrations() => false;
32  }
33 }
string ConnectionString
The connection string for the database
override void OnConfiguring(DbContextOptionsBuilder options)
- -
For initially seeding a database
-
DatabaseContext<TParentContext> for Sqlserver
+ +
For initially seeding a database
+
DatabaseContext<TParentContext> for Sqlserver
-
SqlServerDatabaseContext(DbContextOptions< SqlServerDatabaseContext > dbContextOptions, IOptions< DatabaseConfiguration > databaseConfiguration, IDatabaseSeeder databaseSeeder, ILogger< SqlServerDatabaseContext > logger)
Construct a SqlServerDatabaseContext
+
SqlServerDatabaseContext(DbContextOptions< SqlServerDatabaseContext > dbContextOptions, IOptions< DatabaseConfiguration > databaseConfiguration, IDatabaseSeeder databaseSeeder, ILogger< SqlServerDatabaseContext > logger)
Construct a SqlServerDatabaseContext
-
Configuration options for the Models.DatabaseContext<TParentContext>
- - - +
Configuration options for the Models.DatabaseContext<TParentContext>
+ +
readonly IDatabaseSeeder databaseSeeder
The IDatabaseSeeder for the DatabaseContext<TParentContext>
+ +
override bool UseMySQLMigrations()
If the MY_ class of migrations should be used instead of the MS_ class
+
diff --git a/_sql_server_database_context_model_snapshot_8cs.html b/_sql_server_database_context_model_snapshot_8cs.html index 502a2c7714..a9f8ef829f 100644 --- a/_sql_server_database_context_model_snapshot_8cs.html +++ b/_sql_server_database_context_model_snapshot_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/SqlServerDatabaseContextModelSnapshot.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_sql_server_database_context_model_snapshot_8cs_source.html b/_sql_server_database_context_model_snapshot_8cs_source.html index 947f76e86a..c53465c5b9 100644 --- a/_sql_server_database_context_model_snapshot_8cs_source.html +++ b/_sql_server_database_context_model_snapshot_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/SqlServerDatabaseContextModelSnapshot.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
SqlServerDatabaseContextModelSnapshot.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.Storage.ValueConversion;
7 
8 namespace Tgstation.Server.Host.Models.Migrations
9 {
10  [DbContext(typeof(SqlServerDatabaseContext))]
12  {
13  protected override void BuildModel(ModelBuilder modelBuilder)
14  {
15 #pragma warning disable 612, 618
16  modelBuilder
17  .HasAnnotation("ProductVersion", "2.1.4-rtm-31024")
18  .HasAnnotation("Relational:MaxIdentifierLength", 128)
19  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
20 
21  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
22  {
23  b.Property<long>("Id")
24  .ValueGeneratedOnAdd()
25  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
26 
27  b.Property<string>("ConnectionString")
28  .IsRequired();
29 
30  b.Property<bool?>("Enabled");
31 
32  b.Property<long>("InstanceId");
33 
34  b.Property<string>("Name")
35  .IsRequired();
36 
37  b.Property<int?>("Provider");
38 
39  b.HasKey("Id");
40 
41  b.HasIndex("InstanceId");
42 
43  b.HasIndex("Name")
44  .IsUnique();
45 
46  b.ToTable("ChatBots");
47  });
48 
49  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
50  {
51  b.Property<long>("Id")
52  .ValueGeneratedOnAdd()
53  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
54 
55  b.Property<long>("ChatSettingsId");
56 
57  b.Property<decimal?>("DiscordChannelId")
58  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
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  .HasFilter("[DiscordChannelId] IS NOT NULL");
78 
79  b.HasIndex("ChatSettingsId", "IrcChannel")
80  .IsUnique()
81  .HasFilter("[IrcChannel] IS NOT NULL");
82 
83  b.ToTable("ChatChannels");
84  });
85 
86  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
87  {
88  b.Property<long>("Id")
89  .ValueGeneratedOnAdd()
90  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
91 
92  b.Property<string>("ByondVersion")
93  .IsRequired();
94 
95  b.Property<Guid?>("DirectoryName")
96  .IsRequired();
97 
98  b.Property<string>("DmeName")
99  .IsRequired();
100 
101  b.Property<long>("JobId");
102 
103  b.Property<int>("MinimumSecurityLevel");
104 
105  b.Property<string>("Output")
106  .IsRequired();
107 
108  b.Property<long>("RevisionInformationId");
109 
110  b.HasKey("Id");
111 
112  b.HasIndex("DirectoryName");
113 
114  b.HasIndex("JobId")
115  .IsUnique();
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<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  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
189 
190  b.Property<long>("AutoUpdateInterval");
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  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
216 
217  b.Property<decimal>("ByondRights")
218  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
219 
220  b.Property<decimal>("ChatBotRights")
221  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
222 
223  b.Property<decimal>("ConfigurationRights")
224  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
225 
226  b.Property<decimal>("DreamDaemonRights")
227  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
228 
229  b.Property<decimal>("DreamMakerRights")
230  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
231 
232  b.Property<long>("InstanceId");
233 
234  b.Property<decimal>("InstanceUserRights")
235  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
236 
237  b.Property<decimal>("RepositoryRights")
238  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
239 
240  b.Property<long?>("UserId")
241  .IsRequired();
242 
243  b.HasKey("Id");
244 
245  b.HasIndex("InstanceId");
246 
247  b.HasIndex("UserId", "InstanceId")
248  .IsUnique();
249 
250  b.ToTable("InstanceUsers");
251  });
252 
253  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
254  {
255  b.Property<long>("Id")
256  .ValueGeneratedOnAdd()
257  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
258 
259  b.Property<decimal?>("CancelRight")
260  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
261 
262  b.Property<decimal?>("CancelRightsType")
263  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
264 
265  b.Property<bool?>("Cancelled")
266  .IsRequired();
267 
268  b.Property<long?>("CancelledById");
269 
270  b.Property<string>("Description")
271  .IsRequired();
272 
273  b.Property<string>("ExceptionDetails");
274 
275  b.Property<long>("InstanceId");
276 
277  b.Property<DateTimeOffset?>("StartedAt")
278  .IsRequired();
279 
280  b.Property<long>("StartedById");
281 
282  b.Property<DateTimeOffset?>("StoppedAt");
283 
284  b.HasKey("Id");
285 
286  b.HasIndex("CancelledById");
287 
288  b.HasIndex("InstanceId");
289 
290  b.HasIndex("StartedById");
291 
292  b.ToTable("Jobs");
293  });
294 
295  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
296  {
297  b.Property<long>("Id")
298  .ValueGeneratedOnAdd()
299  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
300 
301  b.Property<string>("AccessIdentifier")
302  .IsRequired();
303 
304  b.Property<string>("ChatChannelsJson")
305  .IsRequired();
306 
307  b.Property<string>("ChatCommandsJson")
308  .IsRequired();
309 
310  b.Property<long>("CompileJobId");
311 
312  b.Property<bool>("IsPrimary");
313 
314  b.Property<int>("Port");
315 
316  b.Property<int>("ProcessId");
317 
318  b.Property<int>("RebootState");
319 
320  b.Property<string>("ServerCommandsJson")
321  .IsRequired();
322 
323  b.HasKey("Id");
324 
325  b.HasIndex("CompileJobId");
326 
327  b.ToTable("ReattachInformations");
328  });
329 
330  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
331  {
332  b.Property<long>("Id")
333  .ValueGeneratedOnAdd()
334  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
335 
336  b.Property<string>("AccessToken");
337 
338  b.Property<string>("AccessUser");
339 
340  b.Property<bool?>("AutoUpdatesKeepTestMerges")
341  .IsRequired();
342 
343  b.Property<bool?>("AutoUpdatesSynchronize")
344  .IsRequired();
345 
346  b.Property<string>("CommitterEmail")
347  .IsRequired();
348 
349  b.Property<string>("CommitterName")
350  .IsRequired();
351 
352  b.Property<long>("InstanceId");
353 
354  b.Property<bool?>("PostTestMergeComment")
355  .IsRequired();
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("InstanceId", "CommitSha")
409  .IsUnique();
410 
411  b.ToTable("RevisionInformations");
412  });
413 
414  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
415  {
416  b.Property<long>("Id")
417  .ValueGeneratedOnAdd()
418  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
419 
420  b.Property<string>("Author")
421  .IsRequired();
422 
423  b.Property<string>("BodyAtMerge")
424  .IsRequired();
425 
426  b.Property<string>("Comment");
427 
428  b.Property<DateTimeOffset>("MergedAt");
429 
430  b.Property<long>("MergedById");
431 
432  b.Property<int?>("Number")
433  .IsRequired();
434 
435  b.Property<long?>("PrimaryRevisionInformationId")
436  .IsRequired();
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 
454  b.ToTable("TestMerges");
455  });
456 
457  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
458  {
459  b.Property<long>("Id")
460  .ValueGeneratedOnAdd()
461  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
462 
463  b.Property<decimal>("AdministrationRights")
464  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
465 
466  b.Property<string>("CanonicalName")
467  .IsRequired();
468 
469  b.Property<DateTimeOffset?>("CreatedAt")
470  .IsRequired();
471 
472  b.Property<long?>("CreatedById");
473 
474  b.Property<bool?>("Enabled")
475  .IsRequired();
476 
477  b.Property<decimal>("InstanceManagerRights")
478  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
479 
480  b.Property<DateTimeOffset?>("LastPasswordUpdate");
481 
482  b.Property<string>("Name")
483  .IsRequired();
484 
485  b.Property<string>("PasswordHash");
486 
487  b.Property<string>("SystemIdentifier");
488 
489  b.HasKey("Id");
490 
491  b.HasIndex("CanonicalName")
492  .IsUnique();
493 
494  b.HasIndex("CreatedById");
495 
496  b.ToTable("Users");
497  });
498 
499  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
500  {
501  b.Property<long>("Id")
502  .ValueGeneratedOnAdd()
503  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
504 
505  b.Property<long?>("AlphaId");
506 
507  b.Property<bool>("AlphaIsActive");
508 
509  b.Property<long?>("BravoId");
510 
511  b.Property<long>("InstanceId");
512 
513  b.HasKey("Id");
514 
515  b.HasIndex("AlphaId");
516 
517  b.HasIndex("BravoId");
518 
519  b.HasIndex("InstanceId")
520  .IsUnique();
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  .WithOne()
545  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
546  .OnDelete(DeleteBehavior.Restrict);
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.InstanceUser", b =>
571  {
572  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
573  .WithMany("InstanceUsers")
574  .HasForeignKey("InstanceId")
575  .OnDelete(DeleteBehavior.Cascade);
576 
577  b.HasOne("Tgstation.Server.Host.Models.User")
578  .WithMany("InstanceUsers")
579  .HasForeignKey("UserId")
580  .OnDelete(DeleteBehavior.Cascade);
581  });
582 
583  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
584  {
585  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
586  .WithMany()
587  .HasForeignKey("CancelledById");
588 
589  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
590  .WithMany("Jobs")
591  .HasForeignKey("InstanceId")
592  .OnDelete(DeleteBehavior.Cascade);
593 
594  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
595  .WithMany()
596  .HasForeignKey("StartedById")
597  .OnDelete(DeleteBehavior.Cascade);
598  });
599 
600  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
601  {
602  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
603  .WithMany()
604  .HasForeignKey("CompileJobId")
605  .OnDelete(DeleteBehavior.Cascade);
606  });
607 
608  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
609  {
610  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
611  .WithOne("RepositorySettings")
612  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
613  .OnDelete(DeleteBehavior.Cascade);
614  });
615 
616  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
617  {
618  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
619  .WithMany("ActiveTestMerges")
620  .HasForeignKey("RevisionInformationId")
621  .OnDelete(DeleteBehavior.Cascade);
622 
623  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
624  .WithMany("RevisonInformations")
625  .HasForeignKey("TestMergeId")
626  .OnDelete(DeleteBehavior.Cascade);
627  });
628 
629  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
630  {
631  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
632  .WithMany("RevisionInformations")
633  .HasForeignKey("InstanceId")
634  .OnDelete(DeleteBehavior.Cascade);
635  });
636 
637  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
638  {
639  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
640  .WithMany("TestMerges")
641  .HasForeignKey("MergedById")
642  .OnDelete(DeleteBehavior.Restrict);
643 
644  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
645  .WithOne("PrimaryTestMerge")
646  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
647  .OnDelete(DeleteBehavior.Restrict);
648  });
649 
650  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
651  {
652  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
653  .WithMany("CreatedUsers")
654  .HasForeignKey("CreatedById");
655  });
656 
657  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
658  {
659  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
660  .WithMany()
661  .HasForeignKey("AlphaId");
662 
663  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
664  .WithMany()
665  .HasForeignKey("BravoId");
666 
667  b.HasOne("Tgstation.Server.Host.Models.Instance")
668  .WithOne("WatchdogReattachInformation")
669  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
670  .OnDelete(DeleteBehavior.Cascade);
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.Storage.ValueConversion;
7 
9 {
10  [DbContext(typeof(SqlServerDatabaseContext))]
12  {
13  protected override void BuildModel(ModelBuilder modelBuilder)
14  {
15 #pragma warning disable 612, 618
16  modelBuilder
17  .HasAnnotation("ProductVersion", "2.1.4-rtm-31024")
18  .HasAnnotation("Relational:MaxIdentifierLength", 128)
19  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
20 
21  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatBot", b =>
22  {
23  b.Property<long>("Id")
24  .ValueGeneratedOnAdd()
25  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
26 
27  b.Property<string>("ConnectionString")
28  .IsRequired();
29 
30  b.Property<bool?>("Enabled");
31 
32  b.Property<long>("InstanceId");
33 
34  b.Property<string>("Name")
35  .IsRequired();
36 
37  b.Property<int?>("Provider");
38 
39  b.HasKey("Id");
40 
41  b.HasIndex("InstanceId");
42 
43  b.HasIndex("Name")
44  .IsUnique();
45 
46  b.ToTable("ChatBots");
47  });
48 
49  modelBuilder.Entity("Tgstation.Server.Host.Models.ChatChannel", b =>
50  {
51  b.Property<long>("Id")
52  .ValueGeneratedOnAdd()
53  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
54 
55  b.Property<long>("ChatSettingsId");
56 
57  b.Property<decimal?>("DiscordChannelId")
58  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
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  .HasFilter("[DiscordChannelId] IS NOT NULL");
78 
79  b.HasIndex("ChatSettingsId", "IrcChannel")
80  .IsUnique()
81  .HasFilter("[IrcChannel] IS NOT NULL");
82 
83  b.ToTable("ChatChannels");
84  });
85 
86  modelBuilder.Entity("Tgstation.Server.Host.Models.CompileJob", b =>
87  {
88  b.Property<long>("Id")
89  .ValueGeneratedOnAdd()
90  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
91 
92  b.Property<string>("ByondVersion")
93  .IsRequired();
94 
95  b.Property<Guid?>("DirectoryName")
96  .IsRequired();
97 
98  b.Property<string>("DmeName")
99  .IsRequired();
100 
101  b.Property<long>("JobId");
102 
103  b.Property<int>("MinimumSecurityLevel");
104 
105  b.Property<string>("Output")
106  .IsRequired();
107 
108  b.Property<long>("RevisionInformationId");
109 
110  b.HasKey("Id");
111 
112  b.HasIndex("DirectoryName");
113 
114  b.HasIndex("JobId")
115  .IsUnique();
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<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  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
189 
190  b.Property<long>("AutoUpdateInterval");
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  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
216 
217  b.Property<decimal>("ByondRights")
218  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
219 
220  b.Property<decimal>("ChatBotRights")
221  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
222 
223  b.Property<decimal>("ConfigurationRights")
224  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
225 
226  b.Property<decimal>("DreamDaemonRights")
227  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
228 
229  b.Property<decimal>("DreamMakerRights")
230  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
231 
232  b.Property<long>("InstanceId");
233 
234  b.Property<decimal>("InstanceUserRights")
235  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
236 
237  b.Property<decimal>("RepositoryRights")
238  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
239 
240  b.Property<long?>("UserId")
241  .IsRequired();
242 
243  b.HasKey("Id");
244 
245  b.HasIndex("InstanceId");
246 
247  b.HasIndex("UserId", "InstanceId")
248  .IsUnique();
249 
250  b.ToTable("InstanceUsers");
251  });
252 
253  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
254  {
255  b.Property<long>("Id")
256  .ValueGeneratedOnAdd()
257  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
258 
259  b.Property<decimal?>("CancelRight")
260  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
261 
262  b.Property<decimal?>("CancelRightsType")
263  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
264 
265  b.Property<bool?>("Cancelled")
266  .IsRequired();
267 
268  b.Property<long?>("CancelledById");
269 
270  b.Property<string>("Description")
271  .IsRequired();
272 
273  b.Property<string>("ExceptionDetails");
274 
275  b.Property<long>("InstanceId");
276 
277  b.Property<DateTimeOffset?>("StartedAt")
278  .IsRequired();
279 
280  b.Property<long>("StartedById");
281 
282  b.Property<DateTimeOffset?>("StoppedAt");
283 
284  b.HasKey("Id");
285 
286  b.HasIndex("CancelledById");
287 
288  b.HasIndex("InstanceId");
289 
290  b.HasIndex("StartedById");
291 
292  b.ToTable("Jobs");
293  });
294 
295  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
296  {
297  b.Property<long>("Id")
298  .ValueGeneratedOnAdd()
299  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
300 
301  b.Property<string>("AccessIdentifier")
302  .IsRequired();
303 
304  b.Property<string>("ChatChannelsJson")
305  .IsRequired();
306 
307  b.Property<string>("ChatCommandsJson")
308  .IsRequired();
309 
310  b.Property<long>("CompileJobId");
311 
312  b.Property<bool>("IsPrimary");
313 
314  b.Property<int>("Port");
315 
316  b.Property<int>("ProcessId");
317 
318  b.Property<int>("RebootState");
319 
320  b.Property<string>("ServerCommandsJson")
321  .IsRequired();
322 
323  b.HasKey("Id");
324 
325  b.HasIndex("CompileJobId");
326 
327  b.ToTable("ReattachInformations");
328  });
329 
330  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
331  {
332  b.Property<long>("Id")
333  .ValueGeneratedOnAdd()
334  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
335 
336  b.Property<string>("AccessToken");
337 
338  b.Property<string>("AccessUser");
339 
340  b.Property<bool?>("AutoUpdatesKeepTestMerges")
341  .IsRequired();
342 
343  b.Property<bool?>("AutoUpdatesSynchronize")
344  .IsRequired();
345 
346  b.Property<string>("CommitterEmail")
347  .IsRequired();
348 
349  b.Property<string>("CommitterName")
350  .IsRequired();
351 
352  b.Property<long>("InstanceId");
353 
354  b.Property<bool?>("PostTestMergeComment")
355  .IsRequired();
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("InstanceId", "CommitSha")
409  .IsUnique();
410 
411  b.ToTable("RevisionInformations");
412  });
413 
414  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
415  {
416  b.Property<long>("Id")
417  .ValueGeneratedOnAdd()
418  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
419 
420  b.Property<string>("Author")
421  .IsRequired();
422 
423  b.Property<string>("BodyAtMerge")
424  .IsRequired();
425 
426  b.Property<string>("Comment");
427 
428  b.Property<DateTimeOffset>("MergedAt");
429 
430  b.Property<long>("MergedById");
431 
432  b.Property<int?>("Number")
433  .IsRequired();
434 
435  b.Property<long?>("PrimaryRevisionInformationId")
436  .IsRequired();
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 
454  b.ToTable("TestMerges");
455  });
456 
457  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
458  {
459  b.Property<long>("Id")
460  .ValueGeneratedOnAdd()
461  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
462 
463  b.Property<decimal>("AdministrationRights")
464  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
465 
466  b.Property<string>("CanonicalName")
467  .IsRequired();
468 
469  b.Property<DateTimeOffset?>("CreatedAt")
470  .IsRequired();
471 
472  b.Property<long?>("CreatedById");
473 
474  b.Property<bool?>("Enabled")
475  .IsRequired();
476 
477  b.Property<decimal>("InstanceManagerRights")
478  .HasConversion(new ValueConverter<decimal, decimal>(v => default(decimal), v => default(decimal), new ConverterMappingHints(precision: 20, scale: 0)));
479 
480  b.Property<DateTimeOffset?>("LastPasswordUpdate");
481 
482  b.Property<string>("Name")
483  .IsRequired();
484 
485  b.Property<string>("PasswordHash");
486 
487  b.Property<string>("SystemIdentifier");
488 
489  b.HasKey("Id");
490 
491  b.HasIndex("CanonicalName")
492  .IsUnique();
493 
494  b.HasIndex("CreatedById");
495 
496  b.ToTable("Users");
497  });
498 
499  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
500  {
501  b.Property<long>("Id")
502  .ValueGeneratedOnAdd()
503  .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
504 
505  b.Property<long?>("AlphaId");
506 
507  b.Property<bool>("AlphaIsActive");
508 
509  b.Property<long?>("BravoId");
510 
511  b.Property<long>("InstanceId");
512 
513  b.HasKey("Id");
514 
515  b.HasIndex("AlphaId");
516 
517  b.HasIndex("BravoId");
518 
519  b.HasIndex("InstanceId")
520  .IsUnique();
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  .WithOne()
545  .HasForeignKey("Tgstation.Server.Host.Models.CompileJob", "JobId")
546  .OnDelete(DeleteBehavior.Restrict);
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.InstanceUser", b =>
571  {
572  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
573  .WithMany("InstanceUsers")
574  .HasForeignKey("InstanceId")
575  .OnDelete(DeleteBehavior.Cascade);
576 
577  b.HasOne("Tgstation.Server.Host.Models.User")
578  .WithMany("InstanceUsers")
579  .HasForeignKey("UserId")
580  .OnDelete(DeleteBehavior.Cascade);
581  });
582 
583  modelBuilder.Entity("Tgstation.Server.Host.Models.Job", b =>
584  {
585  b.HasOne("Tgstation.Server.Host.Models.User", "CancelledBy")
586  .WithMany()
587  .HasForeignKey("CancelledById");
588 
589  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
590  .WithMany("Jobs")
591  .HasForeignKey("InstanceId")
592  .OnDelete(DeleteBehavior.Cascade);
593 
594  b.HasOne("Tgstation.Server.Host.Models.User", "StartedBy")
595  .WithMany()
596  .HasForeignKey("StartedById")
597  .OnDelete(DeleteBehavior.Cascade);
598  });
599 
600  modelBuilder.Entity("Tgstation.Server.Host.Models.ReattachInformation", b =>
601  {
602  b.HasOne("Tgstation.Server.Host.Models.CompileJob", "CompileJob")
603  .WithMany()
604  .HasForeignKey("CompileJobId")
605  .OnDelete(DeleteBehavior.Cascade);
606  });
607 
608  modelBuilder.Entity("Tgstation.Server.Host.Models.RepositorySettings", b =>
609  {
610  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
611  .WithOne("RepositorySettings")
612  .HasForeignKey("Tgstation.Server.Host.Models.RepositorySettings", "InstanceId")
613  .OnDelete(DeleteBehavior.Cascade);
614  });
615 
616  modelBuilder.Entity("Tgstation.Server.Host.Models.RevInfoTestMerge", b =>
617  {
618  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "RevisionInformation")
619  .WithMany("ActiveTestMerges")
620  .HasForeignKey("RevisionInformationId")
621  .OnDelete(DeleteBehavior.Cascade);
622 
623  b.HasOne("Tgstation.Server.Host.Models.TestMerge", "TestMerge")
624  .WithMany("RevisonInformations")
625  .HasForeignKey("TestMergeId")
626  .OnDelete(DeleteBehavior.Cascade);
627  });
628 
629  modelBuilder.Entity("Tgstation.Server.Host.Models.RevisionInformation", b =>
630  {
631  b.HasOne("Tgstation.Server.Host.Models.Instance", "Instance")
632  .WithMany("RevisionInformations")
633  .HasForeignKey("InstanceId")
634  .OnDelete(DeleteBehavior.Cascade);
635  });
636 
637  modelBuilder.Entity("Tgstation.Server.Host.Models.TestMerge", b =>
638  {
639  b.HasOne("Tgstation.Server.Host.Models.User", "MergedBy")
640  .WithMany("TestMerges")
641  .HasForeignKey("MergedById")
642  .OnDelete(DeleteBehavior.Restrict);
643 
644  b.HasOne("Tgstation.Server.Host.Models.RevisionInformation", "PrimaryRevisionInformation")
645  .WithOne("PrimaryTestMerge")
646  .HasForeignKey("Tgstation.Server.Host.Models.TestMerge", "PrimaryRevisionInformationId")
647  .OnDelete(DeleteBehavior.Restrict);
648  });
649 
650  modelBuilder.Entity("Tgstation.Server.Host.Models.User", b =>
651  {
652  b.HasOne("Tgstation.Server.Host.Models.User", "CreatedBy")
653  .WithMany("CreatedUsers")
654  .HasForeignKey("CreatedById");
655  });
656 
657  modelBuilder.Entity("Tgstation.Server.Host.Models.WatchdogReattachInformation", b =>
658  {
659  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Alpha")
660  .WithMany()
661  .HasForeignKey("AlphaId");
662 
663  b.HasOne("Tgstation.Server.Host.Models.ReattachInformation", "Bravo")
664  .WithMany()
665  .HasForeignKey("BravoId");
666 
667  b.HasOne("Tgstation.Server.Host.Models.Instance")
668  .WithOne("WatchdogReattachInformation")
669  .HasForeignKey("Tgstation.Server.Host.Models.WatchdogReattachInformation", "InstanceId")
670  .OnDelete(DeleteBehavior.Cascade);
671  });
672 #pragma warning restore 612, 618
673  }
674  }
675 }
- -
diff --git a/_sql_server_design_time_db_context_factory_8cs.html b/_sql_server_design_time_db_context_factory_8cs.html index 5134d34754..4648d45ecb 100644 --- a/_sql_server_design_time_db_context_factory_8cs.html +++ b/_sql_server_design_time_db_context_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/SqlServerDesignTimeDbContextFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
namespace  Tgstation.Server.Host.Models.Migrations
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_sql_server_design_time_db_context_factory_8cs_source.html b/_sql_server_design_time_db_context_factory_8cs_source.html index e03aeeb243..9e1d6858b0 100644 --- a/_sql_server_design_time_db_context_factory_8cs_source.html +++ b/_sql_server_design_time_db_context_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations/SqlServerDesignTimeDbContextFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
SqlServerDesignTimeDbContextFactory.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 
7 namespace Tgstation.Server.Host.Models.Migrations
8 {
10  sealed class SqlServerDesignTimeDbContextFactory : IDesignTimeDbContextFactory<SqlServerDatabaseContext>
11  {
13  public SqlServerDatabaseContext CreateDbContext(string[] args) => new SqlServerDatabaseContext(new DbContextOptions<SqlServerDatabaseContext>(), DesignTimeDbContextFactoryHelpers.GetDbContextOptions(), new DatabaseSeeder(new CryptographySuite(new PasswordHasher<User>())), new LoggerFactory().CreateLogger<SqlServerDatabaseContext>());
14  }
15 }
static IOptions< DatabaseConfiguration > GetDbContextOptions()
Get the IOptions<TOptions> for the DatabaseConfiguration
- -
Contains helpers for creating design time Models.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;
6 
8 {
10  sealed class SqlServerDesignTimeDbContextFactory : IDesignTimeDbContextFactory<SqlServerDatabaseContext>
11  {
14  {
15  using (var loggerFactory = new LoggerFactory())
16  {
17  return new SqlServerDatabaseContext(new DbContextOptions<SqlServerDatabaseContext>(), DesignTimeDbContextFactoryHelpers.GetDbContextOptions(), new DatabaseSeeder(new CryptographySuite(new PasswordHasher<User>())), loggerFactory.CreateLogger<SqlServerDatabaseContext>());
18  }
19  }
20  }
21 }
static IOptions< DatabaseConfiguration > GetDbContextOptions()
Get the IOptions<TOptions> for the DatabaseConfiguration
+ +
Contains helpers for creating design time DatabaseContext<TParentContext>s
-
DatabaseContext<TParentContext> for Sqlserver
+
DatabaseContext<TParentContext> for Sqlserver
+ - + - - + +
diff --git a/_synchronous_i_o_manager_8cs.html b/_synchronous_i_o_manager_8cs.html index a6a7f4126e..815d89687a 100644 --- a/_synchronous_i_o_manager_8cs.html +++ b/_synchronous_i_o_manager_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/SynchronousIOManager.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.IO
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_synchronous_i_o_manager_8cs_source.html b/_synchronous_i_o_manager_8cs_source.html index bcb4b9e608..89f86b4b5f 100644 --- a/_synchronous_i_o_manager_8cs_source.html +++ b/_synchronous_i_o_manager_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/SynchronousIOManager.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
SynchronousIOManager.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.Linq;
6 using System.Security.Cryptography;
7 using System.Threading;
8 
9 namespace Tgstation.Server.Host.IO
10 {
13  {
15  public bool CreateDirectory(string path, CancellationToken cancellationToken)
16  {
17  if (IsDirectory(path))
18  return true;
19  cancellationToken.ThrowIfCancellationRequested();
20  Directory.CreateDirectory(path);
21  return false;
22  }
23 
25  public bool DeleteDirectory(string path)
26  {
27  if (File.Exists(path))
28  return false;
29 
30  if (!Directory.Exists(path))
31  return true;
32 
33  if (Directory.EnumerateFileSystemEntries(path).Any())
34  return false;
35 
36  Directory.Delete(path);
37  return true;
38  }
39 
41  public IEnumerable<string> GetDirectories(string path, CancellationToken cancellationToken)
42  {
43  foreach (var I in Directory.EnumerateDirectories(path))
44  {
45  yield return Path.GetFileName(I);
46  cancellationToken.ThrowIfCancellationRequested();
47  }
48  }
49 
51  public IEnumerable<string> GetFiles(string path, CancellationToken cancellationToken)
52  {
53  foreach (var I in Directory.EnumerateFiles(path))
54  {
55  yield return Path.GetFileName(I);
56  cancellationToken.ThrowIfCancellationRequested();
57  }
58  }
59 
61  public bool IsDirectory(string path)
62  {
63  if (path == null)
64  throw new ArgumentNullException(nameof(path));
65  return Directory.Exists(path);
66  }
67 
69  public byte[] ReadFile(string path)
70  {
71  if (path == null)
72  throw new ArgumentNullException(nameof(path));
73  return File.ReadAllBytes(path);
74  }
75 
77  public bool WriteFileChecked(string path, byte[] data, ref string sha1InOut, CancellationToken cancellationToken)
78  {
79  if (path == null)
80  throw new ArgumentNullException(nameof(path));
81  cancellationToken.ThrowIfCancellationRequested();
82  var directory = Path.GetDirectoryName(path);
83  Directory.CreateDirectory(directory);
84  cancellationToken.ThrowIfCancellationRequested();
85  using (var file = File.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
86  {
87  cancellationToken.ThrowIfCancellationRequested();
88 
89  // as nice as it would be to not have to arrayify the memory stream, we have to
90  // because, oddly enough sha1(memorystream) != sha1(memorystream.ToArray())
91  // vOv
92  byte[] originalBytes;
93  using (var readMs = new MemoryStream())
94  {
95  file.CopyTo(readMs);
96  originalBytes = readMs.ToArray();
97  }
98 
99  // no sha1? no write
100  if (originalBytes.Length != 0 && sha1InOut == null)
101  return false;
102 
103  // suppressed due to only using for consistency checks
104 #pragma warning disable CA5350 // Do not use insecure cryptographic algorithm SHA1.
105  using (var sha1 = new SHA1Managed())
106 #pragma warning restore CA5350 // Do not use insecure cryptographic algorithm SHA1.
107  {
108  string GetSha1(byte[] dataToHash) => dataToHash != null && dataToHash.Length != 0 ? String.Join(String.Empty, sha1.ComputeHash(dataToHash).Select(b => b.ToString("x2", CultureInfo.InvariantCulture))) : null;
109  var originalSha1 = GetSha1(originalBytes);
110  if (originalSha1 != sha1InOut)
111  {
112  sha1InOut = originalSha1;
113  return false;
114  }
115 
116  sha1InOut = GetSha1(data);
117  }
118 
119  cancellationToken.ThrowIfCancellationRequested();
120 
121  if (data != null)
122  {
123  file.Seek(0, SeekOrigin.Begin);
124 
125  cancellationToken.ThrowIfCancellationRequested();
126  file.SetLength(data.Length);
127  file.Write(data, 0, data.Length);
128  }
129  }
130 
131  if (data == null)
132  File.Delete(path);
133  return true;
134  }
135  }
136 }
IEnumerable< string > GetDirectories(string path, CancellationToken cancellationToken)
Enumerate directories in a given path
-
bool CreateDirectory(string path, CancellationToken cancellationToken)
Create an empty directory at path
- -
byte[] ReadFile(string path)
Read the bytes of a file at a given path
- -
For accessing the disk in a synchronous manner
-
bool WriteFileChecked(string path, byte[] data, ref string sha1InOut, CancellationToken cancellationToken)
Write data to a file at a given 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.Linq;
6 using System.Security.Cryptography;
7 using System.Threading;
8 
10 {
13  {
15  public bool CreateDirectory(string path, CancellationToken cancellationToken)
16  {
17  if (IsDirectory(path))
18  return true;
19  cancellationToken.ThrowIfCancellationRequested();
20  Directory.CreateDirectory(path);
21  return false;
22  }
23 
25  public bool DeleteDirectory(string path)
26  {
27  if (File.Exists(path))
28  return false;
29 
30  if (!Directory.Exists(path))
31  return true;
32 
33  if (Directory.EnumerateFileSystemEntries(path).Any())
34  return false;
35 
36  Directory.Delete(path);
37  return true;
38  }
39 
41  public IEnumerable<string> GetDirectories(string path, CancellationToken cancellationToken)
42  {
43  foreach (var I in Directory.EnumerateDirectories(path))
44  {
45  yield return Path.GetFileName(I);
46  cancellationToken.ThrowIfCancellationRequested();
47  }
48  }
49 
51  public IEnumerable<string> GetFiles(string path, CancellationToken cancellationToken)
52  {
53  foreach (var I in Directory.EnumerateFiles(path))
54  {
55  yield return Path.GetFileName(I);
56  cancellationToken.ThrowIfCancellationRequested();
57  }
58  }
59 
61  public bool IsDirectory(string path)
62  {
63  if (path == null)
64  throw new ArgumentNullException(nameof(path));
65  return Directory.Exists(path);
66  }
67 
69  public byte[] ReadFile(string path)
70  {
71  if (path == null)
72  throw new ArgumentNullException(nameof(path));
73  return File.ReadAllBytes(path);
74  }
75 
77  public bool WriteFileChecked(string path, byte[] data, ref string sha1InOut, CancellationToken cancellationToken)
78  {
79  if (path == null)
80  throw new ArgumentNullException(nameof(path));
81  cancellationToken.ThrowIfCancellationRequested();
82  var directory = Path.GetDirectoryName(path);
83  Directory.CreateDirectory(directory);
84  cancellationToken.ThrowIfCancellationRequested();
85  using (var file = File.Open(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None))
86  {
87  cancellationToken.ThrowIfCancellationRequested();
88 
89  // as nice as it would be to not have to arrayify the memory stream, we have to
90  // because, oddly enough sha1(memorystream) != sha1(memorystream.ToArray())
91  // vOv
92  byte[] originalBytes;
93  using (var readMs = new MemoryStream())
94  {
95  file.CopyTo(readMs);
96  originalBytes = readMs.ToArray();
97  }
98 
99  // no sha1? no write
100  if (originalBytes.Length != 0 && sha1InOut == null)
101  return false;
102 
103  // suppressed due to only using for consistency checks
104 #pragma warning disable CA5350 // Do not use insecure cryptographic algorithm SHA1.
105  using (var sha1 = new SHA1Managed())
106 #pragma warning restore CA5350 // Do not use insecure cryptographic algorithm SHA1.
107  {
108  string GetSha1(byte[] dataToHash) => dataToHash != null && dataToHash.Length != 0 ? String.Join(String.Empty, sha1.ComputeHash(dataToHash).Select(b => b.ToString("x2", CultureInfo.InvariantCulture))) : null;
109  var originalSha1 = GetSha1(originalBytes);
110  if (originalSha1 != sha1InOut)
111  {
112  sha1InOut = originalSha1;
113  return false;
114  }
115 
116  sha1InOut = GetSha1(data);
117  }
118 
119  cancellationToken.ThrowIfCancellationRequested();
120 
121  if (data != null)
122  {
123  file.Seek(0, SeekOrigin.Begin);
124 
125  cancellationToken.ThrowIfCancellationRequested();
126  file.SetLength(data.Length);
127  file.Write(data, 0, data.Length);
128  }
129  }
130 
131  if (data == null)
132  File.Delete(path);
133  return true;
134  }
135  }
136 }
IEnumerable< string > GetDirectories(string path, CancellationToken cancellationToken)
Enumerate directories in a given path
+
bool CreateDirectory(string path, CancellationToken cancellationToken)
Create an empty directory at path
+
byte [] ReadFile(string path)
Read the bytes of a file at a given path
+
For accessing the disk in a synchronous manner
+
bool WriteFileChecked(string path, byte[] data, ref string sha1InOut, CancellationToken cancellationToken)
Write data to a file at a given path
-
bool IsDirectory(string path)
Checks if a given path is a directory
-
bool DeleteDirectory(string path)
Deletes a directory at path if it&#39;s empty
-
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
+
bool DeleteDirectory(string path)
Deletes a directory at path if it's empty
+
IEnumerable< string > GetFiles(string path, CancellationToken cancellationToken)
Enumerate files in a given path
+
diff --git a/_task_extensions_8cs.html b/_task_extensions_8cs.html new file mode 100644 index 0000000000..5eca39fb8f --- /dev/null +++ b/_task_extensions_8cs.html @@ -0,0 +1,105 @@ + + + + + + + +tgstation-server: src/Tgstation.Server.Host/Core/TaskExtensions.cs File Reference + + + + + + + + + +
+
+ + + + + + + +
+
tgstation-server +
+
The /tg/station 13 server suite
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+ +
+
TaskExtensions.cs File Reference
+
+
+ +

Go to the source code of this file.

+ + + + + +

+Classes

class  Tgstation.Server.Host.Core.TaskExtensions
 Extensions for the Task class. More...
 
+ + + + + + + + + +

+Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
+
+ + + + diff --git a/_task_extensions_8cs_source.html b/_task_extensions_8cs_source.html new file mode 100644 index 0000000000..00970a5b57 --- /dev/null +++ b/_task_extensions_8cs_source.html @@ -0,0 +1,86 @@ + + + + + + + +tgstation-server: src/Tgstation.Server.Host/Core/TaskExtensions.cs Source File + + + + + + + + + +
+
+ + + + + + + +
+
tgstation-server +
+
The /tg/station 13 server suite
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
TaskExtensions.cs
+
+
+Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
4 
6 {
10  static class TaskExtensions
11  {
18  public static Task WithToken(this Task task, CancellationToken cancellationToken)
19  {
20  if (task == null)
21  throw new ArgumentNullException(nameof(task));
22 
23  async Task<object> Wrap()
24  {
25  await task.ConfigureAwait(false);
26  return null;
27  }
28 
29  return Wrap().WithToken(cancellationToken);
30  }
31 
39  public static async Task<T> WithToken<T>(this Task<T> task, CancellationToken cancellationToken)
40  {
41  if (task == null)
42  throw new ArgumentNullException(nameof(task));
43 
44  var cancelTcs = new TaskCompletionSource<object>();
45  using (cancellationToken.Register(() => cancelTcs.SetCanceled()))
46  await Task.WhenAny(task, cancelTcs.Task).ConfigureAwait(false);
47  cancellationToken.ThrowIfCancellationRequested();
48 
49  return await task.ConfigureAwait(false);
50  }
51  }
52 }
static async Task< T > WithToken< T >(this Task< T > task, CancellationToken cancellationToken)
Create a Task<TResult> that can be awaited while respecting a given cancellationToken .
+
static Task WithToken(this Task task, CancellationToken cancellationToken)
Create a Task that can be awaited while respecting a given cancellationToken .
+ +
Extensions for the Task class.
+
+ + + + diff --git a/_temporary_dmb_provider_8cs.html b/_temporary_dmb_provider_8cs.html index 39acf87ea0..38dacf5a8c 100644 --- a/_temporary_dmb_provider_8cs.html +++ b/_temporary_dmb_provider_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Compiler/TemporaryDmbProvider.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Components.Compiler.TemporaryDmbProvider - Temporary IDmbProvider More...
+ Temporary IDmbProvider More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Compiler
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_temporary_dmb_provider_8cs_source.html b/_temporary_dmb_provider_8cs_source.html index b24a198c1e..3e73a503b5 100644 --- a/_temporary_dmb_provider_8cs_source.html +++ b/_temporary_dmb_provider_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Compiler/TemporaryDmbProvider.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TemporaryDmbProvider.cs
-Go to the documentation of this file.
1 using System;
3 
4 namespace Tgstation.Server.Host.Components.Compiler
5 {
10  {
12  public string DmbName { get; }
13 
15  public string PrimaryDirectory { get; }
16 
18  public string SecondaryDirectory => throw new NotSupportedException();
19 
21  public CompileJob CompileJob { get; }
22 
29  public TemporaryDmbProvider(string directory, string dmb, CompileJob compileJob)
30  {
31  DmbName = dmb ?? throw new ArgumentNullException(nameof(dmb));
32  PrimaryDirectory = directory ?? throw new ArgumentNullException(nameof(directory));
33  CompileJob = compileJob ?? throw new ArgumentNullException(nameof(compileJob));
34  }
35 
37  public void Dispose() { }
38 
40  public void KeepAlive() => throw new NotSupportedException();
41  }
42 }
TemporaryDmbProvider(string directory, string dmb, CompileJob compileJob)
Construct a TemporaryDmbProvider
- +Go to the documentation of this file.
1 using System;
3 
5 {
10  {
12  public string DmbName { get; }
13 
15  public string PrimaryDirectory { get; }
16 
18  public string SecondaryDirectory => throw new NotSupportedException();
19 
21  public CompileJob CompileJob { get; }
22 
29  public TemporaryDmbProvider(string directory, string dmb, CompileJob compileJob)
30  {
31  DmbName = dmb ?? throw new ArgumentNullException(nameof(dmb));
32  PrimaryDirectory = directory ?? throw new ArgumentNullException(nameof(directory));
33  CompileJob = compileJob ?? throw new ArgumentNullException(nameof(compileJob));
34  }
35 
37  public void Dispose() { }
38 
40  public void KeepAlive() => throw new NotSupportedException();
41  }
42 }
TemporaryDmbProvider(string directory, string dmb, CompileJob compileJob)
Construct a TemporaryDmbProvider
+ - - + + - -
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/_test_api_client_8cs.html b/_test_api_client_8cs.html index 9355dc72cc..5c0bc06fc1 100644 --- a/_test_api_client_8cs.html +++ b/_test_api_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Client.Tests/TestApiClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Tests
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_test_api_client_8cs_source.html b/_test_api_client_8cs_source.html index ba324c0a70..ea65668486 100644 --- a/_test_api_client_8cs_source.html +++ b/_test_api_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Client.Tests/TestApiClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestApiClient.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using Moq;
3 using Newtonsoft.Json;
4 using Newtonsoft.Json.Converters;
5 using Newtonsoft.Json.Serialization;
6 using System;
7 using System.Net;
8 using System.Net.Http;
9 using System.Net.Http.Headers;
10 using System.Threading;
11 using System.Threading.Tasks;
12 using Tgstation.Server.Api;
14 
15 namespace Tgstation.Server.Client.Tests
16 {
17  [TestClass]
18  public sealed class TestApiClient
19  {
20  [TestMethod]
22  {
23  var sample = new Byond
24  {
25  Version = new Version(511, 1385)
26  };
27 
28  var sampleJson = JsonConvert.SerializeObject(sample, new JsonSerializerSettings
29  {
30  ContractResolver = new CamelCasePropertyNamesContractResolver(),
31  Converters = new[] { new VersionConverter() }
32  });
33 
34  var response = new HttpResponseMessage(HttpStatusCode.OK)
35  {
36  Content = new StringContent(sampleJson)
37  };
38 
39  var httpClient = new Mock<IHttpClient>();
40  httpClient.Setup(x => x.SendAsync(It.IsNotNull<HttpRequestMessage>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(response));
41 
42  var client = new ApiClient(httpClient.Object, new Uri("http://fake.com"), new ApiHeaders(new ProductHeaderValue("fake"), "fake"));
43 
44  var result = await client.Read<Byond>(Routes.Byond, default).ConfigureAwait(false);
45  Assert.AreEqual(sample.Version, result.Version);
46  }
47 
48  [TestMethod]
49  public async Task TestUnrecognizedResponse()
50  {
51  var sample = new Byond
52  {
53  Version = new Version(511, 1385)
54  };
55 
56  var fakeJson = "asdfasd <>F#(*)U*#JLI";
57 
58  var response = new HttpResponseMessage(HttpStatusCode.OK)
59  {
60  Content = new StringContent(fakeJson)
61  };
62 
63  var httpClient = new Mock<IHttpClient>();
64  httpClient.Setup(x => x.SendAsync(It.IsNotNull<HttpRequestMessage>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(response));
65 
66  var client = new ApiClient(httpClient.Object, new Uri("http://fake.com"), new ApiHeaders(new ProductHeaderValue("fake"), "fake"));
67 
68  await Assert.ThrowsExceptionAsync<UnrecognizedResponseException>(() => client.Read<Byond>(Routes.Byond, default)).ConfigureAwait(false);
69  }
70  }
71 }
const string Byond
The Models.Byond controller
Definition: Routes.cs:34
-
Occurs when a response is received that did not deserialize to one of the expected Api...
+Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using Moq;
3 using Newtonsoft.Json;
4 using Newtonsoft.Json.Converters;
5 using Newtonsoft.Json.Serialization;
6 using System;
7 using System.Net;
8 using System.Net.Http;
9 using System.Net.Http.Headers;
10 using System.Threading;
11 using System.Threading.Tasks;
12 using Tgstation.Server.Api;
14 
16 {
17  [TestClass]
18  public sealed class TestApiClient
19  {
20  [TestMethod]
22  {
23  var sample = new Byond
24  {
25  Version = new Version(511, 1385)
26  };
27 
28  var sampleJson = JsonConvert.SerializeObject(sample, new JsonSerializerSettings
29  {
30  ContractResolver = new CamelCasePropertyNamesContractResolver(),
31  Converters = new[] { new VersionConverter() }
32  });
33 
34  var response = new HttpResponseMessage(HttpStatusCode.OK)
35  {
36  Content = new StringContent(sampleJson)
37  };
38 
39  var httpClient = new Mock<IHttpClient>();
40  httpClient.Setup(x => x.SendAsync(It.IsNotNull<HttpRequestMessage>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(response));
41 
42  var client = new ApiClient(httpClient.Object, new Uri("http://fake.com"), new ApiHeaders(new ProductHeaderValue("fake"), "fake"));
43 
44  var result = await client.Read<Byond>(Routes.Byond, default).ConfigureAwait(false);
45  Assert.AreEqual(sample.Version, result.Version);
46  }
47 
48  [TestMethod]
49  public async Task TestUnrecognizedResponse()
50  {
51  var sample = new Byond
52  {
53  Version = new Version(511, 1385)
54  };
55 
56  var fakeJson = "asdfasd <>F#(*)U*#JLI";
57 
58  var response = new HttpResponseMessage(HttpStatusCode.OK)
59  {
60  Content = new StringContent(fakeJson)
61  };
62 
63  var httpClient = new Mock<IHttpClient>();
64  httpClient.Setup(x => x.SendAsync(It.IsNotNull<HttpRequestMessage>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(response));
65 
66  var client = new ApiClient(httpClient.Object, new Uri("http://fake.com"), new ApiHeaders(new ProductHeaderValue("fake"), "fake"));
67 
68  await Assert.ThrowsExceptionAsync<UnrecognizedResponseException>(() => client.Read<Byond>(Routes.Byond, default)).ConfigureAwait(false);
69  }
70  }
71 }
const string Byond
The Models.Byond controller
Definition: Routes.cs:34
+ +
Occurs when a response is received that did not deserialize to one of the expected Api....
- - -
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
-
Routes to a server actions
Definition: Routes.cs:9
+
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
+
Routes to a server actions
Definition: Routes.cs:9
-
Represents a BYOND installation
Definition: Byond.cs:8
- - +
Represents a BYOND installation
Definition: Byond.cs:8
+ - +
diff --git a/_test_api_headers_8cs.html b/_test_api_headers_8cs.html index b02764d9b4..960cc88f00 100644 --- a/_test_api_headers_8cs.html +++ b/_test_api_headers_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Api.Tests/TestApiHeaders.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Api.Tests.TestApiHeadersTests for ApiHeaders More...
Tests for ApiHeaders More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Tests
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_test_api_headers_8cs_source.html b/_test_api_headers_8cs_source.html index efd2009efc..a310363232 100644 --- a/_test_api_headers_8cs_source.html +++ b/_test_api_headers_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Api.Tests/TestApiHeaders.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestApiHeaders.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Http;
2 using Microsoft.AspNetCore.Http.Headers;
3 using Microsoft.VisualStudio.TestTools.UnitTesting;
4 using System;
5 using System.Net.Http.Headers;
6 
7 namespace Tgstation.Server.Api.Tests
8 {
12  [TestClass]
13  public sealed class TestApiHeaders
14  {
15  readonly ProductHeaderValue productHeaderValue = new ProductHeaderValue("Tgstation.Server.Api.Tests", "1.0.0");
16 
17  [TestMethod]
18  public void TestConstruction()
19  {
20  Assert.ThrowsException<ArgumentNullException>(() => new ApiHeaders(null, null));
21  Assert.ThrowsException<ArgumentNullException>(() => new ApiHeaders(productHeaderValue, null));
22  var headers = new ApiHeaders(productHeaderValue, String.Empty);
23  }
24 
25  [TestMethod]
26  public void TestUserAgentsAreValid()
27  {
28  const string BrowserHeader = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36.";
29  const string ConformantHeader = "TGSClient/3.2.1.4";
30 
31  ApiHeaders TestHeader(string userAgent)
32  {
33  var headers = new HeaderDictionary
34  {
35  { "Accept", ApiHeaders.ApplicationJson },
36  { "Api", "Tgstation.Server.Api/4.0.0.0" },
37  { "Authorization", "Bearer asdfasdf" },
38  { "User-Agent", userAgent }
39  };
40 
41  return new ApiHeaders(new RequestHeaders(headers));
42  };
43 
44  var header = TestHeader(BrowserHeader);
45  Assert.AreEqual(BrowserHeader, header.RawUserAgent);
46  Assert.IsNull(header.UserAgent);
47 
48  header = TestHeader(ConformantHeader);
49  Assert.AreEqual(ConformantHeader, header.RawUserAgent);
50  Assert.IsNotNull(header.UserAgent);
51 
52  Assert.ThrowsException<InvalidOperationException>(() => TestHeader(String.Empty));
53  }
54  }
55 }
const string ApplicationJson
TODO: Remove this when https://github.com/dotnet/corefx/pull/26701 makes it into the sdk ...
Definition: ApiHeaders.cs:21
- +Go to the documentation of this file.
1 using Microsoft.AspNetCore.Http;
2 using Microsoft.AspNetCore.Http.Headers;
3 using Microsoft.VisualStudio.TestTools.UnitTesting;
4 using System;
5 using System.Net.Http.Headers;
6 
8 {
12  [TestClass]
13  public sealed class TestApiHeaders
14  {
15  readonly ProductHeaderValue productHeaderValue = new ProductHeaderValue("Tgstation.Server.Api.Tests", "1.0.0");
16 
17  [TestMethod]
18  public void TestConstruction()
19  {
20  Assert.ThrowsException<ArgumentNullException>(() => new ApiHeaders(null, null));
21  Assert.ThrowsException<ArgumentNullException>(() => new ApiHeaders(productHeaderValue, null));
22  var headers = new ApiHeaders(productHeaderValue, String.Empty);
23  }
24 
25  [TestMethod]
26  public void TestUserAgentsAreValid()
27  {
28  const string BrowserHeader = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36.";
29  const string ConformantHeader = "TGSClient/3.2.1.4";
30 
31  ApiHeaders TestHeader(string userAgent)
32  {
33  var headers = new HeaderDictionary
34  {
35  { "Accept", ApiHeaders.ApplicationJson },
36  { "Api", "Tgstation.Server.Api/4.0.0.0" },
37  { "Authorization", "Bearer asdfasdf" },
38  { "User-Agent", userAgent }
39  };
40 
41  return new ApiHeaders(new RequestHeaders(headers));
42  };
43 
44  var header = TestHeader(BrowserHeader);
45  Assert.AreEqual(BrowserHeader, header.RawUserAgent);
46  Assert.IsNull(header.UserAgent);
47 
48  header = TestHeader(ConformantHeader);
49  Assert.AreEqual(ConformantHeader, header.RawUserAgent);
50  Assert.IsNotNull(header.UserAgent);
51 
52  Assert.ThrowsException<InvalidOperationException>(() => TestHeader(String.Empty));
53  }
54  }
55 }
const string ApplicationJson
TODO: Remove this when https://github.com/dotnet/corefx/pull/26701 makes it into the sdk
Definition: ApiHeaders.cs:21
+
readonly ProductHeaderValue productHeaderValue
+ -
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
- +
Represents the header that must be present for every server request
Definition: ApiHeaders.cs:16
+ -
diff --git a/_test_application_8cs.html b/_test_application_8cs.html index 18d11cce87..3dd814495a 100644 --- a/_test_application_8cs.html +++ b/_test_application_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestApplication.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
namespace  Tgstation.Server.Host.Core.Tests
 
@@ -118,7 +105,7 @@ Namespaces diff --git a/_test_application_8cs_source.html b/_test_application_8cs_source.html index e4b94e6f26..a7f83e811f 100644 --- a/_test_application_8cs_source.html +++ b/_test_application_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestApplication.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestApplication.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Builder;
2 using Microsoft.AspNetCore.Hosting;
3 using Microsoft.Extensions.Configuration;
4 using Microsoft.Extensions.DependencyInjection;
5 using Microsoft.Extensions.Options;
6 using Microsoft.VisualStudio.TestTools.UnitTesting;
7 using Moq;
8 using System;
9 using System.Collections.Generic;
10 using System.Threading;
11 using System.Threading.Tasks;
14 
15 namespace Tgstation.Server.Host.Core.Tests
16 {
20  [TestClass]
21  public sealed class TestApplication
22  {
23  [TestMethod]
24  public void TestMethodThrows()
25  {
26  Assert.ThrowsException<ArgumentNullException>(() => new Application(null, null));
27  var mockConfiguration = new Mock<IConfiguration>();
28  Assert.ThrowsException<ArgumentNullException>(() => new Application(mockConfiguration.Object, null));
29 
30  var mockHostingEnvironment = new Mock<IHostingEnvironment>();
31 
32  var app = new Application(mockConfiguration.Object, mockHostingEnvironment.Object);
33 
34  Assert.ThrowsException<ArgumentNullException>(() => app.ConfigureServices(null));
35  Assert.ThrowsException<ArgumentNullException>(() => app.Configure(null, null, null, null, null));
36 
37  var mockAppBuilder = new Mock<IApplicationBuilder>();
38  Assert.ThrowsException<ArgumentNullException>(() => app.Configure(mockAppBuilder.Object, null, null, null, null));
39 
40  var mockServerControl = new Mock<IServerControl>();
41  Assert.ThrowsException<ArgumentNullException>(() => app.Configure(mockAppBuilder.Object, mockServerControl.Object, null, null, null));
42 
43  var mockTokenFactory = new Mock<ITokenFactory>();
44  Assert.ThrowsException<ArgumentNullException>(() => app.Configure(mockAppBuilder.Object, mockServerControl.Object, mockTokenFactory.Object, null, null));
45 
46  var mockControlPanelOptions = new Mock<IOptions<ControlPanelConfiguration>>();
47  mockControlPanelOptions.SetupGet(x => x.Value).Returns(new ControlPanelConfiguration()).Verifiable();
48  Assert.ThrowsException<ArgumentNullException>(() => app.Configure(mockAppBuilder.Object, mockServerControl.Object, mockTokenFactory.Object, mockControlPanelOptions.Object, null));
49  mockControlPanelOptions.VerifyAll();
50  }
51 
53  {
54  public Task<bool> CheckRunWizard(CancellationToken cancellationToken) => Task.FromResult(true);
55  }
56 
58  {
59  public CancellationToken ApplicationStarted => default;
60 
61  public CancellationToken ApplicationStopping => default;
62 
63  public CancellationToken ApplicationStopped => default;
64 
65  public void StopApplication() { }
66  }
67 
68  [TestMethod]
70  {
71  var mockConfiguration = new Mock<IConfiguration>();
72  Assert.ThrowsException<ArgumentNullException>(() => new Application(mockConfiguration.Object, null));
73 
74  var mockHostingEnvironment = new Mock<IHostingEnvironment>();
75 
76  var app = new Application(mockConfiguration.Object, mockHostingEnvironment.Object);
77 
78  var mockOptions = new Mock<IOptions<GeneralConfiguration>>();
79  mockOptions.SetupGet(x => x.Value).Returns(new GeneralConfiguration
80  {
82  }).Verifiable();
83 
84  var fakeServiceDescriptor = new List<ServiceDescriptor>()
85  {
86  new ServiceDescriptor(typeof(IApplicationLifetime), typeof(MockApplicationLifetime), ServiceLifetime.Singleton),
87  new ServiceDescriptor(typeof(ISetupWizard), typeof(MockSetupWizard), ServiceLifetime.Singleton),
88  new ServiceDescriptor(typeof(IOptions<GeneralConfiguration>), mockOptions.Object)
89  };
90 
91  var mockServiceCollection = new Mock<IServiceCollection>();
92 
93  var mockConfigSection = new Mock<IConfigurationSection>();
94 
95  mockConfiguration.Setup(x => x.GetSection(It.IsNotNull<string>())).Returns(mockConfigSection.Object).Verifiable();
96  mockServiceCollection.Setup(x => x.GetEnumerator()).Returns(() => fakeServiceDescriptor.GetEnumerator()).Verifiable();
97 
98  Assert.ThrowsException<OperationCanceledException>(() => app.ConfigureServices(mockServiceCollection.Object));
99 
100  mockOptions.VerifyAll();
101  mockConfiguration.VerifyAll();
102  mockServiceCollection.VerifyAll();
103  }
104  }
105 }
SetupWizardMode
Determines if the Core.ISetupWizard will run
+Go to the documentation of this file.
1 using Microsoft.AspNetCore.Builder;
2 using Microsoft.AspNetCore.Hosting;
3 using Microsoft.Extensions.Configuration;
4 using Microsoft.Extensions.DependencyInjection;
5 using Microsoft.Extensions.Options;
6 using Microsoft.VisualStudio.TestTools.UnitTesting;
7 using Moq;
8 using System;
9 using System.Collections.Generic;
10 using System.Threading;
11 using System.Threading.Tasks;
14 
16 {
20  [TestClass]
21  public sealed class TestApplication
22  {
23  [TestMethod]
24  public void TestMethodThrows()
25  {
26  Assert.ThrowsException<ArgumentNullException>(() => new Application(null, null));
27  var mockConfiguration = new Mock<IConfiguration>();
28  Assert.ThrowsException<ArgumentNullException>(() => new Application(mockConfiguration.Object, null));
29 
30  var mockHostingEnvironment = new Mock<IHostingEnvironment>();
31 
32  var app = new Application(mockConfiguration.Object, mockHostingEnvironment.Object);
33 
34  Assert.ThrowsException<ArgumentNullException>(() => app.ConfigureServices(null));
35  Assert.ThrowsException<ArgumentNullException>(() => app.Configure(null, null, null, null, null));
36 
37  var mockAppBuilder = new Mock<IApplicationBuilder>();
38  Assert.ThrowsException<ArgumentNullException>(() => app.Configure(mockAppBuilder.Object, null, null, null, null));
39 
40  var mockServerControl = new Mock<IServerControl>();
41  Assert.ThrowsException<ArgumentNullException>(() => app.Configure(mockAppBuilder.Object, mockServerControl.Object, null, null, null));
42 
43  var mockTokenFactory = new Mock<ITokenFactory>();
44  Assert.ThrowsException<ArgumentNullException>(() => app.Configure(mockAppBuilder.Object, mockServerControl.Object, mockTokenFactory.Object, null, null));
45 
46  var mockControlPanelOptions = new Mock<IOptions<ControlPanelConfiguration>>();
47  mockControlPanelOptions.SetupGet(x => x.Value).Returns(new ControlPanelConfiguration()).Verifiable();
48  Assert.ThrowsException<ArgumentNullException>(() => app.Configure(mockAppBuilder.Object, mockServerControl.Object, mockTokenFactory.Object, mockControlPanelOptions.Object, null));
49  mockControlPanelOptions.VerifyAll();
50  }
51 
53  {
54  public Task<bool> CheckRunWizard(CancellationToken cancellationToken) => Task.FromResult(true);
55  }
56 
58  {
59  public CancellationToken ApplicationStarted => default;
60 
61  public CancellationToken ApplicationStopping => default;
62 
63  public CancellationToken ApplicationStopped => default;
64 
65  public void StopApplication() { }
66  }
67 
68  [TestMethod]
70  {
71  var mockConfiguration = new Mock<IConfiguration>();
72  Assert.ThrowsException<ArgumentNullException>(() => new Application(mockConfiguration.Object, null));
73 
74  var mockHostingEnvironment = new Mock<IHostingEnvironment>();
75 
76  var app = new Application(mockConfiguration.Object, mockHostingEnvironment.Object);
77 
78  var mockOptions = new Mock<IOptions<GeneralConfiguration>>();
79  mockOptions.SetupGet(x => x.Value).Returns(new GeneralConfiguration
80  {
82  }).Verifiable();
83 
84  var fakeServiceDescriptor = new List<ServiceDescriptor>()
85  {
86  new ServiceDescriptor(typeof(IApplicationLifetime), typeof(MockApplicationLifetime), ServiceLifetime.Singleton),
87  new ServiceDescriptor(typeof(ISetupWizard), typeof(MockSetupWizard), ServiceLifetime.Singleton),
88  new ServiceDescriptor(typeof(IOptions<GeneralConfiguration>), mockOptions.Object)
89  };
90 
91  var mockServiceCollection = new Mock<IServiceCollection>();
92 
93  var mockConfigSection = new Mock<IConfigurationSection>();
94 
95  mockConfiguration.Setup(x => x.GetSection(It.IsNotNull<string>())).Returns(mockConfigSection.Object).Verifiable();
96  mockServiceCollection.Setup(x => x.GetEnumerator()).Returns(() => fakeServiceDescriptor.GetEnumerator()).Verifiable();
97 
98  Assert.ThrowsException<OperationCanceledException>(() => app.ConfigureServices(mockServiceCollection.Object));
99 
100  mockOptions.VerifyAll();
101  mockConfiguration.VerifyAll();
102  mockServiceCollection.VerifyAll();
103  }
104  }
105 }
Task< bool > CheckRunWizard(CancellationToken cancellationToken)
Run the setup wizard if necessary
+ + +
SetupWizardMode
Determines if the Core.ISetupWizard will run
- - + - + - -
The command line Configuration setup wizard
Definition: ISetupWizard.cs:9
- - - - - + +
The command line Configuration setup wizard
Definition: ISetupWizard.cs:9
+ + + + +
diff --git a/_test_async_delayer_8cs.html b/_test_async_delayer_8cs.html index 7331e91cd2..67640d113d 100644 --- a/_test_async_delayer_8cs.html +++ b/_test_async_delayer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestAsyncDelayer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
namespace  Tgstation.Server.Host.Core.Tests
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_test_async_delayer_8cs_source.html b/_test_async_delayer_8cs_source.html index 912253ba96..8bc3775ef6 100644 --- a/_test_async_delayer_8cs_source.html +++ b/_test_async_delayer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestAsyncDelayer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestAsyncDelayer.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.Threading;
4 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Host.Core.Tests
7 {
8  [TestClass]
9  public sealed class TestAsyncDelayer
10  {
11  [TestMethod]
12  public async Task TestDelay()
13  {
14  var delayer = new AsyncDelayer();
15  var startDelay = delayer.Delay(TimeSpan.FromSeconds(1), default);
16  var checkDelay = Task.Delay(TimeSpan.FromSeconds(1) - TimeSpan.FromMilliseconds(10), default);
17  await startDelay.ConfigureAwait(false);
18  Assert.IsTrue(checkDelay.IsCompleted);
19  }
20 
21  [TestMethod]
22  public async Task TestCancel()
23  {
24  var delayer = new AsyncDelayer();
25  using (var cts = new CancellationTokenSource())
26  {
27  cts.Cancel();
28  await Assert.ThrowsExceptionAsync<TaskCanceledException>(() => delayer.Delay(TimeSpan.FromSeconds(1), cts.Token)).ConfigureAwait(false);
29  }
30  }
31  }
32 }
- - +Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.Threading;
4 using System.Threading.Tasks;
5 
7 {
8  [TestClass]
9  public sealed class TestAsyncDelayer
10  {
11  [TestMethod]
12  public async Task TestDelay()
13  {
14  var delayer = new AsyncDelayer();
15  var startDelay = delayer.Delay(TimeSpan.FromSeconds(1), default);
16  var checkDelay = Task.Delay(TimeSpan.FromSeconds(1) - TimeSpan.FromMilliseconds(10), default);
17  await startDelay.ConfigureAwait(false);
18  Assert.IsTrue(checkDelay.IsCompleted);
19  }
20 
21  [TestMethod]
22  public async Task TestCancel()
23  {
24  var delayer = new AsyncDelayer();
25  using (var cts = new CancellationTokenSource())
26  {
27  cts.Cancel();
28  await Assert.ThrowsExceptionAsync<TaskCanceledException>(() => delayer.Delay(TimeSpan.FromSeconds(1), cts.Token)).ConfigureAwait(false);
29  }
30  }
31  }
32 }
- +
diff --git a/_test_authentication_context_8cs.html b/_test_authentication_context_8cs.html index e5c15ea8c3..8d508bd6e0 100644 --- a/_test_authentication_context_8cs.html +++ b/_test_authentication_context_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Security/TestAuthenticationContext.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Security.Tests.TestAuthenticationContextTests for AuthenticationContext More...
Tests for AuthenticationContext More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
namespace  Tgstation.Server.Host.Security.Tests
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_test_authentication_context_8cs_source.html b/_test_authentication_context_8cs_source.html index d0563d15f7..2c000d277f 100644 --- a/_test_authentication_context_8cs_source.html +++ b/_test_authentication_context_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Security/TestAuthenticationContext.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestAuthenticationContext.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using Moq;
3 using System;
6 
7 namespace Tgstation.Server.Host.Security.Tests
8 {
12  [TestClass]
13  public sealed class TestAuthenticationContext
14  {
15  [TestMethod]
16  public void TestConstruction()
17  {
18  Assert.ThrowsException<ArgumentNullException>(() => new AuthenticationContext(null, null, null));
19  var mockSystemIdentity = new Mock<ISystemIdentity>();
20 
21  var user = new User();
22 
23  var authContext = new AuthenticationContext(null, user, null);
24  Assert.ThrowsException<ArgumentNullException>(() => new AuthenticationContext(mockSystemIdentity.Object, null, null));
25 
26  var instanceUser = new InstanceUser();
27 
28  Assert.ThrowsException<ArgumentNullException>(() => new AuthenticationContext(null, null, instanceUser));
29  Assert.ThrowsException<ArgumentNullException>(() => new AuthenticationContext(mockSystemIdentity.Object, null, instanceUser));
30  authContext = new AuthenticationContext(mockSystemIdentity.Object, user, null);
31  authContext = new AuthenticationContext(null, user, instanceUser);
32  authContext = new AuthenticationContext(mockSystemIdentity.Object, user, instanceUser);
33  user.SystemIdentifier = "root";
34  Assert.ThrowsException<ArgumentNullException>(() => new AuthenticationContext(null, user, null));
35  }
36 
37 
38  [TestMethod]
39  public void TestGetRightsGeneric()
40  {
41  var user = new User();
42  var instanceUser = new InstanceUser();
43  var authContext = new AuthenticationContext(null, user, instanceUser);
44 
45  user.AdministrationRights = AdministrationRights.WriteUsers;
46  instanceUser.ByondRights = ByondRights.ChangeVersion | ByondRights.ReadActive;
47  Assert.AreEqual((ulong)user.AdministrationRights, authContext.GetRight(RightsType.Administration));
48  Assert.AreEqual((ulong)instanceUser.ByondRights, authContext.GetRight(RightsType.Byond));
49  }
50  }
51 }
- -
ByondRights
Rights for Models.Byond
Definition: ByondRights.cs:9
-
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
+Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using Moq;
3 using System;
6 
8 {
12  [TestClass]
13  public sealed class TestAuthenticationContext
14  {
15  [TestMethod]
16  public void TestConstruction()
17  {
18  Assert.ThrowsException<ArgumentNullException>(() => new AuthenticationContext(null, null, null));
19  var mockSystemIdentity = new Mock<ISystemIdentity>();
20 
21  var user = new User();
22 
23  var authContext = new AuthenticationContext(null, user, null);
24  Assert.ThrowsException<ArgumentNullException>(() => new AuthenticationContext(mockSystemIdentity.Object, null, null));
25 
26  var instanceUser = new InstanceUser();
27 
28  Assert.ThrowsException<ArgumentNullException>(() => new AuthenticationContext(null, null, instanceUser));
29  Assert.ThrowsException<ArgumentNullException>(() => new AuthenticationContext(mockSystemIdentity.Object, null, instanceUser));
30  authContext = new AuthenticationContext(mockSystemIdentity.Object, user, null);
31  authContext = new AuthenticationContext(null, user, instanceUser);
32  authContext = new AuthenticationContext(mockSystemIdentity.Object, user, instanceUser);
33  user.SystemIdentifier = "root";
34  Assert.ThrowsException<ArgumentNullException>(() => new AuthenticationContext(null, user, null));
35  }
36 
37 
38  [TestMethod]
39  public void TestGetRightsGeneric()
40  {
41  var user = new User();
42  var instanceUser = new InstanceUser();
43  var authContext = new AuthenticationContext(null, user, instanceUser);
44 
45  user.AdministrationRights = AdministrationRights.WriteUsers;
46  instanceUser.ByondRights = ByondRights.ChangeVersion | ByondRights.ReadActive;
47  Assert.AreEqual((ulong)user.AdministrationRights, authContext.GetRight(RightsType.Administration));
48  Assert.AreEqual((ulong)instanceUser.ByondRights, authContext.GetRight(RightsType.Byond));
49  }
50  }
51 }
+ +
ByondRights
Rights for Models.Byond
Definition: ByondRights.cs:9
+
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
- -
AdministrationRights
Rights for Models.Administration
+
AdministrationRights
Rights for Models.Administration
+ - - - + - - - + + +
diff --git a/_test_console_8cs.html b/_test_console_8cs.html index 9cea070d99..d76ccbd28f 100644 --- a/_test_console_8cs.html +++ b/_test_console_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/IO/TestConsole.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.IO
 
namespace  Tgstation.Server.Host.IO.Tests
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_test_console_8cs_source.html b/_test_console_8cs_source.html index 9470afc743..12b28c80d4 100644 --- a/_test_console_8cs_source.html +++ b/_test_console_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/IO/TestConsole.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestConsole.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.IO;
4 using System.Threading;
5 using System.Threading.Tasks;
6 
7 namespace Tgstation.Server.Host.IO.Tests
8 {
9  [TestClass]
10  public sealed class TestConsole
11  {
12  [TestMethod]
13  public async Task TestWriteLine()
14  {
15  var console = new Console();
16  await Assert.ThrowsExceptionAsync<InvalidOperationException>(() => console.WriteAsync(null, false, default)).ConfigureAwait(false);
17  try
18  {
19  await console.WriteAsync(null, true, default).ConfigureAwait(false);
20  await console.WriteAsync(String.Empty, false, default).ConfigureAwait(true);
21  }
22  catch(InvalidOperationException)
23  {
24  Assert.IsFalse(console.Available);
25  }
26  }
27 
28  [TestMethod]
29  public void TestUserInteractive()
30  {
31  var console = new Console();
32  Assert.AreEqual(Environment.UserInteractive, console.Available);
33  }
34  }
35 }
- +Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.IO;
4 using System.Threading;
5 using System.Threading.Tasks;
6 
8 {
9  [TestClass]
10  public sealed class TestConsole
11  {
12  [TestMethod]
13  public async Task TestWriteLine()
14  {
15  var console = new Console();
16  await Assert.ThrowsExceptionAsync<InvalidOperationException>(() => console.WriteAsync(null, false, default)).ConfigureAwait(false);
17  try
18  {
19  await console.WriteAsync(null, true, default).ConfigureAwait(false);
20  await console.WriteAsync(String.Empty, false, default).ConfigureAwait(true);
21  }
22  catch(InvalidOperationException)
23  {
24  Assert.IsFalse(console.Available);
25  }
26  }
27 
28  [TestMethod]
29  public void TestUserInteractive()
30  {
31  var console = new Console();
32  Assert.AreEqual(Environment.UserInteractive, console.Available);
33  }
34  }
35 }
+ - -
diff --git a/_test_d_b_connection_factory_8cs.html b/_test_d_b_connection_factory_8cs.html index dbf5b2e8de..b484e92a48 100644 --- a/_test_d_b_connection_factory_8cs.html +++ b/_test_d_b_connection_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestDBConnectionFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
namespace  Tgstation.Server.Host.Core.Tests
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_test_d_b_connection_factory_8cs_source.html b/_test_d_b_connection_factory_8cs_source.html index 24b539411d..1014711c4b 100644 --- a/_test_d_b_connection_factory_8cs_source.html +++ b/_test_d_b_connection_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestDBConnectionFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestDBConnectionFactory.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using MySql.Data.MySqlClient;
3 using System;
4 using System.Data.SqlClient;
6 
7 namespace Tgstation.Server.Host.Core.Tests
8 {
9  [TestClass]
10  public sealed class TestDBConnectionFactory
11  {
12  [TestMethod]
13  public void TestBadParameters()
14  {
15  var factory = new DBConnectionFactory();
16  Assert.ThrowsException<ArgumentNullException>(() => factory.CreateConnection(null, default));
17  Assert.ThrowsException<ArgumentOutOfRangeException>(() => factory.CreateConnection(String.Empty, (DatabaseType)42));
18  }
19 
20  [TestMethod]
21  public void TestWorks()
22  {
23  var factory = new DBConnectionFactory();
24  Assert.IsInstanceOfType(factory.CreateConnection(String.Empty, DatabaseType.MariaDB), typeof(MySqlConnection));
25  Assert.IsInstanceOfType(factory.CreateConnection(String.Empty, DatabaseType.MySql), typeof(MySqlConnection));
26  Assert.IsInstanceOfType(factory.CreateConnection(String.Empty, DatabaseType.SqlServer), typeof(SqlConnection));
27  }
28  }
29 }
+Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using MySql.Data.MySqlClient;
3 using System;
4 using System.Data.SqlClient;
6 
8 {
9  [TestClass]
10  public sealed class TestDBConnectionFactory
11  {
12  [TestMethod]
13  public void TestBadParameters()
14  {
15  var factory = new DBConnectionFactory();
16  Assert.ThrowsException<ArgumentNullException>(() => factory.CreateConnection(null, default));
17  Assert.ThrowsException<ArgumentOutOfRangeException>(() => factory.CreateConnection(String.Empty, (DatabaseType)42));
18  }
19 
20  [TestMethod]
21  public void TestWorks()
22  {
23  var factory = new DBConnectionFactory();
24  Assert.IsInstanceOfType(factory.CreateConnection(String.Empty, DatabaseType.MariaDB), typeof(MySqlConnection));
25  Assert.IsInstanceOfType(factory.CreateConnection(String.Empty, DatabaseType.MySql), typeof(MySqlConnection));
26  Assert.IsInstanceOfType(factory.CreateConnection(String.Empty, DatabaseType.SqlServer), typeof(SqlConnection));
27  }
28  }
29 }
- - - + -
DatabaseType
Type of database to user
Definition: DatabaseType.cs:6
- - +
DatabaseType
Type of database to user
Definition: DatabaseType.cs:6
+ + + - +
diff --git a/_test_database_context_factory_8cs.html b/_test_database_context_factory_8cs.html index b158a5c833..c1d6cb4ca2 100644 --- a/_test_database_context_factory_8cs.html +++ b/_test_database_context_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestDatabaseContextFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
namespace  Tgstation.Server.Host.Core.Tests
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_test_database_context_factory_8cs_source.html b/_test_database_context_factory_8cs_source.html index 4715e87579..343acc388a 100644 --- a/_test_database_context_factory_8cs_source.html +++ b/_test_database_context_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestDatabaseContextFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestDatabaseContextFactory.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.DependencyInjection;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 using Moq;
4 using System;
5 using System.Threading.Tasks;
7 
8 namespace Tgstation.Server.Host.Core.Tests
9 {
10  [TestClass]
11  public sealed class TestDatabaseContextFactory
12  {
13  [TestMethod]
14  public void TestConstructionThrows()
15  {
16  Assert.ThrowsException<ArgumentNullException>(() => new DatabaseContextFactory(null));
17  var mockProvider = new Mock<IServiceProvider>();
18  mockProvider.Setup(x => x.GetService(typeof(IDatabaseContext))).Verifiable();
19  var mockScope = new Mock<IServiceScope>();
20  mockScope.SetupGet(x => x.ServiceProvider).Returns(mockProvider.Object).Verifiable();
21  var mockScopeFactory = new Mock<IServiceScopeFactory>();
22  mockScopeFactory.Setup(x => x.CreateScope()).Returns(mockScope.Object).Verifiable();
23  Assert.ThrowsException<InvalidOperationException>(() => new DatabaseContextFactory(mockScopeFactory.Object));
24  mockScopeFactory.VerifyAll();
25  mockScope.VerifyAll();
26  mockProvider.VerifyAll();
27  }
28 
29  [TestMethod]
30  public async Task TestWorks()
31  {
32  var mockDatabase = new Mock<IDatabaseContext>();
33  var mockProvider = new Mock<IServiceProvider>();
34  var mockDbo = mockDatabase.Object;
35  mockProvider.Setup(x => x.GetService(typeof(IDatabaseContext))).Returns(mockDbo).Verifiable();
36  var mockScope = new Mock<IServiceScope>();
37  mockScope.SetupGet(x => x.ServiceProvider).Returns(mockProvider.Object).Verifiable();
38  var mockScopeFactory = new Mock<IServiceScopeFactory>();
39  mockScopeFactory.Setup(x => x.CreateScope()).Returns(mockScope.Object).Verifiable();
40 
41  var factory = new DatabaseContextFactory(mockScopeFactory.Object);
42 
43  await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => factory.UseContext(null)).ConfigureAwait(false);
44 
45  await factory.UseContext(context =>
46  {
47  Assert.AreSame(mockDbo, context);
48  return Task.CompletedTask;
49  });
50 
51  mockScopeFactory.VerifyAll();
52  mockScope.VerifyAll();
53  mockProvider.VerifyAll();
54  }
55  }
56 }
- +Go to the documentation of this file.
1 using Microsoft.Extensions.DependencyInjection;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 using Moq;
4 using System;
5 using System.Threading.Tasks;
7 
9 {
10  [TestClass]
11  public sealed class TestDatabaseContextFactory
12  {
13  [TestMethod]
14  public void TestConstructionThrows()
15  {
16  Assert.ThrowsException<ArgumentNullException>(() => new DatabaseContextFactory(null));
17  var mockProvider = new Mock<IServiceProvider>();
18  mockProvider.Setup(x => x.GetService(typeof(IDatabaseContext))).Verifiable();
19  var mockScope = new Mock<IServiceScope>();
20  mockScope.SetupGet(x => x.ServiceProvider).Returns(mockProvider.Object).Verifiable();
21  var mockScopeFactory = new Mock<IServiceScopeFactory>();
22  mockScopeFactory.Setup(x => x.CreateScope()).Returns(mockScope.Object).Verifiable();
23  Assert.ThrowsException<InvalidOperationException>(() => new DatabaseContextFactory(mockScopeFactory.Object));
24  mockScopeFactory.VerifyAll();
25  mockScope.VerifyAll();
26  mockProvider.VerifyAll();
27  }
28 
29  [TestMethod]
30  public async Task TestWorks()
31  {
32  var mockDatabase = new Mock<IDatabaseContext>();
33  var mockProvider = new Mock<IServiceProvider>();
34  var mockDbo = mockDatabase.Object;
35  mockProvider.Setup(x => x.GetService(typeof(IDatabaseContext))).Returns(mockDbo).Verifiable();
36  var mockScope = new Mock<IServiceScope>();
37  mockScope.SetupGet(x => x.ServiceProvider).Returns(mockProvider.Object).Verifiable();
38  var mockScopeFactory = new Mock<IServiceScopeFactory>();
39  mockScopeFactory.Setup(x => x.CreateScope()).Returns(mockScope.Object).Verifiable();
40 
41  var factory = new DatabaseContextFactory(mockScopeFactory.Object);
42 
43  await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => factory.UseContext(null)).ConfigureAwait(false);
44 
45  await factory.UseContext(context =>
46  {
47  Assert.AreSame(mockDbo, context);
48  return Task.CompletedTask;
49  });
50 
51  mockScopeFactory.VerifyAll();
52  mockScope.VerifyAll();
53  mockProvider.VerifyAll();
54  }
55  }
56 }
- - - - - + + + +
diff --git a/_test_discord_provider_8cs.html b/_test_discord_provider_8cs.html index 58c2a44194..e76a500a6c 100644 --- a/_test_discord_provider_8cs.html +++ b/_test_discord_provider_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Components/Chat/Providers/TestDiscordProvider.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
namespace  Tgstation.Server.Host.Components.Chat.Providers
 
namespace  Tgstation.Server.Host.Components.Chat.Providers.Tests
 
@@ -113,7 +104,7 @@ Namespaces diff --git a/_test_discord_provider_8cs_source.html b/_test_discord_provider_8cs_source.html index fe534d5933..7d273873ae 100644 --- a/_test_discord_provider_8cs_source.html +++ b/_test_discord_provider_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Components/Chat/Providers/TestDiscordProvider.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestDiscordProvider.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 using Moq;
4 using System;
5 using System.Threading;
6 using System.Threading.Tasks;
7 
8 namespace Tgstation.Server.Host.Components.Chat.Providers.Tests
9 {
10  [TestClass]
11  public sealed class TestDiscordProvider
12  {
13  string testToken1;
14 
15  [TestInitialize]
16  public void Initialize()
17  {
18  testToken1 = Environment.GetEnvironmentVariable("TGS4_TEST_DISCORD_TOKEN_1");
19  }
20 
21  [TestMethod]
23  {
24  Assert.ThrowsException<ArgumentNullException>(() => new DiscordProvider(null, null));
25  var mockLogger = new Mock<ILogger<DiscordProvider>>();
26  Assert.ThrowsException<ArgumentNullException>(() => new DiscordProvider(mockLogger.Object, null));
27  var mockToken = "asdf";
28  new DiscordProvider(mockLogger.Object, mockToken).Dispose();
29  }
30 
31  [TestMethod]
32  public async Task TestConnectWithFakeTokenFails()
33  {
34  var mockLogger = new Mock<ILogger<DiscordProvider>>();
35  using (var provider = new DiscordProvider(mockLogger.Object, "asdf"))
36  {
37  Assert.IsFalse(await provider.Connect(default).ConfigureAwait(false));
38  Assert.IsFalse(provider.Connected);
39  }
40  }
41 
42  [Ignore("Broken due to dependency issues after first call to .Connect()")]
43  [TestMethod]
44  public async Task TestConnectAndDisconnect()
45  {
46  if (testToken1 == null)
47  Assert.Inconclusive("Required environment variable TGS4_TEST_DISCORD_TOKEN_1 isn't set!");
48 
49 
50  var mockLogger = new Mock<ILogger<DiscordProvider>>();
51  using (var provider = new DiscordProvider(mockLogger.Object, testToken1))
52  {
53  Assert.IsFalse(provider.Connected);
54  await provider.Disconnect(default).ConfigureAwait(false);
55  Assert.IsFalse(provider.Connected);
56  Assert.IsTrue(await provider.Connect(default).ConfigureAwait(false));
57  Assert.IsTrue(provider.Connected);
58  Assert.IsTrue(await provider.Connect(default).ConfigureAwait(false));
59  Assert.IsTrue(provider.Connected);
60 
61  await provider.Disconnect(default).ConfigureAwait(false);
62  Assert.IsFalse(provider.Connected);
63  await provider.Disconnect(default).ConfigureAwait(false);
64  Assert.IsFalse(provider.Connected);
65 
66  //now try it with cancellationTokens
67  using (var cts = new CancellationTokenSource())
68  {
69  cts.Cancel();
70  var cancellationToken = cts.Token;
71  await Assert.ThrowsExceptionAsync<OperationCanceledException>(() => provider.Connect(cancellationToken)).ConfigureAwait(false);
72  Assert.IsFalse(provider.Connected);
73  Assert.IsTrue(await provider.Connect(default).ConfigureAwait(false));
74  Assert.IsTrue(provider.Connected);
75  await Assert.ThrowsExceptionAsync<OperationCanceledException>(() => provider.Disconnect(cancellationToken)).ConfigureAwait(false);
76  Assert.IsTrue(provider.Connected);
77  await provider.Disconnect(default).ConfigureAwait(false);
78  Assert.IsFalse(provider.Connected);
79  }
80 
81  }
82  }
83  }
84 }
- - +Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 using Moq;
4 using System;
5 using System.Threading;
6 using System.Threading.Tasks;
7 
9 {
10  [TestClass]
11  public sealed class TestDiscordProvider
12  {
13  string testToken1;
14 
15  [TestInitialize]
16  public void Initialize()
17  {
18  testToken1 = Environment.GetEnvironmentVariable("TGS4_TEST_DISCORD_TOKEN_1");
19  }
20 
21  [TestMethod]
23  {
24  Assert.ThrowsException<ArgumentNullException>(() => new DiscordProvider(null, null));
25  var mockLogger = new Mock<ILogger<DiscordProvider>>();
26  Assert.ThrowsException<ArgumentNullException>(() => new DiscordProvider(mockLogger.Object, null));
27  var mockToken = "asdf";
28  new DiscordProvider(mockLogger.Object, mockToken).Dispose();
29  }
30 
31  [TestMethod]
32  public async Task TestConnectWithFakeTokenFails()
33  {
34  var mockLogger = new Mock<ILogger<DiscordProvider>>();
35  using (var provider = new DiscordProvider(mockLogger.Object, "asdf"))
36  {
37  Assert.IsFalse(await provider.Connect(default).ConfigureAwait(false));
38  Assert.IsFalse(provider.Connected);
39  }
40  }
41 
42  [Ignore("Broken due to dependency issues after first call to .Connect()")]
43  [TestMethod]
44  public async Task TestConnectAndDisconnect()
45  {
46  if (testToken1 == null)
47  Assert.Inconclusive("Required environment variable TGS4_TEST_DISCORD_TOKEN_1 isn't set!");
48 
49 
50  var mockLogger = new Mock<ILogger<DiscordProvider>>();
51  using (var provider = new DiscordProvider(mockLogger.Object, testToken1))
52  {
53  Assert.IsFalse(provider.Connected);
54  await provider.Disconnect(default).ConfigureAwait(false);
55  Assert.IsFalse(provider.Connected);
56  Assert.IsTrue(await provider.Connect(default).ConfigureAwait(false));
57  Assert.IsTrue(provider.Connected);
58  Assert.IsTrue(await provider.Connect(default).ConfigureAwait(false));
59  Assert.IsTrue(provider.Connected);
60 
61  await provider.Disconnect(default).ConfigureAwait(false);
62  Assert.IsFalse(provider.Connected);
63  await provider.Disconnect(default).ConfigureAwait(false);
64  Assert.IsFalse(provider.Connected);
65 
66  //now try it with cancellationTokens
67  using (var cts = new CancellationTokenSource())
68  {
69  cts.Cancel();
70  var cancellationToken = cts.Token;
71  await Assert.ThrowsExceptionAsync<OperationCanceledException>(() => provider.Connect(cancellationToken)).ConfigureAwait(false);
72  Assert.IsFalse(provider.Connected);
73  Assert.IsTrue(await provider.Connect(default).ConfigureAwait(false));
74  Assert.IsTrue(provider.Connected);
75  await Assert.ThrowsExceptionAsync<OperationCanceledException>(() => provider.Disconnect(cancellationToken)).ConfigureAwait(false);
76  Assert.IsTrue(provider.Connected);
77  await provider.Disconnect(default).ConfigureAwait(false);
78  Assert.IsFalse(provider.Connected);
79  }
80 
81  }
82  }
83  }
84 }
+ - + - - -
diff --git a/_test_dream_daemon_client_8cs.html b/_test_dream_daemon_client_8cs.html index 5d3e356ccd..ca660d0b9f 100644 --- a/_test_dream_daemon_client_8cs.html +++ b/_test_dream_daemon_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Client.Tests/Components/TestDreamDaemonClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Components
 
namespace  Tgstation.Server.Client.Components.Tests
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_test_dream_daemon_client_8cs_source.html b/_test_dream_daemon_client_8cs_source.html index 3cea74279a..4a64e8c48e 100644 --- a/_test_dream_daemon_client_8cs_source.html +++ b/_test_dream_daemon_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Client.Tests/Components/TestDreamDaemonClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestDreamDaemonClient.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using Moq;
3 using System;
4 using System.Collections.Generic;
5 using System.Text;
6 using System.Threading;
7 using System.Threading.Tasks;
8 using Tgstation.Server.Api;
10 
11 namespace Tgstation.Server.Client.Components.Tests
12 {
13  [TestClass]
14  public sealed class TestDreamDaemonClient
15  {
16  [TestMethod]
17  public async Task TestStart()
18  {
19  var example = new Job
20  {
21  Id = 347,
22  StartedAt = DateTimeOffset.Now
23  };
24 
25  var inst = new Instance
26  {
27  Id = 4958
28  };
29 
30  var mockApiClient = new Mock<IApiClient>();
31  mockApiClient.Setup(x => x.Create<Job>(Routes.DreamDaemon, inst.Id, It.IsAny<CancellationToken>())).Returns(Task.FromResult(example));
32 
33  var client = new DreamDaemonClient(mockApiClient.Object, inst);
34 
35  var result = await client.Start(default).ConfigureAwait(false);
36  Assert.AreSame(example, result);
37  }
38  }
39 }
- - +Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using Moq;
3 using System;
4 using System.Collections.Generic;
5 using System.Text;
6 using System.Threading;
7 using System.Threading.Tasks;
8 using Tgstation.Server.Api;
10 
12 {
13  [TestClass]
14  public sealed class TestDreamDaemonClient
15  {
16  [TestMethod]
17  public async Task TestStart()
18  {
19  var example = new Job
20  {
21  Id = 347,
22  StartedAt = DateTimeOffset.Now
23  };
24 
25  var inst = new Instance
26  {
27  Id = 4958
28  };
29 
30  var mockApiClient = new Mock<IApiClient>();
31  mockApiClient.Setup(x => x.Create<Job>(Routes.DreamDaemon, inst.Id, It.IsAny<CancellationToken>())).Returns(Task.FromResult(example));
32 
33  var client = new DreamDaemonClient(mockApiClient.Object, inst);
34 
35  var result = await client.Start(default).ConfigureAwait(false);
36  Assert.AreSame(example, result);
37  }
38  }
39 }
-
Routes to a server actions
Definition: Routes.cs:9
+
Routes to a server actions
Definition: Routes.cs:9
-
const string DreamDaemon
The Models.DreamDaemon controller
Definition: Routes.cs:44
+
const string DreamDaemon
The Models.DreamDaemon controller
Definition: Routes.cs:44
+ -
Metadata about a server instance
Definition: Instance.cs:9
+
Metadata about a server instance
Definition: Instance.cs:9
- - - -
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job ...
Definition: Job.cs:6
+ + +
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job
Definition: Job.cs:6
diff --git a/_test_git_hub_client_factory_8cs.html b/_test_git_hub_client_factory_8cs.html index fbf0c77056..973cb9edc5 100644 --- a/_test_git_hub_client_factory_8cs.html +++ b/_test_git_hub_client_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestGitHubClientFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
namespace  Tgstation.Server.Host.Core.Tests
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_test_git_hub_client_factory_8cs_source.html b/_test_git_hub_client_factory_8cs_source.html index 22ebbd4942..dd7aa6484f 100644 --- a/_test_git_hub_client_factory_8cs_source.html +++ b/_test_git_hub_client_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestGitHubClientFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestGitHubClientFactory.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using Moq;
3 using Octokit;
4 using System;
5 using System.Threading.Tasks;
6 
7 namespace Tgstation.Server.Host.Core.Tests
8 {
9  [TestClass]
10  public sealed class TestGitHubClientFactory
11  {
12  [TestMethod]
13  public void TestContruction() => Assert.ThrowsException<ArgumentNullException>(() => new GitHubClientFactory(null));
14 
15  [TestMethod]
16  public async Task TestCreateBasicClient()
17  {
18  var mockApp = new Mock<IApplication>();
19  mockApp.SetupGet(x => x.Version).Returns(new Version()).Verifiable();
20  mockApp.SetupGet(x => x.VersionPrefix).Returns("TGSTests").Verifiable();
21 
22  var factory = new GitHubClientFactory(mockApp.Object);
23 
24  var client = factory.CreateClient();
25  Assert.IsNotNull(client);
26  var credentials = await client.Connection.CredentialStore.GetCredentials().ConfigureAwait(false);
27 
28  Assert.AreEqual(AuthenticationType.Anonymous, credentials.AuthenticationType);
29 
30 
31  mockApp.VerifyAll();
32  }
33 
34  [TestMethod]
35  public async Task TestCreateTokenClient()
36  {
37  var mockApp = new Mock<IApplication>();
38  mockApp.SetupGet(x => x.Version).Returns(new Version()).Verifiable();
39  mockApp.SetupGet(x => x.VersionPrefix).Returns("TGSTests").Verifiable();
40 
41  var factory = new GitHubClientFactory(mockApp.Object);
42 
43  Assert.ThrowsException<ArgumentNullException>(() => factory.CreateClient(null));
44 
45  var client = factory.CreateClient("asdf");
46  Assert.IsNotNull(client);
47 
48  var credentials = await client.Connection.CredentialStore.GetCredentials().ConfigureAwait(false);
49 
50  Assert.AreEqual(AuthenticationType.Oauth, credentials.AuthenticationType);
51 
52  mockApp.VerifyAll();
53  }
54  }
55 }
- - - +Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using Moq;
3 using Octokit;
4 using System;
5 using System.Threading.Tasks;
6 
8 {
9  [TestClass]
10  public sealed class TestGitHubClientFactory
11  {
12  [TestMethod]
13  public void TestContruction() => Assert.ThrowsException<ArgumentNullException>(() => new GitHubClientFactory(null));
14 
15  [TestMethod]
16  public async Task TestCreateBasicClient()
17  {
18  var mockApp = new Mock<IApplication>();
19  mockApp.SetupGet(x => x.Version).Returns(new Version()).Verifiable();
20  mockApp.SetupGet(x => x.VersionPrefix).Returns("TGSTests").Verifiable();
21 
22  var factory = new GitHubClientFactory(mockApp.Object);
23 
24  var client = factory.CreateClient();
25  Assert.IsNotNull(client);
26  var credentials = await client.Connection.CredentialStore.GetCredentials().ConfigureAwait(false);
27 
28  Assert.AreEqual(AuthenticationType.Anonymous, credentials.AuthenticationType);
29 
30 
31  mockApp.VerifyAll();
32  }
33 
34  [TestMethod]
35  public async Task TestCreateTokenClient()
36  {
37  var mockApp = new Mock<IApplication>();
38  mockApp.SetupGet(x => x.Version).Returns(new Version()).Verifiable();
39  mockApp.SetupGet(x => x.VersionPrefix).Returns("TGSTests").Verifiable();
40 
41  var factory = new GitHubClientFactory(mockApp.Object);
42 
43  Assert.ThrowsException<ArgumentNullException>(() => factory.CreateClient(null));
44 
45  var client = factory.CreateClient("asdf");
46  Assert.IsNotNull(client);
47 
48  var credentials = await client.Connection.CredentialStore.GetCredentials().ConfigureAwait(false);
49 
50  Assert.AreEqual(AuthenticationType.Oauth, credentials.AuthenticationType);
51 
52  mockApp.VerifyAll();
53  }
54  }
55 }
+ - - +
diff --git a/_test_irc_connection_string_builder_8cs.html b/_test_irc_connection_string_builder_8cs.html index 34c216280f..2ed9e27c44 100644 --- a/_test_irc_connection_string_builder_8cs.html +++ b/_test_irc_connection_string_builder_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Api.Tests/Models/TestIrcConnectionStringBuilder.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
namespace  Tgstation.Server.Api.Models.Tests
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_test_irc_connection_string_builder_8cs_source.html b/_test_irc_connection_string_builder_8cs_source.html index f1c369432c..e70a9fecfe 100644 --- a/_test_irc_connection_string_builder_8cs_source.html +++ b/_test_irc_connection_string_builder_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Api.Tests/Models/TestIrcConnectionStringBuilder.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestIrcConnectionStringBuilder.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 
3 namespace Tgstation.Server.Api.Models.Tests
4 {
5  [TestClass]
6  public sealed class TestIrcConnectionStringBuilder
7  {
8  [TestMethod]
9  public void TestBasicParseAndBuild()
10  {
11  const string exampleString = "server;1234;nick;1;2;asdf";
12  var builder = new IrcConnectionStringBuilder(exampleString);
13 
14  Assert.IsTrue(builder.Valid);
15  Assert.AreEqual("server", builder.Address);
16  Assert.AreEqual((ushort)1234, builder.Port);
17  Assert.AreEqual("nick", builder.Nickname);
18  Assert.IsTrue(builder.UseSsl.Value);
19  Assert.AreEqual(IrcPasswordType.NickServ, builder.PasswordType);
20  Assert.AreEqual("asdf", builder.Password);
21 
22  Assert.AreEqual(exampleString, builder.ToString());
23  }
24  }
25 }
- -
IrcPasswordType
Represents the type of a password for a ChatProvider.Irc
+Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 
4 {
5  [TestClass]
6  public sealed class TestIrcConnectionStringBuilder
7  {
8  [TestMethod]
9  public void TestBasicParseAndBuild()
10  {
11  const string exampleString = "server;1234;nick;1;2;asdf";
12  var builder = new IrcConnectionStringBuilder(exampleString);
13 
14  Assert.IsTrue(builder.Valid);
15  Assert.AreEqual("server", builder.Address);
16  Assert.AreEqual((ushort)1234, builder.Port);
17  Assert.AreEqual("nick", builder.Nickname);
18  Assert.IsTrue(builder.UseSsl.Value);
19  Assert.AreEqual(IrcPasswordType.NickServ, builder.PasswordType);
20  Assert.AreEqual("asdf", builder.Password);
21 
22  Assert.AreEqual(exampleString, builder.ToString());
23  }
24  }
25 }
+
IrcPasswordType
Represents the type of a password for a ChatProvider.Irc
+ -
ChatConnectionStringBuilder for ChatProvider.Irc
- +
ChatConnectionStringBuilder for ChatProvider.Irc
diff --git a/_test_job_exception_8cs.html b/_test_job_exception_8cs.html index 2068ae371d..cd1ad2c548 100644 --- a/_test_job_exception_8cs.html +++ b/_test_job_exception_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestJobException.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
namespace  Tgstation.Server.Host.Core.Tests
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_test_job_exception_8cs_source.html b/_test_job_exception_8cs_source.html index 9b9f5ba37c..370b08d048 100644 --- a/_test_job_exception_8cs_source.html +++ b/_test_job_exception_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestJobException.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestJobException.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 
4 namespace Tgstation.Server.Host.Core.Tests
5 {
6  [TestClass]
7  public sealed class TestJobException
8  {
9  [TestMethod]
10  public void TestConstruction()
11  {
12  new JobException();
13  new JobException("Message");
14  new JobException("Message", new Exception());
15  }
16  }
17 }
- - +Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 
5 {
6  [TestClass]
7  public sealed class TestJobException
8  {
9  [TestMethod]
10  public void TestConstruction()
11  {
12  new JobException();
13  new JobException("Message");
14  new JobException("Message", new Exception());
15  }
16  }
17 }
-
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
- + +
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
diff --git a/_test_job_handler_8cs.html b/_test_job_handler_8cs.html index 5954c6ea13..a603cb7869 100644 --- a/_test_job_handler_8cs.html +++ b/_test_job_handler_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestJobHandler.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
namespace  Tgstation.Server.Host.Core.Tests
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_test_job_handler_8cs_source.html b/_test_job_handler_8cs_source.html index c062b7c690..04d19a402e 100644 --- a/_test_job_handler_8cs_source.html +++ b/_test_job_handler_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestJobHandler.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestJobHandler.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.Threading;
4 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Host.Core.Tests
7 {
8  [TestClass]
9  public sealed class TestJobHandler
10  {
12  bool cancelled;
13 
14  async Task TestJob(CancellationToken cancellationToken)
15  {
16  await currentWaitTask.ConfigureAwait(false);
17  cancelled = cancellationToken.IsCancellationRequested;
18  }
19 
20  [TestMethod]
22  {
23  cancelled = false;
24  Assert.ThrowsException<ArgumentNullException>(() => new JobHandler(null));
25 
26  currentWaitTask = Task.CompletedTask;
27  new JobHandler(TestJob).Dispose();
28  Assert.IsFalse(cancelled);
29  }
30 
31  [TestMethod]
32  public async Task TestWait()
33  {
34  cancelled = false;
35  //test with a cancelled cts
36  using (var cts = new CancellationTokenSource())
37  {
38  var tcs = new TaskCompletionSource<object>();
39  currentWaitTask = tcs.Task;
40  cts.Cancel();
41  using(var handler = new JobHandler(TestJob))
42  {
43  await Assert.ThrowsExceptionAsync<OperationCanceledException>(() => handler.Wait(cts.Token)).ConfigureAwait(false);
44  tcs.SetResult(null);
45  await handler.Wait(default).ConfigureAwait(false);
46  }
47  }
48  Assert.IsFalse(cancelled);
49  }
50 
51  [TestMethod]
52  public void TestProgress()
53  {
54  currentWaitTask = Task.CompletedTask;
55  cancelled = false;
56  using (var handler = new JobHandler(TestJob))
57  {
58  Assert.IsFalse(handler.Progress.HasValue);
59  handler.Progress = 42;
60  Assert.AreEqual(42, handler.Progress);
61  }
62  Assert.IsFalse(cancelled);
63  }
64 
65  [TestMethod]
66  public async Task TestCancellation()
67  {
68  var tcs = new TaskCompletionSource<object>();
69  currentWaitTask = tcs.Task;
70  cancelled = false;
71  using(var handler = new JobHandler(TestJob))
72  {
73  handler.Cancel();
74  tcs.SetResult(null);
75  await handler.Wait(default).ConfigureAwait(false);
76  }
77  Assert.IsTrue(cancelled);
78  }
79  }
80 }
+Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.Threading;
4 using System.Threading.Tasks;
5 
7 {
8  [TestClass]
9  public sealed class TestJobHandler
10  {
12  bool cancelled;
13 
14  async Task TestJob(CancellationToken cancellationToken)
15  {
16  await currentWaitTask.ConfigureAwait(false);
17  cancelled = cancellationToken.IsCancellationRequested;
18  }
19 
20  [TestMethod]
22  {
23  cancelled = false;
24  Assert.ThrowsException<ArgumentNullException>(() => new JobHandler(null));
25 
26  currentWaitTask = Task.CompletedTask;
27  new JobHandler(TestJob).Dispose();
28  Assert.IsFalse(cancelled);
29  }
30 
31  [TestMethod]
32  public async Task TestWait()
33  {
34  cancelled = false;
35  //test with a cancelled cts
36  using (var cts = new CancellationTokenSource())
37  {
38  var tcs = new TaskCompletionSource<object>();
39  currentWaitTask = tcs.Task;
40  cts.Cancel();
41  using(var handler = new JobHandler(TestJob))
42  {
43  await Assert.ThrowsExceptionAsync<OperationCanceledException>(() => handler.Wait(cts.Token)).ConfigureAwait(false);
44  tcs.SetResult(null);
45  await handler.Wait(default).ConfigureAwait(false);
46  }
47  }
48  Assert.IsFalse(cancelled);
49  }
50 
51  [TestMethod]
52  public void TestProgress()
53  {
54  currentWaitTask = Task.CompletedTask;
55  cancelled = false;
56  using (var handler = new JobHandler(TestJob))
57  {
58  Assert.IsFalse(handler.Progress.HasValue);
59  handler.Progress = 42;
60  Assert.AreEqual(42, handler.Progress);
61  }
62  Assert.IsFalse(cancelled);
63  }
64 
65  [TestMethod]
66  public async Task TestCancellation()
67  {
68  var tcs = new TaskCompletionSource<object>();
69  currentWaitTask = tcs.Task;
70  cancelled = false;
71  using(var handler = new JobHandler(TestJob))
72  {
73  handler.Cancel();
74  tcs.SetResult(null);
75  await handler.Wait(default).ConfigureAwait(false);
76  }
77  Assert.IsTrue(cancelled);
78  }
79  }
80 }
- - @@ -103,14 +80,14 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
async Task TestJob(CancellationToken cancellationToken)
- -
Class for pairing Tasks with CancellationTokenSources
Definition: JobHandler.cs:10
+ +
Class for pairing Tasks with CancellationTokenSources
Definition: JobHandler.cs:10
diff --git a/_test_merge_base_8cs.html b/_test_merge_base_8cs.html index 09640eb793..1341264a08 100644 --- a/_test_merge_base_8cs.html +++ b/_test_merge_base_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/TestMergeBase.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
namespace  Tgstation.Server.Api.Models.Internal
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_test_merge_base_8cs_source.html b/_test_merge_base_8cs_source.html index e6093e2441..1bcb5b8c81 100644 --- a/_test_merge_base_8cs_source.html +++ b/_test_merge_base_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/TestMergeBase.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestMergeBase.cs
-Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
3 
4 namespace Tgstation.Server.Api.Models.Internal
5 {
9  public abstract class TestMergeBase : TestMergeParameters
10  {
14  [Required]
15  public string TitleAtMerge { get; set; }
16 
20  [Required]
21  public string BodyAtMerge { get; set; }
22 
26  [Required]
27 #pragma warning disable CA1056 // Uri properties should not be strings
28  public string Url { get; set; }
29 #pragma warning restore CA1056 // Uri properties should not be strings
30 
34  [Required]
35  public string Author { get; set; }
36 
40  protected TestMergeBase() { }
41 
46  protected TestMergeBase(TestMergeBase copy)
47  {
48  if (copy == null)
49  throw new ArgumentNullException(nameof(copy));
50  Author = copy.Author;
51  BodyAtMerge = copy.BodyAtMerge;
52  Comment = copy.Comment;
53  Number = copy.Number;
54  PullRequestRevision = copy.PullRequestRevision;
55  TitleAtMerge = copy.TitleAtMerge;
56  Url = copy.Url;
57  }
58  }
59 }
- -
string TitleAtMerge
The title of the pull request
-
string Author
The author of the pull request
-
Layer of test merge data required internally
Definition: TestMergeBase.cs:9
-
int Number
The number of the pull request
-
string BodyAtMerge
The body of the pull request
-
Parameters for creating a TestMerge
- -
string Url
The URL of the pull request
-
TestMergeBase(TestMergeBase copy)
Construct a TestMergeBase from a copy
+Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
3 
5 {
9  public abstract class TestMergeBase : TestMergeParameters
10  {
14  [Required]
15  public string TitleAtMerge { get; set; }
16 
20  [Required]
21  public string BodyAtMerge { get; set; }
22 
26  [Required]
27 #pragma warning disable CA1056 // Uri properties should not be strings
28  public string Url { get; set; }
29 #pragma warning restore CA1056 // Uri properties should not be strings
30 
34  [Required]
35  public string Author { get; set; }
36 
40  protected TestMergeBase() { }
41 
46  protected TestMergeBase(TestMergeBase copy)
47  {
48  if (copy == null)
49  throw new ArgumentNullException(nameof(copy));
50  Author = copy.Author;
51  BodyAtMerge = copy.BodyAtMerge;
52  Comment = copy.Comment;
53  Number = copy.Number;
56  Url = copy.Url;
57  }
58  }
59 }
string TitleAtMerge
The title of the pull request
+
string Author
The author of the pull request
+
Layer of test merge data required internally
Definition: TestMergeBase.cs:9
+
int? Number
The number of the pull request
+
string BodyAtMerge
The body of the pull request
+ + + +
string Url
The URL of the pull request
+
TestMergeBase(TestMergeBase copy)
Construct a TestMergeBase from a copy
string PullRequestRevision
The sha of the pull request revision to merge. If not specified, the latest commit shall be used (sem...
-
string Comment
Optional comment about the test
- +
string Comment
Optional comment about the test
diff --git a/_test_merge_parameters_8cs.html b/_test_merge_parameters_8cs.html index d8e16f9beb..3794c0ca7c 100644 --- a/_test_merge_parameters_8cs.html +++ b/_test_merge_parameters_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/TestMergeParameters.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_test_merge_parameters_8cs_source.html b/_test_merge_parameters_8cs_source.html index e29132fe19..d13da118a5 100644 --- a/_test_merge_parameters_8cs_source.html +++ b/_test_merge_parameters_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/TestMergeParameters.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestMergeParameters.cs
-Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
3 namespace Tgstation.Server.Api.Models
4 {
8  public class TestMergeParameters
9  {
13  [Required]
14  public int? Number { get; set; }
15 
19  [Required]
20  public string PullRequestRevision { get; set; }
21 
25  public string Comment { get; set; }
26  }
27 }
- -
Parameters for creating a TestMerge
- +Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
4 {
8  public class TestMergeParameters
9  {
13  [Required]
14  public int? Number { get; set; }
15 
19  [Required]
20  public string PullRequestRevision { get; set; }
21 
25  public string Comment { get; set; }
26  }
27 }
+
int? Number
The number of the pull request
+ +
string PullRequestRevision
The sha of the pull request revision to merge. If not specified, the latest commit shall be used (sem...
+
string Comment
Optional comment about the test
diff --git a/_test_platform_identifier_8cs.html b/_test_platform_identifier_8cs.html index bff4cea287..d610326d68 100644 --- a/_test_platform_identifier_8cs.html +++ b/_test_platform_identifier_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestPlatformIdentifier.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
namespace  Tgstation.Server.Host.Core.Tests
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_test_platform_identifier_8cs_source.html b/_test_platform_identifier_8cs_source.html index 0a60a90072..67f8fcdd68 100644 --- a/_test_platform_identifier_8cs_source.html +++ b/_test_platform_identifier_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestPlatformIdentifier.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestPlatformIdentifier.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System.Runtime.InteropServices;
3 
4 namespace Tgstation.Server.Host.Core.Tests
5 {
6  [TestClass]
7  public sealed class TestPlatformIdentifier
8  {
9  [TestMethod]
10  public void TestCorrectPlatform()
11  {
12  var identifier = new PlatformIdentifier();
13 
14  var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
15  const string WindowsScriptExtension = "bat";
16  const string PosixScriptExtension = "sh";
17 
18 
19  Assert.AreEqual(isWindows, identifier.IsWindows);
20 
21  Assert.AreEqual(isWindows ? WindowsScriptExtension : PosixScriptExtension, identifier.ScriptFileExtension);
22  }
23  }
24 }
- - +Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System.Runtime.InteropServices;
3 
5 {
6  [TestClass]
7  public sealed class TestPlatformIdentifier
8  {
9  [TestMethod]
10  public void TestCorrectPlatform()
11  {
12  var identifier = new PlatformIdentifier();
13 
14  var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
15  const string WindowsScriptExtension = "bat";
16  const string PosixScriptExtension = "sh";
17 
18 
19  Assert.AreEqual(isWindows, identifier.IsWindows);
20 
21  Assert.AreEqual(isWindows ? WindowsScriptExtension : PosixScriptExtension, identifier.ScriptFileExtension);
22  }
23  }
24 }
- +
diff --git a/_test_posix_byond_installer_8cs.html b/_test_posix_byond_installer_8cs.html index 163188524e..fd80b77c1c 100644 --- a/_test_posix_byond_installer_8cs.html +++ b/_test_posix_byond_installer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Components/Byond/TestPosixByondInstaller.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Byond
 
namespace  Tgstation.Server.Host.Components.Byond.Tests
 
@@ -113,7 +102,7 @@ Namespaces diff --git a/_test_posix_byond_installer_8cs_source.html b/_test_posix_byond_installer_8cs_source.html index ff5dad62cb..6c6f860bb4 100644 --- a/_test_posix_byond_installer_8cs_source.html +++ b/_test_posix_byond_installer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Components/Byond/TestPosixByondInstaller.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestPosixByondInstaller.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 using Moq;
4 using System;
5 using System.Threading.Tasks;
6 using Tgstation.Server.Host.IO;
7 
8 namespace Tgstation.Server.Host.Components.Byond.Tests
9 {
10  [TestClass]
11  public sealed class TestPosixByondInstaller
12  {
13  [TestMethod]
14  public void TestConstruction()
15  {
16  Assert.ThrowsException<ArgumentNullException>(() => new PosixByondInstaller(null, null, null));
17  var mockIOManager = new Mock<IIOManager>();
18  Assert.ThrowsException<ArgumentNullException>(() => new PosixByondInstaller(mockIOManager.Object, null, null));
19  var mockPostWriteHandler = new Mock<IPostWriteHandler>();
20  Assert.ThrowsException<ArgumentNullException>(() => new PosixByondInstaller(mockIOManager.Object, mockPostWriteHandler.Object, null));
21 
22  var mockLogger = new Mock<ILogger<PosixByondInstaller>>();
23  new PosixByondInstaller(mockIOManager.Object, mockPostWriteHandler.Object, mockLogger.Object);
24  }
25 
26  [TestMethod]
27  public async Task TestCacheClean()
28  {
29  var mockIOManager = new Mock<IIOManager>();
30  var mockPostWriteHandler = new Mock<IPostWriteHandler>();
31  var mockLogger = new Mock<ILogger<PosixByondInstaller>>();
32  var installer = new PosixByondInstaller(mockIOManager.Object, mockPostWriteHandler.Object, mockLogger.Object);
33 
34  const string ByondCachePath = "~/.byond/cache";
35 
36  mockIOManager.Setup(x => x.DeleteDirectory(ByondCachePath, default)).Returns(Task.CompletedTask).Verifiable();
37 
38  await installer.CleanCache(default);
39 
40  mockIOManager.Verify();
41 
42 
43  mockIOManager.Setup(x => x.DeleteDirectory(ByondCachePath, default)).Throws(new OperationCanceledException()).Verifiable();
44 
45  await Assert.ThrowsExceptionAsync<OperationCanceledException>(() => installer.CleanCache(default)).ConfigureAwait(false);
46 
47  mockIOManager.Verify();
48 
49  mockIOManager.Setup(x => x.DeleteDirectory(ByondCachePath, default)).Throws(new Exception()).Verifiable();
50 
51  await installer.CleanCache(default).ConfigureAwait(false);
52 
53  mockIOManager.Verify();
54  }
55 
56 
57  [TestMethod]
58  public async Task TestDownload()
59  {
60  var mockIOManager = new Mock<IIOManager>();
61  var mockPostWriteHandler = new Mock<IPostWriteHandler>();
62  var mockLogger = new Mock<ILogger<PosixByondInstaller>>();
63  var installer = new PosixByondInstaller(mockIOManager.Object, mockPostWriteHandler.Object, mockLogger.Object);
64 
65  await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => installer.DownloadVersion(null, default)).ConfigureAwait(false);
66 
67  var ourArray = Array.Empty<byte>();
68  mockIOManager.Setup(x => x.DownloadFile(It.Is<Uri>(uri => uri == new Uri("https://secure.byond.com/download/build/511/511.1385_byond_linux.zip")), default)).Returns(Task.FromResult(ourArray)).Verifiable();
69 
70  var result = await installer.DownloadVersion(new Version(511, 1385), default).ConfigureAwait(false);
71 
72  Assert.AreSame(ourArray, result);
73  mockIOManager.Verify();
74  }
75 
76  [TestMethod]
77  public async Task TestInstallByond()
78  {
79  var mockIOManager = new Mock<IIOManager>();
80  var mockPostWriteHandler = new Mock<IPostWriteHandler>();
81  var mockLogger = new Mock<ILogger<PosixByondInstaller>>();
82  var installer = new PosixByondInstaller(mockIOManager.Object, mockPostWriteHandler.Object, mockLogger.Object);
83 
84  const string FakePath = "fake";
85  await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => installer.InstallByond(null, null, default)).ConfigureAwait(false);
86  await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => installer.InstallByond(FakePath, null, default)).ConfigureAwait(false);
87 
88  await installer.InstallByond(FakePath, new Version(511, 1385), default).ConfigureAwait(false);
89 
90  mockIOManager.Verify(x => x.ConcatPath(It.IsAny<string>(), It.IsNotNull<string>()), Times.Exactly(5));
91  mockIOManager.Verify(x => x.WriteAllBytes(It.IsAny<string>(), It.IsNotNull<byte[]>(), default), Times.Exactly(2));
92  mockPostWriteHandler.Verify(x => x.HandleWrite(It.IsAny<string>()), Times.Exactly(4));
93  }
94  }
95 }
+Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 using Moq;
4 using System;
5 using System.Threading.Tasks;
6 using Tgstation.Server.Host.IO;
7 
9 {
10  [TestClass]
11  public sealed class TestPosixByondInstaller
12  {
13  [TestMethod]
14  public void TestConstruction()
15  {
16  Assert.ThrowsException<ArgumentNullException>(() => new PosixByondInstaller(null, null, null));
17  var mockIOManager = new Mock<IIOManager>();
18  Assert.ThrowsException<ArgumentNullException>(() => new PosixByondInstaller(mockIOManager.Object, null, null));
19  var mockPostWriteHandler = new Mock<IPostWriteHandler>();
20  Assert.ThrowsException<ArgumentNullException>(() => new PosixByondInstaller(mockIOManager.Object, mockPostWriteHandler.Object, null));
21 
22  var mockLogger = new Mock<ILogger<PosixByondInstaller>>();
23  new PosixByondInstaller(mockIOManager.Object, mockPostWriteHandler.Object, mockLogger.Object);
24  }
25 
26  [TestMethod]
27  public async Task TestCacheClean()
28  {
29  var mockIOManager = new Mock<IIOManager>();
30  var mockPostWriteHandler = new Mock<IPostWriteHandler>();
31  var mockLogger = new Mock<ILogger<PosixByondInstaller>>();
32  var installer = new PosixByondInstaller(mockIOManager.Object, mockPostWriteHandler.Object, mockLogger.Object);
33 
34  const string ByondCachePath = "~/.byond/cache";
35 
36  mockIOManager.Setup(x => x.DeleteDirectory(ByondCachePath, default)).Returns(Task.CompletedTask).Verifiable();
37 
38  await installer.CleanCache(default);
39 
40  mockIOManager.Verify();
41 
42 
43  mockIOManager.Setup(x => x.DeleteDirectory(ByondCachePath, default)).Throws(new OperationCanceledException()).Verifiable();
44 
45  await Assert.ThrowsExceptionAsync<OperationCanceledException>(() => installer.CleanCache(default)).ConfigureAwait(false);
46 
47  mockIOManager.Verify();
48 
49  mockIOManager.Setup(x => x.DeleteDirectory(ByondCachePath, default)).Throws(new Exception()).Verifiable();
50 
51  await installer.CleanCache(default).ConfigureAwait(false);
52 
53  mockIOManager.Verify();
54  }
55 
56 
57  [TestMethod]
58  public async Task TestDownload()
59  {
60  var mockIOManager = new Mock<IIOManager>();
61  var mockPostWriteHandler = new Mock<IPostWriteHandler>();
62  var mockLogger = new Mock<ILogger<PosixByondInstaller>>();
63  var installer = new PosixByondInstaller(mockIOManager.Object, mockPostWriteHandler.Object, mockLogger.Object);
64 
65  await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => installer.DownloadVersion(null, default)).ConfigureAwait(false);
66 
67  var ourArray = Array.Empty<byte>();
68  mockIOManager.Setup(x => x.DownloadFile(It.Is<Uri>(uri => uri == new Uri("https://secure.byond.com/download/build/511/511.1385_byond_linux.zip")), default)).Returns(Task.FromResult(ourArray)).Verifiable();
69 
70  var result = await installer.DownloadVersion(new Version(511, 1385), default).ConfigureAwait(false);
71 
72  Assert.AreSame(ourArray, result);
73  mockIOManager.Verify();
74  }
75 
76  [TestMethod]
77  public async Task TestInstallByond()
78  {
79  var mockIOManager = new Mock<IIOManager>();
80  var mockPostWriteHandler = new Mock<IPostWriteHandler>();
81  var mockLogger = new Mock<ILogger<PosixByondInstaller>>();
82  var installer = new PosixByondInstaller(mockIOManager.Object, mockPostWriteHandler.Object, mockLogger.Object);
83 
84  const string FakePath = "fake";
85  await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => installer.InstallByond(null, null, default)).ConfigureAwait(false);
86  await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => installer.InstallByond(FakePath, null, default)).ConfigureAwait(false);
87 
88  await installer.InstallByond(FakePath, new Version(511, 1385), default).ConfigureAwait(false);
89 
90  mockIOManager.Verify(x => x.ConcatPath(It.IsAny<string>(), It.IsNotNull<string>()), Times.Exactly(5));
91  mockIOManager.Verify(x => x.WriteAllBytes(It.IsAny<string>(), It.IsNotNull<byte[]>(), default), Times.Exactly(2));
92  mockPostWriteHandler.Verify(x => x.HandleWrite(It.IsAny<string>()), Times.Exactly(4));
93  }
94  }
95 }
- - - - - + + - + - + +
diff --git a/_test_post_write_handler_8cs.html b/_test_post_write_handler_8cs.html index d079905a61..6c09b6d65f 100644 --- a/_test_post_write_handler_8cs.html +++ b/_test_post_write_handler_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/IO/TestPostWriteHandler.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.IO
 
namespace  Tgstation.Server.Host.IO.Tests
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_test_post_write_handler_8cs_source.html b/_test_post_write_handler_8cs_source.html index 802ae3da32..cc5374cf90 100644 --- a/_test_post_write_handler_8cs_source.html +++ b/_test_post_write_handler_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/IO/TestPostWriteHandler.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestPostWriteHandler.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using Mono.Unix;
3 using System;
4 using System.Diagnostics;
5 using System.IO;
6 using System.Runtime.InteropServices;
7 using System.Text;
8 
9 namespace Tgstation.Server.Host.IO.Tests
10 {
11  [TestClass]
12  public sealed class TestPostWriteHandler
13  {
14  [TestMethod]
15  public void TestThrowsWithNullArg()
16  {
17  IPostWriteHandler postWriteHandler;
18  var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
19  if (isWindows)
20  postWriteHandler = new WindowsPostWriteHandler();
21  else
22  postWriteHandler = new PosixPostWriteHandler();
23 
24  Assert.ThrowsException<ArgumentNullException>(() => postWriteHandler.HandleWrite(null));
25  }
26 
27  [TestMethod]
28  public void TestPostWrite()
29  {
30  IPostWriteHandler postWriteHandler;
31  var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
32  if (isWindows)
33  postWriteHandler = new WindowsPostWriteHandler();
34  else
35  postWriteHandler = new PosixPostWriteHandler();
36 
37  //test on a valid file first
38  var tmpFile = Path.GetTempFileName();
39  try
40  {
41  postWriteHandler.HandleWrite(tmpFile);
42 
43  if (isWindows)
44  return; //you do nothing
45 
46  //ensure it is now executable
47  File.WriteAllBytes(tmpFile, Encoding.UTF8.GetBytes("#!/bin/sh\n"));
48 
49  using (var process = Process.Start(tmpFile))
50  {
51  process.WaitForExit();
52  Assert.AreEqual(0, process.ExitCode);
53  }
54 
55  //run it again for the code coverage on that part where no changes are made if it's already executable
56  postWriteHandler.HandleWrite(tmpFile);
57  }
58  finally
59  {
60  File.Delete(tmpFile);
61  }
62  }
63 
64  [TestMethod]
65  public void TestThrowsOnUnix()
66  {
67  if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
68  return;
69  var postWriteHandler = new PosixPostWriteHandler();
70  var tmpFile = Path.GetTempFileName();
71  File.Delete(tmpFile);
72  Assert.ThrowsException<UnixIOException>(() => postWriteHandler.HandleWrite(tmpFile));
73  }
74  }
75 }
-
IPostWriteHandler for POSIX systems
-
Handles changing file modes/permissions after writing
- +Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using Mono.Unix;
3 using System;
4 using System.Diagnostics;
5 using System.IO;
6 using System.Runtime.InteropServices;
7 using System.Text;
8 
10 {
11  [TestClass]
12  public sealed class TestPostWriteHandler
13  {
14  [TestMethod]
15  public void TestThrowsWithNullArg()
16  {
17  IPostWriteHandler postWriteHandler;
18  var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
19  if (isWindows)
20  postWriteHandler = new WindowsPostWriteHandler();
21  else
22  postWriteHandler = new PosixPostWriteHandler();
23 
24  Assert.ThrowsException<ArgumentNullException>(() => postWriteHandler.HandleWrite(null));
25  }
26 
27  [TestMethod]
28  public void TestPostWrite()
29  {
30  IPostWriteHandler postWriteHandler;
31  var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
32  if (isWindows)
33  postWriteHandler = new WindowsPostWriteHandler();
34  else
35  postWriteHandler = new PosixPostWriteHandler();
36 
37  //test on a valid file first
38  var tmpFile = Path.GetTempFileName();
39  try
40  {
41  postWriteHandler.HandleWrite(tmpFile);
42 
43  if (isWindows)
44  return; //you do nothing
45 
46  //ensure it is now executable
47  File.WriteAllBytes(tmpFile, Encoding.UTF8.GetBytes("#!/bin/sh\n"));
48 
49  using (var process = Process.Start(tmpFile))
50  {
51  process.WaitForExit();
52  Assert.AreEqual(0, process.ExitCode);
53  }
54 
55  //run it again for the code coverage on that part where no changes are made if it's already executable
56  postWriteHandler.HandleWrite(tmpFile);
57  }
58  finally
59  {
60  File.Delete(tmpFile);
61  }
62  }
63 
64  [TestMethod]
65  public void TestThrowsOnUnix()
66  {
67  if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
68  return;
69  var postWriteHandler = new PosixPostWriteHandler();
70  var tmpFile = Path.GetTempFileName();
71  File.Delete(tmpFile);
72  Assert.ThrowsException<UnixIOException>(() => postWriteHandler.HandleWrite(tmpFile));
73  }
74  }
75 }
+
IPostWriteHandler for POSIX systems
+
Handles changing file modes/permissions after writing
void TestThrowsWithNullArg()
- -
void HandleWrite(string filePath)
For handling system specific necessities after a write
+
void HandleWrite(string filePath)
For handling system specific necessities after a write
void TestThrowsOnUnix()
+
void TestPostWrite()
-
IPostWriteHandler for Windows systems
- +
IPostWriteHandler for Windows systems
diff --git a/_test_program_8cs.html b/_test_program_8cs.html index 8f4e75eafb..1a427d6c53 100644 --- a/_test_program_8cs.html +++ b/_test_program_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Console.Tests/TestProgram.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Console
 
namespace  Tgstation.Server.Host.Console.Tests
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_test_program_8cs_source.html b/_test_program_8cs_source.html index dc14089464..889c04be6d 100644 --- a/_test_program_8cs_source.html +++ b/_test_program_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Console.Tests/TestProgram.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestProgram.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 using Moq;
4 using System;
5 using System.Threading;
6 using System.Threading.Tasks;
8 
9 namespace Tgstation.Server.Host.Console.Tests
10 {
11  [TestClass]
12  public class TestProgram
13  {
14  [TestMethod]
15  public async Task TestProgramRuns()
16  {
17  var mockServer = new Mock<IWatchdog>();
18  var args = Array.Empty<string>();
19  mockServer.Setup(x => x.RunAsync(false, args, It.IsAny<CancellationToken>())).Returns(Task.CompletedTask).Verifiable();
20  var mockServerFactory = new Mock<IWatchdogFactory>();
21  mockServerFactory.Setup(x => x.CreateWatchdog(It.IsAny<ILoggerFactory>())).Returns(mockServer.Object).Verifiable();
22  Program.WatchdogFactory = mockServerFactory.Object;
23  await Program.Main(args).ConfigureAwait(false);
24  mockServer.VerifyAll();
25  mockServerFactory.VerifyAll();
26  }
27  }
28 }
Contains the entrypoint for the application
Definition: Program.cs:13
- +Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 using Moq;
4 using System;
5 using System.Threading;
6 using System.Threading.Tasks;
8 
10 {
11  [TestClass]
12  public class TestProgram
13  {
14  [TestMethod]
15  public async Task TestProgramRuns()
16  {
17  var mockServer = new Mock<IWatchdog>();
18  var args = Array.Empty<string>();
19  mockServer.Setup(x => x.RunAsync(false, args, It.IsAny<CancellationToken>())).Returns(Task.CompletedTask).Verifiable();
20  var mockServerFactory = new Mock<IWatchdogFactory>();
21  mockServerFactory.Setup(x => x.CreateWatchdog(It.IsAny<ILoggerFactory>())).Returns(mockServer.Object).Verifiable();
22  Program.WatchdogFactory = mockServerFactory.Object;
23  await Program.Main(args).ConfigureAwait(false);
24  mockServer.VerifyAll();
25  mockServerFactory.VerifyAll();
26  }
27  }
28 }
Contains the entrypoint for the application
Definition: Program.cs:13
+
static internal async Task Main(string[] args)
Entrypoint for the application
Definition: Program.cs:25
+
static internal IWatchdogFactory WatchdogFactory
The IWatchdogFactory for the Program
Definition: Program.cs:18
+ - - - + - - + +
diff --git a/_test_rights_8cs.html b/_test_rights_8cs.html index b1c6754933..23c899522b 100644 --- a/_test_rights_8cs.html +++ b/_test_rights_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Api.Tests/Rights/TestRights.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Rights
 
namespace  Tgstation.Server.Api.Rights.Tests
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_test_rights_8cs_source.html b/_test_rights_8cs_source.html index d6bf4b8228..402b4da154 100644 --- a/_test_rights_8cs_source.html +++ b/_test_rights_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Api.Tests/Rights/TestRights.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestRights.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.Linq;
4 
5 namespace Tgstation.Server.Api.Rights.Tests
6 {
10  [TestClass]
11  public sealed class TestRights
12  {
13  [TestMethod]
14  public void TestAllPowerOfTwo()
15  {
16  var ulongType = typeof(ulong);
17  foreach (var I in Enum.GetValues(typeof(RightsType)).Cast<RightsType>())
18  {
19  var expectedLog = -1;
20  var rightType = RightsHelper.RightToType(I);
21  foreach (var J in Enum.GetValues(rightType))
22  {
23  Assert.AreEqual(ulongType, Enum.GetUnderlyingType(rightType));
24  var asUlong = (ulong)J;
25  var isOne = asUlong == 1;
26  if(!isOne)
27  Assert.AreEqual(0U, asUlong % 2, String.Format("Enum {0} of {1} is not a power of 2!", Enum.GetName(rightType, asUlong), rightType));
28 
29  if (expectedLog > -1)
30  {
31  var log = Math.Log(asUlong, 2);
32  if (log != expectedLog)
33  Assert.Fail(String.Format("Expected Log2({1}) == {0} to come next for {2}, got {3} instead!", expectedLog, Enum.GetName(rightType, asUlong), rightType, log));
34  }
35  ++expectedLog;
36  }
37  }
38  }
39  }
40 }
- +Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.Linq;
4 
6 {
10  [TestClass]
11  public sealed class TestRights
12  {
13  [TestMethod]
14  public void TestAllPowerOfTwo()
15  {
16  var ulongType = typeof(ulong);
17  foreach (var I in Enum.GetValues(typeof(RightsType)).Cast<RightsType>())
18  {
19  var expectedLog = -1;
20  var rightType = RightsHelper.RightToType(I);
21  foreach (var J in Enum.GetValues(rightType))
22  {
23  Assert.AreEqual(ulongType, Enum.GetUnderlyingType(rightType));
24  var asUlong = (ulong)J;
25  var isOne = asUlong == 1;
26  if(!isOne)
27  Assert.AreEqual(0U, asUlong % 2, String.Format("Enum {0} of {1} is not a power of 2!", Enum.GetName(rightType, asUlong), rightType));
28 
29  if (expectedLog > -1)
30  {
31  var log = Math.Log(asUlong, 2);
32  if (log != expectedLog)
33  Assert.Fail(String.Format("Expected Log2({1}) == {0} to come next for {2}, got {3} instead!", expectedLog, Enum.GetName(rightType, asUlong), rightType, log));
34  }
35  ++expectedLog;
36  }
37  }
38  }
39  }
40 }
+ -
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
- -
static Type RightToType(RightsType rightsType)
Map a given rightsType to its respective Enum Type
- +
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
+ +
static Type RightToType(RightsType rightsType)
Map a given rightsType to its respective Enum Type
diff --git a/_test_server_client_factory_8cs.html b/_test_server_client_factory_8cs.html index 3edb235ba5..2d46d8c749 100644 --- a/_test_server_client_factory_8cs.html +++ b/_test_server_client_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Client.Tests/TestServerClientFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
namespace  Tgstation.Server.Client.Tests
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_test_server_client_factory_8cs_source.html b/_test_server_client_factory_8cs_source.html index 560db30657..931af40713 100644 --- a/_test_server_client_factory_8cs_source.html +++ b/_test_server_client_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Client.Tests/TestServerClientFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestServerClientFactory.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.Net.Http.Headers;
4 
5 namespace Tgstation.Server.Client.Tests
6 {
7  [TestClass]
8  public sealed class TestServerClientFactory
9  {
10  [TestMethod]
11  public void TestConstruction()
12  {
13  Assert.ThrowsException<ArgumentNullException>(() => new ServerClientFactory(null));
14  new ServerClientFactory(new ProductHeaderValue("Tgstation.Server.Client.Tests", GetType().Assembly.GetName().Version.ToString()));
15  }
16  }
17 }
- - +Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.Net.Http.Headers;
4 
6 {
7  [TestClass]
8  public sealed class TestServerClientFactory
9  {
10  [TestMethod]
11  public void TestConstruction()
12  {
13  Assert.ThrowsException<ArgumentNullException>(() => new ServerClientFactory(null));
14  new ServerClientFactory(new ProductHeaderValue("Tgstation.Server.Client.Tests", GetType().Assembly.GetName().Version.ToString()));
15  }
16  }
17 }
+ -
diff --git a/_test_server_factory_8cs.html b/_test_server_factory_8cs.html index b712903772..1e0d44be45 100644 --- a/_test_server_factory_8cs.html +++ b/_test_server_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/TestServerFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Tests
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_test_server_factory_8cs_source.html b/_test_server_factory_8cs_source.html index 488c289421..e0d06a6bc7 100644 --- a/_test_server_factory_8cs_source.html +++ b/_test_server_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/TestServerFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestServerFactory.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 
4 namespace Tgstation.Server.Host.Tests
5 {
9  [TestClass]
10  public sealed class TestServerFactory
11  {
12  [TestMethod]
14  {
15  var factory = new ServerFactory();
16 
17  Assert.ThrowsException<ArgumentNullException>(() => factory.CreateServer(null, null));
18  factory.CreateServer(Array.Empty<string>(), null);
19  }
20 
21  [TestMethod]
23  {
24  var factory = new ServerFactory();
25  const string Path = "/test";
26 
27  Assert.ThrowsException<ArgumentNullException>(() => factory.CreateServer(null, null));
28  Assert.ThrowsException<ArgumentNullException>(() => factory.CreateServer(null, Path));
29  factory.CreateServer(Array.Empty<string>(), Path);
30  }
31  }
32 }
- +Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 
5 {
9  [TestClass]
10  public sealed class TestServerFactory
11  {
12  [TestMethod]
14  {
15  var factory = new ServerFactory();
16 
17  Assert.ThrowsException<ArgumentNullException>(() => factory.CreateServer(null, null));
18  factory.CreateServer(Array.Empty<string>(), null);
19  }
20 
21  [TestMethod]
23  {
24  var factory = new ServerFactory();
25  const string Path = "/test";
26 
27  Assert.ThrowsException<ArgumentNullException>(() => factory.CreateServer(null, null));
28  Assert.ThrowsException<ArgumentNullException>(() => factory.CreateServer(null, Path));
29  factory.CreateServer(Array.Empty<string>(), Path);
30  }
31  }
32 }
- + -
diff --git a/_test_server_service_8cs.html b/_test_server_service_8cs.html index 702b5c0ebd..60b3e16517 100644 --- a/_test_server_service_8cs.html +++ b/_test_server_service_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Service.Tests/TestServerService.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Service.Tests.TestServerServiceTests for ServerService More...
Tests for ServerService More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Service
 
namespace  Tgstation.Server.Host.Service.Tests
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_test_server_service_8cs_source.html b/_test_server_service_8cs_source.html index dd505a2cca..cf24384545 100644 --- a/_test_server_service_8cs_source.html +++ b/_test_server_service_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Service.Tests/TestServerService.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestServerService.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 using Moq;
4 using System;
5 using System.Reflection;
6 using System.Threading;
7 using System.Threading.Tasks;
9 
10 namespace Tgstation.Server.Host.Service.Tests
11 {
15  [TestClass]
16  public sealed class TestServerService
17  {
18  [TestMethod]
20  {
21  Assert.ThrowsException<ArgumentNullException>(() => new ServerService(null, null, default));
22  var mockWatchdogFactory = new Mock<IWatchdogFactory>();
23  Assert.ThrowsException<ArgumentNullException>(() => new ServerService(mockWatchdogFactory.Object, null, default));
24  var mockLoggerFactory = new LoggerFactory();
25  new ServerService(mockWatchdogFactory.Object, mockLoggerFactory, default).Dispose();
26  }
27 
28  [TestMethod]
29  public void TestRun()
30  {
31  var type = typeof(ServerService);
32  var onStart = type.GetMethod("OnStart", BindingFlags.Instance | BindingFlags.NonPublic);
33  var onStop = type.GetMethod("OnStop", BindingFlags.Instance | BindingFlags.NonPublic);
34 
35  var mockWatchdog = new Mock<IWatchdog>();
36  var args = Array.Empty<string>();
37  CancellationToken cancellationToken, originalToken;
38  using(var cts = new CancellationTokenSource())
39  {
40  originalToken = cts.Token;
41  cancellationToken = originalToken;
42  }
43  var cancelled = false;
44 
45  mockWatchdog.Setup(x => x.RunAsync(false, args, It.IsAny<CancellationToken>())).Callback((bool x, string[] _, CancellationToken token) => token.Register(() => cancelled = true)).Returns(Task.CompletedTask).Verifiable();
46  var mockWatchdogFactory = new Mock<IWatchdogFactory>();
47  var mockLoggerFactory = new LoggerFactory();
48  mockWatchdogFactory.Setup(x => x.CreateWatchdog(mockLoggerFactory)).Returns(mockWatchdog.Object).Verifiable();
49 
50  using (var service = new ServerService(mockWatchdogFactory.Object, mockLoggerFactory, default))
51  {
52  Assert.IsFalse(cancelled);
53  onStart.Invoke(service, new object[] { args });
54  mockWatchdog.VerifyAll();
55 
56  Assert.AreNotSame(cancellationToken, originalToken);
57 
58  onStop.Invoke(service, Array.Empty<object>());
59  Assert.IsTrue(cancelled);
60  }
61  mockWatchdogFactory.VerifyAll();
62  }
63  }
64 }
+Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 using Moq;
4 using System;
5 using System.Reflection;
6 using System.Threading;
7 using System.Threading.Tasks;
9 
11 {
15  [TestClass]
16  public sealed class TestServerService
17  {
18  [TestMethod]
20  {
21  Assert.ThrowsException<ArgumentNullException>(() => new ServerService(null, null, default));
22  var mockWatchdogFactory = new Mock<IWatchdogFactory>();
23  Assert.ThrowsException<ArgumentNullException>(() => new ServerService(mockWatchdogFactory.Object, null, default));
24  var mockLoggerFactory = new LoggerFactory();
25  new ServerService(mockWatchdogFactory.Object, mockLoggerFactory, default).Dispose();
26  }
27 
28  [TestMethod]
29  public void TestRun()
30  {
31  var type = typeof(ServerService);
32  var onStart = type.GetMethod("OnStart", BindingFlags.Instance | BindingFlags.NonPublic);
33  var onStop = type.GetMethod("OnStop", BindingFlags.Instance | BindingFlags.NonPublic);
34 
35  var mockWatchdog = new Mock<IWatchdog>();
36  var args = Array.Empty<string>();
37  CancellationToken cancellationToken;
38  mockWatchdog.Setup(x => x.RunAsync(false, args, It.IsAny<CancellationToken>())).Callback((bool x, string[] _, CancellationToken token) => cancellationToken = token).Returns(Task.CompletedTask).Verifiable();
39  var mockWatchdogFactory = new Mock<IWatchdogFactory>();
40  var mockLoggerFactory = new LoggerFactory();
41  mockWatchdogFactory.Setup(x => x.CreateWatchdog(mockLoggerFactory)).Returns(mockWatchdog.Object).Verifiable();
42 
43  using (var service = new ServerService(mockWatchdogFactory.Object, mockLoggerFactory, default))
44  {
45  onStart.Invoke(service, new object[] { args });
46 
47  Assert.IsFalse(cancellationToken.IsCancellationRequested);
48 
49  onStop.Invoke(service, Array.Empty<object>());
50  Assert.IsTrue(cancellationToken.IsCancellationRequested);
51  mockWatchdog.VerifyAll();
52  }
53 
54  mockWatchdogFactory.VerifyAll();
55  }
56  }
57 }
- -
override void Dispose(bool disposing)
+
override void Dispose(bool disposing)
- -
Represents a IWatchdog as a ServiceBase
- - - - - + +
Represents a IWatchdog as a ServiceBase
+ + + +
diff --git a/_test_service_collection_extensions_8cs.html b/_test_service_collection_extensions_8cs.html index 32e0cf5bb1..616b8e61cc 100644 --- a/_test_service_collection_extensions_8cs.html +++ b/_test_service_collection_extensions_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestServiceCollectionExtensions.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
namespace  Tgstation.Server.Host.Core.Tests
 
@@ -121,7 +108,7 @@ Namespaces diff --git a/_test_service_collection_extensions_8cs_source.html b/_test_service_collection_extensions_8cs_source.html index 4614e5674a..70a6b6d917 100644 --- a/_test_service_collection_extensions_8cs_source.html +++ b/_test_service_collection_extensions_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestServiceCollectionExtensions.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestServiceCollectionExtensions.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Configuration;
2 using Microsoft.Extensions.DependencyInjection;
3 using Microsoft.VisualStudio.TestTools.UnitTesting;
4 using Moq;
5 using System;
6 
7 namespace Tgstation.Server.Host.Core.Tests
8 {
9  [TestClass]
10  public sealed class TestServiceCollectionExtensions
11  {
12  class GoodConfig
13  {
14  public const string Section = "asdf";
15  }
16 
17  class BadConfig1
18  {
19  const string Section = "asdf";
20  }
21 
22  class BadConfig2
23  {
24  public const bool Section = false;
25  }
26 
27  class BadConfig3
28  {
29  //nah
30  }
31 
32  [TestMethod]
33  public void TestUseStandardConfig()
34  {
35  var serviceCollection = new ServiceCollection();
36  var mockConfig = new Mock<IConfigurationSection>();
37  mockConfig.Setup(x => x.GetSection(It.IsNotNull<string>())).Returns(mockConfig.Object).Verifiable();
38  Assert.ThrowsException<ArgumentNullException>(() => ServiceCollectionExtensions.UseStandardConfig<GoodConfig>(null, null));
39  Assert.ThrowsException<ArgumentNullException>(() => serviceCollection.UseStandardConfig<GoodConfig>(null));
40  serviceCollection.UseStandardConfig<GoodConfig>(mockConfig.Object);
41  Assert.ThrowsException<InvalidOperationException>(() => serviceCollection.UseStandardConfig<BadConfig1>(mockConfig.Object));
42  Assert.ThrowsException<InvalidOperationException>(() => serviceCollection.UseStandardConfig<BadConfig2>(mockConfig.Object));
43  Assert.ThrowsException<InvalidOperationException>(() => serviceCollection.UseStandardConfig<BadConfig3>(mockConfig.Object));
44  mockConfig.Verify();
45  }
46  }
47 }
- - +Go to the documentation of this file.
1 using Microsoft.Extensions.Configuration;
2 using Microsoft.Extensions.DependencyInjection;
3 using Microsoft.VisualStudio.TestTools.UnitTesting;
4 using Moq;
5 using System;
6 
8 {
9  [TestClass]
10  public sealed class TestServiceCollectionExtensions
11  {
12  class GoodConfig
13  {
14  public const string Section = "asdf";
15  }
16 
17  class BadConfig1
18  {
19  const string Section = "asdf";
20  }
21 
22  class BadConfig2
23  {
24  public const bool Section = false;
25  }
26 
27  class BadConfig3
28  {
29  //nah
30  }
31 
32  [TestMethod]
33  public void TestUseStandardConfig()
34  {
35  var serviceCollection = new ServiceCollection();
36  var mockConfig = new Mock<IConfigurationSection>();
37  mockConfig.Setup(x => x.GetSection(It.IsNotNull<string>())).Returns(mockConfig.Object).Verifiable();
38  Assert.ThrowsException<ArgumentNullException>(() => ServiceCollectionExtensions.UseStandardConfig<GoodConfig>(null, null));
39  Assert.ThrowsException<ArgumentNullException>(() => serviceCollection.UseStandardConfig<GoodConfig>(null));
40  serviceCollection.UseStandardConfig<GoodConfig>(mockConfig.Object);
41  Assert.ThrowsException<InvalidOperationException>(() => serviceCollection.UseStandardConfig<BadConfig1>(mockConfig.Object));
42  Assert.ThrowsException<InvalidOperationException>(() => serviceCollection.UseStandardConfig<BadConfig2>(mockConfig.Object));
43  Assert.ThrowsException<InvalidOperationException>(() => serviceCollection.UseStandardConfig<BadConfig3>(mockConfig.Object));
44  mockConfig.Verify();
45  }
46  }
47 }
+ + - + - - + +
diff --git a/_test_setup_wizard_8cs.html b/_test_setup_wizard_8cs.html index aefde59ae0..54c7a08621 100644 --- a/_test_setup_wizard_8cs.html +++ b/_test_setup_wizard_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestSetupWizard.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Core
 
namespace  Tgstation.Server.Host.Core.Tests
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_test_setup_wizard_8cs_source.html b/_test_setup_wizard_8cs_source.html index d06a532fa7..c87c1a147c 100644 --- a/_test_setup_wizard_8cs_source.html +++ b/_test_setup_wizard_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core/TestSetupWizard.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestSetupWizard.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Hosting;
2 using Microsoft.Extensions.Logging;
3 using Microsoft.Extensions.Options;
4 using Microsoft.VisualStudio.TestTools.UnitTesting;
5 using Moq;
6 using Moq.Protected;
7 using System;
8 using System.Collections.Generic;
9 using System.Data.Common;
10 using System.Runtime.InteropServices;
11 using System.Text;
12 using System.Threading;
13 using System.Threading.Tasks;
15 using Tgstation.Server.Host.IO;
16 
17 namespace Tgstation.Server.Host.Core.Tests
18 {
19  [TestClass]
20  public sealed class TestSetupWizard
21  {
22  [TestMethod]
23  public void TestConstructionThrows()
24  {
25  Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(null, null, null, null, null, null, null, null, null));
26  var mockIOManager = new Mock<IIOManager>();
27  Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, null, null, null, null, null, null, null, null));
28  var mockConsole = new Mock<IConsole>();
29  Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, null, null, null, null, null, null, null));
30  var mockHostingEnvironment = new Mock<IHostingEnvironment>();
31  Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, null, null, null, null, null, null));
32  var mockApplication = new Mock<IApplication>();
33  Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockApplication.Object, null, null, null, null, null));
34  var mockDBConnectionFactory = new Mock<IDBConnectionFactory>();
35  Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockApplication.Object, mockDBConnectionFactory.Object, null, null, null, null));
36  var mockPlatformIdentifier = new Mock<IPlatformIdentifier>();
37  Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockApplication.Object, mockDBConnectionFactory.Object, mockPlatformIdentifier.Object, null, null, null));
38  var mockAsyncDelayer = new Mock<IAsyncDelayer>();
39  Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockApplication.Object, mockDBConnectionFactory.Object, mockPlatformIdentifier.Object, mockAsyncDelayer.Object, null, null));
40  var mockLogger = new Mock<ILogger<SetupWizard>>();
41  Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockApplication.Object, mockDBConnectionFactory.Object, mockPlatformIdentifier.Object, mockAsyncDelayer.Object, mockLogger.Object, null));
42  }
43 
44  [TestMethod]
45  public async Task TestWithUserStupiditiy()
46  {
47  var mockIOManager = new Mock<IIOManager>();
48  var mockConsole = new Mock<IConsole>();
49  var mockHostingEnvironment = new Mock<IHostingEnvironment>();
50  var mockApplication = new Mock<IApplication>();
51  var mockDBConnectionFactory = new Mock<IDBConnectionFactory>();
52  var mockLogger = new Mock<ILogger<SetupWizard>>();
53  var mockGeneralConfigurationOptions = new Mock<IOptions<GeneralConfiguration>>();
54  var mockPlatformIdentifier = new Mock<IPlatformIdentifier>();
55  var mockAsyncDelayer = new Mock<IAsyncDelayer>();
56 
57  var testGeneralConfig = new GeneralConfiguration
58  {
60  };
61  mockGeneralConfigurationOptions.SetupGet(x => x.Value).Returns(testGeneralConfig).Verifiable();
62 
63  var wizard = new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockApplication.Object, mockDBConnectionFactory.Object, mockPlatformIdentifier.Object, mockAsyncDelayer.Object, mockLogger.Object, mockGeneralConfigurationOptions.Object);
64 
65  mockPlatformIdentifier.SetupGet(x => x.IsWindows).Returns(true).Verifiable();
66  mockAsyncDelayer.Setup(x => x.Delay(It.IsAny<TimeSpan>(), It.IsAny<CancellationToken>())).Returns(Task.CompletedTask).Verifiable();
67 
68  Assert.IsFalse(await wizard.CheckRunWizard(default).ConfigureAwait(false));
69 
70  testGeneralConfig.SetupWizardMode = SetupWizardMode.Force;
71  await Assert.ThrowsExceptionAsync<InvalidOperationException>(() => wizard.CheckRunWizard(default)).ConfigureAwait(false);
72 
73  testGeneralConfig.SetupWizardMode = SetupWizardMode.Only;
74  await Assert.ThrowsExceptionAsync<InvalidOperationException>(() => wizard.CheckRunWizard(default)).ConfigureAwait(false);
75 
76  mockConsole.SetupGet(x => x.Available).Returns(true).Verifiable();
77  mockIOManager.Setup(x => x.FileExists(It.IsNotNull<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(true)).Verifiable();
78  mockIOManager.Setup(x => x.ReadAllBytes(It.IsNotNull<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(Encoding.UTF8.GetBytes("cucked"))).Verifiable();
79  mockIOManager.Setup(x => x.WriteAllBytes(It.IsNotNull<string>(), It.IsNotNull<byte[]>(), It.IsAny<CancellationToken>())).Returns(Task.CompletedTask).Verifiable();
80 
81  var mockSuccessCommand = new Mock<DbCommand>();
82  mockSuccessCommand.Setup(x => x.ExecuteNonQueryAsync(It.IsAny<CancellationToken>())).Returns(Task.FromResult(0)).Verifiable();
83  mockSuccessCommand.Setup(x => x.ExecuteScalarAsync(It.IsAny<CancellationToken>())).Returns(Task.FromResult<object>("1.2.3")).Verifiable();
84  var mockFailCommand = new Mock<DbCommand>();
85  mockFailCommand.Setup(x => x.ExecuteNonQueryAsync(It.IsAny<CancellationToken>())).Throws(new Exception()).Verifiable();
86 
87  void SetDbCommandCreator(Mock<DbConnection> mock, Func<DbCommand> creator) => mock.Protected().Setup<DbCommand>("CreateDbCommand").Returns(creator).Verifiable();
88 
89  var mockGoodDbConnection = new Mock<DbConnection>();
90  mockGoodDbConnection.Setup(x => x.OpenAsync(It.IsAny<CancellationToken>())).Returns(Task.CompletedTask).Verifiable();
91  SetDbCommandCreator(mockGoodDbConnection, () => mockSuccessCommand.Object);
92 
93  var mockBadDbConnection = new Mock<DbConnection>();
94  mockBadDbConnection.Setup(x => x.OpenAsync(It.IsAny<CancellationToken>())).Throws(new Exception()).Verifiable();
95  var invokeTimes = 0;
96  var mockUglyDbConnection = new Mock<DbConnection>();
97  SetDbCommandCreator(mockUglyDbConnection, () =>
98  {
99  if (invokeTimes < 2)
100  {
101  ++invokeTimes;
102  return mockSuccessCommand.Object;
103  }
104  else
105  return mockFailCommand.Object;
106  });
107 
108  mockDBConnectionFactory.Setup(x => x.CreateConnection(It.IsAny<string>(), DatabaseType.SqlServer)).Returns(mockBadDbConnection.Object).Verifiable();
109  mockDBConnectionFactory.Setup(x => x.CreateConnection(It.IsAny<string>(), DatabaseType.MariaDB)).Returns(mockGoodDbConnection.Object).Verifiable();
110  mockDBConnectionFactory.Setup(x => x.CreateConnection(It.IsAny<string>(), DatabaseType.MySql)).Returns(mockUglyDbConnection.Object).Verifiable();
111 
112  var finalInputSequence = new List<string>()
113  {
114  //first run, just say no to the force prompt after testing it
115  "fake",
116  "n",
117  //second run say yes to the force prompt
118  "y",
119  //first normal run
120  "bad port number",
121  "0",
122  "666",
123  "FakeDBType",
124  nameof(DatabaseType.SqlServer),
125  "this isn't validated",
126  "nor is this",
127  "no",
128  //test winauth
129  "yes",
130  //sql server will always fail so reconfigure with maria
131  nameof(DatabaseType.MariaDB),
132  "bleh",
133  "blah",
134  "NO",
135  "user",
136  "pass",
137  //general config
138  "four",
139  "-12",
140  "16",
141  "eight",
142  "-27",
143  "5000",
144  "fake token",
145  //logging config
146  "no",
147  //cp config
148  "y",
149  "y",
150  //saved, now for second run
151  //this time use defaults amap
152  String.Empty,
153  //test MySQL errors
154  nameof(DatabaseType.MySql),
155  String.Empty,
156  String.Empty,
157  "DbName",
158  "n",
159  "user",
160  "pass",
161  //general config
162  "y",
163  String.Empty,
164  String.Empty,
165  String.Empty,
166  //logging config
167  "y",
168  "not actually verified because lol mocks /../!@#$%^&*()/..///.",
169  "Warning",
170  String.Empty,
171  //cp config
172  "y",
173  "n",
174  String.Empty,
175  //third run, we already hit all the code coverage so just get through it
176  String.Empty,
177  nameof(DatabaseType.MariaDB),
178  String.Empty,
179  "dbname",
180  "y",
181  "user",
182  "pass",
183  //general
184  "y",
185  String.Empty,
186  String.Empty,
187  String.Empty,
188  "y",
189  "will faile",
190  String.Empty,
191  String.Empty,
192  "fake",
193  "None",
194  "Critical",
195  //cp config
196  "y",
197  "n",
198  "http://fake.com, https://example.org",
199  };
200 
201  var inputPos = 0;
202 
203  mockApplication.SetupGet(x => x.VersionPrefix).Returns("sumfuk").Verifiable();
204 
205  mockConsole.Setup(x => x.PressAnyKeyAsync(It.IsAny<CancellationToken>())).Returns(Task.CompletedTask).Verifiable();
206  mockConsole.Setup(x => x.ReadLineAsync(It.IsAny<bool>(), It.IsAny<CancellationToken>())).Returns(() =>
207  {
208  if (inputPos == finalInputSequence.Count)
209  Assert.Fail("Exhausted input sequence!");
210  var res = finalInputSequence[inputPos++];
211  return Task.FromResult(res);
212  }).Verifiable();
213  mockConsole.Setup(x => x.WriteAsync(It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<CancellationToken>())).Returns(Task.CompletedTask).Verifiable();
214 
215  Assert.IsFalse(await wizard.CheckRunWizard(default).ConfigureAwait(false));
216  //first real run
217  Assert.IsTrue(await wizard.CheckRunWizard(default).ConfigureAwait(false));
218 
219  //second run
220  mockIOManager.Setup(x => x.ReadAllBytes(It.IsNotNull<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(Encoding.UTF8.GetBytes(String.Empty))).Verifiable();
221  Assert.IsTrue(await wizard.CheckRunWizard(default).ConfigureAwait(false));
222 
223  //third run
224  testGeneralConfig.SetupWizardMode = SetupWizardMode.Autodetect;
225  mockIOManager.Setup(x => x.WriteAllBytes(It.IsNotNull<string>(), It.IsNotNull<byte[]>(), It.IsAny<CancellationToken>())).Throws(new Exception()).Verifiable();
226  var firstRun = true;
227  mockIOManager.Setup(x => x.CreateDirectory(It.IsNotNull<string>(), It.IsAny<CancellationToken>())).Returns(() =>
228  {
229  if (firstRun)
230  {
231  firstRun = false;
232  throw new Exception();
233  }
234  return Task.CompletedTask;
235  }).Verifiable();
236 
237  await Assert.ThrowsExceptionAsync<OperationCanceledException>(() => wizard.CheckRunWizard(default)).ConfigureAwait(false);
238 
239  Assert.AreEqual(finalInputSequence.Count, inputPos);
240  mockFailCommand.VerifyAll();
241  mockSuccessCommand.VerifyAll();
242  mockIOManager.VerifyAll();
243  mockGeneralConfigurationOptions.VerifyAll();
244  mockConsole.VerifyAll();
245  mockGoodDbConnection.VerifyAll();
246  mockBadDbConnection.VerifyAll();
247  mockUglyDbConnection.VerifyAll();
248  mockDBConnectionFactory.VerifyAll();
249  mockApplication.VerifyAll();
250  mockPlatformIdentifier.VerifyAll();
251  mockAsyncDelayer.VerifyAll();
252  }
253  }
254 }
-
SetupWizardMode
Determines if the Core.ISetupWizard will run
- +Go to the documentation of this file.
1 using Microsoft.AspNetCore.Hosting;
2 using Microsoft.Extensions.Logging;
3 using Microsoft.Extensions.Options;
4 using Microsoft.VisualStudio.TestTools.UnitTesting;
5 using Moq;
6 using Moq.Protected;
7 using System;
8 using System.Collections.Generic;
9 using System.Data.Common;
10 using System.Runtime.InteropServices;
11 using System.Text;
12 using System.Threading;
13 using System.Threading.Tasks;
15 using Tgstation.Server.Host.IO;
16 
18 {
19  [TestClass]
20  public sealed class TestSetupWizard
21  {
22  [TestMethod]
23  public void TestConstructionThrows()
24  {
25  Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(null, null, null, null, null, null, null, null, null));
26  var mockIOManager = new Mock<IIOManager>();
27  Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, null, null, null, null, null, null, null, null));
28  var mockConsole = new Mock<IConsole>();
29  Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, null, null, null, null, null, null, null));
30  var mockHostingEnvironment = new Mock<IHostingEnvironment>();
31  Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, null, null, null, null, null, null));
32  var mockApplication = new Mock<IApplication>();
33  Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockApplication.Object, null, null, null, null, null));
34  var mockDBConnectionFactory = new Mock<IDBConnectionFactory>();
35  Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockApplication.Object, mockDBConnectionFactory.Object, null, null, null, null));
36  var mockPlatformIdentifier = new Mock<IPlatformIdentifier>();
37  Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockApplication.Object, mockDBConnectionFactory.Object, mockPlatformIdentifier.Object, null, null, null));
38  var mockAsyncDelayer = new Mock<IAsyncDelayer>();
39  Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockApplication.Object, mockDBConnectionFactory.Object, mockPlatformIdentifier.Object, mockAsyncDelayer.Object, null, null));
40  var mockLogger = new Mock<ILogger<SetupWizard>>();
41  Assert.ThrowsException<ArgumentNullException>(() => new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockApplication.Object, mockDBConnectionFactory.Object, mockPlatformIdentifier.Object, mockAsyncDelayer.Object, mockLogger.Object, null));
42  }
43 
44  [TestMethod]
45  public async Task TestWithUserStupiditiy()
46  {
47  var mockIOManager = new Mock<IIOManager>();
48  var mockConsole = new Mock<IConsole>();
49  var mockHostingEnvironment = new Mock<IHostingEnvironment>();
50  var mockApplication = new Mock<IApplication>();
51  var mockDBConnectionFactory = new Mock<IDBConnectionFactory>();
52  var mockLogger = new Mock<ILogger<SetupWizard>>();
53  var mockGeneralConfigurationOptions = new Mock<IOptions<GeneralConfiguration>>();
54  var mockPlatformIdentifier = new Mock<IPlatformIdentifier>();
55  var mockAsyncDelayer = new Mock<IAsyncDelayer>();
56 
57  var testGeneralConfig = new GeneralConfiguration
58  {
60  };
61  mockGeneralConfigurationOptions.SetupGet(x => x.Value).Returns(testGeneralConfig).Verifiable();
62 
63  var wizard = new SetupWizard(mockIOManager.Object, mockConsole.Object, mockHostingEnvironment.Object, mockApplication.Object, mockDBConnectionFactory.Object, mockPlatformIdentifier.Object, mockAsyncDelayer.Object, mockLogger.Object, mockGeneralConfigurationOptions.Object);
64 
65  mockPlatformIdentifier.SetupGet(x => x.IsWindows).Returns(true).Verifiable();
66  mockAsyncDelayer.Setup(x => x.Delay(It.IsAny<TimeSpan>(), It.IsAny<CancellationToken>())).Returns(Task.CompletedTask).Verifiable();
67 
68  Assert.IsFalse(await wizard.CheckRunWizard(default).ConfigureAwait(false));
69 
70  testGeneralConfig.SetupWizardMode = SetupWizardMode.Force;
71  await Assert.ThrowsExceptionAsync<InvalidOperationException>(() => wizard.CheckRunWizard(default)).ConfigureAwait(false);
72 
73  testGeneralConfig.SetupWizardMode = SetupWizardMode.Only;
74  await Assert.ThrowsExceptionAsync<InvalidOperationException>(() => wizard.CheckRunWizard(default)).ConfigureAwait(false);
75 
76  mockConsole.SetupGet(x => x.Available).Returns(true).Verifiable();
77  mockIOManager.Setup(x => x.FileExists(It.IsNotNull<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(true)).Verifiable();
78  mockIOManager.Setup(x => x.ReadAllBytes(It.IsNotNull<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(Encoding.UTF8.GetBytes("cucked"))).Verifiable();
79  mockIOManager.Setup(x => x.WriteAllBytes(It.IsNotNull<string>(), It.IsNotNull<byte[]>(), It.IsAny<CancellationToken>())).Returns(Task.CompletedTask).Verifiable();
80 
81  var mockSuccessCommand = new Mock<DbCommand>();
82  mockSuccessCommand.Setup(x => x.ExecuteNonQueryAsync(It.IsAny<CancellationToken>())).Returns(Task.FromResult(0)).Verifiable();
83  mockSuccessCommand.Setup(x => x.ExecuteScalarAsync(It.IsAny<CancellationToken>())).Returns(Task.FromResult<object>("1.2.3")).Verifiable();
84  var mockFailCommand = new Mock<DbCommand>();
85  mockFailCommand.Setup(x => x.ExecuteNonQueryAsync(It.IsAny<CancellationToken>())).Throws(new Exception()).Verifiable();
86 
87  void SetDbCommandCreator(Mock<DbConnection> mock, Func<DbCommand> creator) => mock.Protected().Setup<DbCommand>("CreateDbCommand").Returns(creator).Verifiable();
88 
89  var mockGoodDbConnection = new Mock<DbConnection>();
90  mockGoodDbConnection.Setup(x => x.OpenAsync(It.IsAny<CancellationToken>())).Returns(Task.CompletedTask).Verifiable();
91  SetDbCommandCreator(mockGoodDbConnection, () => mockSuccessCommand.Object);
92 
93  var mockBadDbConnection = new Mock<DbConnection>();
94  mockBadDbConnection.Setup(x => x.OpenAsync(It.IsAny<CancellationToken>())).Throws(new Exception()).Verifiable();
95  var invokeTimes = 0;
96  var mockUglyDbConnection = new Mock<DbConnection>();
97  SetDbCommandCreator(mockUglyDbConnection, () =>
98  {
99  if (invokeTimes < 2)
100  {
101  ++invokeTimes;
102  return mockSuccessCommand.Object;
103  }
104  else
105  return mockFailCommand.Object;
106  });
107 
108  mockDBConnectionFactory.Setup(x => x.CreateConnection(It.IsAny<string>(), DatabaseType.SqlServer)).Returns(mockBadDbConnection.Object).Verifiable();
109  mockDBConnectionFactory.Setup(x => x.CreateConnection(It.IsAny<string>(), DatabaseType.MariaDB)).Returns(mockGoodDbConnection.Object).Verifiable();
110  mockDBConnectionFactory.Setup(x => x.CreateConnection(It.IsAny<string>(), DatabaseType.MySql)).Returns(mockUglyDbConnection.Object).Verifiable();
111 
112  var finalInputSequence = new List<string>()
113  {
114  //first run, just say no to the force prompt after testing it
115  "fake",
116  "n",
117  //second run say yes to the force prompt
118  "y",
119  //first normal run
120  "bad port number",
121  "0",
122  "666",
123  "FakeDBType",
124  nameof(DatabaseType.SqlServer),
125  "this isn't validated",
126  "nor is this",
127  "no",
128  //test winauth
129  "yes",
130  //sql server will always fail so reconfigure with maria
131  nameof(DatabaseType.MariaDB),
132  "bleh",
133  "blah",
134  "NO",
135  "user",
136  "pass",
137  //general config
138  "four",
139  "-12",
140  "16",
141  "eight",
142  "-27",
143  "5000",
144  "fake token",
145  //logging config
146  "no",
147  //cp config
148  "y",
149  "y",
150  //saved, now for second run
151  //this time use defaults amap
152  String.Empty,
153  //test MySQL errors
154  nameof(DatabaseType.MySql),
155  String.Empty,
156  String.Empty,
157  "DbName",
158  "n",
159  "user",
160  "pass",
161  //general config
162  "y",
163  String.Empty,
164  String.Empty,
165  String.Empty,
166  //logging config
167  "y",
168  "not actually verified because lol mocks /../!@#$%^&*()/..///.",
169  "Warning",
170  String.Empty,
171  //cp config
172  "y",
173  "n",
174  String.Empty,
175  //third run, we already hit all the code coverage so just get through it
176  String.Empty,
177  nameof(DatabaseType.MariaDB),
178  String.Empty,
179  "dbname",
180  "y",
181  "user",
182  "pass",
183  //general
184  "y",
185  String.Empty,
186  String.Empty,
187  String.Empty,
188  "y",
189  "will faile",
190  String.Empty,
191  String.Empty,
192  "fake",
193  "None",
194  "Critical",
195  //cp config
196  "y",
197  "n",
198  "http://fake.com, https://example.org",
199  };
200 
201  var inputPos = 0;
202 
203  mockApplication.SetupGet(x => x.VersionPrefix).Returns("sumfuk").Verifiable();
204 
205 
206  // This list is here for ease of debugging.
207  var consolePlayback = new List<string>();
208 
209  mockConsole.Setup(x => x.PressAnyKeyAsync(It.IsAny<CancellationToken>())).Returns(Task.CompletedTask).Verifiable();
210  mockConsole.Setup(x => x.ReadLineAsync(It.IsAny<bool>(), It.IsAny<CancellationToken>())).Returns(() =>
211  {
212  if (inputPos == finalInputSequence.Count)
213  Assert.Fail("Exhausted input sequence!");
214  var res = finalInputSequence[inputPos++];
215  consolePlayback.Add($"Input: {res}");
216  return Task.FromResult(res);
217  }).Verifiable();
218 
219  mockConsole
220  .Setup(x => x.WriteAsync(It.IsAny<string>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()))
221  .Callback<string, bool, CancellationToken>((message, error, token) => consolePlayback.Add($"Output: {message}"))
222  .Returns(Task.CompletedTask)
223  .Verifiable();
224 
225  Assert.IsFalse(await wizard.CheckRunWizard(default).ConfigureAwait(false));
226  //first real run
227  Assert.IsTrue(await wizard.CheckRunWizard(default).ConfigureAwait(false));
228 
229  //second run
230  mockIOManager.Setup(x => x.ReadAllBytes(It.IsNotNull<string>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(Encoding.UTF8.GetBytes(String.Empty))).Verifiable();
231  Assert.IsTrue(await wizard.CheckRunWizard(default).ConfigureAwait(false));
232 
233  //third run
234  testGeneralConfig.SetupWizardMode = SetupWizardMode.Autodetect;
235  mockIOManager.Setup(x => x.WriteAllBytes(It.IsNotNull<string>(), It.IsNotNull<byte[]>(), It.IsAny<CancellationToken>())).Throws(new Exception()).Verifiable();
236  var firstRun = true;
237  mockIOManager.Setup(x => x.CreateDirectory(It.IsNotNull<string>(), It.IsAny<CancellationToken>())).Returns(() =>
238  {
239  if (firstRun)
240  {
241  firstRun = false;
242  throw new Exception();
243  }
244  return Task.CompletedTask;
245  }).Verifiable();
246 
247  await Assert.ThrowsExceptionAsync<OperationCanceledException>(() => wizard.CheckRunWizard(default)).ConfigureAwait(false);
248 
249  Assert.AreEqual(finalInputSequence.Count, inputPos);
250  mockFailCommand.VerifyAll();
251  mockSuccessCommand.VerifyAll();
252  mockIOManager.VerifyAll();
253  mockGeneralConfigurationOptions.VerifyAll();
254  mockConsole.VerifyAll();
255  mockGoodDbConnection.VerifyAll();
256  mockBadDbConnection.VerifyAll();
257  mockUglyDbConnection.VerifyAll();
258  mockDBConnectionFactory.VerifyAll();
259  mockApplication.VerifyAll();
260  mockPlatformIdentifier.VerifyAll();
261  mockAsyncDelayer.VerifyAll();
262  }
263  }
264 }
SetupWizardMode
Determines if the Core.ISetupWizard will run
- -
DatabaseType
Type of database to user
Definition: DatabaseType.cs:6
- + +
DatabaseType
Type of database to user
Definition: DatabaseType.cs:6
+ - - + + - +
diff --git a/_test_symlink_factory_8cs.html b/_test_symlink_factory_8cs.html index a5ddf49732..3304fed15d 100644 --- a/_test_symlink_factory_8cs.html +++ b/_test_symlink_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/IO/TestSymlinkFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.IO
 
namespace  Tgstation.Server.Host.IO.Tests
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_test_symlink_factory_8cs_source.html b/_test_symlink_factory_8cs_source.html index 23f42c5530..37448db7d3 100644 --- a/_test_symlink_factory_8cs_source.html +++ b/_test_symlink_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/IO/TestSymlinkFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestSymlinkFactory.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.IO;
4 using System.Runtime.InteropServices;
5 using System.Security.Principal;
6 using System.Threading.Tasks;
7 
8 namespace Tgstation.Server.Host.IO.Tests
9 {
10  [TestClass]
11  public sealed class TestSymlinkFactory
12  {
14 
15  [TestInitialize]
16  public void SelectFactory()
17  {
18  if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
19  symlinkFactory = new WindowsSymlinkFactory();
20  else
21  symlinkFactory = new PosixSymlinkFactory();
22  }
23 
24  public static bool HasPermissionToMakeSymlinks()
25  {
26  if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
27  return true;
28  var identity = WindowsIdentity.GetCurrent();
29  var principal = new WindowsPrincipal(identity);
30  return principal.IsInRole(WindowsBuiltInRole.Administrator);
31  }
32 
33  [TestMethod]
34  public async Task TestFileWorks()
35  {
36  if (!HasPermissionToMakeSymlinks())
37  Assert.Inconclusive("Current user does not have permission to create symlinks!");
38  const string Text = "Hello world";
39  string f2 = null;
40  var f1 = Path.GetTempFileName();
41  try
42  {
43  f2 = f1 + ".linked";
44  File.WriteAllText(f1, Text);
45 
46  await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => symlinkFactory.CreateSymbolicLink(null, null, default)).ConfigureAwait(false);
47  await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => symlinkFactory.CreateSymbolicLink(f1, null, default)).ConfigureAwait(false);
48 
49  await symlinkFactory.CreateSymbolicLink(f1, f2, default).ConfigureAwait(false);
50  Assert.IsTrue(File.Exists(f2));
51 
52  var f2Contents = File.ReadAllText(f2);
53  Assert.AreEqual(Text, f2Contents);
54  }
55  finally
56  {
57  File.Delete(f2);
58  File.Delete(f1);
59  }
60  }
61 
62  [TestMethod]
63  public async Task TestDirectoryWorks()
64  {
65  if (!HasPermissionToMakeSymlinks())
66  Assert.Inconclusive("Current user does not have permission to create symlinks!");
67  const string FileName = "TestFile.txt";
68  const string Text = "Hello world";
69  string f2 = null;
70  var f1 = Path.GetTempFileName();
71  File.Delete(f1);
72  Directory.CreateDirectory(f1);
73  try
74  {
75  f2 = f1 + ".linked";
76  var p1 = Path.Combine(f1, FileName);
77  File.WriteAllText(p1, Text);
78 
79  await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => symlinkFactory.CreateSymbolicLink(null, null, default)).ConfigureAwait(false);
80  await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => symlinkFactory.CreateSymbolicLink(f1, null, default)).ConfigureAwait(false);
81 
82  await symlinkFactory.CreateSymbolicLink(f1, f2, default).ConfigureAwait(false);
83 
84  var p2 = Path.Combine(f2, FileName);
85  Assert.IsTrue(File.Exists(p2));
86 
87  var f2Contents = File.ReadAllText(p2);
88  Assert.AreEqual(Text, f2Contents);
89 
90  File.Delete(p2);
91  Assert.IsFalse(File.Exists(p1));
92  }
93  finally
94  {
95  Directory.Delete(f2, true);
96  Directory.Delete(f1, true);
97  }
98  }
99 
100  [TestMethod]
101  public async Task TestFailsProperly()
102  {
103  const string BadPath = "/../../?>!@#$%^&*()O(UF+}P{{??>/////";
104 
105  try
106  {
107  await symlinkFactory.CreateSymbolicLink(BadPath, BadPath, default).ConfigureAwait(false);
108  Assert.Fail("No exception thrown!");
109  }
110  catch { }
111  }
112  }
113 }
- - +Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.IO;
4 using System.Runtime.InteropServices;
5 using System.Security.Principal;
6 using System.Threading.Tasks;
7 
9 {
10  [TestClass]
11  public sealed class TestSymlinkFactory
12  {
14 
15  [TestInitialize]
16  public void SelectFactory()
17  {
18  if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
20  else
22  }
23 
24  public static bool HasPermissionToMakeSymlinks()
25  {
26  if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
27  return true;
28  var identity = WindowsIdentity.GetCurrent();
29  var principal = new WindowsPrincipal(identity);
30  return principal.IsInRole(WindowsBuiltInRole.Administrator);
31  }
32 
33  [TestMethod]
34  public async Task TestFileWorks()
35  {
37  Assert.Inconclusive("Current user does not have permission to create symlinks!");
38  const string Text = "Hello world";
39  string f2 = null;
40  var f1 = Path.GetTempFileName();
41  try
42  {
43  f2 = f1 + ".linked";
44  File.WriteAllText(f1, Text);
45 
46  await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => symlinkFactory.CreateSymbolicLink(null, null, default)).ConfigureAwait(false);
47  await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => symlinkFactory.CreateSymbolicLink(f1, null, default)).ConfigureAwait(false);
48 
49  await symlinkFactory.CreateSymbolicLink(f1, f2, default).ConfigureAwait(false);
50  Assert.IsTrue(File.Exists(f2));
51 
52  var f2Contents = File.ReadAllText(f2);
53  Assert.AreEqual(Text, f2Contents);
54  }
55  finally
56  {
57  File.Delete(f2);
58  File.Delete(f1);
59  }
60  }
61 
62  [TestMethod]
63  public async Task TestDirectoryWorks()
64  {
66  Assert.Inconclusive("Current user does not have permission to create symlinks!");
67  const string FileName = "TestFile.txt";
68  const string Text = "Hello world";
69  string f2 = null;
70  var f1 = Path.GetTempFileName();
71  File.Delete(f1);
72  Directory.CreateDirectory(f1);
73  try
74  {
75  f2 = f1 + ".linked";
76  var p1 = Path.Combine(f1, FileName);
77  File.WriteAllText(p1, Text);
78 
79  await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => symlinkFactory.CreateSymbolicLink(null, null, default)).ConfigureAwait(false);
80  await Assert.ThrowsExceptionAsync<ArgumentNullException>(() => symlinkFactory.CreateSymbolicLink(f1, null, default)).ConfigureAwait(false);
81 
82  await symlinkFactory.CreateSymbolicLink(f1, f2, default).ConfigureAwait(false);
83 
84  var p2 = Path.Combine(f2, FileName);
85  Assert.IsTrue(File.Exists(p2));
86 
87  var f2Contents = File.ReadAllText(p2);
88  Assert.AreEqual(Text, f2Contents);
89 
90  File.Delete(p2);
91  Assert.IsFalse(File.Exists(p1));
92  }
93  finally
94  {
95  Directory.Delete(f2, true);
96  Directory.Delete(f1, true);
97  }
98  }
99 
100  [TestMethod]
101  public async Task TestFailsProperly()
102  {
103  const string BadPath = "/../../?>!@#$%^&*()O(UF+}P{{??>/////";
104 
105  try
106  {
107  await symlinkFactory.CreateSymbolicLink(BadPath, BadPath, default).ConfigureAwait(false);
108  Assert.Fail("No exception thrown!");
109  }
110  catch { }
111  }
112  }
113 }
- + - + + - - +
diff --git a/_test_watchdog_factory_8cs.html b/_test_watchdog_factory_8cs.html index 8b6cdd3534..f99352f2bf 100644 --- a/_test_watchdog_factory_8cs.html +++ b/_test_watchdog_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Watchdog.Tests/TestWatchdogFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Watchdog
 
namespace  Tgstation.Server.Host.Watchdog.Tests
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_test_watchdog_factory_8cs_source.html b/_test_watchdog_factory_8cs_source.html index a6b8a8fb80..2f9c3f7394 100644 --- a/_test_watchdog_factory_8cs_source.html +++ b/_test_watchdog_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Watchdog.Tests/TestWatchdogFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestWatchdogFactory.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 
4 namespace Tgstation.Server.Host.Watchdog.Tests
5 {
9  [TestClass]
10  public sealed class TestWatchdogFactory
11  {
12  [TestMethod]
13  public void TestCreateWatchdog()
14  {
15  var factory = new WatchdogFactory();
16  Assert.IsNotNull(factory.CreateWatchdog(new LoggerFactory()));
17  }
18  }
19 }
+Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 
5 {
9  [TestClass]
10  public sealed class TestWatchdogFactory
11  {
12  [TestMethod]
13  public void TestCreateWatchdog()
14  {
15  var factory = new WatchdogFactory();
16  Assert.IsNotNull(factory.CreateWatchdog(new LoggerFactory()));
17  }
18  }
19 }
- + -
diff --git a/_testing_server_8cs.html b/_testing_server_8cs.html index e7a372f05e..b47ecce38c 100644 --- a/_testing_server_8cs.html +++ b/_testing_server_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Tests/TestingServer.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Tests
 
@@ -113,7 +96,7 @@ Namespaces diff --git a/_testing_server_8cs_source.html b/_testing_server_8cs_source.html index 9ec8932778..62ae7a4d04 100644 --- a/_testing_server_8cs_source.html +++ b/_testing_server_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Tests/TestingServer.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestingServer.cs
-Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.Collections.Generic;
4 using System.Globalization;
5 using System.IO;
6 using System.Threading;
7 using System.Threading.Tasks;
8 using Tgstation.Server.Host;
10 
11 namespace Tgstation.Server.Tests
12 {
13  sealed class TestingServer : IServer
14  {
15  public Uri Url { get; }
16 
17  public string Directory { get; }
18  public bool RestartRequested => realServer.RestartRequested;
19 
20  readonly IServer realServer;
21 
22  public TestingServer(string updatePath)
23  {
24  Directory = Path.GetTempFileName();
25  File.Delete(Directory);
26  System.IO.Directory.CreateDirectory(Directory);
27  Url = new Uri("http://localhost:5001");
28 
29  //so we need a db
30  //we have to rely on env vars
31  var databaseType = Environment.GetEnvironmentVariable("TGS4_TEST_DATABASE_TYPE");
32  var connectionString = Environment.GetEnvironmentVariable("TGS4_TEST_CONNECTION_STRING");
33  var gitHubAccessToken = Environment.GetEnvironmentVariable("TGS4_TEST_GITHUB_TOKEN");
34 
35  if (String.IsNullOrEmpty(databaseType))
36  Assert.Inconclusive("No database type configured in env var TGS4_TEST_DATABASE_TYPE!");
37 
38  if (String.IsNullOrEmpty(connectionString))
39  Assert.Inconclusive("No connection string configured in env var TGS4_TEST_CONNECTION_STRING!");
40 
41  if (String.IsNullOrEmpty(gitHubAccessToken))
42  Console.WriteLine("WARNING: No GitHub access token configured, test may fail due to rate limits!");
43 
44  var args = new List<string>()
45  {
46  String.Format(CultureInfo.InvariantCulture, "Kestrel:EndPoints:Http:Url={0}", Url),
47  String.Format(CultureInfo.InvariantCulture, "Database:DatabaseType={0}", databaseType),
48  String.Format(CultureInfo.InvariantCulture, "Database:ConnectionString={0}", connectionString),
49  String.Format(CultureInfo.InvariantCulture, "Database:DropDatabase={0}", true),
50  String.Format(CultureInfo.InvariantCulture, "General:SetupWizardMode={0}", SetupWizardMode.Never)
51  };
52 
53  if (!String.IsNullOrEmpty(gitHubAccessToken))
54  args.Add(String.Format(CultureInfo.InvariantCulture, "General:GitHubAccessToken={0}", gitHubAccessToken));
55 
56  realServer = new ServerFactory().CreateServer(args.ToArray(), updatePath);
57  }
58 
59  public void Dispose()
60  {
61  System.IO.Directory.Delete(Directory, true);
62  }
63 
64  public Task RunAsync(CancellationToken cancellationToken) => realServer.RunAsync(cancellationToken);
65  }
66 }
bool RestartRequested
If the IServer should restart
Definition: IServer.cs:14
-
SetupWizardMode
Determines if the Core.ISetupWizard will run
+Go to the documentation of this file.
1 using Microsoft.VisualStudio.TestTools.UnitTesting;
2 using System;
3 using System.Collections.Generic;
4 using System.Globalization;
5 using System.IO;
6 using System.Threading;
7 using System.Threading.Tasks;
8 using Tgstation.Server.Host;
10 
11 namespace Tgstation.Server.Tests
12 {
13  sealed class TestingServer : IServer
14  {
15  public Uri Url { get; }
16 
17  public string Directory { get; }
19 
20  readonly IServer realServer;
21 
22  public TestingServer(string updatePath)
23  {
24  Directory = Path.GetTempFileName();
25  File.Delete(Directory);
26  System.IO.Directory.CreateDirectory(Directory);
27  Url = new Uri("http://localhost:5001");
28 
29  //so we need a db
30  //we have to rely on env vars
31  var databaseType = Environment.GetEnvironmentVariable("TGS4_TEST_DATABASE_TYPE");
32  var connectionString = Environment.GetEnvironmentVariable("TGS4_TEST_CONNECTION_STRING");
33  var gitHubAccessToken = Environment.GetEnvironmentVariable("TGS4_TEST_GITHUB_TOKEN");
34 
35  if (String.IsNullOrEmpty(databaseType))
36  Assert.Inconclusive("No database type configured in env var TGS4_TEST_DATABASE_TYPE!");
37 
38  if (String.IsNullOrEmpty(connectionString))
39  Assert.Inconclusive("No connection string configured in env var TGS4_TEST_CONNECTION_STRING!");
40 
41  if (String.IsNullOrEmpty(gitHubAccessToken))
42  Console.WriteLine("WARNING: No GitHub access token configured, test may fail due to rate limits!");
43 
44  var args = new List<string>()
45  {
46  String.Format(CultureInfo.InvariantCulture, "Kestrel:EndPoints:Http:Url={0}", Url),
47  String.Format(CultureInfo.InvariantCulture, "Database:DatabaseType={0}", databaseType),
48  String.Format(CultureInfo.InvariantCulture, "Database:ConnectionString={0}", connectionString),
49  String.Format(CultureInfo.InvariantCulture, "Database:DropDatabase={0}", true),
50  String.Format(CultureInfo.InvariantCulture, "General:SetupWizardMode={0}", SetupWizardMode.Never)
51  };
52 
53  if (!String.IsNullOrEmpty(gitHubAccessToken))
54  args.Add(String.Format(CultureInfo.InvariantCulture, "General:GitHubAccessToken={0}", gitHubAccessToken));
55 
56  realServer = new ServerFactory().CreateServer(args.ToArray(), updatePath);
57  }
58 
59  public void Dispose()
60  {
61  System.IO.Directory.Delete(Directory, true);
62  }
63 
64  public Task RunAsync(CancellationToken cancellationToken) => realServer.RunAsync(cancellationToken);
65  }
66 }
bool RestartRequested
If the IServer should restart
Definition: IServer.cs:14
+ +
SetupWizardMode
Determines if the Core.ISetupWizard will run
- -
Represents the host
Definition: IServer.cs:9
+ + +
Represents the host
Definition: IServer.cs:9
-
IServer CreateServer(string[] args, string updatePath)
Create a IServer
+
Task RunAsync(CancellationToken cancellationToken)
Runs the IServer
+
IServer CreateServer(string[] args, string updatePath)
Create a IServer
+
Task RunAsync(CancellationToken cancellationToken)
Runs the IServer
- - - - + + + +
diff --git a/_tgs_authorize_attribute_8cs.html b/_tgs_authorize_attribute_8cs.html index b8dd3082a2..4a7d58412d 100644 --- a/_tgs_authorize_attribute_8cs.html +++ b/_tgs_authorize_attribute_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/TgsAuthorizeAttribute.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Controllers
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_tgs_authorize_attribute_8cs_source.html b/_tgs_authorize_attribute_8cs_source.html index df5c1a3043..e77408f812 100644 --- a/_tgs_authorize_attribute_8cs_source.html +++ b/_tgs_authorize_attribute_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/TgsAuthorizeAttribute.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TgsAuthorizeAttribute.cs
-Go to the documentation of this file.
1 using System;
2 using Microsoft.AspNetCore.Authorization;
4 
5 namespace Tgstation.Server.Host.Controllers
6 {
10  #pragma warning disable CA1019
11  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
13  {
17  public TgsAuthorizeAttribute() { }
18 
24  {
25  Roles = RightsHelper.RoleNames(requiredRights);
26  }
27 
33  {
34  Roles = RightsHelper.RoleNames(requiredRights);
35  }
36 
41  public TgsAuthorizeAttribute(RepositoryRights requiredRights)
42  {
43  Roles = RightsHelper.RoleNames(requiredRights);
44  }
45 
50  public TgsAuthorizeAttribute(ByondRights requiredRights)
51  {
52  Roles = RightsHelper.RoleNames(requiredRights);
53  }
54 
59  public TgsAuthorizeAttribute(DreamMakerRights requiredRights)
60  {
61  Roles = RightsHelper.RoleNames(requiredRights);
62  }
63 
69  {
70  Roles = RightsHelper.RoleNames(requiredRights);
71  }
72 
77  public TgsAuthorizeAttribute(ChatBotRights requiredRights)
78  {
79  Roles = RightsHelper.RoleNames(requiredRights);
80  }
81 
87  {
88  Roles = RightsHelper.RoleNames(requiredRights);
89  }
90 
96  {
97  Roles = RightsHelper.RoleNames(requiredRights);
98  }
99  }
100 }
ConfigurationRights
Rights for Models.ConfigurationFile
- -
ByondRights
Rights for Models.Byond
Definition: ByondRights.cs:9
+Go to the documentation of this file.
1 using System;
2 using Microsoft.AspNetCore.Authorization;
4 
6 {
10  #pragma warning disable CA1019
11  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
13  {
17  public TgsAuthorizeAttribute() { }
18 
24  {
25  Roles = RightsHelper.RoleNames(requiredRights);
26  }
27 
33  {
34  Roles = RightsHelper.RoleNames(requiredRights);
35  }
36 
41  public TgsAuthorizeAttribute(RepositoryRights requiredRights)
42  {
43  Roles = RightsHelper.RoleNames(requiredRights);
44  }
45 
50  public TgsAuthorizeAttribute(ByondRights requiredRights)
51  {
52  Roles = RightsHelper.RoleNames(requiredRights);
53  }
54 
59  public TgsAuthorizeAttribute(DreamMakerRights requiredRights)
60  {
61  Roles = RightsHelper.RoleNames(requiredRights);
62  }
63 
69  {
70  Roles = RightsHelper.RoleNames(requiredRights);
71  }
72 
77  public TgsAuthorizeAttribute(ChatBotRights requiredRights)
78  {
79  Roles = RightsHelper.RoleNames(requiredRights);
80  }
81 
87  {
88  Roles = RightsHelper.RoleNames(requiredRights);
89  }
90 
96  {
97  Roles = RightsHelper.RoleNames(requiredRights);
98  }
99  }
100 }
ConfigurationRights
Rights for Models.ConfigurationFile
+ + +
ByondRights
Rights for Models.Byond
Definition: ByondRights.cs:9
-
InstanceUserRights
Rights for an Models.Instance
- -
TgsAuthorizeAttribute(ByondRights requiredRights)
Construct a TgsAuthorizeAttribute for ByondRights
-
Helper for using the AuthorizeAttribute with the Api.Rights system
- -
TgsAuthorizeAttribute(InstanceManagerRights requiredRights)
Construct a TgsAuthorizeAttribute for InstanceManagerRights
-
AdministrationRights
Rights for Models.Administration
- -
DreamDaemonRights
Rights for Models.DreamDaemon
-
InstanceManagerRights
Rights for managing Models.Instances
-
TgsAuthorizeAttribute(AdministrationRights requiredRights)
Construct a TgsAuthorizeAttribute for AdministrationRights
-
DreamMakerRights
Rights for Models.DreamMaker
-
TgsAuthorizeAttribute(ConfigurationRights requiredRights)
Construct a TgsAuthorizeAttribute for ConfigurationRights
-
TgsAuthorizeAttribute(DreamMakerRights requiredRights)
Construct a TgsAuthorizeAttribute for DreamMakerRights
-
RepositoryRights
Rights for a Models.Repository
-
TgsAuthorizeAttribute(InstanceUserRights requiredRights)
Construct a TgsAuthorizeAttribute for InstanceUserRights
+
InstanceUserRights
Rights for an Models.Instance
+
TgsAuthorizeAttribute(ByondRights requiredRights)
Construct a TgsAuthorizeAttribute for ByondRights
+
Helper for using the AuthorizeAttribute with the Api.Rights system
+
TgsAuthorizeAttribute(InstanceManagerRights requiredRights)
Construct a TgsAuthorizeAttribute for InstanceManagerRights
+
AdministrationRights
Rights for Models.Administration
+ +
DreamDaemonRights
Rights for Models.DreamDaemon
+
InstanceManagerRights
Rights for managing Models.Instances
+
TgsAuthorizeAttribute(AdministrationRights requiredRights)
Construct a TgsAuthorizeAttribute for AdministrationRights
+
DreamMakerRights
Rights for Models.DreamMaker
+
TgsAuthorizeAttribute(ConfigurationRights requiredRights)
Construct a TgsAuthorizeAttribute for ConfigurationRights
+
TgsAuthorizeAttribute(DreamMakerRights requiredRights)
Construct a TgsAuthorizeAttribute for DreamMakerRights
+
RepositoryRights
Rights for a Models.Repository
+
TgsAuthorizeAttribute(InstanceUserRights requiredRights)
Construct a TgsAuthorizeAttribute for InstanceUserRights
- -
TgsAuthorizeAttribute(RepositoryRights requiredRights)
Construct a TgsAuthorizeAttribute for RepositoryRights
-
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
-
TgsAuthorizeAttribute(ChatBotRights requiredRights)
Construct a TgsAuthorizeAttribute for ChatBotRights
+ +
TgsAuthorizeAttribute(RepositoryRights requiredRights)
Construct a TgsAuthorizeAttribute for RepositoryRights
+
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
+
TgsAuthorizeAttribute(ChatBotRights requiredRights)
Construct a TgsAuthorizeAttribute for ChatBotRights
-
TgsAuthorizeAttribute(DreamDaemonRights requiredRights)
Construct a TgsAuthorizeAttribute for DreamDaemonRights
- +
TgsAuthorizeAttribute(DreamDaemonRights requiredRights)
Construct a TgsAuthorizeAttribute for DreamDaemonRights
+
diff --git a/_tgstation_8_server_8_api_2_models_2_chat_bot_8cs.html b/_tgstation_8_server_8_api_2_models_2_chat_bot_8cs.html index 89b48d6a9b..7f3e61e772 100644 --- a/_tgstation_8_server_8_api_2_models_2_chat_bot_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_chat_bot_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/ChatBot.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_chat_bot_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_chat_bot_8cs_source.html index f623054d72..d2ed5e11d0 100644 --- a/_tgstation_8_server_8_api_2_models_2_chat_bot_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_chat_bot_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/ChatBot.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ChatBot.cs
-Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 
5 namespace Tgstation.Server.Api.Models
6 {
8  public sealed class ChatBot : Internal.ChatBot
9  {
13  public List<ChatChannel> Channels { get; set; }
14 
20  {
21  switch (Provider)
22  {
23  case ChatProvider.Discord:
24  return Channels?.Select(x => x.DiscordChannelId.HasValue && x.IrcChannel == null).All(x => x) ?? true;
25  case ChatProvider.Irc:
26  return Channels?.Select(x => !x.DiscordChannelId.HasValue && x.IrcChannel != null).All(x => x) ?? true;
27  default:
28  throw new InvalidOperationException("Invalid provider type!");
29  }
30  }
31  }
32 }
- +Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 
6 {
8  public sealed class ChatBot : Internal.ChatBot
9  {
13  public List<ChatChannel> Channels { get; set; }
14 
20  {
21  switch (Provider)
22  {
23  case ChatProvider.Discord:
24  return Channels?.Select(x => x.DiscordChannelId.HasValue && x.IrcChannel == null).All(x => x) ?? true;
25  case ChatProvider.Irc:
26  return Channels?.Select(x => !x.DiscordChannelId.HasValue && x.IrcChannel != null).All(x => x) ?? true;
27  default:
28  throw new InvalidOperationException("Invalid provider type!");
29  }
30  }
31  }
32 }
List< ChatChannel > Channels
Channels the Discord bot should listen/announce in
Definition: ChatBot.cs:13
+ -
bool ValidateProviderChannelTypes()
Validates Channels are correct for the Internal.ChatBot.Provider
Definition: ChatBot.cs:19
-
ChatProvider
Represents a chat service provider
Definition: ChatProvider.cs:6
- +
bool ValidateProviderChannelTypes()
Validates Channels are correct for the Internal.ChatBot.Provider
Definition: ChatBot.cs:19
+
ChatProvider
Represents a chat service provider
Definition: ChatProvider.cs:6
+
ChatProvider? Provider
The ChatProvider used for the connection
Definition: ChatBot.cs:30
diff --git a/_tgstation_8_server_8_api_2_models_2_chat_channel_8cs.html b/_tgstation_8_server_8_api_2_models_2_chat_channel_8cs.html index cd23f74b0d..5c3118e873 100644 --- a/_tgstation_8_server_8_api_2_models_2_chat_channel_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_chat_channel_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/ChatChannel.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_chat_channel_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_chat_channel_8cs_source.html index 5b842d78c3..c9bb8fdbb0 100644 --- a/_tgstation_8_server_8_api_2_models_2_chat_channel_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_chat_channel_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/ChatChannel.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ChatChannel.cs
-Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
3 namespace Tgstation.Server.Api.Models
4 {
8  public class ChatChannel
9  {
13  public string IrcChannel { get; set; }
14 
18  public ulong? DiscordChannelId { get; set; }
19 
23  [Required]
24  public bool? IsAdminChannel { get; set; }
25 
29  [Required]
30  public bool? IsWatchdogChannel { get; set; }
31 
35  [Required]
36  public bool? IsUpdatesChannel { get; set; }
37 
41  public string Tag { get; set; }
42  }
43 }
Indicates a chat channel
Definition: ChatChannel.cs:8
- - - +Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
4 {
8  public class ChatChannel
9  {
13  public string IrcChannel { get; set; }
14 
18  public ulong? DiscordChannelId { get; set; }
19 
23  [Required]
24  public bool? IsAdminChannel { get; set; }
25 
29  [Required]
30  public bool? IsWatchdogChannel { get; set; }
31 
35  [Required]
36  public bool? IsUpdatesChannel { get; set; }
37 
41  public string Tag { get; set; }
42  }
43 }
+ +
string IrcChannel
The IRC channel name
Definition: ChatChannel.cs:13
+
string Tag
A custom tag users can define to group channels together
Definition: ChatChannel.cs:41
+
bool? IsAdminChannel
If the ChatChannel is an admin channel
Definition: ChatChannel.cs:24
+
ulong? DiscordChannelId
The Discord channel ID
Definition: ChatChannel.cs:18
+
bool? IsUpdatesChannel
If the ChatChannel is an updates channel
Definition: ChatChannel.cs:36
+
bool? IsWatchdogChannel
If the ChatChannel is a watchdog channel
Definition: ChatChannel.cs:30
diff --git a/_tgstation_8_server_8_api_2_models_2_compile_job_8cs.html b/_tgstation_8_server_8_api_2_models_2_compile_job_8cs.html index 410162ed76..d7c3c77eb2 100644 --- a/_tgstation_8_server_8_api_2_models_2_compile_job_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_compile_job_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/CompileJob.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_compile_job_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_compile_job_8cs_source.html index 271511987e..490e501b5b 100644 --- a/_tgstation_8_server_8_api_2_models_2_compile_job_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_compile_job_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/CompileJob.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
CompileJob.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Api.Models
4 {
6  public sealed class CompileJob : Internal.CompileJob
7  {
11  public Job Job { get; set; }
12 
17 
21  public Version ByondVersion { get; set; }
22  }
23 }
- - +Go to the documentation of this file.
1 using System;
2 
4 {
6  public sealed class CompileJob : Internal.CompileJob
7  {
11  public Job Job { get; set; }
12 
17 
21  public Version ByondVersion { get; set; }
22  }
23 }
+ +
Version ByondVersion
The Byond.Version the CompileJob was made with
Definition: CompileJob.cs:21
- -
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job ...
Definition: Job.cs:6
+
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job
Definition: Job.cs:6
diff --git a/_tgstation_8_server_8_api_2_models_2_dream_maker_8cs.html b/_tgstation_8_server_8_api_2_models_2_dream_maker_8cs.html index 8870d37bc1..9af435521a 100644 --- a/_tgstation_8_server_8_api_2_models_2_dream_maker_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_dream_maker_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/DreamMaker.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Api.Models.DreamMaker - Represents the state of the DreamMaker compiler. Create action starts a new compile. Delete action cancels the current compile More...
+ Represents the state of the DreamMaker compiler. Create action starts a new compile. Delete action cancels the current compile More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_dream_maker_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_dream_maker_8cs_source.html index 259eebb940..e967d71702 100644 --- a/_tgstation_8_server_8_api_2_models_2_dream_maker_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_dream_maker_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/DreamMaker.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
DreamMaker.cs
-Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
3 namespace Tgstation.Server.Api.Models
4 {
8  public class DreamMaker
9  {
13  public string ProjectName { get; set; }
14 
18  [Required]
19  public ushort? ApiValidationPort { get; set; }
20 
24  [Required]
25  public DreamDaemonSecurity? ApiValidationSecurityLevel { get; set; }
26  }
27 }
Represents the state of the DreamMaker compiler. Create action starts a new compile. Delete action cancels the current compile
Definition: DreamMaker.cs:8
- - -
DreamDaemonSecurity
DreamDaemon&#39;s security level
- +Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
4 {
8  public class DreamMaker
9  {
13  public string ProjectName { get; set; }
14 
18  [Required]
19  public ushort? ApiValidationPort { get; set; }
20 
24  [Required]
26  }
27 }
Represents the state of the DreamMaker compiler. Create action starts a new compile....
Definition: DreamMaker.cs:8
+
ushort? ApiValidationPort
The port used during compilation to validate the DMAPI
Definition: DreamMaker.cs:19
+ +
string ProjectName
The .dme file DreamMaker tries to compile with without the extension
Definition: DreamMaker.cs:13
+
DreamDaemonSecurity? ApiValidationSecurityLevel
The DreamDaemonSecurity level used to validate the DMAPI
Definition: DreamMaker.cs:25
+
DreamDaemonSecurity
DreamDaemon's security level
diff --git a/_tgstation_8_server_8_api_2_models_2_instance_8cs.html b/_tgstation_8_server_8_api_2_models_2_instance_8cs.html index 68d354c1f4..9ac5867956 100644 --- a/_tgstation_8_server_8_api_2_models_2_instance_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_instance_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Instance.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_instance_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_instance_8cs_source.html index 580d83b288..986448e87d 100644 --- a/_tgstation_8_server_8_api_2_models_2_instance_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_instance_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Instance.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Instance.cs
-Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 using System.ComponentModel.DataAnnotations.Schema;
3 
4 namespace Tgstation.Server.Api.Models
5 {
9  public class Instance
10  {
14  public long Id { get; set; }
15 
19  [Required]
20  public string Name { get; set; }
21 
25  [Required]
26  public string Path { get; set; }
27 
31  [Required]
32  public bool? Online { get; set; }
33 
37  [Required]
38  public ConfigurationType? ConfigurationType { get; set; }
39 
43  [Required]
44  public uint? AutoUpdateInterval { get; set; }
45 
50  [NotMapped]
51  public Job MoveJob { get; set; }
52 
57  public Instance CloneMetadata() => new Instance
58  {
59  Id = Id,
60  Name = Name,
61  Path = Path,
62  Online = Online,
64  AutoUpdateInterval = AutoUpdateInterval
65  };
66  }
67 }
- -
ConfigurationType
The type of configuration allowed on an Instance
-
Metadata about a server instance
Definition: Instance.cs:9
- - -
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job ...
Definition: Job.cs:6
+Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 using System.ComponentModel.DataAnnotations.Schema;
3 
5 {
9  public class Instance
10  {
14  public long Id { get; set; }
15 
19  [Required]
20  public string Name { get; set; }
21 
25  [Required]
26  public string Path { get; set; }
27 
31  [Required]
32  public bool? Online { get; set; }
33 
37  [Required]
38  public ConfigurationType? ConfigurationType { get; set; }
39 
43  [Required]
44  public uint? AutoUpdateInterval { get; set; }
45 
50  [NotMapped]
51  public Job MoveJob { get; set; }
52 
57  public Instance CloneMetadata() => new Instance
58  {
59  Id = Id,
60  Name = Name,
61  Path = Path,
62  Online = Online,
65  };
66  }
67 }
ConfigurationType
The type of configuration allowed on an Instance
+ +
string Path
The path to where the Instance is located. Can only be changed while the Instance is offline....
Definition: Instance.cs:26
+
string Name
The name of the Instance
Definition: Instance.cs:20
+
Instance CloneMetadata()
Create a clone of the essential Instance metadata
+
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
+
ConfigurationType? ConfigurationType
If ConfigurationFile can be used on the Instance
Definition: Instance.cs:38
+
Metadata about a server instance
Definition: Instance.cs:9
+
uint? AutoUpdateInterval
The time interval in minutes the repository is automatically pulled and compiles. 0 disables
Definition: Instance.cs:44
+
Job MoveJob
The Job representing a change of Path
Definition: Instance.cs:51
+
bool? Online
If the Instance is online
Definition: Instance.cs:32
+
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job
Definition: Job.cs:6
diff --git a/_tgstation_8_server_8_api_2_models_2_instance_user_8cs.html b/_tgstation_8_server_8_api_2_models_2_instance_user_8cs.html index d55c5a7f7b..67a554a2e8 100644 --- a/_tgstation_8_server_8_api_2_models_2_instance_user_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_instance_user_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/InstanceUser.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Api.Models.InstanceUser - Represents a Users permissions in an Instance More...
+ Represents a Users permissions in an Instance More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_instance_user_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_instance_user_8cs_source.html index 0163c9b558..7d5cc24f7b 100644 --- a/_tgstation_8_server_8_api_2_models_2_instance_user_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_instance_user_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/InstanceUser.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
InstanceUser.cs
-Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
3 
4 namespace Tgstation.Server.Api.Models
5 {
9  public class InstanceUser
10  {
14  [Required]
15  public long? UserId { get; set; }
16 
20  [Required]
21  public InstanceUserRights? InstanceUserRights { get; set; }
22 
26  [Required]
27  public ByondRights? ByondRights { get; set; }
28 
32  [Required]
33  public DreamDaemonRights? DreamDaemonRights { get; set; }
34 
38  [Required]
39  public DreamMakerRights? DreamMakerRights { get; set; }
40 
44  [Required]
45  public RepositoryRights? RepositoryRights { get; set; }
46 
50  [Required]
51  public ChatBotRights? ChatBotRights { get; set; }
52 
56  [Required]
58  }
59 }
ConfigurationRights
Rights for Models.ConfigurationFile
-
ByondRights
Rights for Models.Byond
Definition: ByondRights.cs:9
+Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
3 
5 {
9  public class InstanceUser
10  {
14  [Required]
15  public long? UserId { get; set; }
16 
20  [Required]
21  public InstanceUserRights? InstanceUserRights { get; set; }
22 
26  [Required]
27  public ByondRights? ByondRights { get; set; }
28 
32  [Required]
33  public DreamDaemonRights? DreamDaemonRights { get; set; }
34 
38  [Required]
39  public DreamMakerRights? DreamMakerRights { get; set; }
40 
44  [Required]
45  public RepositoryRights? RepositoryRights { get; set; }
46 
50  [Required]
51  public ChatBotRights? ChatBotRights { get; set; }
52 
56  [Required]
58  }
59 }
ConfigurationRights
Rights for Models.ConfigurationFile
+
long? UserId
The Internal.User.Id of the User the InstanceUser belongs to
Definition: InstanceUser.cs:15
+
ByondRights
Rights for Models.Byond
Definition: ByondRights.cs:9
-
InstanceUserRights
Rights for an Models.Instance
- - -
DreamDaemonRights
Rights for Models.DreamDaemon
-
Represents a Users permissions in an Instance
Definition: InstanceUser.cs:9
-
DreamMakerRights
Rights for Models.DreamMaker
-
RepositoryRights
Rights for a Models.Repository
+
InstanceUserRights
Rights for an Models.Instance
+ +
DreamDaemonRights
Rights for Models.DreamDaemon
+
Represents a Users permissions in an Instance
Definition: InstanceUser.cs:9
+
DreamMakerRights
Rights for Models.DreamMaker
+
RepositoryRights
Rights for a Models.Repository
- -
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
- + +
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
+
diff --git a/_tgstation_8_server_8_api_2_models_2_internal_2_chat_bot_8cs.html b/_tgstation_8_server_8_api_2_models_2_internal_2_chat_bot_8cs.html index c4d532b79d..b5d2412fe9 100644 --- a/_tgstation_8_server_8_api_2_models_2_internal_2_chat_bot_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_internal_2_chat_bot_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/ChatBot.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
namespace  Tgstation.Server.Api.Models.Internal
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_internal_2_chat_bot_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_internal_2_chat_bot_8cs_source.html index e3dd82762d..e85795bd26 100644 --- a/_tgstation_8_server_8_api_2_models_2_internal_2_chat_bot_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_internal_2_chat_bot_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/ChatBot.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ChatBot.cs
-Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
3 using System.ComponentModel.DataAnnotations.Schema;
4 
5 namespace Tgstation.Server.Api.Models.Internal
6 {
10  public class ChatBot
11  {
15  public long Id { get; set; }
16 
20  [Required]
21  public string Name { get; set; }
22 
26  public bool? Enabled { get; set; }
27 
31  public ChatProvider? Provider { get; set; }
32 
36  [Required]
37  public string ConnectionString { get; set; }
38 
42  [NotMapped]
43  public ChatConnectionStringBuilder ConnectionStringBuilder
44  {
45  get
46  {
47  if (ConnectionString == null)
48  return null;
49  switch (Provider)
50  {
51  case ChatProvider.Discord:
52  return new DiscordConnectionStringBuilder(ConnectionString);
53  case ChatProvider.Irc:
54  return new IrcConnectionStringBuilder(ConnectionString);
55  default:
56  throw new InvalidOperationException("Invalid Provider!");
57  }
58  }
59  set
60  {
61  if (value?.Valid == false)
62  throw new InvalidOperationException("Cannot set invalid ChatConnectionStringBuilder!");
63  ConnectionString = value?.ToString();
64  }
65  }
66  }
67 }
- -
ChatConnectionStringBuilder for ChatProvider.Discord
-
Manage the server chat bots
Definition: ChatBot.cs:10
- -
ChatConnectionStringBuilder for ChatProvider.Irc
-
ChatProvider
Represents a chat service provider
Definition: ChatProvider.cs:6
- +Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
3 
5 {
9  public class ChatBot
10  {
14  public long Id { get; set; }
15 
19  [Required]
20  public string Name { get; set; }
21 
25  public bool? Enabled { get; set; }
26 
30  public ChatProvider? Provider { get; set; }
31 
35  [Required]
36  public string ConnectionString { get; set; }
37 
43  {
44  if (ConnectionString == null)
45  return null;
46  switch (Provider)
47  {
48  case ChatProvider.Discord:
50  case ChatProvider.Irc:
52  default:
53  throw new InvalidOperationException("Invalid Provider!");
54  }
55  }
56 
62  {
63  ConnectionString = stringBuilder?.ToString();
64  }
65  }
66 }
abstract override string ToString()
Gets the ChatBot.ConnectionString associated with the ChatConnectionStringBuilder
+
ChatConnectionStringBuilder for ChatProvider.Discord
+
Manage the server chat bots
Definition: ChatBot.cs:9
+ +
string ConnectionString
The information used to connect to the Provider
Definition: ChatBot.cs:36
+
bool? Enabled
If the connection is enabled
Definition: ChatBot.cs:25
+ + +
ChatConnectionStringBuilder CreateConnectionStringBuilder()
Get the ChatConnectionStringBuilder which maps to the ConnectionString.
Definition: ChatBot.cs:42
+
ChatConnectionStringBuilder for ChatProvider.Irc
+
ChatProvider
Represents a chat service provider
Definition: ChatProvider.cs:6
+
void SetConnectionStringBuilder(ChatConnectionStringBuilder stringBuilder)
Set the ChatConnectionStringBuilder for the ChatBot. Also updates the ConnectionString.
Definition: ChatBot.cs:61
+
ChatProvider? Provider
The ChatProvider used for the connection
Definition: ChatBot.cs:30
+
string Name
The name of the connection
Definition: ChatBot.cs:20
diff --git a/_tgstation_8_server_8_api_2_models_2_internal_2_compile_job_8cs.html b/_tgstation_8_server_8_api_2_models_2_internal_2_compile_job_8cs.html index 958db397b3..5e606763f2 100644 --- a/_tgstation_8_server_8_api_2_models_2_internal_2_compile_job_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_internal_2_compile_job_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/CompileJob.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Api.Models.Internal.CompileJob - Represents a run of DreamMaker More...
+ Represents a run of DreamMaker More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
namespace  Tgstation.Server.Api.Models.Internal
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_internal_2_compile_job_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_internal_2_compile_job_8cs_source.html index 6a44e5d9f1..b671f0e79e 100644 --- a/_tgstation_8_server_8_api_2_models_2_internal_2_compile_job_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_internal_2_compile_job_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/CompileJob.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
CompileJob.cs
-Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
3 
4 namespace Tgstation.Server.Api.Models.Internal
5 {
9  public class CompileJob
10  {
14  public long Id { get; set; }
15 
19  [Required]
20  public string DmeName { get; set; }
21 
25  [Required]
26  public string Output { get; set; }
27 
31  [Required]
32  public Guid? DirectoryName { get; set; }
33 
37  [Required]
38  public DreamDaemonSecurity? MinimumSecurityLevel { get; set; }
39  }
40 }
- -
Represents a run of DreamMaker
Definition: CompileJob.cs:9
-
DreamDaemonSecurity
DreamDaemon&#39;s security level
- +Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
3 
5 {
9  public class CompileJob
10  {
14  public long Id { get; set; }
15 
19  [Required]
20  public string DmeName { get; set; }
21 
25  [Required]
26  public string Output { get; set; }
27 
31  [Required]
32  public Guid? DirectoryName { get; set; }
33 
37  [Required]
39  }
40 }
DreamDaemonSecurity? MinimumSecurityLevel
The minimum DreamDaemonSecurity required to run the CompileJob's output
Definition: CompileJob.cs:38
+ +
string DmeName
The .dme file used for compilation
Definition: CompileJob.cs:20
+
Represents a run of DreamMaker
Definition: CompileJob.cs:9
+
Guid? DirectoryName
The Game folder the results were compiled into
Definition: CompileJob.cs:32
+ + +
DreamDaemonSecurity
DreamDaemon's security level
diff --git a/_tgstation_8_server_8_api_2_models_2_internal_2_dream_daemon_settings_8cs.html b/_tgstation_8_server_8_api_2_models_2_internal_2_dream_daemon_settings_8cs.html index 8919a3883c..4a97d5aaab 100644 --- a/_tgstation_8_server_8_api_2_models_2_internal_2_dream_daemon_settings_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_internal_2_dream_daemon_settings_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/DreamDaemonSettings.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Api.Models.Internal.DreamDaemonSettings - Configurable settings for DreamDaemon More...
+ Configurable settings for DreamDaemon More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
namespace  Tgstation.Server.Api.Models.Internal
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_internal_2_dream_daemon_settings_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_internal_2_dream_daemon_settings_8cs_source.html index 5bce7c5bc7..cf2fb887ff 100644 --- a/_tgstation_8_server_8_api_2_models_2_internal_2_dream_daemon_settings_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_internal_2_dream_daemon_settings_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/DreamDaemonSettings.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
DreamDaemonSettings.cs
-Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
3 namespace Tgstation.Server.Api.Models.Internal
4 {
9  {
13  [Required]
14  public bool? AutoStart { get; set; }
15 
19  [Required]
20  public bool? SoftRestart { get; set; }
21 
25  [Required]
26  public bool? SoftShutdown { get; set; }
27  }
28 }
- - - - +Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
4 {
9  {
13  [Required]
14  public bool? AutoStart { get; set; }
15 
19  [Required]
20  public bool? SoftRestart { get; set; }
21 
25  [Required]
26  public bool? SoftShutdown { get; set; }
27  }
28 }
+
bool? AutoStart
If DreamDaemon starts when it's Instance starts
+ + +
bool? SoftRestart
If the server is undergoing a soft reset. This may be automatically set by changes to other fields
+
bool? SoftShutdown
If the server is undergoing a soft shutdown
diff --git a/_tgstation_8_server_8_api_2_models_2_internal_2_job_8cs.html b/_tgstation_8_server_8_api_2_models_2_internal_2_job_8cs.html index f2a26acda7..1a474223b4 100644 --- a/_tgstation_8_server_8_api_2_models_2_internal_2_job_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_internal_2_job_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/Job.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
namespace  Tgstation.Server.Api.Models.Internal
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_internal_2_job_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_internal_2_job_8cs_source.html index ce9e8f610c..ba795cf310 100644 --- a/_tgstation_8_server_8_api_2_models_2_internal_2_job_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_internal_2_job_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/Job.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Job.cs
-Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
4 
5 namespace Tgstation.Server.Api.Models.Internal
6 {
10  public class Job
11  {
15  public long Id { get; set; }
16 
20  [Required]
21  public string Description { get; set; }
22 
26  public string ExceptionDetails { get; set; }
27 
31  [Required]
32  public DateTimeOffset? StartedAt { get; set; }
33 
37  public DateTimeOffset? StoppedAt { get; set; }
38 
42  [Required]
43  public bool? Cancelled { get; set; }
44 
48  public RightsType? CancelRightsType { get; set; }
49 
53  public ulong? CancelRight { get; set; }
54  }
55 }
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
+Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
4 
6 {
10  public class Job
11  {
15  public long Id { get; set; }
16 
20  [Required]
21  public string Description { get; set; }
22 
26  public string ExceptionDetails { get; set; }
27 
31  [Required]
32  public DateTimeOffset? StartedAt { get; set; }
33 
37  public DateTimeOffset? StoppedAt { get; set; }
38 
42  [Required]
43  public bool? Cancelled { get; set; }
44 
48  public RightsType? CancelRightsType { get; set; }
49 
53  public ulong? CancelRight { get; set; }
54  }
55 }
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
- - -
Represents a long running job
Definition: Job.cs:10
+
string Description
English description of the Job
Definition: Job.cs:21
+
string ExceptionDetails
Details of any exceptions caught during the Job
Definition: Job.cs:26
+
ulong? CancelRight
The Rights required to cancel the Job
Definition: Job.cs:53
+
DateTimeOffset? StoppedAt
When the Job stopped
Definition: Job.cs:37
+
bool? Cancelled
If the Job was cancelled
Definition: Job.cs:43
+
DateTimeOffset? StartedAt
When the Job was started
Definition: Job.cs:32
+
Represents a long running job
Definition: Job.cs:10
+ + - - + +
RightsType? CancelRightsType
The RightsType of CancelRight if it can be cancelled
Definition: Job.cs:48
+
diff --git a/_tgstation_8_server_8_api_2_models_2_internal_2_repository_settings_8cs.html b/_tgstation_8_server_8_api_2_models_2_internal_2_repository_settings_8cs.html index 6ab907dd03..1e32a14119 100644 --- a/_tgstation_8_server_8_api_2_models_2_internal_2_repository_settings_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_internal_2_repository_settings_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/RepositorySettings.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Api.Models.Internal.RepositorySettings - Represents configurable settings for a Repository More...
+ Represents configurable settings for a Repository More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
namespace  Tgstation.Server.Api.Models.Internal
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_internal_2_repository_settings_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_internal_2_repository_settings_8cs_source.html index 8964ae7560..6fc42337fc 100644 --- a/_tgstation_8_server_8_api_2_models_2_internal_2_repository_settings_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_internal_2_repository_settings_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/RepositorySettings.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
RepositorySettings.cs
-Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
3 namespace Tgstation.Server.Api.Models.Internal
4 {
8  public class RepositorySettings
9  {
13  [Required]
14  public string CommitterName { get; set; }
15 
19  [Required]
20  public string CommitterEmail { get; set; }
21 
25  public string AccessUser { get; set; }
26 
30  public string AccessToken { get; set; }
31 
35  [Required]
36  public bool? PushTestMergeCommits { get; set; }
37 
41  [Required]
42  public bool? ShowTestMergeCommitters { get; set; }
43 
47  [Required]
48  public bool? AutoUpdatesKeepTestMerges { get; set; }
49 
53  [Required]
54  public bool? AutoUpdatesSynchronize { get; set; }
55 
59  [Required]
60  public bool? PostTestMergeComment { get; set; }
61  }
62 }
Represents configurable settings for a Repository
- - - +Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
4 {
8  public class RepositorySettings
9  {
13  [Required]
14  public string CommitterName { get; set; }
15 
19  [Required]
20  public string CommitterEmail { get; set; }
21 
25  public string AccessUser { get; set; }
26 
30  public string AccessToken { get; set; }
31 
35  [Required]
36  public bool? PushTestMergeCommits { get; set; }
37 
41  [Required]
42  public bool? ShowTestMergeCommitters { get; set; }
43 
47  [Required]
48  public bool? AutoUpdatesKeepTestMerges { get; set; }
49 
53  [Required]
54  public bool? AutoUpdatesSynchronize { get; set; }
55 
59  [Required]
60  public bool? PostTestMergeComment { get; set; }
61  }
62 }
Represents configurable settings for a Repository
+ +
bool? AutoUpdatesSynchronize
If synchronization should occur when auto updating
+
bool? ShowTestMergeCommitters
If test merge commits are signed with the username of the person who merged it. Note this only affect...
+
bool? AutoUpdatesKeepTestMerges
If test merge commits should be kept when auto updating. May cause merge conflicts which will block t...
+
string AccessUser
The username to access the git repository with
+ +
bool? PushTestMergeCommits
If commits created from testmerges are pushed to the remote
+
bool? PostTestMergeComment
If test merging should create a comment
+ +
string AccessToken
The token/password to access the git repository with
diff --git a/_tgstation_8_server_8_api_2_models_2_internal_2_revision_information_8cs.html b/_tgstation_8_server_8_api_2_models_2_internal_2_revision_information_8cs.html index db9afc6d11..977e82ba0c 100644 --- a/_tgstation_8_server_8_api_2_models_2_internal_2_revision_information_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_internal_2_revision_information_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/RevisionInformation.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
namespace  Tgstation.Server.Api.Models.Internal
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_internal_2_revision_information_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_internal_2_revision_information_8cs_source.html index 7c33abfbec..00533b0aaa 100644 --- a/_tgstation_8_server_8_api_2_models_2_internal_2_revision_information_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_internal_2_revision_information_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/RevisionInformation.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
RevisionInformation.cs
-Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
3 namespace Tgstation.Server.Api.Models.Internal
4 {
8  public class RevisionInformation
9  {
13  [Required]
14  [StringLength(40)]
15  public string CommitSha { get; set; }
16 
20  [Required]
21  [StringLength(40)]
22  public string OriginCommitSha { get; set; }
23  }
24 }
- -
Represents information about a current git revison
- +Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
4 {
8  public class RevisionInformation
9  {
13  [Required]
14  [StringLength(40)]
15  public string CommitSha { get; set; }
16 
20  [Required]
21  [StringLength(40)]
22  public string OriginCommitSha { get; set; }
23  }
24 }
+ +
Represents information about a current git revison
+
string OriginCommitSha
The sha of the most recent remote commit
diff --git a/_tgstation_8_server_8_api_2_models_2_internal_2_test_merge_8cs.html b/_tgstation_8_server_8_api_2_models_2_internal_2_test_merge_8cs.html index 7c275f87b7..5c0bf5befc 100644 --- a/_tgstation_8_server_8_api_2_models_2_internal_2_test_merge_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_internal_2_test_merge_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/TestMerge.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
namespace  Tgstation.Server.Api.Models.Internal
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_internal_2_test_merge_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_internal_2_test_merge_8cs_source.html index 19a405f8d6..abf6015b19 100644 --- a/_tgstation_8_server_8_api_2_models_2_internal_2_test_merge_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_internal_2_test_merge_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/TestMerge.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestMerge.cs
-Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
3 
4 namespace Tgstation.Server.Api.Models.Internal
5 {
9  public class TestMerge : TestMergeBase
10  {
14  public long Id { get; set; }
15 
19  [Required]
20  public DateTimeOffset MergedAt { get; set; }
21  }
22 }
- -
Represents a merge of a GitHub pull request
Definition: TestMerge.cs:9
-
Layer of test merge data required internally
Definition: TestMergeBase.cs:9
- +Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
3 
5 {
9  public class TestMerge : TestMergeBase
10  {
14  public long Id { get; set; }
15 
19  [Required]
20  public DateTimeOffset MergedAt { get; set; }
21  }
22 }
Represents a merge of a GitHub pull request
Definition: TestMerge.cs:9
+
Layer of test merge data required internally
Definition: TestMergeBase.cs:9
+ +
DateTimeOffset MergedAt
When the TestMerge was created
Definition: TestMerge.cs:20
+
diff --git a/_tgstation_8_server_8_api_2_models_2_internal_2_user_8cs.html b/_tgstation_8_server_8_api_2_models_2_internal_2_user_8cs.html index 6eb01d34bc..6b39fc470e 100644 --- a/_tgstation_8_server_8_api_2_models_2_internal_2_user_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_internal_2_user_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/User.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Api.Models.Internal.User - Represents a server User More...
+ Represents a server User More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
namespace  Tgstation.Server.Api.Models.Internal
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_internal_2_user_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_internal_2_user_8cs_source.html index 5be0334d61..e9da7dd4e0 100644 --- a/_tgstation_8_server_8_api_2_models_2_internal_2_user_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_internal_2_user_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Internal/User.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
User.cs
-Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
4 
5 namespace Tgstation.Server.Api.Models.Internal
6 {
10  public class User
11  {
15  public long Id { get; set; }
16 
20  [Required]
21  public bool? Enabled { get; set; }
22 
26  [Required]
27  public DateTimeOffset? CreatedAt { get; set; }
28 
32  public string SystemIdentifier { get; set; }
33 
37  [Required]
38  public string Name { get; set; }
39 
43  [Required]
45 
49  [Required]
51  }
52 }
- -
Represents a server User
Definition: User.cs:10
- -
AdministrationRights
Rights for Models.Administration
-
InstanceManagerRights
Rights for managing Models.Instances
+Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
4 
6 {
10  public class User
11  {
15  public long Id { get; set; }
16 
20  [Required]
21  public bool? Enabled { get; set; }
22 
26  [Required]
27  public DateTimeOffset? CreatedAt { get; set; }
28 
32  public string SystemIdentifier { get; set; }
33 
37  [Required]
38  public string Name { get; set; }
39 
43  [Required]
45 
49  [Required]
51  }
52 }
string Name
The name of the User
Definition: User.cs:38
+ +
Represents a server User
Definition: User.cs:10
+
AdministrationRights
Rights for Models.Administration
+
InstanceManagerRights
Rights for managing Models.Instances
+ - - +
long Id
The ID of the User
Definition: User.cs:15
+
DateTimeOffset? CreatedAt
When the User was created
Definition: User.cs:27
+ +
bool? Enabled
If the User is enabled since users cannot be deleted. System users cannot be disabled
Definition: User.cs:21
+
string SystemIdentifier
The SID/UID of the User on Windows/POSIX respectively
Definition: User.cs:32
+
diff --git a/_tgstation_8_server_8_api_2_models_2_job_8cs.html b/_tgstation_8_server_8_api_2_models_2_job_8cs.html index 09ca059230..33ba04cff4 100644 --- a/_tgstation_8_server_8_api_2_models_2_job_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_job_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Job.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_job_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_job_8cs_source.html index 15455e754c..d849c0b51d 100644 --- a/_tgstation_8_server_8_api_2_models_2_job_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_job_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Job.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Job.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Api.Models
2 {
6  public sealed class Job : Internal.Job
7  {
11  public User StartedBy { get; set; }
12 
16  public User CancelledBy { get; set; }
17 
21  public int? Progress { get; set; }
22  }
23 }
+Go to the documentation of this file.
2 {
6  public sealed class Job : Internal.Job
7  {
11  public User StartedBy { get; set; }
12 
16  public User CancelledBy { get; set; }
17 
21  public int? Progress { get; set; }
22  }
23 }
User CancelledBy
The User that cancelled the job
Definition: Job.cs:16
+ +
int? Progress
Optional progress between 0 and 100 inclusive
Definition: Job.cs:21
- -
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job ...
Definition: Job.cs:6
+
User StartedBy
The User that started the job
Definition: Job.cs:11
+
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job
Definition: Job.cs:6
diff --git a/_tgstation_8_server_8_api_2_models_2_repository_8cs.html b/_tgstation_8_server_8_api_2_models_2_repository_8cs.html index f2a32ac996..92ebe9fd37 100644 --- a/_tgstation_8_server_8_api_2_models_2_repository_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_repository_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Repository.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_repository_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_repository_8cs_source.html index d9da67fef5..b688414f0f 100644 --- a/_tgstation_8_server_8_api_2_models_2_repository_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_repository_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Repository.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Repository.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 
3 namespace Tgstation.Server.Api.Models
4 {
8  public sealed class Repository : Internal.RepositorySettings
9  {
13  public string Origin { get; set; }
14 
18  public string CheckoutSha { get; set; }
19 
24 
28  public string GitHubOwner { get; set; }
29 
33  public string GitHubName { get; set; }
34 
38  public Job ActiveJob { get; set; }
39 
43  public bool? UpdateFromOrigin { get; set; }
44 
48  public string Reference { get; set; }
49 
53  public List<TestMergeParameters> NewTestMerges { get; set; }
54  }
55 }
- -
Represents a git repository
Definition: Repository.cs:8
+Go to the documentation of this file.
1 using System.Collections.Generic;
2 
4 {
8  public sealed class Repository : Internal.RepositorySettings
9  {
13  public string Origin { get; set; }
14 
18  public string CheckoutSha { get; set; }
19 
24 
28  public string GitHubOwner { get; set; }
29 
33  public string GitHubName { get; set; }
34 
38  public Job ActiveJob { get; set; }
39 
43  public bool? UpdateFromOrigin { get; set; }
44 
48  public string Reference { get; set; }
49 
53  public List<TestMergeParameters> NewTestMerges { get; set; }
54  }
55 }
string GitHubOwner
If the repository was cloned from GitHub.com this will be set with the owner of the repository
Definition: Repository.cs:28
+
string CheckoutSha
The commit HEAD should point to. Not populated in responses, use RevisionInformation instead for retr...
Definition: Repository.cs:18
+ +
List< TestMergeParameters > NewTestMerges
TestMergeParameters for new TestMerges. Note that merges that conflict will not be performed
Definition: Repository.cs:53
+
Job ActiveJob
The Job started by the Repository if any
Definition: Repository.cs:38
+
Represents a git repository
Definition: Repository.cs:8
+
string Reference
The branch or tag HEAD points to
Definition: Repository.cs:48
+
string Origin
The origin URL. If null, the Repository does not exist
Definition: Repository.cs:13
+
string GitHubName
If the repository was cloned from GitHub.com this will be set with the name of the repository
Definition: Repository.cs:33
+
bool? UpdateFromOrigin
Do the equivalent of a git pull. Will attempt to merge unless Reference is also specified in which ca...
Definition: Repository.cs:43
- -
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job ...
Definition: Job.cs:6
+
Represents a long running job on the server. Model is read-only, updates attempt to cancel the job
Definition: Job.cs:6
diff --git a/_tgstation_8_server_8_api_2_models_2_revision_information_8cs.html b/_tgstation_8_server_8_api_2_models_2_revision_information_8cs.html index f21a9cae7d..f60aa8e1a4 100644 --- a/_tgstation_8_server_8_api_2_models_2_revision_information_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_revision_information_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/RevisionInformation.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_revision_information_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_revision_information_8cs_source.html index f9ba0b1738..1fc0cc6d92 100644 --- a/_tgstation_8_server_8_api_2_models_2_revision_information_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_revision_information_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/RevisionInformation.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
RevisionInformation.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 
3 namespace Tgstation.Server.Api.Models
4 {
6  public sealed class RevisionInformation : Internal.RevisionInformation
7  {
11  public TestMerge PrimaryTestMerge { get; set; }
12 
16  public List<TestMerge> ActiveTestMerges { get; set; }
17 
21  public List<CompileJob> CompileJobs { get; set; }
22  }
23 }
- - +Go to the documentation of this file.
1 using System.Collections.Generic;
2 
4 {
6  public sealed class RevisionInformation : Internal.RevisionInformation
7  {
11  public TestMerge PrimaryTestMerge { get; set; }
12 
16  public List<TestMerge> ActiveTestMerges { get; set; }
17 
21  public List<CompileJob> CompileJobs { get; set; }
22  }
23 }
List< CompileJob > CompileJobs
The CompileJobs made from the RevisionInformation
+ +
TestMerge PrimaryTestMerge
The TestMerge that was created with this RevisionInformation
+
List< TestMerge > ActiveTestMerges
The TestMerges active in the RevisionInformation
+ -
diff --git a/_tgstation_8_server_8_api_2_models_2_test_merge_8cs.html b/_tgstation_8_server_8_api_2_models_2_test_merge_8cs.html index 965c002f2b..6f45325dee 100644 --- a/_tgstation_8_server_8_api_2_models_2_test_merge_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_test_merge_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/TestMerge.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_test_merge_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_test_merge_8cs_source.html index 2301ae4fd3..a0dcef345a 100644 --- a/_tgstation_8_server_8_api_2_models_2_test_merge_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_test_merge_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/TestMerge.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestMerge.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Api.Models
2 {
4  public sealed class TestMerge : Internal.TestMerge
5  {
9  public User MergedBy { get; set; }
10  }
11 }
- +Go to the documentation of this file.
2 {
4  public sealed class TestMerge : Internal.TestMerge
5  {
9  public User MergedBy { get; set; }
10  }
11 }
+ - +
User MergedBy
The User who created the TestMerge
Definition: TestMerge.cs:9
diff --git a/_tgstation_8_server_8_api_2_models_2_user_8cs.html b/_tgstation_8_server_8_api_2_models_2_user_8cs.html index 439f16b042..d258c53d67 100644 --- a/_tgstation_8_server_8_api_2_models_2_user_8cs.html +++ b/_tgstation_8_server_8_api_2_models_2_user_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/User.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_tgstation_8_server_8_api_2_models_2_user_8cs_source.html b/_tgstation_8_server_8_api_2_models_2_user_8cs_source.html index 57e872a1c0..d516a2ce37 100644 --- a/_tgstation_8_server_8_api_2_models_2_user_8cs_source.html +++ b/_tgstation_8_server_8_api_2_models_2_user_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/User.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
User.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Api.Models
2 {
4  public class User : Internal.User
5  {
9  public const string AdminName = "Admin";
10 
14  public const string DefaultAdminPassword = "ISolemlySwearToDeleteTheDataDirectory";
15 
19  public User CreatedBy { get; set; }
20  }
21 }
+Go to the documentation of this file.
2 {
4  public class User : Internal.User
5  {
9  public const string AdminName = "Admin";
10 
14  public const string DefaultAdminPassword = "ISolemlySwearToDeleteTheDataDirectory";
15 
19  public User CreatedBy { get; set; }
20  }
21 }
const string AdminName
The name of the default admin user
Definition: User.cs:9
+
User CreatedBy
The User who created this User
Definition: User.cs:19
+ +
const string DefaultAdminPassword
The default admin password
Definition: User.cs:14
-
diff --git a/_tgstation_8_server_8_api_8_assembly_info_8cs.html b/_tgstation_8_server_8_api_8_assembly_info_8cs.html index 88fc90fce7..b00c4d90fb 100644 --- a/_tgstation_8_server_8_api_8_assembly_info_8cs.html +++ b/_tgstation_8_server_8_api_8_assembly_info_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Api/obj/Release/netstandard2.0/Tgstation.Server.Api.AssemblyInfo.cs File Reference + + +tgstation-server: src/Tgstation.Server.Api/obj/Debug/netstandard2.0/Tgstation.Server.Api.AssemblyInfo.cs File Reference - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -99,7 +78,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_tgstation_8_server_8_api_8_assembly_info_8cs_source.html b/_tgstation_8_server_8_api_8_assembly_info_8cs_source.html index 0ac5c81d45..6190314e1c 100644 --- a/_tgstation_8_server_8_api_8_assembly_info_8cs_source.html +++ b/_tgstation_8_server_8_api_8_assembly_info_8cs_source.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Api/obj/Release/netstandard2.0/Tgstation.Server.Api.AssemblyInfo.cs Source File + + +tgstation-server: src/Tgstation.Server.Api/obj/Debug/netstandard2.0/Tgstation.Server.Api.AssemblyInfo.cs Source File - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,13 +71,12 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
Tgstation.Server.Api.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("/tg/station")]
15 [assembly: System.Reflection.AssemblyConfigurationAttribute("Release")]
16 [assembly: System.Reflection.AssemblyCopyrightAttribute("2018")]
17 [assembly: System.Reflection.AssemblyDescriptionAttribute("API definitions for tgstation-server")]
18 [assembly: System.Reflection.AssemblyFileVersionAttribute("4.0.2.0")]
19 [assembly: System.Reflection.AssemblyInformationalVersionAttribute("4.0.2.0")]
20 [assembly: System.Reflection.AssemblyProductAttribute("Tgstation.Server.Api")]
21 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Api")]
22 [assembly: System.Reflection.AssemblyVersionAttribute("4.0.2.0")]
23 
24 // Generated by the MSBuild WriteCodeFragment class.
25 
-
+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("/tg/station")]
15 [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
16 [assembly: System.Reflection.AssemblyCopyrightAttribute("2018")]
17 [assembly: System.Reflection.AssemblyDescriptionAttribute("API definitions for tgstation-server")]
18 [assembly: System.Reflection.AssemblyFileVersionAttribute("4.0.2.0")]
19 [assembly: System.Reflection.AssemblyInformationalVersionAttribute("4.0.2")]
20 [assembly: System.Reflection.AssemblyProductAttribute("Tgstation.Server.Api")]
21 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Api")]
22 [assembly: System.Reflection.AssemblyVersionAttribute("4.0.2.0")]
23 
24 // Generated by the MSBuild WriteCodeFragment class.
25 
diff --git a/_tgstation_8_server_8_api_8_tests_8_assembly_info_8cs.html b/_tgstation_8_server_8_api_8_tests_8_assembly_info_8cs.html index 9ee00c17c0..9117eaef1a 100644 --- a/_tgstation_8_server_8_api_8_tests_8_assembly_info_8cs.html +++ b/_tgstation_8_server_8_api_8_tests_8_assembly_info_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Api.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Api.Tests.AssemblyInfo.cs File Reference + + +tgstation-server: tests/Tgstation.Server.Api.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Api.Tests.AssemblyInfo.cs File Reference - @@ -33,41 +31,22 @@ - + - - + + + +
@@ -99,7 +78,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_tgstation_8_server_8_api_8_tests_8_assembly_info_8cs_source.html b/_tgstation_8_server_8_api_8_tests_8_assembly_info_8cs_source.html index f0cb13b64e..9129d1e6ff 100644 --- a/_tgstation_8_server_8_api_8_tests_8_assembly_info_8cs_source.html +++ b/_tgstation_8_server_8_api_8_tests_8_assembly_info_8cs_source.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Api.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Api.Tests.AssemblyInfo.cs Source File + + +tgstation-server: tests/Tgstation.Server.Api.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Api.Tests.AssemblyInfo.cs Source File - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,13 +71,12 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
Tgstation.Server.Api.Tests.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("Tgstation.Server.Api.Tests")]
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("Tgstation.Server.Api.Tests")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Api.Tests")]
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("Tgstation.Server.Api.Tests")]
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("Tgstation.Server.Api.Tests")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Api.Tests")]
20 [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
21 
22 // Generated by the MSBuild WriteCodeFragment class.
23 
diff --git a/_tgstation_8_server_8_api_8_tests_8_program_8cs.html b/_tgstation_8_server_8_api_8_tests_8_program_8cs.html index 3f7bf9e441..8a9302aed4 100644 --- a/_tgstation_8_server_8_api_8_tests_8_program_8cs.html +++ b/_tgstation_8_server_8_api_8_tests_8_program_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Api.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Api.Tests.Program.cs File Reference + + +tgstation-server: tests/Tgstation.Server.Api.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Api.Tests.Program.cs File Reference - @@ -33,41 +31,22 @@ - + - - + + + +
@@ -107,7 +86,7 @@ Classes diff --git a/_tgstation_8_server_8_api_8_tests_8_program_8cs_source.html b/_tgstation_8_server_8_api_8_tests_8_program_8cs_source.html index f735cdd6bf..66b479083e 100644 --- a/_tgstation_8_server_8_api_8_tests_8_program_8cs_source.html +++ b/_tgstation_8_server_8_api_8_tests_8_program_8cs_source.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Api.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Api.Tests.Program.cs Source File + + +tgstation-server: tests/Tgstation.Server.Api.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Api.Tests.Program.cs Source File - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,15 +71,14 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
Tgstation.Server.Api.Tests.Program.cs
-Go to the documentation of this file.
1 // <auto-generated> This file has been auto generated. </auto-generated>
2 using System;
3 [Microsoft.VisualStudio.TestPlatform.TestSDKAutoGeneratedCode]
4 class AutoGeneratedProgram {static void Main(string[] args){}}
- +Go to the documentation of this file.
1 // <auto-generated> This file has been auto generated. </auto-generated>
2 using System;
3 [Microsoft.VisualStudio.TestPlatform.TestSDKAutoGeneratedCode]
4 class AutoGeneratedProgram {static void Main(string[] args){}}
static void Main(string[] args)
diff --git a/src_2_tgstation_8_server_8_client_2_assembly_info_8cs.html b/_tgstation_8_server_8_client_2_assembly_info_8cs.html similarity index 60% rename from src_2_tgstation_8_server_8_client_2_assembly_info_8cs.html rename to _tgstation_8_server_8_client_2_assembly_info_8cs.html index 35298bd0dd..31ce1b5b9b 100644 --- a/src_2_tgstation_8_server_8_client_2_assembly_info_8cs.html +++ b/_tgstation_8_server_8_client_2_assembly_info_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/AssemblyInfo.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
diff --git a/_tgstation_8_server_8_client_2_assembly_info_8cs_source.html b/_tgstation_8_server_8_client_2_assembly_info_8cs_source.html new file mode 100644 index 0000000000..e31cddfdf3 --- /dev/null +++ b/_tgstation_8_server_8_client_2_assembly_info_8cs_source.html @@ -0,0 +1,82 @@ + + + + + + + +tgstation-server: src/Tgstation.Server.Client/AssemblyInfo.cs Source File + + + + + + + + + +
+
+ + + + + + + +
+
tgstation-server +
+
The /tg/station 13 server suite
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
AssemblyInfo.cs
+
+
+Go to the documentation of this file.
1 using System.Runtime.CompilerServices;
2 
3 [assembly: InternalsVisibleTo("Tgstation.Server.Client.Tests")]
4 [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
+ + + + diff --git a/_tgstation_8_server_8_client_8_assembly_info_8cs.html b/_tgstation_8_server_8_client_8_assembly_info_8cs.html index c1b2251f60..cab70e71a0 100644 --- a/_tgstation_8_server_8_client_8_assembly_info_8cs.html +++ b/_tgstation_8_server_8_client_8_assembly_info_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Client/obj/Release/netstandard2.0/Tgstation.Server.Client.AssemblyInfo.cs File Reference + + +tgstation-server: src/Tgstation.Server.Client/obj/Debug/netstandard2.0/Tgstation.Server.Client.AssemblyInfo.cs File Reference - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -99,7 +78,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_tgstation_8_server_8_client_8_assembly_info_8cs_source.html b/_tgstation_8_server_8_client_8_assembly_info_8cs_source.html index 5b9074c139..335e64038e 100644 --- a/_tgstation_8_server_8_client_8_assembly_info_8cs_source.html +++ b/_tgstation_8_server_8_client_8_assembly_info_8cs_source.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Client/obj/Release/netstandard2.0/Tgstation.Server.Client.AssemblyInfo.cs Source File + + +tgstation-server: src/Tgstation.Server.Client/obj/Debug/netstandard2.0/Tgstation.Server.Client.AssemblyInfo.cs Source File - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,13 +71,12 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
Tgstation.Server.Client.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("/tg/station 13")]
15 [assembly: System.Reflection.AssemblyConfigurationAttribute("Release")]
16 [assembly: System.Reflection.AssemblyCopyrightAttribute("2018")]
17 [assembly: System.Reflection.AssemblyDescriptionAttribute("Client library for tgstation-server")]
18 [assembly: System.Reflection.AssemblyFileVersionAttribute("4.0.3.0")]
19 [assembly: System.Reflection.AssemblyInformationalVersionAttribute("4.0.3.0")]
20 [assembly: System.Reflection.AssemblyProductAttribute("Tgstation.Server.Client")]
21 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Client")]
22 [assembly: System.Reflection.AssemblyVersionAttribute("4.0.3.0")]
23 [assembly: System.Resources.NeutralResourcesLanguageAttribute("en-CA")]
24 
25 // Generated by the MSBuild WriteCodeFragment class.
26 
-
+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("/tg/station 13")]
15 [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
16 [assembly: System.Reflection.AssemblyCopyrightAttribute("2018")]
17 [assembly: System.Reflection.AssemblyDescriptionAttribute("Client library for tgstation-server")]
18 [assembly: System.Reflection.AssemblyFileVersionAttribute("4.0.3.0")]
19 [assembly: System.Reflection.AssemblyInformationalVersionAttribute("4.0.3.0")]
20 [assembly: System.Reflection.AssemblyProductAttribute("Tgstation.Server.Client")]
21 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Client")]
22 [assembly: System.Reflection.AssemblyVersionAttribute("4.0.3.0")]
23 [assembly: System.Resources.NeutralResourcesLanguageAttribute("en-CA")]
24 
25 // Generated by the MSBuild WriteCodeFragment class.
26 
diff --git a/_tgstation_8_server_8_client_8_tests_8_assembly_info_8cs.html b/_tgstation_8_server_8_client_8_tests_8_assembly_info_8cs.html index dd6a3e2dae..afa3ebcfa4 100644 --- a/_tgstation_8_server_8_client_8_tests_8_assembly_info_8cs.html +++ b/_tgstation_8_server_8_client_8_tests_8_assembly_info_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Client.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Client.Tests.AssemblyInfo.cs File Reference + + +tgstation-server: tests/Tgstation.Server.Client.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Client.Tests.AssemblyInfo.cs File Reference - @@ -33,41 +31,22 @@ - + - - + + + +
@@ -99,7 +78,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_tgstation_8_server_8_client_8_tests_8_assembly_info_8cs_source.html b/_tgstation_8_server_8_client_8_tests_8_assembly_info_8cs_source.html index 3eef0f64ad..aaa765b6a0 100644 --- a/_tgstation_8_server_8_client_8_tests_8_assembly_info_8cs_source.html +++ b/_tgstation_8_server_8_client_8_tests_8_assembly_info_8cs_source.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Client.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Client.Tests.AssemblyInfo.cs Source File + + +tgstation-server: tests/Tgstation.Server.Client.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Client.Tests.AssemblyInfo.cs Source File - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,13 +71,12 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
Tgstation.Server.Client.Tests.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("Tgstation.Server.Client.Tests")]
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("Tgstation.Server.Client.Tests")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Client.Tests")]
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("Tgstation.Server.Client.Tests")]
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("Tgstation.Server.Client.Tests")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Client.Tests")]
20 [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
21 
22 // Generated by the MSBuild WriteCodeFragment class.
23 
diff --git a/_tgstation_8_server_8_client_8_tests_8_program_8cs.html b/_tgstation_8_server_8_client_8_tests_8_program_8cs.html index 85ce55f127..b60afa3af8 100644 --- a/_tgstation_8_server_8_client_8_tests_8_program_8cs.html +++ b/_tgstation_8_server_8_client_8_tests_8_program_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Client.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Client.Tests.Program.cs File Reference + + +tgstation-server: tests/Tgstation.Server.Client.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Client.Tests.Program.cs File Reference - @@ -33,41 +31,22 @@ - + - - + + + +
@@ -107,7 +86,7 @@ Classes diff --git a/_tgstation_8_server_8_client_8_tests_8_program_8cs_source.html b/_tgstation_8_server_8_client_8_tests_8_program_8cs_source.html index 0bb889fa5e..b40386a6c6 100644 --- a/_tgstation_8_server_8_client_8_tests_8_program_8cs_source.html +++ b/_tgstation_8_server_8_client_8_tests_8_program_8cs_source.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Client.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Client.Tests.Program.cs Source File + + +tgstation-server: tests/Tgstation.Server.Client.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Client.Tests.Program.cs Source File - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,15 +71,14 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
Tgstation.Server.Client.Tests.Program.cs
-Go to the documentation of this file.
1 // <auto-generated> This file has been auto generated. </auto-generated>
2 using System;
3 [Microsoft.VisualStudio.TestPlatform.TestSDKAutoGeneratedCode]
4 class AutoGeneratedProgram {static void Main(string[] args){}}
- +Go to the documentation of this file.
1 // <auto-generated> This file has been auto generated. </auto-generated>
2 using System;
3 [Microsoft.VisualStudio.TestPlatform.TestSDKAutoGeneratedCode]
4 class AutoGeneratedProgram {static void Main(string[] args){}}
diff --git a/src_2_tgstation_8_server_8_host_2_assembly_info_8cs.html b/_tgstation_8_server_8_host_2_assembly_info_8cs.html similarity index 60% rename from src_2_tgstation_8_server_8_host_2_assembly_info_8cs.html rename to _tgstation_8_server_8_host_2_assembly_info_8cs.html index dfd060facf..a787c564b7 100644 --- a/src_2_tgstation_8_server_8_host_2_assembly_info_8cs.html +++ b/_tgstation_8_server_8_host_2_assembly_info_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/AssemblyInfo.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
diff --git a/_tgstation_8_server_8_host_2_assembly_info_8cs_source.html b/_tgstation_8_server_8_host_2_assembly_info_8cs_source.html new file mode 100644 index 0000000000..dfbbd653f6 --- /dev/null +++ b/_tgstation_8_server_8_host_2_assembly_info_8cs_source.html @@ -0,0 +1,82 @@ + + + + + + + +tgstation-server: src/Tgstation.Server.Host/AssemblyInfo.cs Source File + + + + + + + + + +
+
+ + + + + + + +
+
tgstation-server +
+
The /tg/station 13 server suite
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
AssemblyInfo.cs
+
+
+Go to the documentation of this file.
1 using System.Runtime.CompilerServices;
2 
3 [assembly: InternalsVisibleTo("Tgstation.Server.Host.Tests")]
4 [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
+ + + + diff --git a/_tgstation_8_server_8_host_2_components_2_chat_2_user_8cs.html b/_tgstation_8_server_8_host_2_components_2_chat_2_user_8cs.html index d7e9bb4d8a..07c53d2a64 100644 --- a/_tgstation_8_server_8_host_2_components_2_chat_2_user_8cs.html +++ b/_tgstation_8_server_8_host_2_components_2_chat_2_user_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/User.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_tgstation_8_server_8_host_2_components_2_chat_2_user_8cs_source.html b/_tgstation_8_server_8_host_2_components_2_chat_2_user_8cs_source.html index 5c59604492..732ec0b9db 100644 --- a/_tgstation_8_server_8_host_2_components_2_chat_2_user_8cs_source.html +++ b/_tgstation_8_server_8_host_2_components_2_chat_2_user_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/User.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
User.cs
-Go to the documentation of this file.
1 using Newtonsoft.Json;
2 using System;
3 using System.Globalization;
4 
5 namespace Tgstation.Server.Host.Components.Chat
6 {
10  public sealed class User
11  {
15  public string Id { get; set; }
16 
20  [JsonIgnore]
21  public ulong RealId
22  {
23  get => UInt64.Parse(Id, CultureInfo.InvariantCulture);
24  set => Id = value.ToString(CultureInfo.InvariantCulture);
25  }
26 
30  public string FriendlyName { get; set; }
31 
35  public string Mention { get; set; }
36 
40  public Channel Channel { get; set; }
41  }
42 }
- -
Represents a Providers.IProvider channel
Definition: Channel.cs:10
-
Represents a tgs_chat_user datum
Definition: User.cs:10
- +Go to the documentation of this file.
1 using Newtonsoft.Json;
2 using System;
3 using System.Globalization;
4 
6 {
10  public sealed class User
11  {
15  public string Id { get; set; }
16 
20  [JsonIgnore]
21  public ulong RealId
22  {
23  get => UInt64.Parse(Id, CultureInfo.InvariantCulture);
24  set => Id = value.ToString(CultureInfo.InvariantCulture);
25  }
26 
30  public string FriendlyName { get; set; }
31 
35  public string Mention { get; set; }
36 
40  public Channel Channel { get; set; }
41  }
42 }
+
string Mention
The text to mention the user
Definition: User.cs:35
+
string FriendlyName
The friendly name of the user
Definition: User.cs:30
+
Represents a Providers.IProvider channel
Definition: Channel.cs:10
+
Represents a tgs_chat_user datum
Definition: User.cs:10
+
ulong RealId
The internal user id
Definition: User.cs:22
+
string Id
Backing field for RealId. Represented as a string to avoid BYOND percision loss
Definition: User.cs:15
diff --git a/_tgstation_8_server_8_host_2_components_2_compiler_2_dream_maker_8cs.html b/_tgstation_8_server_8_host_2_components_2_compiler_2_dream_maker_8cs.html index 9676159366..1d3d41dfa7 100644 --- a/_tgstation_8_server_8_host_2_components_2_compiler_2_dream_maker_8cs.html +++ b/_tgstation_8_server_8_host_2_components_2_compiler_2_dream_maker_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Compiler/DreamMaker.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Compiler
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_tgstation_8_server_8_host_2_components_2_compiler_2_dream_maker_8cs_source.html b/_tgstation_8_server_8_host_2_components_2_compiler_2_dream_maker_8cs_source.html index ea0d36bd4b..dd306b7483 100644 --- a/_tgstation_8_server_8_host_2_components_2_compiler_2_dream_maker_8cs_source.html +++ b/_tgstation_8_server_8_host_2_components_2_compiler_2_dream_maker_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Compiler/DreamMaker.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
DreamMaker.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.Text;
7 using System.Threading;
8 using System.Threading.Tasks;
16 using Tgstation.Server.Host.IO;
17 
18 namespace Tgstation.Server.Host.Components.Compiler
19 {
21  sealed class DreamMaker : IDreamMaker
22  {
26  public const string ADirectoryName = "A";
27 
31  public const string BDirectoryName = "B";
32 
36  public const string DmbExtension = ".dmb";
37 
41  const string DmeExtension = "dme";
42 
46  readonly IByondManager byond;
47 
52 
56  readonly StaticFiles.IConfiguration configuration;
57 
62 
67 
72 
77 
81  readonly IChat chat;
82 
87 
91  readonly IWatchdog watchdog;
92 
96  readonly ILogger<DreamMaker> logger;
97 
101  bool compiling;
102 
110  static async Task ProgressTask(Action<int> progressReporter, TimeSpan estimatedDuration, CancellationToken cancellationToken)
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  }
125 
140  public 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)
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  }
154 
165  async Task VerifyApi(uint timeout, DreamDaemonSecurity securityLevel, Models.CompileJob job, IByondExecutableLock byondLock, ushort portToUse, CancellationToken cancellationToken)
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 provider = new TemporaryDmbProvider(ioManager.ResolvePath(dirA), String.Concat(job.DmeName, DmbExtension), job);
180 
181  var timeoutAt = DateTimeOffset.Now.AddSeconds(timeout);
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  }
227 
235  async Task<int> RunDreamMaker(string dreamMakerPath, Models.CompileJob job, CancellationToken cancellationToken)
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  }
250 
257  async Task ModifyDme(Models.CompileJob job, CancellationToken cancellationToken)
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  }
304 
312  async Task CleanupFailedCompile(Models.CompileJob job, bool cancelled, CancellationToken cancellationToken)
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  }
328 
336  async Task SendDeploymentMessage(Models.RevisionInformation revisionInformation, IByondExecutableLock byondLock, CancellationToken cancellationToken)
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  }
359 
370  async Task RunCompileJob(Models.CompileJob job, Api.Models.DreamMaker dreamMakerSettings, IByondExecutableLock byondLock, IRepository repository, uint apiValidateTimeout, CancellationToken cancellationToken)
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  }
459 
461  public async Task<Models.CompileJob> Compile(Models.RevisionInformation revisionInformation, Api.Models.DreamMaker dreamMakerSettings, uint apiValidateTimeout, IRepository repository, Action<int> progressReporter, TimeSpan? estimatedDuration, CancellationToken cancellationToken)
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  }
522  }
523 }
+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.Text;
7 using System.Threading;
8 using System.Threading.Tasks;
16 using Tgstation.Server.Host.IO;
17 
19 {
21  sealed class DreamMaker : IDreamMaker
22  {
26  public const string ADirectoryName = "A";
27 
31  public const string BDirectoryName = "B";
32 
36  public const string DmbExtension = ".dmb";
37 
41  const string DmeExtension = "dme";
42 
46  readonly IByondManager byond;
47 
52 
56  readonly StaticFiles.IConfiguration configuration;
57 
62 
67 
72 
77 
81  readonly IChat chat;
82 
87 
91  readonly IWatchdog watchdog;
92 
96  readonly ILogger<DreamMaker> logger;
97 
101  bool compiling;
102 
110  static async Task ProgressTask(Action<int> progressReporter, TimeSpan estimatedDuration, CancellationToken cancellationToken)
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  }
125 
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  }
154 
165  async Task VerifyApi(uint timeout, DreamDaemonSecurity securityLevel, Models.CompileJob job, IByondExecutableLock byondLock, ushort portToUse, CancellationToken cancellationToken)
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  }
227 
235  async Task<int> RunDreamMaker(string dreamMakerPath, Models.CompileJob job, CancellationToken cancellationToken)
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  }
250 
257  async Task ModifyDme(Models.CompileJob job, CancellationToken cancellationToken)
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  }
304 
312  async Task CleanupFailedCompile(Models.CompileJob job, bool cancelled, CancellationToken cancellationToken)
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  }
328 
336  async Task SendDeploymentMessage(Models.RevisionInformation revisionInformation, IByondExecutableLock byondLock, CancellationToken cancellationToken)
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  }
359 
370  async Task RunCompileJob(Models.CompileJob job, Api.Models.DreamMaker dreamMakerSettings, IByondExecutableLock byondLock, IRepository repository, uint apiValidateTimeout, CancellationToken cancellationToken)
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  }
459 
461  public async Task<Models.CompileJob> Compile(Models.RevisionInformation revisionInformation, Api.Models.DreamMaker dreamMakerSettings, uint apiValidateTimeout, IRepository repository, Action<int> progressReporter, TimeSpan? estimatedDuration, CancellationToken cancellationToken)
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  }
522  }
523 }
+
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
- -
readonly ILogger< DreamMaker > logger
The ILogger for DreamMaker
Definition: DreamMaker.cs:96
+
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
-
Consumes EventTypes and takes the appropriate actions
+
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
-
readonly StaticFiles.IConfiguration configuration
The StaticFiles.IConfiguration for DreamMaker
Definition: DreamMaker.cs:56
-
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
- - - +
readonly StaticFiles.IConfiguration configuration
The StaticFiles.IConfiguration for DreamMaker
Definition: DreamMaker.cs:56
+
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
+
Task SendUpdateMessage(string message, CancellationToken cancellationToken)
Send a chat message to configured update channels
+ - -
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
+
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
-
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
-
Represents an on-disk git repository
Definition: IRepository.cs:11
-
async Task< Models.CompileJob > Compile(Models.RevisionInformation revisionInformation, Api.Models.DreamMaker dreamMakerSettings, uint apiValidateTimeout, IRepository repository, Action< int > progressReporter, TimeSpan?estimatedDuration, CancellationToken cancellationToken)
Definition: DreamMaker.cs:461
-
bool compiling
If a compile job is running
Definition: DreamMaker.cs:101
-
For managing connected chat services
Definition: IChat.cs:13
+
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
+
Represents an on-disk git repository
Definition: IRepository.cs:11
+
bool compiling
If a compile job is running
Definition: DreamMaker.cs:101
+
For managing connected chat services
Definition: IChat.cs:13
+
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
-
readonly ISessionControllerFactory sessionControllerFactory
The ISessionControllerFactory for DreamMaker
Definition: DreamMaker.cs:61
-
readonly IEventConsumer eventConsumer
The IEventConsumer for DreamMaker
Definition: DreamMaker.cs:76
+
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
+
readonly ISessionControllerFactory sessionControllerFactory
The ISessionControllerFactory for DreamMaker
Definition: DreamMaker.cs:61
+
readonly IEventConsumer eventConsumer
The IEventConsumer for DreamMaker
Definition: DreamMaker.cs:76
- -
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
- -
For managing the BYOND installation
-
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
-
Represents usage of the two primary BYOND server executables
- -
readonly ICompileJobConsumer compileJobConsumer
The ICompileJobConsumer for DreamMaker
Definition: DreamMaker.cs:66
- -
DreamDaemonSecurity
DreamDaemon&#39;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
-
readonly IIOManager ioManager
The IIOManager for DreamMaker
Definition: DreamMaker.cs:51
-
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
Definition: DreamMaker.cs:140
-
Interface for using filesystems
Definition: IIOManager.cs:11
-
Represents information about a current git revison
-
Version Version
The System.Version of the locked executables
-
readonly IApplication application
The IApplication for DreamMaker
Definition: DreamMaker.cs:71
- -
async Task< int > RunDreamMaker(string dreamMakerPath, Models.CompileJob job, CancellationToken cancellationToken)
Compiles a .dme with DreamMaker
Definition: DreamMaker.cs:235
-
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
-
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
-
ApiValidationStatus
Status of DMAPI validation
+
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
+
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
+ +
IProcess LaunchProcess(string fileName, string workingDirectory, string arguments=null, bool readOutput=false, bool readError=false, bool noShellExecute=false)
Launch a IProcess
+
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
+
const string DmbExtension
Extension for .dmbs
Definition: DreamMaker.cs:36
+ + +
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
+
Represents usage of the two primary BYOND server executables
+ +
readonly ICompileJobConsumer compileJobConsumer
The ICompileJobConsumer for DreamMaker
Definition: DreamMaker.cs:66
+ +
const string DmeExtension
Extension for .dmes
Definition: DreamMaker.cs:41
+
DreamDaemonSecurity
DreamDaemon's security level
+
bool Running
If the watchdog is running
Definition: IWatchdog.cs:17
+
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
+
readonly IIOManager ioManager
The IIOManager for DreamMaker
Definition: DreamMaker.cs:51
+
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
Definition: DreamMaker.cs:140
+
Interface for using filesystems
Definition: IIOManager.cs:11
+
async Task< Models.CompileJob > Compile(Models.RevisionInformation revisionInformation, Api.Models.DreamMaker dreamMakerSettings, uint apiValidateTimeout, IRepository repository, Action< int > progressReporter, TimeSpan? estimatedDuration, CancellationToken cancellationToken)
Definition: DreamMaker.cs:461
+
Represents information about a current git revison
+
Task< bool > HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
Handle a given eventType
+
Version Version
The System.Version of the locked executables
+
Task< byte[]> ReadAllBytes(string path, CancellationToken cancellationToken)
Returns all the contents of a file at path as a byte array
+
readonly IApplication application
The IApplication for DreamMaker
Definition: DreamMaker.cs:71
+ +
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
+ +
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
+
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
+
ApiValidationStatus
Status of DMAPI validation
diff --git a/_tgstation_8_server_8_host_2_components_2_instance_8cs.html b/_tgstation_8_server_8_host_2_components_2_instance_8cs.html index ac71faf1ac..0fb518cecc 100644 --- a/_tgstation_8_server_8_host_2_components_2_instance_8cs.html +++ b/_tgstation_8_server_8_host_2_components_2_instance_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Instance.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_tgstation_8_server_8_host_2_components_2_instance_8cs_source.html b/_tgstation_8_server_8_host_2_components_2_instance_8cs_source.html index 86a947d5a1..7b76b91a46 100644 --- a/_tgstation_8_server_8_host_2_components_2_instance_8cs_source.html +++ b/_tgstation_8_server_8_host_2_components_2_instance_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Instance.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Instance.cs
-Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using Microsoft.Extensions.Logging;
3 using Octokit;
4 using System;
5 using System.Collections.Generic;
6 using System.Globalization;
7 using System.Linq;
8 using System.Threading;
9 using System.Threading.Tasks;
18 
19 namespace Tgstation.Server.Host.Components
20 {
22  #pragma warning disable CA1506 // TODO: Decomplexify
23  sealed class Instance : IInstance
24  {
27 
29  public IByondManager ByondManager { get; }
30 
32  public IWatchdog Watchdog { get; }
33 
35  public IChat Chat { get; }
36 
38  public StaticFiles.IConfiguration Configuration { get; }
39 
44 
49 
54 
59 
64 
69 
74 
78  readonly ILogger<Instance> logger;
79 
83  readonly Api.Models.Instance metadata;
84 
88  Task timerTask;
89 
93  CancellationTokenSource timerCts;
94 
112  public Instance(Api.Models.Instance metadata, IRepositoryManager repositoryManager, IByondManager byondManager, IDreamMaker dreamMaker, IWatchdog watchdog, IChat chat, StaticFiles.IConfiguration configuration, ICompileJobConsumer compileJobConsumer, IDatabaseContextFactory databaseContextFactory, IDmbFactory dmbFactory, IJobManager jobManager, IEventConsumer eventConsumer, IGitHubClientFactory gitHubClientFactory, ILogger<Instance> logger)
113  {
114  this.metadata = metadata ?? throw new ArgumentNullException(nameof(metadata));
115  RepositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager));
116  ByondManager = byondManager ?? throw new ArgumentNullException(nameof(byondManager));
117  this.dreamMaker = dreamMaker ?? throw new ArgumentNullException(nameof(dreamMaker));
118  Watchdog = watchdog ?? throw new ArgumentNullException(nameof(watchdog));
119  Chat = chat ?? throw new ArgumentNullException(nameof(chat));
120  Configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
121  this.compileJobConsumer = compileJobConsumer ?? throw new ArgumentNullException(nameof(compileJobConsumer));
122  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
123  this.dmbFactory = dmbFactory ?? throw new ArgumentNullException(nameof(dmbFactory));
124  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
125  this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
126  this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
127  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
128  }
129 
131  public void Dispose()
132  {
133  timerCts?.Dispose();
134  compileJobConsumer.Dispose();
135  Configuration.Dispose();
136  Chat.Dispose();
137  Watchdog.Dispose();
139  }
140 
142  public async Task CompileProcess(Job job, IDatabaseContext databaseContext, Action<int> progressReporter, CancellationToken cancellationToken)
143  {
144 #pragma warning disable IDE0016 // Use 'throw' expression
145  if (job == null)
146  throw new ArgumentNullException(nameof(job));
147 #pragma warning restore IDE0016 // Use 'throw' expression
148  if (databaseContext == null)
149  throw new ArgumentNullException(nameof(databaseContext));
150  if (progressReporter == null)
151  throw new ArgumentNullException(nameof(progressReporter));
152 
153  var ddSettingsTask = databaseContext.DreamDaemonSettings.Where(x => x.InstanceId == metadata.Id).Select(x => new DreamDaemonSettings
154  {
155  StartupTimeout = x.StartupTimeout,
156  }).FirstOrDefaultAsync(cancellationToken);
157 
158  var compileJobsTask = databaseContext.CompileJobs
159  .Where(x => x.Job.Instance.Id == metadata.Id)
160  .OrderByDescending(x => x.Job.StoppedAt)
161  .Select(x => new Job
162  {
163  StoppedAt = x.Job.StoppedAt,
164  StartedAt = x.Job.StartedAt
165  })
166  .Take(10)
167  .ToListAsync(cancellationToken);
168 
169  var dreamMakerSettings = await databaseContext.DreamMakerSettings.Where(x => x.InstanceId == metadata.Id).FirstAsync(cancellationToken).ConfigureAwait(false);
170  if (dreamMakerSettings == default)
171  throw new JobException("Missing DreamMakerSettings in DB!");
172  var ddSettings = await ddSettingsTask.ConfigureAwait(false);
173  if (ddSettings == default)
174  throw new JobException("Missing DreamDaemonSettings in DB!");
175 
176  Task<RepositorySettings> repositorySettingsTask = null;
177  string repoOwner = null;
178  string repoName = null;
179  CompileJob compileJob;
180  RevisionInformation revInfo;
181  using (var repo = await RepositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false))
182  {
183  if (repo == null)
184  throw new JobException("Missing Repository!");
185 
186  if (repo.IsGitHubRepository)
187  {
188  repoOwner = repo.GitHubOwner;
189  repoName = repo.GitHubRepoName;
190  repositorySettingsTask = databaseContext.RepositorySettings.Where(x => x.InstanceId == metadata.Id).Select(x => new RepositorySettings
191  {
192  AccessToken = x.AccessToken,
193  ShowTestMergeCommitters = x.ShowTestMergeCommitters,
194  PushTestMergeCommits = x.PushTestMergeCommits
195  }).FirstOrDefaultAsync(cancellationToken);
196  }
197 
198  var repoSha = repo.Head;
199  revInfo = await databaseContext.RevisionInformations.Where(x => x.CommitSha == repoSha && x.Instance.Id == metadata.Id).Include(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).ThenInclude(x => x.MergedBy).FirstOrDefaultAsync().ConfigureAwait(false);
200 
201  if (revInfo == default)
202  {
203  revInfo = new RevisionInformation
204  {
205  CommitSha = repoSha,
206  OriginCommitSha = repoSha,
207  Instance = new Models.Instance
208  {
209  Id = metadata.Id
210  }
211  };
212  logger.LogWarning(Repository.Repository.OriginTrackingErrorTemplate, repoSha);
213  databaseContext.Instances.Attach(revInfo.Instance);
214  }
215 
216  TimeSpan? averageSpan = null;
217  var previousCompileJobs = await compileJobsTask.ConfigureAwait(false);
218  if(previousCompileJobs.Count != 0)
219  {
220  var totalSpan = TimeSpan.Zero;
221  foreach (var I in previousCompileJobs)
222  totalSpan += I.StoppedAt.Value - I.StartedAt.Value;
223  averageSpan = totalSpan / previousCompileJobs.Count;
224  }
225 
226  compileJob = await dreamMaker.Compile(revInfo, dreamMakerSettings, ddSettings.StartupTimeout.Value, repo, progressReporter, averageSpan, cancellationToken).ConfigureAwait(false);
227  }
228 
229  compileJob.Job = job;
230 
231  databaseContext.CompileJobs.Add(compileJob); // will be saved by job context
232 
233  job.PostComplete = ct => compileJobConsumer.LoadCompileJob(compileJob, ct);
234 
235  if (repositorySettingsTask != null)
236  {
237  var repositorySettings = await repositorySettingsTask.ConfigureAwait(false);
238  if (repositorySettings == default)
239  throw new JobException("Missing repository settings!");
240 
241  if (repositorySettings.AccessToken != null)
242  {
243  // potential for commenting on a test merge change
244  var outgoingCompileJob = LatestCompileJob();
245 
246  if(outgoingCompileJob != null && outgoingCompileJob.RevisionInformation.CommitSha != compileJob.RevisionInformation.CommitSha && repositorySettings.PostTestMergeComment.Value)
247  {
248  var gitHubClient = gitHubClientFactory.CreateClient(repositorySettings.AccessToken);
249 
250  async Task CommentOnPR(int prNumber, string comment)
251  {
252  try
253  {
254  await gitHubClient.Issue.Comment.Create(repoOwner, repoName, prNumber, comment).ConfigureAwait(false);
255  }
256  catch (ApiException e)
257  {
258  logger.LogWarning("Error posting GitHub comment! Exception: {0}", e);
259  }
260  }
261 
262  var tasks = new List<Task>();
263 
264  string FormatTestMerge(TestMerge testMerge, bool updated) => String.Format(CultureInfo.InvariantCulture, "#### Test Merge {4}{0}{0}##### Server Instance{0}{5}{1}{0}{0}##### Revision{0}Origin: {6}{0}Pull Request: {2}{0}Server: {7}{3}",
265  Environment.NewLine,
266  repositorySettings.ShowTestMergeCommitters.Value ? String.Format(CultureInfo.InvariantCulture, "{0}{0}##### Merged By{0}{1}", Environment.NewLine, testMerge.MergedBy.Name) : String.Empty,
267  testMerge.PullRequestRevision,
268  testMerge.Comment != null ? String.Format(CultureInfo.InvariantCulture, "{0}{0}##### Comment{0}{1}", Environment.NewLine, testMerge.Comment) : String.Empty,
269  updated ? "Updated" : "Deployed",
270  metadata.Name,
272  compileJob.RevisionInformation.CommitSha);
273 
274  // added prs
275  foreach (var I in compileJob
277  .ActiveTestMerges
278  .Select(x => x.TestMerge)
279  .Where(x => !outgoingCompileJob
281  .ActiveTestMerges
282  .Any(y => y.TestMerge.Number == x.Number)))
283  tasks.Add(CommentOnPR(I.Number.Value, FormatTestMerge(I, false)));
284 
285  // removed prs
286  foreach (var I in outgoingCompileJob
288  .ActiveTestMerges
289  .Select(x => x.TestMerge)
290  .Where(x => !compileJob
293  .Any(y => y.TestMerge.Number == x.Number)))
294  tasks.Add(CommentOnPR(I.Number.Value, "#### Test Merge Removed"));
295 
296  // updated prs
297  foreach(var I in compileJob
299  .ActiveTestMerges
300  .Select(x => x.TestMerge)
301  .Where(x => outgoingCompileJob
302  .RevisionInformation
303  .ActiveTestMerges
304  .Any(y => y.TestMerge.Number == x.Number)))
305  tasks.Add(CommentOnPR(I.Number.Value, FormatTestMerge(I, true)));
306 
307  if (tasks.Any())
308  await Task.WhenAll(tasks).ConfigureAwait(false);
309  }
310  }
311  }
312  }
313 
320  #pragma warning disable CA1502 // TODO: Decomplexify
321  async Task TimerLoop(uint minutes, CancellationToken cancellationToken)
322  {
323  while (true)
324  try
325  {
326  await Task.Delay(TimeSpan.FromMinutes(minutes > Int32.MaxValue ? Int32.MaxValue : (int)minutes), cancellationToken).ConfigureAwait(false);
327  logger.LogDebug("Beginning auto update...");
328  await eventConsumer.HandleEvent(EventType.InstanceAutoUpdateStart, new List<string>(), cancellationToken).ConfigureAwait(false);
329  try
330  {
331  Models.User user = null;
332  await databaseContextFactory.UseContext(async (db) => user = await db.Users.Where(x => x.CanonicalName == Api.Models.User.AdminName.ToUpperInvariant()).FirstAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false);
333  var repositoryUpdateJob = new Job
334  {
335  Instance = new Models.Instance
336  {
337  Id = metadata.Id
338  },
339  Description = "Scheduled repository update",
340  CancelRightsType = RightsType.Repository,
341  CancelRight = (ulong)RepositoryRights.CancelPendingChanges,
342  StartedBy = user
343  };
344 
345  string deploySha = null;
346  await jobManager.RegisterOperation(repositoryUpdateJob, async (paramJob, databaseContext, progressReporter, jobCancellationToken) =>
347  {
348  var repositorySettingsTask = databaseContext.RepositorySettings.Where(x => x.InstanceId == metadata.Id).FirstAsync(jobCancellationToken);
349 
350  // assume 5 steps with synchronize
351  const int ProgressSections = 7;
352  const int ProgressStep = 100 / ProgressSections;
353 
354  const int NumSteps = 3;
355  var doneSteps = 0;
356 
357  Action<int> NextProgressReporter()
358  {
359  var tmpDoneSteps = doneSteps;
360  ++doneSteps;
361  return progress => progressReporter((progress + (100 * tmpDoneSteps)) / NumSteps);
362  }
363 
364  using (var repo = await RepositoryManager.LoadRepository(jobCancellationToken).ConfigureAwait(false))
365  {
366  if (repo == null)
367  {
368  logger.LogTrace("Aborting repo update, no repository!");
369  return;
370  }
371 
372  var startSha = repo.Head;
373  if (!repo.Tracking)
374  {
375  logger.LogTrace("Aborting repo update, not tracking origin!");
376  deploySha = startSha;
377  return;
378  }
379 
380  var repositorySettings = await repositorySettingsTask.ConfigureAwait(false);
381 
382  // the main point of auto update is to pull the remote
383  await repo.FetchOrigin(repositorySettings.AccessUser, repositorySettings.AccessToken, NextProgressReporter(), jobCancellationToken).ConfigureAwait(false);
384 
385  RevisionInformation currentRevInfo = null;
386  bool hasDbChanges = false;
387 
388  Task<RevisionInformation> LoadRevInfo() => databaseContext.RevisionInformations
389  .Where(x => x.CommitSha == startSha && x.Instance.Id == metadata.Id)
390  .Include(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge)
391  .FirstOrDefaultAsync(cancellationToken);
392 
393  async Task UpdateRevInfo(string currentHead, bool onOrigin)
394  {
395  if(currentRevInfo == null)
396  currentRevInfo = await LoadRevInfo().ConfigureAwait(false);
397 
398  if (currentRevInfo == default)
399  {
400  logger.LogWarning(Repository.Repository.OriginTrackingErrorTemplate, currentHead);
401  onOrigin = true;
402  }
403 
404  var attachedInstance = new Models.Instance
405  {
406  Id = metadata.Id
407  };
408  var oldRevInfo = currentRevInfo;
409  currentRevInfo = new RevisionInformation
410  {
411  CommitSha = currentHead,
412  OriginCommitSha = onOrigin ? currentHead : oldRevInfo.OriginCommitSha,
413  Instance = attachedInstance
414  };
415  if (!onOrigin)
416  currentRevInfo.ActiveTestMerges = new List<RevInfoTestMerge>(oldRevInfo.ActiveTestMerges);
417 
418  databaseContext.Instances.Attach(attachedInstance);
419  databaseContext.RevisionInformations.Add(currentRevInfo);
420  hasDbChanges = true;
421  }
422 
423  // take appropriate auto update actions
424  bool shouldSyncTracked;
425  if (repositorySettings.AutoUpdatesKeepTestMerges.Value)
426  {
427  logger.LogTrace("Preserving test merges...");
428 
429  var currentRevInfoTask = LoadRevInfo();
430 
431  var result = await repo.MergeOrigin(repositorySettings.CommitterName, repositorySettings.CommitterEmail, NextProgressReporter(), jobCancellationToken).ConfigureAwait(false);
432 
433  if (!result.HasValue)
434  throw new JobException("Merge conflict while preserving test merges!");
435 
436  currentRevInfo = await currentRevInfoTask.ConfigureAwait(false);
437 
438  var lastRevInfoWasOriginCommit = currentRevInfo == default || currentRevInfo.CommitSha == currentRevInfo.OriginCommitSha;
439  var stillOnOrigin = result.Value && lastRevInfoWasOriginCommit;
440 
441  var currentHead = repo.Head;
442  if (currentHead != startSha)
443  {
444  await UpdateRevInfo(currentHead, stillOnOrigin).ConfigureAwait(false);
445  shouldSyncTracked = stillOnOrigin;
446  }
447  else
448  shouldSyncTracked = false;
449  }
450  else
451  {
452  logger.LogTrace("Not preserving test merges...");
453  await repo.ResetToOrigin(NextProgressReporter(), jobCancellationToken).ConfigureAwait(false);
454 
455  var currentHead = repo.Head;
456 
457  currentRevInfo = await databaseContext.RevisionInformations
458  .Where(x => x.CommitSha == currentHead && x.Instance.Id == metadata.Id)
459  .FirstOrDefaultAsync(jobCancellationToken).ConfigureAwait(false);
460 
461  if (currentHead != startSha && currentRevInfo != default)
462  await UpdateRevInfo(currentHead, true).ConfigureAwait(false);
463 
464  shouldSyncTracked = true;
465  }
466 
467  // synch if necessary
468  if (repositorySettings.AutoUpdatesSynchronize.Value && startSha != repo.Head)
469  {
470  var pushedOrigin = await repo.Sychronize(repositorySettings.AccessUser, repositorySettings.AccessToken, repositorySettings.CommitterName, repositorySettings.CommitterEmail, NextProgressReporter(), shouldSyncTracked, jobCancellationToken).ConfigureAwait(false);
471  var currentHead = repo.Head;
472  if (currentHead != currentRevInfo.CommitSha)
473  await UpdateRevInfo(currentHead, pushedOrigin).ConfigureAwait(false);
474  }
475 
476  if(hasDbChanges)
477  try
478  {
479  await databaseContext.Save(cancellationToken).ConfigureAwait(false);
480  }
481  catch
482  {
483  await repo.ResetToSha(startSha, progressReporter, default).ConfigureAwait(false);
484  throw;
485  }
486 
487  progressReporter(5 * ProgressStep);
488  deploySha = repo.Head;
489  }
490  }, cancellationToken).ConfigureAwait(false);
491 
492  await jobManager.WaitForJobCompletion(repositoryUpdateJob, user, cancellationToken, default).ConfigureAwait(false);
493 
494  if (deploySha == null)
495  {
496  logger.LogTrace("Aborting auto update, repository error!");
497  continue;
498  }
499 
500  if(deploySha == LatestCompileJob()?.RevisionInformation.CommitSha)
501  {
502  logger.LogTrace("Aborting auto update, same revision as latest CompileJob");
503  continue;
504  }
505 
506  // finally set up the job
507  var compileProcessJob = new Job
508  {
509  StartedBy = user,
510  Instance = repositoryUpdateJob.Instance,
511  Description = "Scheduled code deployment",
512  CancelRightsType = RightsType.DreamMaker,
513  CancelRight = (ulong)DreamMakerRights.CancelCompile
514  };
515 
516  await jobManager.RegisterOperation(compileProcessJob, CompileProcess, cancellationToken).ConfigureAwait(false);
517 
518  await jobManager.WaitForJobCompletion(compileProcessJob, user, cancellationToken, default).ConfigureAwait(false);
519  }
520  catch (OperationCanceledException)
521  {
522  logger.LogDebug("Cancelled auto update job!");
523  throw;
524  }
525  catch (Exception e)
526  {
527  logger.LogWarning("Error in auto update loop! Exception: {0}", e);
528  continue;
529  }
530  }
531  catch (OperationCanceledException)
532  {
533  break;
534  }
535 
536  logger.LogTrace("Leaving auto update loop...");
537  }
538  #pragma warning restore CA1502
539 
541  public void Rename(string newName)
542  {
543  if (String.IsNullOrWhiteSpace(newName))
544  throw new ArgumentNullException(nameof(newName));
545  metadata.Name = newName;
546  }
547 
549  public async Task StartAsync(CancellationToken cancellationToken)
550  {
551  await Task.WhenAll(SetAutoUpdateInterval(metadata.AutoUpdateInterval.Value), Configuration.StartAsync(cancellationToken), ByondManager.StartAsync(cancellationToken), Chat.StartAsync(cancellationToken), compileJobConsumer.StartAsync(cancellationToken)).ConfigureAwait(false);
552 
553  // dependent on so many things, its just safer this way
554  await Watchdog.StartAsync(cancellationToken).ConfigureAwait(false);
555 
556  CompileJob latestCompileJob = null;
557  await databaseContextFactory.UseContext(async db =>
558  {
559  latestCompileJob = await db.CompileJobs.Where(x => x.Job.Instance.Id == metadata.Id).OrderByDescending(x => x.Job.StoppedAt).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
560  }).ConfigureAwait(false);
561  await dmbFactory.CleanUnusedCompileJobs(latestCompileJob, cancellationToken).ConfigureAwait(false);
562  }
563 
565  public Task StopAsync(CancellationToken cancellationToken) => Task.WhenAll(SetAutoUpdateInterval(0), Configuration.StopAsync(cancellationToken), ByondManager.StopAsync(cancellationToken), Watchdog.StopAsync(cancellationToken), Chat.StopAsync(cancellationToken), compileJobConsumer.StopAsync(cancellationToken));
566 
568  public async Task SetAutoUpdateInterval(uint newInterval)
569  {
570  Task toWait;
571  lock (this)
572  {
573  if (timerTask != null)
574  {
575  timerCts.Cancel();
576  toWait = timerTask;
577  }
578  else
579  toWait = Task.CompletedTask;
580  }
581 
582  await toWait.ConfigureAwait(false);
583  if (newInterval == 0)
584  return;
585  lock (this)
586  {
587  // race condition, just quit
588  if (timerTask != null)
589  return;
590  timerCts?.Dispose();
591  timerCts = new CancellationTokenSource();
592  timerTask = TimerLoop(newInterval, timerCts.Token);
593  }
594  }
595 
598  {
599  if (!dmbFactory.DmbAvailable)
600  return null;
601  return dmbFactory.LockNextDmb(0)?.CompileJob;
602  }
603  }
604 }
-
string Name
The name of the User
Definition: User.cs:38
- -
Manages the runtime of Jobs
Definition: IJobManager.cs:12
-
DbSet< Instance > Instances
The Instances in the IDatabaseContext
-
async 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.IJobManager
Definition: Instance.cs:142
+Go to the documentation of this file.
1 using Microsoft.EntityFrameworkCore;
2 using Microsoft.Extensions.Logging;
3 using Octokit;
4 using System;
5 using System.Collections.Generic;
6 using System.Globalization;
7 using System.Linq;
8 using System.Threading;
9 using System.Threading.Tasks;
18 
20 {
22  #pragma warning disable CA1506 // TODO: Decomplexify
23  sealed class Instance : IInstance
24  {
27 
29  public IByondManager ByondManager { get; }
30 
32  public IWatchdog Watchdog { get; }
33 
35  public IChat Chat { get; }
36 
38  public StaticFiles.IConfiguration Configuration { get; }
39 
44 
49 
54 
59 
64 
69 
74 
78  readonly ILogger<Instance> logger;
79 
83  readonly Api.Models.Instance metadata;
84 
88  Task timerTask;
89 
93  CancellationTokenSource timerCts;
94 
113  {
114  this.metadata = metadata ?? throw new ArgumentNullException(nameof(metadata));
115  RepositoryManager = repositoryManager ?? throw new ArgumentNullException(nameof(repositoryManager));
116  ByondManager = byondManager ?? throw new ArgumentNullException(nameof(byondManager));
117  this.dreamMaker = dreamMaker ?? throw new ArgumentNullException(nameof(dreamMaker));
118  Watchdog = watchdog ?? throw new ArgumentNullException(nameof(watchdog));
119  Chat = chat ?? throw new ArgumentNullException(nameof(chat));
120  Configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
121  this.compileJobConsumer = compileJobConsumer ?? throw new ArgumentNullException(nameof(compileJobConsumer));
122  this.databaseContextFactory = databaseContextFactory ?? throw new ArgumentNullException(nameof(databaseContextFactory));
123  this.dmbFactory = dmbFactory ?? throw new ArgumentNullException(nameof(dmbFactory));
124  this.jobManager = jobManager ?? throw new ArgumentNullException(nameof(jobManager));
125  this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
126  this.gitHubClientFactory = gitHubClientFactory ?? throw new ArgumentNullException(nameof(gitHubClientFactory));
127  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
128  }
129 
131  public void Dispose()
132  {
133  timerCts?.Dispose();
134  compileJobConsumer.Dispose();
135  Configuration.Dispose();
136  Chat.Dispose();
137  Watchdog.Dispose();
139  }
140 
142  public async Task CompileProcess(Job job, IDatabaseContext databaseContext, Action<int> progressReporter, CancellationToken cancellationToken)
143  {
144 #pragma warning disable IDE0016 // Use 'throw' expression
145  if (job == null)
146  throw new ArgumentNullException(nameof(job));
147 #pragma warning restore IDE0016 // Use 'throw' expression
148  if (databaseContext == null)
149  throw new ArgumentNullException(nameof(databaseContext));
150  if (progressReporter == null)
151  throw new ArgumentNullException(nameof(progressReporter));
152 
153  var ddSettingsTask = databaseContext.DreamDaemonSettings.Where(x => x.InstanceId == metadata.Id).Select(x => new DreamDaemonSettings
154  {
155  StartupTimeout = x.StartupTimeout,
156  }).FirstOrDefaultAsync(cancellationToken);
157 
158  var compileJobsTask = databaseContext.CompileJobs
159  .Where(x => x.Job.Instance.Id == metadata.Id)
160  .OrderByDescending(x => x.Job.StoppedAt)
161  .Select(x => new Job
162  {
163  StoppedAt = x.Job.StoppedAt,
164  StartedAt = x.Job.StartedAt
165  })
166  .Take(10)
167  .ToListAsync(cancellationToken);
168 
169  var dreamMakerSettings = await databaseContext.DreamMakerSettings.Where(x => x.InstanceId == metadata.Id).FirstAsync(cancellationToken).ConfigureAwait(false);
170  if (dreamMakerSettings == default)
171  throw new JobException("Missing DreamMakerSettings in DB!");
172  var ddSettings = await ddSettingsTask.ConfigureAwait(false);
173  if (ddSettings == default)
174  throw new JobException("Missing DreamDaemonSettings in DB!");
175 
176  Task<RepositorySettings> repositorySettingsTask = null;
177  string repoOwner = null;
178  string repoName = null;
179  CompileJob compileJob;
180  RevisionInformation revInfo;
181  using (var repo = await RepositoryManager.LoadRepository(cancellationToken).ConfigureAwait(false))
182  {
183  if (repo == null)
184  throw new JobException("Missing Repository!");
185 
186  if (repo.IsGitHubRepository)
187  {
188  repoOwner = repo.GitHubOwner;
189  repoName = repo.GitHubRepoName;
190  repositorySettingsTask = databaseContext.RepositorySettings.Where(x => x.InstanceId == metadata.Id).Select(x => new RepositorySettings
191  {
192  AccessToken = x.AccessToken,
193  ShowTestMergeCommitters = x.ShowTestMergeCommitters,
194  PushTestMergeCommits = x.PushTestMergeCommits
195  }).FirstOrDefaultAsync(cancellationToken);
196  }
197 
198  var repoSha = repo.Head;
199  revInfo = await databaseContext.RevisionInformations.Where(x => x.CommitSha == repoSha && x.Instance.Id == metadata.Id).Include(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge).ThenInclude(x => x.MergedBy).FirstOrDefaultAsync().ConfigureAwait(false);
200 
201  if (revInfo == default)
202  {
203  revInfo = new RevisionInformation
204  {
205  CommitSha = repoSha,
206  OriginCommitSha = repoSha,
207  Instance = new Models.Instance
208  {
209  Id = metadata.Id
210  }
211  };
212  logger.LogWarning(Repository.Repository.OriginTrackingErrorTemplate, repoSha);
213  databaseContext.Instances.Attach(revInfo.Instance);
214  }
215 
216  TimeSpan? averageSpan = null;
217  var previousCompileJobs = await compileJobsTask.ConfigureAwait(false);
218  if(previousCompileJobs.Count != 0)
219  {
220  var totalSpan = TimeSpan.Zero;
221  foreach (var I in previousCompileJobs)
222  totalSpan += I.StoppedAt.Value - I.StartedAt.Value;
223  averageSpan = totalSpan / previousCompileJobs.Count;
224  }
225 
226  compileJob = await dreamMaker.Compile(revInfo, dreamMakerSettings, ddSettings.StartupTimeout.Value, repo, progressReporter, averageSpan, cancellationToken).ConfigureAwait(false);
227  }
228 
229  compileJob.Job = job;
230 
231  databaseContext.CompileJobs.Add(compileJob); // will be saved by job context
232 
233  job.PostComplete = ct => compileJobConsumer.LoadCompileJob(compileJob, ct);
234 
235  if (repositorySettingsTask != null)
236  {
237  var repositorySettings = await repositorySettingsTask.ConfigureAwait(false);
238  if (repositorySettings == default)
239  throw new JobException("Missing repository settings!");
240 
241  if (repositorySettings.AccessToken != null)
242  {
243  // potential for commenting on a test merge change
244  var outgoingCompileJob = LatestCompileJob();
245 
246  if(outgoingCompileJob != null && outgoingCompileJob.RevisionInformation.CommitSha != compileJob.RevisionInformation.CommitSha && repositorySettings.PostTestMergeComment.Value)
247  {
248  var gitHubClient = gitHubClientFactory.CreateClient(repositorySettings.AccessToken);
249 
250  async Task CommentOnPR(int prNumber, string comment)
251  {
252  try
253  {
254  await gitHubClient.Issue.Comment.Create(repoOwner, repoName, prNumber, comment).ConfigureAwait(false);
255  }
256  catch (ApiException e)
257  {
258  logger.LogWarning("Error posting GitHub comment! Exception: {0}", e);
259  }
260  }
261 
262  var tasks = new List<Task>();
263 
264  string FormatTestMerge(TestMerge testMerge, bool updated) => String.Format(CultureInfo.InvariantCulture, "#### Test Merge {4}{0}{0}##### Server Instance{0}{5}{1}{0}{0}##### Revision{0}Origin: {6}{0}Pull Request: {2}{0}Server: {7}{3}",
265  Environment.NewLine,
266  repositorySettings.ShowTestMergeCommitters.Value ? String.Format(CultureInfo.InvariantCulture, "{0}{0}##### Merged By{0}{1}", Environment.NewLine, testMerge.MergedBy.Name) : String.Empty,
267  testMerge.PullRequestRevision,
268  testMerge.Comment != null ? String.Format(CultureInfo.InvariantCulture, "{0}{0}##### Comment{0}{1}", Environment.NewLine, testMerge.Comment) : String.Empty,
269  updated ? "Updated" : "Deployed",
270  metadata.Name,
272  compileJob.RevisionInformation.CommitSha);
273 
274  // added prs
275  foreach (var I in compileJob
277  .ActiveTestMerges
278  .Select(x => x.TestMerge)
279  .Where(x => !outgoingCompileJob
281  .ActiveTestMerges
282  .Any(y => y.TestMerge.Number == x.Number)))
283  tasks.Add(CommentOnPR(I.Number.Value, FormatTestMerge(I, false)));
284 
285  // removed prs
286  foreach (var I in outgoingCompileJob
288  .ActiveTestMerges
289  .Select(x => x.TestMerge)
290  .Where(x => !compileJob
293  .Any(y => y.TestMerge.Number == x.Number)))
294  tasks.Add(CommentOnPR(I.Number.Value, "#### Test Merge Removed"));
295 
296  // updated prs
297  foreach(var I in compileJob
299  .ActiveTestMerges
300  .Select(x => x.TestMerge)
301  .Where(x => outgoingCompileJob
302  .RevisionInformation
303  .ActiveTestMerges
304  .Any(y => y.TestMerge.Number == x.Number)))
305  tasks.Add(CommentOnPR(I.Number.Value, FormatTestMerge(I, true)));
306 
307  if (tasks.Any())
308  await Task.WhenAll(tasks).ConfigureAwait(false);
309  }
310  }
311  }
312  }
313 
320  #pragma warning disable CA1502 // TODO: Decomplexify
321  async Task TimerLoop(uint minutes, CancellationToken cancellationToken)
322  {
323  while (true)
324  try
325  {
326  await Task.Delay(TimeSpan.FromMinutes(minutes > Int32.MaxValue ? Int32.MaxValue : (int)minutes), cancellationToken).ConfigureAwait(false);
327  logger.LogDebug("Beginning auto update...");
328  await eventConsumer.HandleEvent(EventType.InstanceAutoUpdateStart, new List<string>(), cancellationToken).ConfigureAwait(false);
329  try
330  {
331  Models.User user = null;
332  await databaseContextFactory.UseContext(async (db) => user = await db.Users.Where(x => x.CanonicalName == Api.Models.User.AdminName.ToUpperInvariant()).FirstAsync(cancellationToken).ConfigureAwait(false)).ConfigureAwait(false);
333  var repositoryUpdateJob = new Job
334  {
335  Instance = new Models.Instance
336  {
337  Id = metadata.Id
338  },
339  Description = "Scheduled repository update",
340  CancelRightsType = RightsType.Repository,
341  CancelRight = (ulong)RepositoryRights.CancelPendingChanges,
342  StartedBy = user
343  };
344 
345  string deploySha = null;
346  await jobManager.RegisterOperation(repositoryUpdateJob, async (paramJob, databaseContext, progressReporter, jobCancellationToken) =>
347  {
348  var repositorySettingsTask = databaseContext.RepositorySettings.Where(x => x.InstanceId == metadata.Id).FirstAsync(jobCancellationToken);
349 
350  // assume 5 steps with synchronize
351  const int ProgressSections = 7;
352  const int ProgressStep = 100 / ProgressSections;
353 
354  const int NumSteps = 3;
355  var doneSteps = 0;
356 
357  Action<int> NextProgressReporter()
358  {
359  var tmpDoneSteps = doneSteps;
360  ++doneSteps;
361  return progress => progressReporter((progress + (100 * tmpDoneSteps)) / NumSteps);
362  }
363 
364  using (var repo = await RepositoryManager.LoadRepository(jobCancellationToken).ConfigureAwait(false))
365  {
366  if (repo == null)
367  {
368  logger.LogTrace("Aborting repo update, no repository!");
369  return;
370  }
371 
372  var startSha = repo.Head;
373  if (!repo.Tracking)
374  {
375  logger.LogTrace("Aborting repo update, not tracking origin!");
376  deploySha = startSha;
377  return;
378  }
379 
380  var repositorySettings = await repositorySettingsTask.ConfigureAwait(false);
381 
382  // the main point of auto update is to pull the remote
383  await repo.FetchOrigin(repositorySettings.AccessUser, repositorySettings.AccessToken, NextProgressReporter(), jobCancellationToken).ConfigureAwait(false);
384 
385  RevisionInformation currentRevInfo = null;
386  bool hasDbChanges = false;
387 
388  Task<RevisionInformation> LoadRevInfo() => databaseContext.RevisionInformations
389  .Where(x => x.CommitSha == startSha && x.Instance.Id == metadata.Id)
390  .Include(x => x.ActiveTestMerges).ThenInclude(x => x.TestMerge)
391  .FirstOrDefaultAsync(cancellationToken);
392 
393  async Task UpdateRevInfo(string currentHead, bool onOrigin)
394  {
395  if(currentRevInfo == null)
396  currentRevInfo = await LoadRevInfo().ConfigureAwait(false);
397 
398  if (currentRevInfo == default)
399  {
400  logger.LogWarning(Repository.Repository.OriginTrackingErrorTemplate, currentHead);
401  onOrigin = true;
402  }
403 
404  var attachedInstance = new Models.Instance
405  {
406  Id = metadata.Id
407  };
408  var oldRevInfo = currentRevInfo;
409  currentRevInfo = new RevisionInformation
410  {
411  CommitSha = currentHead,
412  OriginCommitSha = onOrigin ? currentHead : oldRevInfo.OriginCommitSha,
413  Instance = attachedInstance
414  };
415  if (!onOrigin)
416  currentRevInfo.ActiveTestMerges = new List<RevInfoTestMerge>(oldRevInfo.ActiveTestMerges);
417 
418  databaseContext.Instances.Attach(attachedInstance);
419  databaseContext.RevisionInformations.Add(currentRevInfo);
420  hasDbChanges = true;
421  }
422 
423  // take appropriate auto update actions
424  bool shouldSyncTracked;
425  if (repositorySettings.AutoUpdatesKeepTestMerges.Value)
426  {
427  logger.LogTrace("Preserving test merges...");
428 
429  var currentRevInfoTask = LoadRevInfo();
430 
431  var result = await repo.MergeOrigin(repositorySettings.CommitterName, repositorySettings.CommitterEmail, NextProgressReporter(), jobCancellationToken).ConfigureAwait(false);
432 
433  if (!result.HasValue)
434  throw new JobException("Merge conflict while preserving test merges!");
435 
436  currentRevInfo = await currentRevInfoTask.ConfigureAwait(false);
437 
438  var lastRevInfoWasOriginCommit = currentRevInfo == default || currentRevInfo.CommitSha == currentRevInfo.OriginCommitSha;
439  var stillOnOrigin = result.Value && lastRevInfoWasOriginCommit;
440 
441  var currentHead = repo.Head;
442  if (currentHead != startSha)
443  {
444  await UpdateRevInfo(currentHead, stillOnOrigin).ConfigureAwait(false);
445  shouldSyncTracked = stillOnOrigin;
446  }
447  else
448  shouldSyncTracked = false;
449  }
450  else
451  {
452  logger.LogTrace("Not preserving test merges...");
453  await repo.ResetToOrigin(NextProgressReporter(), jobCancellationToken).ConfigureAwait(false);
454 
455  var currentHead = repo.Head;
456 
457  currentRevInfo = await databaseContext.RevisionInformations
458  .Where(x => x.CommitSha == currentHead && x.Instance.Id == metadata.Id)
459  .FirstOrDefaultAsync(jobCancellationToken).ConfigureAwait(false);
460 
461  if (currentHead != startSha && currentRevInfo != default)
462  await UpdateRevInfo(currentHead, true).ConfigureAwait(false);
463 
464  shouldSyncTracked = true;
465  }
466 
467  // synch if necessary
468  if (repositorySettings.AutoUpdatesSynchronize.Value && startSha != repo.Head)
469  {
470  var pushedOrigin = await repo.Sychronize(repositorySettings.AccessUser, repositorySettings.AccessToken, repositorySettings.CommitterName, repositorySettings.CommitterEmail, NextProgressReporter(), shouldSyncTracked, jobCancellationToken).ConfigureAwait(false);
471  var currentHead = repo.Head;
472  if (currentHead != currentRevInfo.CommitSha)
473  await UpdateRevInfo(currentHead, pushedOrigin).ConfigureAwait(false);
474  }
475 
476  if(hasDbChanges)
477  try
478  {
479  await databaseContext.Save(cancellationToken).ConfigureAwait(false);
480  }
481  catch
482  {
483  await repo.ResetToSha(startSha, progressReporter, default).ConfigureAwait(false);
484  throw;
485  }
486 
487  progressReporter(5 * ProgressStep);
488  deploySha = repo.Head;
489  }
490  }, cancellationToken).ConfigureAwait(false);
491 
492  await jobManager.WaitForJobCompletion(repositoryUpdateJob, user, cancellationToken, default).ConfigureAwait(false);
493 
494  if (deploySha == null)
495  {
496  logger.LogTrace("Aborting auto update, repository error!");
497  continue;
498  }
499 
501  {
502  logger.LogTrace("Aborting auto update, same revision as latest CompileJob");
503  continue;
504  }
505 
506  // finally set up the job
507  var compileProcessJob = new Job
508  {
509  StartedBy = user,
510  Instance = repositoryUpdateJob.Instance,
511  Description = "Scheduled code deployment",
512  CancelRightsType = RightsType.DreamMaker,
513  CancelRight = (ulong)DreamMakerRights.CancelCompile
514  };
515 
516  await jobManager.RegisterOperation(compileProcessJob, CompileProcess, cancellationToken).ConfigureAwait(false);
517 
518  await jobManager.WaitForJobCompletion(compileProcessJob, user, cancellationToken, default).ConfigureAwait(false);
519  }
520  catch (OperationCanceledException)
521  {
522  logger.LogDebug("Cancelled auto update job!");
523  throw;
524  }
525  catch (Exception e)
526  {
527  logger.LogWarning("Error in auto update loop! Exception: {0}", e);
528  continue;
529  }
530  }
531  catch (OperationCanceledException)
532  {
533  break;
534  }
535 
536  logger.LogTrace("Leaving auto update loop...");
537  }
538  #pragma warning restore CA1502
539 
541  public void Rename(string newName)
542  {
543  if (String.IsNullOrWhiteSpace(newName))
544  throw new ArgumentNullException(nameof(newName));
545  metadata.Name = newName;
546  }
547 
549  public async Task StartAsync(CancellationToken cancellationToken)
550  {
551  await Task.WhenAll(SetAutoUpdateInterval(metadata.AutoUpdateInterval.Value), Configuration.StartAsync(cancellationToken), ByondManager.StartAsync(cancellationToken), Chat.StartAsync(cancellationToken), compileJobConsumer.StartAsync(cancellationToken)).ConfigureAwait(false);
552 
553  // dependent on so many things, its just safer this way
554  await Watchdog.StartAsync(cancellationToken).ConfigureAwait(false);
555 
556  CompileJob latestCompileJob = null;
557  await databaseContextFactory.UseContext(async db =>
558  {
559  latestCompileJob = await db.CompileJobs.Where(x => x.Job.Instance.Id == metadata.Id).OrderByDescending(x => x.Job.StoppedAt).FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
560  }).ConfigureAwait(false);
561  await dmbFactory.CleanUnusedCompileJobs(latestCompileJob, cancellationToken).ConfigureAwait(false);
562  }
563 
565  public Task StopAsync(CancellationToken cancellationToken) => Task.WhenAll(SetAutoUpdateInterval(0), Configuration.StopAsync(cancellationToken), ByondManager.StopAsync(cancellationToken), Watchdog.StopAsync(cancellationToken), Chat.StopAsync(cancellationToken), compileJobConsumer.StopAsync(cancellationToken));
566 
568  public async Task SetAutoUpdateInterval(uint newInterval)
569  {
570  Task toWait;
571  lock (this)
572  {
573  if (timerTask != null)
574  {
575  timerCts.Cancel();
576  toWait = timerTask;
577  }
578  else
579  toWait = Task.CompletedTask;
580  }
581 
582  await toWait.ConfigureAwait(false);
583  if (newInterval == 0)
584  return;
585  lock (this)
586  {
587  // race condition, just quit
588  if (timerTask != null)
589  return;
590  timerCts?.Dispose();
591  timerCts = new CancellationTokenSource();
592  timerTask = TimerLoop(newInterval, timerCts.Token);
593  }
594  }
595 
598  {
600  return null;
601  return dmbFactory.LockNextDmb(0)?.CompileJob;
602  }
603  }
604 }
+
string Name
The name of the User
Definition: User.cs:38
+ +
Manages the runtime of Jobs
Definition: IJobManager.cs:12
+
DbSet< Instance > Instances
The Instances in the IDatabaseContext
+
async 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....
Definition: Instance.cs:142
-
async Task SetAutoUpdateInterval(uint newInterval)
Change the Api.Models.Instance.AutoUpdateInterval for the IInstance
Definition: Instance.cs:568
+
async Task SetAutoUpdateInterval(uint newInterval)
Change the Api.Models.Instance.AutoUpdateInterval for the IInstance
Definition: Instance.cs:568
+
Task LoadCompileJob(CompileJob job, CancellationToken cancellationToken)
Load a new job into the ICompileJobConsumer
+
CompileJob CompileJob
The CompileJob of the .dmb
Definition: IDmbProvider.cs:29
-
CompileJob LatestCompileJob()
The latest staged CompileJob
Definition: Instance.cs:597
- +
CompileJob LatestCompileJob()
The latest staged CompileJob
Definition: Instance.cs:597
+ -
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
-
User MergedBy
See Api.Models.TestMerge.MergedBy
Definition: TestMerge.cs:13
-
Consumes EventTypes and takes the appropriate actions
+
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
+
User MergedBy
See Api.Models.TestMerge.MergedBy
Definition: TestMerge.cs:13
+
Consumes EventTypes and takes the appropriate actions
- - - -
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
+
Factory for scoping usage of IDatabaseContexts. Meant for use by Components
-
void Rename(string newName)
Rename the IInstance
Definition: Instance.cs:541
-
DateTimeOffset StoppedAt
When the Job stopped
Definition: Job.cs:37
-
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
+
void Rename(string newName)
Rename the IInstance
Definition: Instance.cs:541
+
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
async Task StartAsync(CancellationToken cancellationToken)
-
readonly ICompileJobConsumer compileJobConsumer
The ICompileJobConsumer for the Instance
Definition: Instance.cs:48
-
For managing connected chat services
Definition: IChat.cs:13
-
Repository(LibGit2Sharp.IRepository repository, IIOManager ioMananger, IEventConsumer eventConsumer, ICredentialsProvider credentialsProvider, ILogger< Repository > logger, Action onDispose)
Construct a Repository
Definition: Repository.cs:103
-
Job Job
See Api.Models.CompileJob.Job
Definition: CompileJob.cs:13
- +
readonly ICompileJobConsumer compileJobConsumer
The ICompileJobConsumer for the Instance
Definition: Instance.cs:48
+
Task StopAsync(CancellationToken cancellationToken)
+
For managing connected chat services
Definition: IChat.cs:13
+
Repository(LibGit2Sharp.IRepository repository, IIOManager ioMananger, IEventConsumer eventConsumer, ICredentialsProvider credentialsProvider, ILogger< Repository > logger, Action onDispose)
Construct a Repository
Definition: Repository.cs:103
+
Job Job
See Api.Models.CompileJob.Job
Definition: CompileJob.cs:13
+
Task RegisterOperation(Job job, Func< Job, IDatabaseContext, Action< int >, CancellationToken, Task > operation, CancellationToken cancellationToken)
Registers a given Job and begins running it
+ + - -
readonly IGitHubClientFactory gitHubClientFactory
The IGitHubClientFactory for the Instance
Definition: Instance.cs:73
-
readonly IEventConsumer eventConsumer
The IEventConsumer for the Instance
Definition: Instance.cs:68
-
Task timerTask
The auto update Task
Definition: Instance.cs:88
+ +
readonly IGitHubClientFactory gitHubClientFactory
The IGitHubClientFactory for the Instance
Definition: Instance.cs:73
+
readonly IEventConsumer eventConsumer
The IEventConsumer for the Instance
Definition: Instance.cs:68
+
Task timerTask
The auto update Task
Definition: Instance.cs:88
+
Task CleanUnusedCompileJobs(CompileJob exceptThisOne, CancellationToken cancellationToken)
Deletes all compile jobs that are inactive in the Game folder exceptThisOne
-
readonly Api.Models.Instance metadata
The Api.Models.Instance for the Instance
Definition: Instance.cs:83
-
Instance(Api.Models.Instance metadata, IRepositoryManager repositoryManager, IByondManager byondManager, IDreamMaker dreamMaker, IWatchdog watchdog, IChat chat, StaticFiles.IConfiguration configuration, ICompileJobConsumer compileJobConsumer, IDatabaseContextFactory databaseContextFactory, IDmbFactory dmbFactory, IJobManager jobManager, IEventConsumer eventConsumer, IGitHubClientFactory gitHubClientFactory, ILogger< Instance > logger)
Construct an Instance
Definition: Instance.cs:112
-
Func< CancellationToken, Task > PostComplete
A Task to run after the job completes. This will not affect the Api.Models.Internal.Job.StoppedAt time, unless it is cancelled or errors
Definition: Job.cs:34
-
CancellationTokenSource timerCts
CancellationTokenSource for timerTask
Definition: Instance.cs:93
+
readonly Api.Models.Instance metadata
The Api.Models.Instance for the Instance
Definition: Instance.cs:83
+
DateTimeOffset? StoppedAt
When the Job stopped
Definition: Job.cs:37
+
Instance(Api.Models.Instance metadata, IRepositoryManager repositoryManager, IByondManager byondManager, IDreamMaker dreamMaker, IWatchdog watchdog, IChat chat, StaticFiles.IConfiguration configuration, ICompileJobConsumer compileJobConsumer, IDatabaseContextFactory databaseContextFactory, IDmbFactory dmbFactory, IJobManager jobManager, IEventConsumer eventConsumer, IGitHubClientFactory gitHubClientFactory, ILogger< Instance > logger)
Construct an Instance
Definition: Instance.cs:112
+
IDmbProvider LockNextDmb(int lockCount)
Gets the next IDmbProvider
+
Func< CancellationToken, Task > PostComplete
A Task to run after the job completes. This will not affect the Api.Models.Internal....
Definition: Job.cs:34
+
CancellationTokenSource timerCts
CancellationTokenSource for timerTask
Definition: Instance.cs:93
-
async Task StopAsync(CancellationToken cancellationToken)
Definition: Watchdog.cs:997
-
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the Instance
Definition: Instance.cs:53
-
DbSet< RepositorySettings > RepositorySettings
The Models.RepositorySettings in the IDatabaseContext
+
async Task StopAsync(CancellationToken cancellationToken)
Definition: Watchdog.cs:1002
+
readonly IDatabaseContextFactory databaseContextFactory
The IDatabaseContextFactory for the Instance
Definition: Instance.cs:53
+
DbSet< RepositorySettings > RepositorySettings
The Models.RepositorySettings in the IDatabaseContext
-
For interacting with the instance services
Definition: IInstance.cs:17
-
DreamMakerRights
Rights for Models.DreamMaker
-
readonly ILogger< Instance > logger
The ILogger for the Instance
Definition: Instance.cs:78
-
For managing the BYOND installation
+
For interacting with the instance services
Definition: IInstance.cs:17
+
DreamMakerRights
Rights for Models.DreamMaker
+
bool DmbAvailable
If LockNextDmb will succeed
Definition: IDmbFactory.cs:22
+
readonly ILogger< Instance > logger
The ILogger for the Instance
Definition: Instance.cs:78
+ +
StaticFiles.IConfiguration Configuration
Definition: Instance.cs:38
async Task StopAsync(CancellationToken cancellationToken)
Definition: Chat.cs:546
-
RepositoryRights
Rights for a Models.Repository
-
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
-
readonly IDreamMaker dreamMaker
The IDreamMaker for the Instance
Definition: Instance.cs:43
-
async Task TimerLoop(uint minutes, CancellationToken cancellationToken)
Pull the repository and compile for every set of given minutes
Definition: Instance.cs:321
- -
DbSet< CompileJob > CompileJobs
The CompileJobs in the IDatabaseContext
+
RepositoryRights
Rights for a Models.Repository
+
readonly IDreamMaker dreamMaker
The IDreamMaker for the Instance
Definition: Instance.cs:43
+
async Task TimerLoop(uint minutes, CancellationToken cancellationToken)
Pull the repository and compile for every set of given minutes
Definition: Instance.cs:321
+
IGitHubClient CreateClient()
Create a client with anonymous authentication. Low rate limit
+
DbSet< CompileJob > CompileJobs
The CompileJobs in the IDatabaseContext
-
DbSet< DreamMakerSettings > DreamMakerSettings
The Models.DreamMakerSettings in the IDatabaseContext
+
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
+
DbSet< DreamMakerSettings > DreamMakerSettings
The Models.DreamMakerSettings in the IDatabaseContext
-
Instance Instance
The Models.Instance the RevisionInformation belongs to
+
Instance Instance
The Models.Instance the RevisionInformation belongs to
-
DbSet< RevisionInformation > RevisionInformations
The RevisionInformations in the IDatabaseContext
- +
DbSet< RevisionInformation > RevisionInformations
The RevisionInformations in the IDatabaseContext
+ -
Factory for creating and loading IRepositorys
-
async Task StartAsync(CancellationToken cancellationToken)
Definition: Watchdog.cs:963
+ +
async Task StartAsync(CancellationToken cancellationToken)
Definition: Watchdog.cs:968
async Task StartAsync(CancellationToken cancellationToken)
Definition: Chat.cs:534
- -
readonly IDmbFactory dmbFactory
The IDmbFactory for the Instance
Definition: Instance.cs:58
- + +
readonly IDmbFactory dmbFactory
The IDmbFactory for the Instance
Definition: Instance.cs:58
+
Task UseContext(Func< IDatabaseContext, Task > operation)
Run an operation in the scope of an IDatabaseContext
+ -
readonly IJobManager jobManager
The IJobManager for the Instance
Definition: Instance.cs:63
-
RevisionInformation RevisionInformation
See Api.Models.CompileJob.RevisionInformation
Definition: CompileJob.cs:24
-
DbSet< DreamDaemonSettings > DreamDaemonSettings
The Models.DreamDaemonSettings in the IDatabaseContext
-
async Task< IRepository > LoadRepository(CancellationToken cancellationToken)
Attempt to load the IRepository from the default location
+
readonly IJobManager jobManager
The IJobManager for the Instance
Definition: Instance.cs:63
+
Task WaitForJobCompletion(Job job, User canceller, CancellationToken jobCancellationToken, CancellationToken cancellationToken)
Wait for a given job to complete
+
RevisionInformation RevisionInformation
See Api.Models.CompileJob.RevisionInformation
Definition: CompileJob.cs:24
+
DbSet< DreamDaemonSettings > DreamDaemonSettings
The Models.DreamDaemonSettings in the IDatabaseContext
+
async Task< IRepository > LoadRepository(CancellationToken cancellationToken)
Attempt to load the IRepository from the default location
async Task StartAsync(CancellationToken cancellationToken)
Definition: Instance.cs:549
+
Task< bool > HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
Handle a given eventType
Task StopAsync(CancellationToken cancellationToken)
-
string AccessToken
The token/password to access the git repository with
+
string AccessToken
The token/password to access the git repository with
string PullRequestRevision
The sha of the pull request revision to merge. If not specified, the latest commit shall be used (sem...
-
List< RevInfoTestMerge > ActiveTestMerges
See Api.Models.RevisionInformation.ActiveTestMerges
-
string Comment
Optional comment about the test
- -
string OriginCommitSha
The sha of the most recent remote commit
-
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
- +
List< RevInfoTestMerge > ActiveTestMerges
See Api.Models.RevisionInformation.ActiveTestMerges
+
string Comment
Optional comment about the test
+ +
string OriginCommitSha
The sha of the most recent remote commit
+
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
+ - -
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
+
Runs and monitors the twin server controllers
Definition: IWatchdog.cs:12
diff --git a/_tgstation_8_server_8_host_2_components_2_interop_2_test_merge_8cs.html b/_tgstation_8_server_8_host_2_components_2_interop_2_test_merge_8cs.html index 5995f53e42..80a3a64858 100644 --- a/_tgstation_8_server_8_host_2_components_2_interop_2_test_merge_8cs.html +++ b/_tgstation_8_server_8_host_2_components_2_interop_2_test_merge_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/TestMerge.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Interop
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_tgstation_8_server_8_host_2_components_2_interop_2_test_merge_8cs_source.html b/_tgstation_8_server_8_host_2_components_2_interop_2_test_merge_8cs_source.html index 37a48c9985..73a7b2812f 100644 --- a/_tgstation_8_server_8_host_2_components_2_interop_2_test_merge_8cs_source.html +++ b/_tgstation_8_server_8_host_2_components_2_interop_2_test_merge_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop/TestMerge.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestMerge.cs
-Go to the documentation of this file.
1 using System;
2 using System.Globalization;
4 
5 namespace Tgstation.Server.Host.Components.Interop
6 {
10  sealed class TestMerge : TestMergeBase
11  {
15  public string TimeMerged { get; set; }
16 
20  public RevisionInformation Revision { get; set; }
21 
27  public TestMerge(Models.TestMerge testMerge, RevisionInformation revision) : base(testMerge)
28  {
29  TimeMerged = testMerge.MergedAt.Ticks.ToString(CultureInfo.InvariantCulture);
30  Revision = revision ?? throw new ArgumentNullException(nameof(revision));
31  }
32  }
33 }
- - -
Layer of test merge data required internally
Definition: TestMergeBase.cs:9
+Go to the documentation of this file.
1 using System;
2 using System.Globalization;
4 
6 {
10  sealed class TestMerge : TestMergeBase
11  {
15  public string TimeMerged { get; set; }
16 
20  public RevisionInformation Revision { get; set; }
21 
27  public TestMerge(Models.TestMerge testMerge, RevisionInformation revision) : base(testMerge)
28  {
29  TimeMerged = testMerge.MergedAt.Ticks.ToString(CultureInfo.InvariantCulture);
30  Revision = revision ?? throw new ArgumentNullException(nameof(revision));
31  }
32  }
33 }
string TimeMerged
The unix time of when the test merge was applied
Definition: TestMerge.cs:15
+ +
Layer of test merge data required internally
Definition: TestMergeBase.cs:9
- -
This model mirrors /datum/tgs_revision_information/test_merge
Definition: TestMerge.cs:10
-
TestMerge(Models.TestMerge testMerge, RevisionInformation revision)
Construct a TestMerge
Definition: TestMerge.cs:27
- -
Represents information about a current git revison
- + +
This model mirrors /datum/tgs_revision_information/test_merge
Definition: TestMerge.cs:10
+
RevisionInformation Revision
The RevisionInformation of the TestMerge
Definition: TestMerge.cs:20
+ +
TestMerge(Models.TestMerge testMerge, RevisionInformation revision)
Construct a TestMerge
Definition: TestMerge.cs:27
+ +
Represents information about a current git revison
+
diff --git a/_tgstation_8_server_8_host_2_components_2_repository_2_repository_8cs.html b/_tgstation_8_server_8_host_2_components_2_repository_2_repository_8cs.html index fc8f557abb..211e6f055c 100644 --- a/_tgstation_8_server_8_host_2_components_2_repository_2_repository_8cs.html +++ b/_tgstation_8_server_8_host_2_components_2_repository_2_repository_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Repository/Repository.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Repository
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_tgstation_8_server_8_host_2_components_2_repository_2_repository_8cs_source.html b/_tgstation_8_server_8_host_2_components_2_repository_2_repository_8cs_source.html index c51af068bb..979139b694 100644 --- a/_tgstation_8_server_8_host_2_components_2_repository_2_repository_8cs_source.html +++ b/_tgstation_8_server_8_host_2_components_2_repository_2_repository_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Repository/Repository.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Repository.cs
-Go to the documentation of this file.
1 using LibGit2Sharp;
2 using LibGit2Sharp.Handlers;
3 using Microsoft.Extensions.Logging;
4 using System;
5 using System.Collections.Generic;
6 using System.Globalization;
7 using System.Linq;
8 using System.Threading;
9 using System.Threading.Tasks;
12 using Tgstation.Server.Host.IO;
13 
14 namespace Tgstation.Server.Host.Components.Repository
15 {
17  sealed class Repository : IRepository
18  {
22  public const string GitHubUrl = "://github.com/";
23 
27  public const string OriginTrackingErrorTemplate = "Unable to determine most recent origin commit of {0}. Marking it as an origin commit. This may result in invalid git metadata until the next hard reset to an origin reference.";
28 
32  public const string RemoteTemporaryBranchName = "___TGSTempBranch";
33 
34  const string UnknownReference = "<UNKNOWN>";
35 
37  public bool IsGitHubRepository { get; }
38 
40  public string GitHubOwner { get; }
41 
43  public string GitHubRepoName { get; }
44 
46  public bool Tracking => Reference != null && repository.Head.IsTracking;
47 
49  public string Head => repository.Head.Tip.Sha;
50 
52  public string Reference => repository.Head.FriendlyName;
53 
55  public string Origin => repository.Network.Remotes.First().Url;
56 
60  readonly LibGit2Sharp.IRepository repository;
61 
66 
71 
76 
80  readonly ILogger<Repository> logger;
81 
85  readonly Action onDispose;
86 
92  static CheckoutProgressHandler CheckoutProgressHandler(Action<int> progressReporter) => (a, completedSteps, totalSteps) => progressReporter((int)(((float)completedSteps) / totalSteps * 100));
93 
103  public Repository(LibGit2Sharp.IRepository repository, IIOManager ioMananger, IEventConsumer eventConsumer, ICredentialsProvider credentialsProvider, ILogger<Repository> logger, Action onDispose)
104  {
105  this.repository = repository ?? throw new ArgumentNullException(nameof(repository));
106  this.ioMananger = ioMananger ?? throw new ArgumentNullException(nameof(ioMananger));
107  this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
108  this.credentialsProvider = credentialsProvider ?? throw new ArgumentNullException(nameof(credentialsProvider));
109  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
110  this.onDispose = onDispose ?? throw new ArgumentNullException(nameof(onDispose));
111  IsGitHubRepository = Origin.Contains(GitHubUrl, StringComparison.InvariantCultureIgnoreCase);
112  if (IsGitHubRepository)
113  {
114  GetRepositoryOwnerName(Origin, out var owner, out var name);
115  GitHubOwner = owner;
116  GitHubRepoName = name;
117  }
118  }
119 
121  public void Dispose()
122  {
123  logger.LogTrace("Disposing...");
124  repository.Dispose();
125  onDispose.Invoke();
126  }
127 
128  void GetRepositoryOwnerName(string remote, out string owner, out string name)
129  {
130  // Assume standard gh format: [(git)|(https)]://github.com/owner/repo(.git)[0-1]
131  // Yes use .git twice in case it was weird
132  var toRemove = new string[] { ".git", "/", ".git" };
133  foreach (string item in toRemove)
134  if (remote.EndsWith(item, StringComparison.OrdinalIgnoreCase))
135  remote = remote.Substring(0, remote.LastIndexOf(item, StringComparison.OrdinalIgnoreCase));
136  var splits = remote.Split('/');
137  name = splits[splits.Length - 1];
138  owner = splits[splits.Length - 2].Split('.')[0];
139 
140  logger.LogTrace("GetRepositoryOwnerName({0}) => {1} / {2}", remote, owner, name);
141  }
142 
151  PushOptions GeneratePushOptions(Action<int> progressReporter, string username, string password, CancellationToken cancellationToken) => new PushOptions
152  {
153  OnPackBuilderProgress = (stage, current, total) =>
154  {
155  var baseProgress = stage == PackBuilderStage.Counting ? 0 : 25;
156  progressReporter(baseProgress + ((int)(25 * ((float)current) / total)));
157  return !cancellationToken.IsCancellationRequested;
158  },
159  OnNegotiationCompletedBeforePush = (a) => !cancellationToken.IsCancellationRequested,
160  OnPushTransferProgress = (a, sentBytes, totalBytes) =>
161  {
162  progressReporter(50 + ((int)(50 * ((float)sentBytes) / totalBytes)));
163  return !cancellationToken.IsCancellationRequested;
164  },
165  CredentialsProvider = credentialsProvider.GenerateHandler(username, password)
166  };
167 
174  void RawCheckout(string committish, Action<int> progressReporter, CancellationToken cancellationToken)
175  {
176  logger.LogTrace("Checkout: {0}", committish);
177 
178  progressReporter(0);
179  cancellationToken.ThrowIfCancellationRequested();
180 
181  Commands.Checkout(repository, committish, new CheckoutOptions
182  {
183  CheckoutModifiers = CheckoutModifiers.Force,
184  OnCheckoutProgress = CheckoutProgressHandler(progressReporter)
185  });
186 
187  cancellationToken.ThrowIfCancellationRequested();
188 
189  repository.RemoveUntrackedFiles();
190  }
191 
193  #pragma warning disable CA1506 // TODO: Decomplexify
194  public async Task<bool?> AddTestMerge(TestMergeParameters testMergeParameters, string committerName, string committerEmail, string username, string password, Action<int> progressReporter, CancellationToken cancellationToken)
195  {
196  if (testMergeParameters == null)
197  throw new ArgumentNullException(nameof(testMergeParameters));
198  if (committerName == null)
199  throw new ArgumentNullException(nameof(committerName));
200  if (committerEmail == null)
201  throw new ArgumentNullException(nameof(committerEmail));
202  if (progressReporter == null)
203  throw new ArgumentNullException(nameof(progressReporter));
204 
205  logger.LogDebug("Begin AddTestMerge: #{0} at {1} ({4}) by <{2} ({3})>", testMergeParameters.Number, testMergeParameters.PullRequestRevision?.Substring(0, 7), committerName, committerEmail, testMergeParameters.Comment);
206 
207  if (!IsGitHubRepository)
208  throw new InvalidOperationException("Test merging is only available on GitHub hosted origin repositories!");
209 
210  var commitMessage = String.Format(CultureInfo.InvariantCulture, "Test merge of pull request #{0}{1}{2}", testMergeParameters.Number.Value, testMergeParameters.Comment != null ? Environment.NewLine : String.Empty, testMergeParameters.Comment ?? String.Empty);
211 
212  var prBranchName = String.Format(CultureInfo.InvariantCulture, "pr-{0}", testMergeParameters.Number);
213  var localBranchName = String.Format(CultureInfo.InvariantCulture, "pull/{0}/headrefs/heads/{1}", testMergeParameters.Number, prBranchName);
214 
215  var refSpec = String.Format(CultureInfo.InvariantCulture, "pull/{0}/head:{1}", testMergeParameters.Number, prBranchName);
216  var refSpecList = new List<string> { refSpec };
217  var logMessage = String.Format(CultureInfo.InvariantCulture, "Merge remote pull request #{0}", testMergeParameters.Number);
218 
219  var originalCommit = repository.Head;
220 
221  MergeResult result = null;
222 
223  var sig = new Signature(new Identity(committerName, committerEmail), DateTimeOffset.Now);
224  await Task.Factory.StartNew(() =>
225  {
226  try
227  {
228  try
229  {
230  logger.LogTrace("Fetching refspec {0}...", refSpec);
231 
232  var remote = repository.Network.Remotes.First();
233  progressReporter(0);
234  Commands.Fetch((LibGit2Sharp.Repository)repository, remote.Name, refSpecList, new FetchOptions
235  {
236  Prune = true,
237  OnProgress = (a) => !cancellationToken.IsCancellationRequested,
238  OnTransferProgress = (a) =>
239  {
240  var percentage = 50 * (((float)a.IndexedObjects + a.ReceivedObjects) / (a.TotalObjects * 2));
241  progressReporter((int)percentage);
242  return !cancellationToken.IsCancellationRequested;
243  },
244  OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
245  CredentialsProvider = credentialsProvider.GenerateHandler(username, password)
246  }, logMessage);
247  }
248  catch (UserCancelledException) { }
249 
250  cancellationToken.ThrowIfCancellationRequested();
251 
252  repository.RemoveUntrackedFiles();
253 
254  cancellationToken.ThrowIfCancellationRequested();
255 
256  testMergeParameters.PullRequestRevision = repository.Lookup(testMergeParameters.PullRequestRevision ?? localBranchName).Sha;
257 
258  cancellationToken.ThrowIfCancellationRequested();
259 
260  logger.LogTrace("Merging {0} into {1}...", testMergeParameters.PullRequestRevision.Substring(0, 7), Reference);
261 
262  result = repository.Merge(testMergeParameters.PullRequestRevision, sig, new MergeOptions
263  {
264  CommitOnSuccess = commitMessage == null,
265  FailOnConflict = true,
266  FastForwardStrategy = FastForwardStrategy.NoFastForward,
267  SkipReuc = true,
268  OnCheckoutProgress = (a, completedSteps, totalSteps) => progressReporter(50 + ((int)(((float)completedSteps) / totalSteps * 50)))
269  });
270  }
271  finally
272  {
273  repository.Branches.Remove(localBranchName);
274  }
275 
276  cancellationToken.ThrowIfCancellationRequested();
277 
278  if (result.Status == MergeStatus.Conflicts)
279  {
280  var revertTo = originalCommit.CanonicalName ?? originalCommit.Tip.Sha;
281  logger.LogDebug("Merge conflict, aborting and reverting to {0}", revertTo);
282  RawCheckout(revertTo, progressReporter, cancellationToken);
283  cancellationToken.ThrowIfCancellationRequested();
284  }
285 
286  repository.RemoveUntrackedFiles();
287  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
288 
289  if (result.Status == MergeStatus.Conflicts)
290  {
291  await eventConsumer.HandleEvent(EventType.RepoMergeConflict, new List<string> { originalCommit.Tip.Sha, testMergeParameters.PullRequestRevision, originalCommit.FriendlyName ?? UnknownReference, prBranchName }, cancellationToken).ConfigureAwait(false);
292  return null;
293  }
294 
295  if (commitMessage != null && result.Status != MergeStatus.UpToDate)
296  {
297  logger.LogTrace("Committing merge: \"{0}\"...", commitMessage);
298  await Task.Factory.StartNew(() => repository.Commit(commitMessage, sig, sig, new CommitOptions
299  {
300  PrettifyMessage = true
301  }), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
302  }
303 
304  await eventConsumer.HandleEvent(EventType.RepoMergePullRequest, new List<string> { testMergeParameters.Number.ToString(), testMergeParameters.PullRequestRevision, testMergeParameters.Comment }, cancellationToken).ConfigureAwait(false);
305 
306  return result.Status != MergeStatus.NonFastForward;
307  }
308  #pragma warning restore CA1506
309 
311  public async Task CheckoutObject(string committish, Action<int> progressReporter, CancellationToken cancellationToken)
312  {
313  if (committish == null)
314  throw new ArgumentNullException(nameof(committish));
315  if (progressReporter == null)
316  throw new ArgumentNullException(nameof(progressReporter));
317  logger.LogDebug("Checkout object: {0}...", committish);
318  await eventConsumer.HandleEvent(EventType.RepoCheckout, new List<string> { committish }, cancellationToken).ConfigureAwait(false);
319  await Task.Factory.StartNew(() =>
320  {
321  repository.RemoveUntrackedFiles();
322  RawCheckout(committish, progressReporter, cancellationToken);
323  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
324  }
325 
327  public async Task FetchOrigin(string username, string password, Action<int> progressReporter, CancellationToken cancellationToken)
328  {
329  if (progressReporter == null)
330  throw new ArgumentNullException(nameof(progressReporter));
331  logger.LogDebug("Fetch origin...");
332  await eventConsumer.HandleEvent(EventType.RepoFetch, Array.Empty<string>(), cancellationToken).ConfigureAwait(false);
333  await Task.Factory.StartNew(() =>
334  {
335  var remote = repository.Network.Remotes.First();
336  try
337  {
338  Commands.Fetch((LibGit2Sharp.Repository)repository, remote.Name, remote.FetchRefSpecs.Select(x => x.Specification), new FetchOptions
339  {
340  Prune = true,
341  OnProgress = (a) => !cancellationToken.IsCancellationRequested,
342  OnTransferProgress = (a) =>
343  {
344  var percentage = 100 * (((float)a.IndexedObjects + a.ReceivedObjects) / (a.TotalObjects * 2));
345  progressReporter((int)percentage);
346  return !cancellationToken.IsCancellationRequested;
347  },
348  OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
349  CredentialsProvider = credentialsProvider.GenerateHandler(username, password)
350  }, "Fetch origin commits");
351  }
352  catch (UserCancelledException)
353  {
354  cancellationToken.ThrowIfCancellationRequested();
355  }
356  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
357  }
358 
367  Task PushHeadToTemporaryBranch(string username, string password, Action<int> progressReporter, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
368  {
369  logger.LogInformation("Pushing changes to temporary remote branch...");
370  var branch = repository.CreateBranch(RemoteTemporaryBranchName);
371  try
372  {
373  cancellationToken.ThrowIfCancellationRequested();
374  var remote = repository.Network.Remotes.First();
375  try
376  {
377  var forcePushString = String.Format(CultureInfo.InvariantCulture, "+{0}:{0}", branch.CanonicalName);
378  repository.Network.Push(remote, forcePushString, GeneratePushOptions(progress => progressReporter((int)(0.9f * progress)), username, password, cancellationToken));
379  var removalString = String.Format(CultureInfo.InvariantCulture, ":{0}", branch.CanonicalName);
380  repository.Network.Push(remote, removalString, GeneratePushOptions(progress => progressReporter(90 + (int)(0.1f * progress)), username, password, cancellationToken));
381  }
382  catch (UserCancelledException)
383  {
384  cancellationToken.ThrowIfCancellationRequested();
385  }
386  catch(LibGit2SharpException e)
387  {
388  logger.LogWarning("Unable to push to temporary branch! Exception: {0}", e);
389  }
390  }
391  finally
392  {
393  repository.Branches.Remove(branch);
394  }
395  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
396 
398  public async Task ResetToOrigin(Action<int> progressReporter, CancellationToken cancellationToken)
399  {
400  if (progressReporter == null)
401  throw new ArgumentNullException(nameof(progressReporter));
402  if (!Tracking)
403  throw new JobException("Cannot reset to origin while not on a tracked reference!");
404  logger.LogTrace("Reset to origin...");
405  var trackedBranch = repository.Head.TrackedBranch;
406  await eventConsumer.HandleEvent(EventType.RepoResetOrigin, new List<string> { trackedBranch.FriendlyName, trackedBranch.Tip.Sha }, cancellationToken).ConfigureAwait(false);
407  await ResetToSha(trackedBranch.Tip.Sha, progressReporter, cancellationToken).ConfigureAwait(false);
408  }
409 
411  public Task ResetToSha(string sha, Action<int> progressReporter, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
412  {
413  if (sha == null)
414  throw new ArgumentNullException(nameof(sha));
415  if (progressReporter == null)
416  throw new ArgumentNullException(nameof(progressReporter));
417 
418  logger.LogDebug("Reset to sha: {0}", sha.Substring(0, 7));
419 
420  repository.RemoveUntrackedFiles();
421  cancellationToken.ThrowIfCancellationRequested();
422 
423  var gitObject = repository.Lookup(sha, ObjectType.Commit);
424  cancellationToken.ThrowIfCancellationRequested();
425 
426  if (gitObject == null)
427  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Cannot reset to non-existent SHA: {0}", sha));
428 
429  repository.Reset(ResetMode.Hard, gitObject.Peel<Commit>(), new CheckoutOptions
430  {
431  OnCheckoutProgress = CheckoutProgressHandler(progressReporter)
432  });
433  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
434 
436  public async Task CopyTo(string path, CancellationToken cancellationToken)
437  {
438  if (path == null)
439  throw new ArgumentNullException(nameof(path));
440  logger.LogTrace("Copying to {0}...", path);
441  await ioMananger.CopyDirectory(".", path, new List<string> { ".git" }, cancellationToken).ConfigureAwait(false);
442  }
443 
445  public async Task<bool?> MergeOrigin(string committerName, string committerEmail, Action<int> progressReporter, CancellationToken cancellationToken)
446  {
447  if (progressReporter == null)
448  throw new ArgumentNullException(nameof(progressReporter));
449 
450  MergeResult result = null;
451  Branch trackedBranch = null;
452 
453  var oldHead = repository.Head;
454  var oldTip = oldHead.Tip;
455 
456  await Task.Factory.StartNew(() =>
457  {
458  if (!Tracking)
459  throw new JobException("Cannot reset to origin while not on a tracked reference!");
460 
461  repository.RemoveUntrackedFiles();
462 
463  cancellationToken.ThrowIfCancellationRequested();
464 
465  trackedBranch = repository.Head.TrackedBranch;
466  logger.LogDebug("Merge origin/{2}: <{0} ({1})>", committerName, committerEmail, trackedBranch.FriendlyName);
467  result = repository.Merge(trackedBranch, new Signature(new Identity(committerName, committerEmail), DateTimeOffset.Now), new MergeOptions
468  {
469  CommitOnSuccess = true,
470  FailOnConflict = true,
471  FastForwardStrategy = FastForwardStrategy.Default,
472  SkipReuc = true,
473  OnCheckoutProgress = CheckoutProgressHandler(progressReporter)
474  });
475 
476  cancellationToken.ThrowIfCancellationRequested();
477 
478  if (result.Status == MergeStatus.Conflicts)
479  {
480  logger.LogDebug("Merge conflict, aborting and reverting to {0}", oldHead.FriendlyName);
481  repository.Reset(ResetMode.Hard, oldTip, new CheckoutOptions
482  {
483  OnCheckoutProgress = CheckoutProgressHandler(progressReporter)
484  });
485  cancellationToken.ThrowIfCancellationRequested();
486  }
487 
488  repository.RemoveUntrackedFiles();
489  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
490 
491  if (result.Status == MergeStatus.Conflicts)
492  {
493  await eventConsumer.HandleEvent(EventType.RepoMergeConflict, new List<string> { oldTip.Sha, trackedBranch.Tip.Sha, oldHead.FriendlyName ?? UnknownReference, trackedBranch.FriendlyName }, cancellationToken).ConfigureAwait(false);
494  return null;
495  }
496 
497  return result.Status == MergeStatus.FastForward;
498  }
499 
501  public async Task<bool> Sychronize(string username, string password, string committerName, string committerEmail, Action<int> progressReporter, bool synchronizeTrackedBranch, CancellationToken cancellationToken)
502  {
503  if (committerName == null)
504  throw new ArgumentNullException(nameof(committerName));
505  if (committerEmail == null)
506  throw new ArgumentNullException(nameof(committerEmail));
507  if (progressReporter == null)
508  throw new ArgumentNullException(nameof(progressReporter));
509 
510  if (username == null && password == null)
511  {
512  logger.LogTrace("Not synchronizing due to lack of credentials!");
513  return false;
514  }
515 
516  logger.LogTrace("Begin Synchronize...");
517 
518  if (username == null)
519  throw new ArgumentNullException(nameof(username));
520  if (password == null)
521  throw new ArgumentNullException(nameof(password));
522 
523  var startHead = Head;
524 
525  logger.LogTrace("Configuring <{0} ({1})> as author/committer", committerName, committerEmail);
526  await Task.Factory.StartNew(() =>
527  {
528  repository.Config.Set("user.name", committerName);
529  cancellationToken.ThrowIfCancellationRequested();
530  repository.Config.Set("user.email", committerEmail);
531  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
532 
533  cancellationToken.ThrowIfCancellationRequested();
534  try
535  {
536  if (!await eventConsumer.HandleEvent(EventType.RepoPreSynchronize, new List<string> { ioMananger.ResolvePath(".") }, cancellationToken).ConfigureAwait(false))
537  {
538  logger.LogDebug("Aborted synchronize due to event handler response!");
539  return false;
540  }
541  }
542  finally
543  {
544  logger.LogTrace("Resetting and cleaning untracked files...");
545  await Task.Factory.StartNew(() =>
546  {
547  repository.RemoveUntrackedFiles();
548  cancellationToken.ThrowIfCancellationRequested();
549  repository.Reset(ResetMode.Hard, repository.Head.Tip, new CheckoutOptions
550  {
551  OnCheckoutProgress = CheckoutProgressHandler(progress => progressReporter(progress / 10))
552  });
553  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
554  }
555 
556  void FinalReporter(int progress) => progressReporter((int)(((float)progress) / 100 * 90));
557 
558  if (!synchronizeTrackedBranch)
559  {
560  await PushHeadToTemporaryBranch(username, password, FinalReporter, cancellationToken).ConfigureAwait(false);
561  return false;
562  }
563 
564  var sameHead = Head == startHead;
565  if (sameHead || !Tracking)
566  {
567  logger.LogTrace("Aborted synchronize due to {0}!", sameHead ? "lack of changes" : "not being on tracked reference");
568  return false;
569  }
570 
571  logger.LogInformation("Synchronizing with origin...");
572 
573  return await Task.Factory.StartNew(() =>
574  {
575  var remote = repository.Network.Remotes.First();
576  try
577  {
578  repository.Network.Push(repository.Head, GeneratePushOptions(FinalReporter, username, password, cancellationToken));
579  return true;
580  }
581  catch (NonFastForwardException)
582  {
583  logger.LogInformation("Synchronize aborted, non-fast forward!");
584  return false;
585  }
586  catch (UserCancelledException e)
587  {
588  cancellationToken.ThrowIfCancellationRequested();
589  throw new InvalidOperationException("Caught UserCancelledException without cancellationToken triggering", e);
590  }
591  catch (LibGit2SharpException e)
592  {
593  logger.LogWarning("Unable to make synchronization push! Exception: {0}", e);
594  return false;
595  }
596  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
597  }
598 
600  public Task<bool> IsSha(string committish, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
601  {
602  // check if it's a tag
603  var gitObject = repository.Lookup(committish, ObjectType.Tag);
604  if (gitObject != null)
605  return false;
606  cancellationToken.ThrowIfCancellationRequested();
607 
608  // check if it's a branch
609  if (repository.Branches[committish] != null)
610  return false;
611  cancellationToken.ThrowIfCancellationRequested();
612 
613  // err on the side of references, if we can't look it up, assume its a reference
614  if (repository.Lookup<Commit>(committish) != null)
615  return true;
616  return false;
617  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
618  }
619 }
Consumes EventTypes and takes the appropriate actions
+Go to the documentation of this file.
1 using LibGit2Sharp;
2 using LibGit2Sharp.Handlers;
3 using Microsoft.Extensions.Logging;
4 using System;
5 using System.Collections.Generic;
6 using System.Globalization;
7 using System.Linq;
8 using System.Threading;
9 using System.Threading.Tasks;
12 using Tgstation.Server.Host.IO;
13 
15 {
17  sealed class Repository : IRepository
18  {
22  public const string GitHubUrl = "://github.com/";
23 
27  public const string OriginTrackingErrorTemplate = "Unable to determine most recent origin commit of {0}. Marking it as an origin commit. This may result in invalid git metadata until the next hard reset to an origin reference.";
28 
32  public const string RemoteTemporaryBranchName = "___TGSTempBranch";
33 
34  const string UnknownReference = "<UNKNOWN>";
35 
37  public bool IsGitHubRepository { get; }
38 
40  public string GitHubOwner { get; }
41 
43  public string GitHubRepoName { get; }
44 
46  public bool Tracking => Reference != null && repository.Head.IsTracking;
47 
49  public string Head => repository.Head.Tip.Sha;
50 
52  public string Reference => repository.Head.FriendlyName;
53 
55  public string Origin => repository.Network.Remotes.First().Url;
56 
60  readonly LibGit2Sharp.IRepository repository;
61 
66 
71 
76 
80  readonly ILogger<Repository> logger;
81 
85  readonly Action onDispose;
86 
92  static CheckoutProgressHandler CheckoutProgressHandler(Action<int> progressReporter) => (a, completedSteps, totalSteps) => progressReporter((int)(((float)completedSteps) / totalSteps * 100));
93 
104  {
105  this.repository = repository ?? throw new ArgumentNullException(nameof(repository));
106  this.ioMananger = ioMananger ?? throw new ArgumentNullException(nameof(ioMananger));
107  this.eventConsumer = eventConsumer ?? throw new ArgumentNullException(nameof(eventConsumer));
108  this.credentialsProvider = credentialsProvider ?? throw new ArgumentNullException(nameof(credentialsProvider));
109  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
110  this.onDispose = onDispose ?? throw new ArgumentNullException(nameof(onDispose));
111  IsGitHubRepository = Origin.Contains(GitHubUrl, StringComparison.InvariantCultureIgnoreCase);
112  if (IsGitHubRepository)
113  {
114  GetRepositoryOwnerName(Origin, out var owner, out var name);
115  GitHubOwner = owner;
116  GitHubRepoName = name;
117  }
118  }
119 
121  public void Dispose()
122  {
123  logger.LogTrace("Disposing...");
124  repository.Dispose();
125  onDispose.Invoke();
126  }
127 
128  void GetRepositoryOwnerName(string remote, out string owner, out string name)
129  {
130  // Assume standard gh format: [(git)|(https)]://github.com/owner/repo(.git)[0-1]
131  // Yes use .git twice in case it was weird
132  var toRemove = new string[] { ".git", "/", ".git" };
133  foreach (string item in toRemove)
134  if (remote.EndsWith(item, StringComparison.OrdinalIgnoreCase))
135  remote = remote.Substring(0, remote.LastIndexOf(item, StringComparison.OrdinalIgnoreCase));
136  var splits = remote.Split('/');
137  name = splits[splits.Length - 1];
138  owner = splits[splits.Length - 2].Split('.')[0];
139 
140  logger.LogTrace("GetRepositoryOwnerName({0}) => {1} / {2}", remote, owner, name);
141  }
142 
151  PushOptions GeneratePushOptions(Action<int> progressReporter, string username, string password, CancellationToken cancellationToken) => new PushOptions
152  {
153  OnPackBuilderProgress = (stage, current, total) =>
154  {
155  var baseProgress = stage == PackBuilderStage.Counting ? 0 : 25;
156  progressReporter(baseProgress + ((int)(25 * ((float)current) / total)));
157  return !cancellationToken.IsCancellationRequested;
158  },
159  OnNegotiationCompletedBeforePush = (a) => !cancellationToken.IsCancellationRequested,
160  OnPushTransferProgress = (a, sentBytes, totalBytes) =>
161  {
162  progressReporter(50 + ((int)(50 * ((float)sentBytes) / totalBytes)));
163  return !cancellationToken.IsCancellationRequested;
164  },
165  CredentialsProvider = credentialsProvider.GenerateHandler(username, password)
166  };
167 
174  void RawCheckout(string committish, Action<int> progressReporter, CancellationToken cancellationToken)
175  {
176  logger.LogTrace("Checkout: {0}", committish);
177 
178  progressReporter(0);
179  cancellationToken.ThrowIfCancellationRequested();
180 
181  Commands.Checkout(repository, committish, new CheckoutOptions
182  {
183  CheckoutModifiers = CheckoutModifiers.Force,
184  OnCheckoutProgress = CheckoutProgressHandler(progressReporter)
185  });
186 
187  cancellationToken.ThrowIfCancellationRequested();
188 
189  repository.RemoveUntrackedFiles();
190  }
191 
193  #pragma warning disable CA1506 // TODO: Decomplexify
194  public async Task<bool?> AddTestMerge(TestMergeParameters testMergeParameters, string committerName, string committerEmail, string username, string password, Action<int> progressReporter, CancellationToken cancellationToken)
195  {
196  if (testMergeParameters == null)
197  throw new ArgumentNullException(nameof(testMergeParameters));
198  if (committerName == null)
199  throw new ArgumentNullException(nameof(committerName));
200  if (committerEmail == null)
201  throw new ArgumentNullException(nameof(committerEmail));
202  if (progressReporter == null)
203  throw new ArgumentNullException(nameof(progressReporter));
204 
205  logger.LogDebug("Begin AddTestMerge: #{0} at {1} ({4}) by <{2} ({3})>", testMergeParameters.Number, testMergeParameters.PullRequestRevision?.Substring(0, 7), committerName, committerEmail, testMergeParameters.Comment);
206 
207  if (!IsGitHubRepository)
208  throw new InvalidOperationException("Test merging is only available on GitHub hosted origin repositories!");
209 
210  var commitMessage = String.Format(CultureInfo.InvariantCulture, "Test merge of pull request #{0}{1}{2}", testMergeParameters.Number.Value, testMergeParameters.Comment != null ? Environment.NewLine : String.Empty, testMergeParameters.Comment ?? String.Empty);
211 
212  var prBranchName = String.Format(CultureInfo.InvariantCulture, "pr-{0}", testMergeParameters.Number);
213  var localBranchName = String.Format(CultureInfo.InvariantCulture, "pull/{0}/headrefs/heads/{1}", testMergeParameters.Number, prBranchName);
214 
215  var refSpec = String.Format(CultureInfo.InvariantCulture, "pull/{0}/head:{1}", testMergeParameters.Number, prBranchName);
216  var refSpecList = new List<string> { refSpec };
217  var logMessage = String.Format(CultureInfo.InvariantCulture, "Merge remote pull request #{0}", testMergeParameters.Number);
218 
219  var originalCommit = repository.Head;
220 
221  MergeResult result = null;
222 
223  var sig = new Signature(new Identity(committerName, committerEmail), DateTimeOffset.Now);
224  await Task.Factory.StartNew(() =>
225  {
226  try
227  {
228  try
229  {
230  logger.LogTrace("Fetching refspec {0}...", refSpec);
231 
232  var remote = repository.Network.Remotes.First();
233  progressReporter(0);
234  Commands.Fetch((LibGit2Sharp.Repository)repository, remote.Name, refSpecList, new FetchOptions
235  {
236  Prune = true,
237  OnProgress = (a) => !cancellationToken.IsCancellationRequested,
238  OnTransferProgress = (a) =>
239  {
240  var percentage = 50 * (((float)a.IndexedObjects + a.ReceivedObjects) / (a.TotalObjects * 2));
241  progressReporter((int)percentage);
242  return !cancellationToken.IsCancellationRequested;
243  },
244  OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
246  }, logMessage);
247  }
248  catch (UserCancelledException) { }
249 
250  cancellationToken.ThrowIfCancellationRequested();
251 
252  repository.RemoveUntrackedFiles();
253 
254  cancellationToken.ThrowIfCancellationRequested();
255 
256  testMergeParameters.PullRequestRevision = repository.Lookup(testMergeParameters.PullRequestRevision ?? localBranchName).Sha;
257 
258  cancellationToken.ThrowIfCancellationRequested();
259 
260  logger.LogTrace("Merging {0} into {1}...", testMergeParameters.PullRequestRevision.Substring(0, 7), Reference);
261 
262  result = repository.Merge(testMergeParameters.PullRequestRevision, sig, new MergeOptions
263  {
264  CommitOnSuccess = commitMessage == null,
265  FailOnConflict = true,
266  FastForwardStrategy = FastForwardStrategy.NoFastForward,
267  SkipReuc = true,
268  OnCheckoutProgress = (a, completedSteps, totalSteps) => progressReporter(50 + ((int)(((float)completedSteps) / totalSteps * 50)))
269  });
270  }
271  finally
272  {
273  repository.Branches.Remove(localBranchName);
274  }
275 
276  cancellationToken.ThrowIfCancellationRequested();
277 
278  if (result.Status == MergeStatus.Conflicts)
279  {
280  var revertTo = originalCommit.CanonicalName ?? originalCommit.Tip.Sha;
281  logger.LogDebug("Merge conflict, aborting and reverting to {0}", revertTo);
282  RawCheckout(revertTo, progressReporter, cancellationToken);
283  cancellationToken.ThrowIfCancellationRequested();
284  }
285 
286  repository.RemoveUntrackedFiles();
287  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
288 
289  if (result.Status == MergeStatus.Conflicts)
290  {
291  await eventConsumer.HandleEvent(EventType.RepoMergeConflict, new List<string> { originalCommit.Tip.Sha, testMergeParameters.PullRequestRevision, originalCommit.FriendlyName ?? UnknownReference, prBranchName }, cancellationToken).ConfigureAwait(false);
292  return null;
293  }
294 
295  if (commitMessage != null && result.Status != MergeStatus.UpToDate)
296  {
297  logger.LogTrace("Committing merge: \"{0}\"...", commitMessage);
298  await Task.Factory.StartNew(() => repository.Commit(commitMessage, sig, sig, new CommitOptions
299  {
300  PrettifyMessage = true
301  }), cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
302  }
303 
304  await eventConsumer.HandleEvent(EventType.RepoMergePullRequest, new List<string> { testMergeParameters.Number.ToString(), testMergeParameters.PullRequestRevision, testMergeParameters.Comment }, cancellationToken).ConfigureAwait(false);
305 
306  return result.Status != MergeStatus.NonFastForward;
307  }
308  #pragma warning restore CA1506
309 
311  public async Task CheckoutObject(string committish, Action<int> progressReporter, CancellationToken cancellationToken)
312  {
313  if (committish == null)
314  throw new ArgumentNullException(nameof(committish));
315  if (progressReporter == null)
316  throw new ArgumentNullException(nameof(progressReporter));
317  logger.LogDebug("Checkout object: {0}...", committish);
318  await eventConsumer.HandleEvent(EventType.RepoCheckout, new List<string> { committish }, cancellationToken).ConfigureAwait(false);
319  await Task.Factory.StartNew(() =>
320  {
321  repository.RemoveUntrackedFiles();
322  RawCheckout(committish, progressReporter, cancellationToken);
323  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
324  }
325 
327  public async Task FetchOrigin(string username, string password, Action<int> progressReporter, CancellationToken cancellationToken)
328  {
329  if (progressReporter == null)
330  throw new ArgumentNullException(nameof(progressReporter));
331  logger.LogDebug("Fetch origin...");
332  await eventConsumer.HandleEvent(EventType.RepoFetch, Array.Empty<string>(), cancellationToken).ConfigureAwait(false);
333  await Task.Factory.StartNew(() =>
334  {
335  var remote = repository.Network.Remotes.First();
336  try
337  {
338  Commands.Fetch((LibGit2Sharp.Repository)repository, remote.Name, remote.FetchRefSpecs.Select(x => x.Specification), new FetchOptions
339  {
340  Prune = true,
341  OnProgress = (a) => !cancellationToken.IsCancellationRequested,
342  OnTransferProgress = (a) =>
343  {
344  var percentage = 100 * (((float)a.IndexedObjects + a.ReceivedObjects) / (a.TotalObjects * 2));
345  progressReporter((int)percentage);
346  return !cancellationToken.IsCancellationRequested;
347  },
348  OnUpdateTips = (a, b, c) => !cancellationToken.IsCancellationRequested,
349  CredentialsProvider = credentialsProvider.GenerateHandler(username, password)
350  }, "Fetch origin commits");
351  }
352  catch (UserCancelledException)
353  {
354  cancellationToken.ThrowIfCancellationRequested();
355  }
356  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
357  }
358 
367  Task PushHeadToTemporaryBranch(string username, string password, Action<int> progressReporter, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
368  {
369  logger.LogInformation("Pushing changes to temporary remote branch...");
370  var branch = repository.CreateBranch(RemoteTemporaryBranchName);
371  try
372  {
373  cancellationToken.ThrowIfCancellationRequested();
374  var remote = repository.Network.Remotes.First();
375  try
376  {
377  var forcePushString = String.Format(CultureInfo.InvariantCulture, "+{0}:{0}", branch.CanonicalName);
378  repository.Network.Push(remote, forcePushString, GeneratePushOptions(progress => progressReporter((int)(0.9f * progress)), username, password, cancellationToken));
379  var removalString = String.Format(CultureInfo.InvariantCulture, ":{0}", branch.CanonicalName);
380  repository.Network.Push(remote, removalString, GeneratePushOptions(progress => progressReporter(90 + (int)(0.1f * progress)), username, password, cancellationToken));
381  }
382  catch (UserCancelledException)
383  {
384  cancellationToken.ThrowIfCancellationRequested();
385  }
386  catch(LibGit2SharpException e)
387  {
388  logger.LogWarning("Unable to push to temporary branch! Exception: {0}", e);
389  }
390  }
391  finally
392  {
393  repository.Branches.Remove(branch);
394  }
395  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
396 
398  public async Task ResetToOrigin(Action<int> progressReporter, CancellationToken cancellationToken)
399  {
400  if (progressReporter == null)
401  throw new ArgumentNullException(nameof(progressReporter));
402  if (!Tracking)
403  throw new JobException("Cannot reset to origin while not on a tracked reference!");
404  logger.LogTrace("Reset to origin...");
405  var trackedBranch = repository.Head.TrackedBranch;
406  await eventConsumer.HandleEvent(EventType.RepoResetOrigin, new List<string> { trackedBranch.FriendlyName, trackedBranch.Tip.Sha }, cancellationToken).ConfigureAwait(false);
407  await ResetToSha(trackedBranch.Tip.Sha, progressReporter, cancellationToken).ConfigureAwait(false);
408  }
409 
411  public Task ResetToSha(string sha, Action<int> progressReporter, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
412  {
413  if (sha == null)
414  throw new ArgumentNullException(nameof(sha));
415  if (progressReporter == null)
416  throw new ArgumentNullException(nameof(progressReporter));
417 
418  logger.LogDebug("Reset to sha: {0}", sha.Substring(0, 7));
419 
420  repository.RemoveUntrackedFiles();
421  cancellationToken.ThrowIfCancellationRequested();
422 
423  var gitObject = repository.Lookup(sha, ObjectType.Commit);
424  cancellationToken.ThrowIfCancellationRequested();
425 
426  if (gitObject == null)
427  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Cannot reset to non-existent SHA: {0}", sha));
428 
429  repository.Reset(ResetMode.Hard, gitObject.Peel<Commit>(), new CheckoutOptions
430  {
431  OnCheckoutProgress = CheckoutProgressHandler(progressReporter)
432  });
433  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
434 
436  public async Task CopyTo(string path, CancellationToken cancellationToken)
437  {
438  if (path == null)
439  throw new ArgumentNullException(nameof(path));
440  logger.LogTrace("Copying to {0}...", path);
441  await ioMananger.CopyDirectory(".", path, new List<string> { ".git" }, cancellationToken).ConfigureAwait(false);
442  }
443 
445  public async Task<bool?> MergeOrigin(string committerName, string committerEmail, Action<int> progressReporter, CancellationToken cancellationToken)
446  {
447  if (progressReporter == null)
448  throw new ArgumentNullException(nameof(progressReporter));
449 
450  MergeResult result = null;
451  Branch trackedBranch = null;
452 
453  var oldHead = repository.Head;
454  var oldTip = oldHead.Tip;
455 
456  await Task.Factory.StartNew(() =>
457  {
458  if (!Tracking)
459  throw new JobException("Cannot reset to origin while not on a tracked reference!");
460 
461  repository.RemoveUntrackedFiles();
462 
463  cancellationToken.ThrowIfCancellationRequested();
464 
465  trackedBranch = repository.Head.TrackedBranch;
466  logger.LogDebug("Merge origin/{2}: <{0} ({1})>", committerName, committerEmail, trackedBranch.FriendlyName);
467  result = repository.Merge(trackedBranch, new Signature(new Identity(committerName, committerEmail), DateTimeOffset.Now), new MergeOptions
468  {
469  CommitOnSuccess = true,
470  FailOnConflict = true,
471  FastForwardStrategy = FastForwardStrategy.Default,
472  SkipReuc = true,
473  OnCheckoutProgress = CheckoutProgressHandler(progressReporter)
474  });
475 
476  cancellationToken.ThrowIfCancellationRequested();
477 
478  if (result.Status == MergeStatus.Conflicts)
479  {
480  logger.LogDebug("Merge conflict, aborting and reverting to {0}", oldHead.FriendlyName);
481  repository.Reset(ResetMode.Hard, oldTip, new CheckoutOptions
482  {
483  OnCheckoutProgress = CheckoutProgressHandler(progressReporter)
484  });
485  cancellationToken.ThrowIfCancellationRequested();
486  }
487 
488  repository.RemoveUntrackedFiles();
489  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
490 
491  if (result.Status == MergeStatus.Conflicts)
492  {
493  await eventConsumer.HandleEvent(EventType.RepoMergeConflict, new List<string> { oldTip.Sha, trackedBranch.Tip.Sha, oldHead.FriendlyName ?? UnknownReference, trackedBranch.FriendlyName }, cancellationToken).ConfigureAwait(false);
494  return null;
495  }
496 
497  return result.Status == MergeStatus.FastForward;
498  }
499 
501  public async Task<bool> Sychronize(string username, string password, string committerName, string committerEmail, Action<int> progressReporter, bool synchronizeTrackedBranch, CancellationToken cancellationToken)
502  {
503  if (committerName == null)
504  throw new ArgumentNullException(nameof(committerName));
505  if (committerEmail == null)
506  throw new ArgumentNullException(nameof(committerEmail));
507  if (progressReporter == null)
508  throw new ArgumentNullException(nameof(progressReporter));
509 
510  if (username == null && password == null)
511  {
512  logger.LogTrace("Not synchronizing due to lack of credentials!");
513  return false;
514  }
515 
516  logger.LogTrace("Begin Synchronize...");
517 
518  if (username == null)
519  throw new ArgumentNullException(nameof(username));
520  if (password == null)
521  throw new ArgumentNullException(nameof(password));
522 
523  var startHead = Head;
524 
525  logger.LogTrace("Configuring <{0} ({1})> as author/committer", committerName, committerEmail);
526  await Task.Factory.StartNew(() =>
527  {
528  repository.Config.Set("user.name", committerName);
529  cancellationToken.ThrowIfCancellationRequested();
530  repository.Config.Set("user.email", committerEmail);
531  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
532 
533  cancellationToken.ThrowIfCancellationRequested();
534  try
535  {
536  if (!await eventConsumer.HandleEvent(EventType.RepoPreSynchronize, new List<string> { ioMananger.ResolvePath(".") }, cancellationToken).ConfigureAwait(false))
537  {
538  logger.LogDebug("Aborted synchronize due to event handler response!");
539  return false;
540  }
541  }
542  finally
543  {
544  logger.LogTrace("Resetting and cleaning untracked files...");
545  await Task.Factory.StartNew(() =>
546  {
547  repository.RemoveUntrackedFiles();
548  cancellationToken.ThrowIfCancellationRequested();
549  repository.Reset(ResetMode.Hard, repository.Head.Tip, new CheckoutOptions
550  {
551  OnCheckoutProgress = CheckoutProgressHandler(progress => progressReporter(progress / 10))
552  });
553  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
554  }
555 
556  void FinalReporter(int progress) => progressReporter((int)(((float)progress) / 100 * 90));
557 
558  if (!synchronizeTrackedBranch)
559  {
560  await PushHeadToTemporaryBranch(username, password, FinalReporter, cancellationToken).ConfigureAwait(false);
561  return false;
562  }
563 
564  var sameHead = Head == startHead;
565  if (sameHead || !Tracking)
566  {
567  logger.LogTrace("Aborted synchronize due to {0}!", sameHead ? "lack of changes" : "not being on tracked reference");
568  return false;
569  }
570 
571  logger.LogInformation("Synchronizing with origin...");
572 
573  return await Task.Factory.StartNew(() =>
574  {
575  var remote = repository.Network.Remotes.First();
576  try
577  {
578  repository.Network.Push(repository.Head, GeneratePushOptions(FinalReporter, username, password, cancellationToken));
579  return true;
580  }
581  catch (NonFastForwardException)
582  {
583  logger.LogInformation("Synchronize aborted, non-fast forward!");
584  return false;
585  }
586  catch (UserCancelledException e)
587  {
588  cancellationToken.ThrowIfCancellationRequested();
589  throw new InvalidOperationException("Caught UserCancelledException without cancellationToken triggering", e);
590  }
591  catch (LibGit2SharpException e)
592  {
593  logger.LogWarning("Unable to make synchronization push! Exception: {0}", e);
594  return false;
595  }
596  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current).ConfigureAwait(false);
597  }
598 
600  public Task<bool> IsSha(string committish, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
601  {
602  // check if it's a tag
603  var gitObject = repository.Lookup(committish, ObjectType.Tag);
604  if (gitObject != null)
605  return false;
606  cancellationToken.ThrowIfCancellationRequested();
607 
608  // check if it's a branch
609  if (repository.Branches[committish] != null)
610  return false;
611  cancellationToken.ThrowIfCancellationRequested();
612 
613  // err on the side of references, if we can't look it up, assume its a reference
614  if (repository.Lookup<Commit>(committish) != null)
615  return true;
616  return false;
617  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
618  }
619 }
+
Consumes EventTypes and takes the appropriate actions
- -
CredentialsHandler GenerateHandler(string username, string password)
Generate a CredentialsHandler from a given username and password
- -
async Task CheckoutObject(string committish, Action< int > progressReporter, CancellationToken cancellationToken)
Checks out a given committish
Definition: Repository.cs:311
-
readonly IIOManager ioMananger
The IIOManager for the Repository
Definition: Repository.cs:65
-
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
- -
Represents an on-disk git repository
Definition: IRepository.cs:11
-
readonly LibGit2Sharp.IRepository repository
The LibGit2Sharp.IRepository for the Repository
Definition: Repository.cs:60
+
CredentialsHandler GenerateHandler(string username, string password)
Generate a CredentialsHandler from a given username and password
+
async Task CheckoutObject(string committish, Action< int > progressReporter, CancellationToken cancellationToken)
Checks out a given committish
Definition: Repository.cs:311
+
readonly IIOManager ioMananger
The IIOManager for the Repository
Definition: Repository.cs:65
+
EventType
Types of events. Mirror in tgs.dm
Definition: EventType.cs:6
+
static CheckoutProgressHandler CheckoutProgressHandler(Action< int > progressReporter)
Converts a given progressReporter to a LibGit2Sharp.Handlers.CheckoutProgressHandler
+
Represents an on-disk git repository
Definition: IRepository.cs:11
+
readonly LibGit2Sharp.IRepository repository
The LibGit2Sharp.IRepository for the Repository
Definition: Repository.cs:60
async Task< bool?> MergeOrigin(string committerName, string committerEmail, Action< int > progressReporter, CancellationToken cancellationToken)
Requires the current HEAD to be a tracked reference. Merges the reference to what it tracks on the or...
Definition: Repository.cs:445
-
readonly ICredentialsProvider credentialsProvider
The ICredentialsProvider for the Repository
Definition: Repository.cs:75
-
Repository(LibGit2Sharp.IRepository repository, IIOManager ioMananger, IEventConsumer eventConsumer, ICredentialsProvider credentialsProvider, ILogger< Repository > logger, Action onDispose)
Construct a Repository
Definition: Repository.cs:103
-
async Task CopyTo(string path, CancellationToken cancellationToken)
Copies the current working directory to a given path
Definition: Repository.cs:436
+
readonly ICredentialsProvider credentialsProvider
The ICredentialsProvider for the Repository
Definition: Repository.cs:75
+
const string OriginTrackingErrorTemplate
Template error message for when tracking of the most recent origin commit fails
Definition: Repository.cs:27
+
Repository(LibGit2Sharp.IRepository repository, IIOManager ioMananger, IEventConsumer eventConsumer, ICredentialsProvider credentialsProvider, ILogger< Repository > logger, Action onDispose)
Construct a Repository
Definition: Repository.cs:103
+
async Task CopyTo(string path, CancellationToken cancellationToken)
Copies the current working directory to a given path
Definition: Repository.cs:436
-
int Number
The number of the pull request
+ -
readonly IEventConsumer eventConsumer
The IEventConsumer for the Repository
Definition: Repository.cs:70
-
readonly Action onDispose
Action to be taken when Dispose is called
Definition: Repository.cs:85
+
readonly IEventConsumer eventConsumer
The IEventConsumer for the Repository
Definition: Repository.cs:70
+ +
int? Number
The number of the pull request
+
readonly Action onDispose
Action to be taken when Dispose is called
Definition: Repository.cs:85
+ -
Represents a git repository
Definition: Repository.cs:8
+
CredentialsHandler GenerateHandler(string username, string password)
Generate a CredentialsHandler from a given username and password
void GetRepositoryOwnerName(string remote, out string owner, out string name)
Definition: Repository.cs:128
- + -
async Task< bool?> AddTestMerge(TestMergeParameters testMergeParameters, string committerName, string committerEmail, string username, string password, Action< int > progressReporter, CancellationToken cancellationToken)
Attempt to merge a GitHub pull request into HEAD
Definition: Repository.cs:194
-
Parameters for creating a TestMerge
+ +
async Task< bool?> AddTestMerge(TestMergeParameters testMergeParameters, string committerName, string committerEmail, string username, string password, Action< int > progressReporter, CancellationToken cancellationToken)
Attempt to merge a GitHub pull request into HEAD
Definition: Repository.cs:194
+
const string RemoteTemporaryBranchName
The branch name used for publishing testmerge commits
Definition: Repository.cs:32
+ +
async Task ResetToOrigin(Action< int > progressReporter, CancellationToken cancellationToken)
Requires the current HEAD to be a tracked reference. Hard resets the reference to what it tracks on t...
Definition: Repository.cs:398
-
string Head
The SHA of the IRepository HEAD
Definition: IRepository.cs:36
-
void RawCheckout(string committish, Action< int > progressReporter, CancellationToken cancellationToken)
Runs a blocking force checkout to committish
Definition: Repository.cs:174
- + + +
string Head
The SHA of the IRepository HEAD
Definition: IRepository.cs:36
+
void RawCheckout(string committish, Action< int > progressReporter, CancellationToken cancellationToken)
Runs a blocking force checkout to committish
Definition: Repository.cs:174
+
async Task< bool > Sychronize(string username, string password, string committerName, string committerEmail, Action< int > progressReporter, bool synchronizeTrackedBranch, CancellationToken cancellationToken)
Runs the synchronize event script and attempts to push any changes made to the IRepository if on a tr...
Definition: Repository.cs:501
-
Interface for using filesystems
Definition: IIOManager.cs:11
+
Interface for using filesystems
Definition: IIOManager.cs:11
+
const string GitHubUrl
Indication of a GitHub repository
Definition: Repository.cs:22
+
Task< bool > HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
Handle a given eventType
-
async Task FetchOrigin(string username, string password, Action< int > progressReporter, CancellationToken cancellationToken)
Fetch commits from the origin repository
Definition: Repository.cs:327
+ +
async Task FetchOrigin(string username, string password, Action< int > progressReporter, CancellationToken cancellationToken)
Fetch commits from the origin repository
Definition: Repository.cs:327
string PullRequestRevision
The sha of the pull request revision to merge. If not specified, the latest commit shall be used (sem...
-
string Comment
Optional comment about the test
- -
readonly ILogger< Repository > logger
The ILogger for the Repository
Definition: Repository.cs:80
-
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
- +
string Comment
Optional comment about the test
+ +
readonly ILogger< Repository > logger
The ILogger for the Repository
Definition: Repository.cs:80
+
PushOptions GeneratePushOptions(Action< int > progressReporter, string username, string password, CancellationToken cancellationToken)
Generate a standard set of PushOptions
+
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
+
diff --git a/_tgstation_8_server_8_host_2_models_2_chat_bot_8cs.html b/_tgstation_8_server_8_host_2_models_2_chat_bot_8cs.html index b1bd45e083..6bc3f13885 100644 --- a/_tgstation_8_server_8_host_2_models_2_chat_bot_8cs.html +++ b/_tgstation_8_server_8_host_2_models_2_chat_bot_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/ChatBot.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_tgstation_8_server_8_host_2_models_2_chat_bot_8cs_source.html b/_tgstation_8_server_8_host_2_models_2_chat_bot_8cs_source.html index 2e8d2fbb04..3e43ac5d69 100644 --- a/_tgstation_8_server_8_host_2_models_2_chat_bot_8cs_source.html +++ b/_tgstation_8_server_8_host_2_models_2_chat_bot_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/ChatBot.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ChatBot.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.ComponentModel.DataAnnotations;
3 using System.Linq;
4 
5 namespace Tgstation.Server.Host.Models
6 {
8  public sealed class ChatBot : Api.Models.Internal.ChatBot
9  {
13  public long InstanceId { get; set; }
14 
18  [Required]
19  public Instance Instance { get; set; }
20 
24  public List<ChatChannel> Channels { get; set; }
25 
30  public Api.Models.ChatBot ToApi() => new Api.Models.ChatBot
31  {
32  Channels = Channels.Select(x => x.ToApi()).ToList(),
33  ConnectionString = ConnectionString,
34  Enabled = Enabled,
35  Provider = Provider,
36  Id = Id,
37  Name = Name
38  };
39  }
40 }
-
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
- - +Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.ComponentModel.DataAnnotations;
3 using System.Linq;
4 
6 {
8  public sealed class ChatBot : Api.Models.Internal.ChatBot
9  {
13  public long InstanceId { get; set; }
14 
18  [Required]
19  public Instance Instance { get; set; }
20 
24  public List<ChatChannel> Channels { get; set; }
25 
30  public Api.Models.ChatBot ToApi() => new Api.Models.ChatBot
31  {
32  Channels = Channels.Select(x => x.ToApi()).ToList(),
34  Enabled = Enabled,
36  Id = Id,
37  Name = Name
38  };
39  }
40 }
+
Api.Models.ChatBot ToApi()
Convert the ChatBot to it's API form
+
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
+
string ConnectionString
The information used to connect to the Provider
Definition: ChatBot.cs:36
+
bool? Enabled
If the connection is enabled
Definition: ChatBot.cs:25
+ +
long InstanceId
The Api.Models.Instance.Id
Definition: ChatBot.cs:13
+
ChatProvider? Provider
The ChatProvider used for the connection
Definition: ChatBot.cs:30
+
List< ChatChannel > Channels
See Api.Models.ChatBot.Channels
Definition: ChatBot.cs:24
+
string Name
The name of the connection
Definition: ChatBot.cs:20
diff --git a/_tgstation_8_server_8_host_2_models_2_chat_channel_8cs.html b/_tgstation_8_server_8_host_2_models_2_chat_channel_8cs.html index efdb7a3d65..5b199bbb8b 100644 --- a/_tgstation_8_server_8_host_2_models_2_chat_channel_8cs.html +++ b/_tgstation_8_server_8_host_2_models_2_chat_channel_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/ChatChannel.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_tgstation_8_server_8_host_2_models_2_chat_channel_8cs_source.html b/_tgstation_8_server_8_host_2_models_2_chat_channel_8cs_source.html index d29e0ef524..091cc3d0e5 100644 --- a/_tgstation_8_server_8_host_2_models_2_chat_channel_8cs_source.html +++ b/_tgstation_8_server_8_host_2_models_2_chat_channel_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/ChatChannel.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
ChatChannel.cs
-Go to the documentation of this file.
2 
3 namespace Tgstation.Server.Host.Models
4 {
6  public sealed class ChatChannel : Api.Models.ChatChannel
7  {
11  public long Id { get; set; }
12 
16  public long ChatSettingsId { get; set; }
17 
21  public ChatBot ChatSettings { get; set; }
22 
27  public Api.Models.ChatChannel ToApi() => new Api.Models.ChatChannel
28  {
29  DiscordChannelId = DiscordChannelId,
30  IsAdminChannel = IsAdminChannel,
31  IsWatchdogChannel = IsWatchdogChannel,
32  IsUpdatesChannel = IsUpdatesChannel,
33  IrcChannel = IrcChannel,
34  Tag = Tag
35  };
36  }
37 }
- +Go to the documentation of this file.
2 
4 {
6  public sealed class ChatChannel : Api.Models.ChatChannel
7  {
11  public long Id { get; set; }
12 
16  public long ChatSettingsId { get; set; }
17 
21  public ChatBot ChatSettings { get; set; }
22 
27  public Api.Models.ChatChannel ToApi() => new Api.Models.ChatChannel
28  {
34  Tag = Tag
35  };
36  }
37 }
+ + - +
string IrcChannel
The IRC channel name
Definition: ChatChannel.cs:13
+
string Tag
A custom tag users can define to group channels together
Definition: ChatChannel.cs:41
+
long ChatSettingsId
The Api.Models.Internal.ChatBot.Id
Definition: ChatChannel.cs:16
+
Api.Models.ChatChannel ToApi()
Convert the ChatChannel to it's API form
+
bool? IsAdminChannel
If the ChatChannel is an admin channel
Definition: ChatChannel.cs:24
+
ulong? DiscordChannelId
The Discord channel ID
Definition: ChatChannel.cs:18
+
bool? IsUpdatesChannel
If the ChatChannel is an updates channel
Definition: ChatChannel.cs:36
+
bool? IsWatchdogChannel
If the ChatChannel is a watchdog channel
Definition: ChatChannel.cs:30
+
ChatBot ChatSettings
The Models.ChatBot
Definition: ChatChannel.cs:21
+ - +
diff --git a/_tgstation_8_server_8_host_2_models_2_compile_job_8cs.html b/_tgstation_8_server_8_host_2_models_2_compile_job_8cs.html index c0b047cb34..234f207bb6 100644 --- a/_tgstation_8_server_8_host_2_models_2_compile_job_8cs.html +++ b/_tgstation_8_server_8_host_2_models_2_compile_job_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/CompileJob.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_tgstation_8_server_8_host_2_models_2_compile_job_8cs_source.html b/_tgstation_8_server_8_host_2_models_2_compile_job_8cs_source.html index 3936a7cc0c..1b5d90a6f2 100644 --- a/_tgstation_8_server_8_host_2_models_2_compile_job_8cs_source.html +++ b/_tgstation_8_server_8_host_2_models_2_compile_job_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/CompileJob.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
CompileJob.cs
-Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
3 
4 namespace Tgstation.Server.Host.Models
5 {
7  public sealed class CompileJob : Api.Models.Internal.CompileJob
8  {
12  [Required]
13  public Job Job { get; set; }
14 
18  public long JobId { get; set; }
19 
23  [Required]
25 
29  [Required]
30  public string ByondVersion { get; set; }
31 
36  public Api.Models.CompileJob ToApi() => new Api.Models.CompileJob
37  {
38  DirectoryName = DirectoryName,
39  DmeName = DmeName,
40  Id = Id,
41  Job = Job.ToApi(),
42  Output = Output,
43  RevisionInformation = RevisionInformation.ToApi(),
44  ByondVersion = Version.Parse(ByondVersion),
45  MinimumSecurityLevel = MinimumSecurityLevel
46  };
47  }
48 }
- +Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
3 
5 {
7  public sealed class CompileJob : Api.Models.Internal.CompileJob
8  {
12  [Required]
13  public Job Job { get; set; }
14 
18  public long JobId { get; set; }
19 
23  [Required]
25 
29  [Required]
30  public string ByondVersion { get; set; }
31 
36  public Api.Models.CompileJob ToApi() => new Api.Models.CompileJob
37  {
39  DmeName = DmeName,
40  Id = Id,
41  Job = Job.ToApi(),
42  Output = Output,
44  ByondVersion = Version.Parse(ByondVersion),
46  };
47  }
48 }
DreamDaemonSecurity? MinimumSecurityLevel
The minimum DreamDaemonSecurity required to run the CompileJob's output
Definition: CompileJob.cs:38
+ +
string DmeName
The .dme file used for compilation
Definition: CompileJob.cs:20
+ +
Guid? DirectoryName
The Game folder the results were compiled into
Definition: CompileJob.cs:32
+
long JobId
The Api.Models.Internal.Job.Id of Job
Definition: CompileJob.cs:18
+ -
Api.Models.RevisionInformation ToApi()
Convert the RevisionInformation to it&#39;s API form
-
Api.Models.Job ToApi()
Convert the Job to it&#39;s API form
- +
Api.Models.RevisionInformation ToApi()
Convert the RevisionInformation to it's API form
+
Api.Models.CompileJob ToApi()
Convert the CompileJob to it's API form
+
Api.Models.Job ToApi()
Convert the Job to it's API form
+
string ByondVersion
The Version the CompileJob was made with in string form
Definition: CompileJob.cs:30
diff --git a/_tgstation_8_server_8_host_2_models_2_dream_daemon_settings_8cs.html b/_tgstation_8_server_8_host_2_models_2_dream_daemon_settings_8cs.html index 73a10752e5..2550c0b01c 100644 --- a/_tgstation_8_server_8_host_2_models_2_dream_daemon_settings_8cs.html +++ b/_tgstation_8_server_8_host_2_models_2_dream_daemon_settings_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/DreamDaemonSettings.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_tgstation_8_server_8_host_2_models_2_dream_daemon_settings_8cs_source.html b/_tgstation_8_server_8_host_2_models_2_dream_daemon_settings_8cs_source.html index 22d4515fe0..6ca2011943 100644 --- a/_tgstation_8_server_8_host_2_models_2_dream_daemon_settings_8cs_source.html +++ b/_tgstation_8_server_8_host_2_models_2_dream_daemon_settings_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/DreamDaemonSettings.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
DreamDaemonSettings.cs
-Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
3 namespace Tgstation.Server.Host.Models
4 {
6  public sealed class DreamDaemonSettings : Api.Models.Internal.DreamDaemonSettings
7  {
11  public long Id { get; set; }
12 
16  public int? ProcessId { get; set; }
17 
21  public string AccessToken { get; set; }
22 
26  public long InstanceId { get; set; }
27 
31  [Required]
32  public Instance Instance { get; set; }
33  }
34 }
- - -
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
- +Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
4 {
6  public sealed class DreamDaemonSettings : Api.Models.Internal.DreamDaemonSettings
7  {
11  public long Id { get; set; }
12 
16  public int? ProcessId { get; set; }
17 
21  public string AccessToken { get; set; }
22 
26  public long InstanceId { get; set; }
27 
31  [Required]
32  public Instance Instance { get; set; }
33  }
34 }
string AccessToken
The access token used for communication with DD
+ + + +
int? ProcessId
The PID of a currently running DD instance
+
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
+
diff --git a/_tgstation_8_server_8_host_2_models_2_instance_8cs.html b/_tgstation_8_server_8_host_2_models_2_instance_8cs.html index ff68971f33..809634949c 100644 --- a/_tgstation_8_server_8_host_2_models_2_instance_8cs.html +++ b/_tgstation_8_server_8_host_2_models_2_instance_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Instance.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.Instance - Represents an Api.Models.Instance in the database More...
+ Represents an Api.Models.Instance in the database More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_tgstation_8_server_8_host_2_models_2_instance_8cs_source.html b/_tgstation_8_server_8_host_2_models_2_instance_8cs_source.html index 0cdd3be308..6c1b97fd4d 100644 --- a/_tgstation_8_server_8_host_2_models_2_instance_8cs_source.html +++ b/_tgstation_8_server_8_host_2_models_2_instance_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Instance.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Instance.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 
3 namespace Tgstation.Server.Host.Models
4 {
8  public sealed class Instance : Api.Models.Instance
9  {
14 
19 
24 
29 
33  public List<InstanceUser> InstanceUsers { get; set; }
34 
38  public List<ChatBot> ChatSettings { get; set; }
39 
43  public List<RevisionInformation> RevisionInformations { get; set; }
44 
48  public List<Job> Jobs { get; set; }
49 
54  public Api.Models.Instance ToApi() => new Api.Models.Instance
55  {
56  AutoUpdateInterval = AutoUpdateInterval,
58  Id = Id,
59  Name = Name,
60  Path = Path,
61  Online = Online
62  };
63  }
64 }
+Go to the documentation of this file.
1 using System.Collections.Generic;
2 
4 {
8  public sealed class Instance : Api.Models.Instance
9  {
14 
19 
24 
29 
33  public List<InstanceUser> InstanceUsers { get; set; }
34 
38  public List<ChatBot> ChatSettings { get; set; }
39 
43  public List<RevisionInformation> RevisionInformations { get; set; }
44 
48  public List<Job> Jobs { get; set; }
49 
54  public Api.Models.Instance ToApi() => new Api.Models.Instance
55  {
58  Id = Id,
59  Name = Name,
60  Path = Path,
61  Online = Online
62  };
63  }
64 }
+
List< InstanceUser > InstanceUsers
The InstanceUsers in the Instance
Definition: Instance.cs:33
-
Database representation of Components.Watchdog.WatchdogReattachInformation
- - +
Database representation of Components.Watchdog.WatchdogReattachInformation
+ -
ConfigurationType
The type of configuration allowed on an Instance
-
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
- +
string Path
The path to where the Instance is located. Can only be changed while the Instance is offline....
Definition: Instance.cs:26
+
string Name
The name of the Instance
Definition: Instance.cs:20
+
List< RevisionInformation > RevisionInformations
The RevisionInformations in the Instance
Definition: Instance.cs:43
+
List< ChatBot > ChatSettings
The ChatBots for the Instance
Definition: Instance.cs:38
+
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
+
long Id
The id of the Instance. Not modifiable
Definition: Instance.cs:14
+
ConfigurationType? ConfigurationType
If ConfigurationFile can be used on the Instance
Definition: Instance.cs:38
+
uint? AutoUpdateInterval
The time interval in minutes the repository is automatically pulled and compiles. 0 disables
Definition: Instance.cs:44
+
bool? Online
If the Instance is online
Definition: Instance.cs:32
+
Api.Models.Instance ToApi()
Convert the Instance to it's API form
+
List< Job > Jobs
The Jobs in the Instance
Definition: Instance.cs:48
diff --git a/_tgstation_8_server_8_host_2_models_2_instance_user_8cs.html b/_tgstation_8_server_8_host_2_models_2_instance_user_8cs.html index 8851566c61..4ab59459d6 100644 --- a/_tgstation_8_server_8_host_2_models_2_instance_user_8cs.html +++ b/_tgstation_8_server_8_host_2_models_2_instance_user_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/InstanceUser.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_tgstation_8_server_8_host_2_models_2_instance_user_8cs_source.html b/_tgstation_8_server_8_host_2_models_2_instance_user_8cs_source.html index 4369eab401..2e5a2ba8bd 100644 --- a/_tgstation_8_server_8_host_2_models_2_instance_user_8cs_source.html +++ b/_tgstation_8_server_8_host_2_models_2_instance_user_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/InstanceUser.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
InstanceUser.cs
-Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
3 namespace Tgstation.Server.Host.Models
4 {
6  public sealed class InstanceUser : Api.Models.InstanceUser
7  {
11  public long Id { get; set; }
12 
16  public long InstanceId { get; set; }
17 
21  [Required]
22  public Instance Instance { get; set; }
23 
27  public bool AnyRights => ByondRights != Api.Rights.ByondRights.None ||
28  ChatBotRights != Api.Rights.ChatBotRights.None ||
29  ConfigurationRights != Api.Rights.ConfigurationRights.None ||
30  DreamDaemonRights != Api.Rights.DreamDaemonRights.None ||
31  DreamMakerRights != Api.Rights.DreamMakerRights.None ||
32  InstanceUserRights != Api.Rights.InstanceUserRights.None;
33 
38  public Api.Models.InstanceUser ToApi() => new Api.Models.InstanceUser
39  {
47  UserId = UserId
48  };
49  }
50 }
ConfigurationRights
Rights for Models.ConfigurationFile
-
ByondRights
Rights for Models.Byond
Definition: ByondRights.cs:9
-
InstanceUserRights
Rights for an Models.Instance
- - -
DreamDaemonRights
Rights for Models.DreamDaemon
-
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
+Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
2 
4 {
6  public sealed class InstanceUser : Api.Models.InstanceUser
7  {
11  public long Id { get; set; }
12 
16  public long InstanceId { get; set; }
17 
21  [Required]
22  public Instance Instance { get; set; }
23 
27  public bool AnyRights => ByondRights != Api.Rights.ByondRights.None ||
28  ChatBotRights != Api.Rights.ChatBotRights.None ||
29  ConfigurationRights != Api.Rights.ConfigurationRights.None ||
30  DreamDaemonRights != Api.Rights.DreamDaemonRights.None ||
31  DreamMakerRights != Api.Rights.DreamMakerRights.None ||
32  InstanceUserRights != Api.Rights.InstanceUserRights.None;
33 
38  public Api.Models.InstanceUser ToApi() => new Api.Models.InstanceUser
39  {
47  UserId = UserId
48  };
49  }
50 }
long? UserId
The Internal.User.Id of the User the InstanceUser belongs to
Definition: InstanceUser.cs:15
+
ByondRights? ByondRights
The Rights.ByondRights of the InstanceUser
Definition: InstanceUser.cs:27
+
RepositoryRights? RepositoryRights
The Rights.RepositoryRights of the InstanceUser
Definition: InstanceUser.cs:45
+ +
long InstanceId
The Api.Models.Instance.Id of Instance
Definition: InstanceUser.cs:16
+
ConfigurationRights? ConfigurationRights
The Rights.ConfigurationRights of the InstanceUser
Definition: InstanceUser.cs:57
+
DreamMakerRights? DreamMakerRights
The Rights.DreamMakerRights of the InstanceUser
Definition: InstanceUser.cs:39
+ +
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
-
DreamMakerRights
Rights for Models.DreamMaker
-
RepositoryRights
Rights for a Models.Repository
-
ChatBotRights
Rights for Models.ChatBot
Definition: ChatBotRights.cs:9
- +
Api.Models.InstanceUser ToApi()
Convert the InstanceUser to it's API form
+
ChatBotRights? ChatBotRights
The Rights.ChatBotRights of the InstanceUser
Definition: InstanceUser.cs:51
+
DreamDaemonRights? DreamDaemonRights
The Rights.DreamDaemonRights of the InstanceUser
Definition: InstanceUser.cs:33
+
InstanceUserRights? InstanceUserRights
The Rights.InstanceUserRights of the InstanceUser
Definition: InstanceUser.cs:21
+
bool AnyRights
If the InstanceUser has any instance rights
Definition: InstanceUser.cs:27
diff --git a/_tgstation_8_server_8_host_2_models_2_job_8cs.html b/_tgstation_8_server_8_host_2_models_2_job_8cs.html index c9b1c1f8d4..d45af29788 100644 --- a/_tgstation_8_server_8_host_2_models_2_job_8cs.html +++ b/_tgstation_8_server_8_host_2_models_2_job_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Job.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_tgstation_8_server_8_host_2_models_2_job_8cs_source.html b/_tgstation_8_server_8_host_2_models_2_job_8cs_source.html index 3bc28444fb..9cb8797835 100644 --- a/_tgstation_8_server_8_host_2_models_2_job_8cs_source.html +++ b/_tgstation_8_server_8_host_2_models_2_job_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Job.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Job.cs
-Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
3 using System.ComponentModel.DataAnnotations.Schema;
4 using System.Threading;
5 using System.Threading.Tasks;
6 
7 namespace Tgstation.Server.Host.Models
8 {
10  public sealed class Job : Api.Models.Internal.Job
11  {
15  [Required]
16  public User StartedBy { get; set; }
17 
21  public User CancelledBy { get; set; }
22 
26  [Required]
27  public Instance Instance { get; set; }
28 
33  [NotMapped]
34  public Func<CancellationToken, Task> PostComplete { get; set; }
35 
40  public Api.Models.Job ToApi() => new Api.Models.Job
41  {
42  Id = Id,
43  StartedAt = StartedAt,
44  StoppedAt = StoppedAt,
45  Cancelled = Cancelled,
46  CancelledBy = CancelledBy?.ToApi(false),
47  CancelRight = CancelRight,
48  CancelRightsType = CancelRightsType,
49  Description = Description,
50  ExceptionDetails = ExceptionDetails,
51  StartedBy = StartedBy.ToApi(false)
52  };
53  }
54 }
- +Go to the documentation of this file.
1 using System;
2 using System.ComponentModel.DataAnnotations;
3 using System.ComponentModel.DataAnnotations.Schema;
4 using System.Threading;
5 using System.Threading.Tasks;
6 
8 {
10  public sealed class Job : Api.Models.Internal.Job
11  {
15  [Required]
16  public User StartedBy { get; set; }
17 
21  public User CancelledBy { get; set; }
22 
26  [Required]
27  public Instance Instance { get; set; }
28 
33  [NotMapped]
34  public Func<CancellationToken, Task> PostComplete { get; set; }
35 
40  public Api.Models.Job ToApi() => new Api.Models.Job
41  {
42  Id = Id,
46  CancelledBy = CancelledBy?.ToApi(false),
51  StartedBy = StartedBy.ToApi(false)
52  };
53  }
54 }
User StartedBy
See Api.Models.Job.StartedBy
Definition: Job.cs:16
+
Api.Models.User ToApi(bool recursive, bool showDetails)
See ToApi(bool)
+ +
string Description
English description of the Job
Definition: Job.cs:21
+
string ExceptionDetails
Details of any exceptions caught during the Job
Definition: Job.cs:26
+
User CancelledBy
See Api.Models.Job.CancelledBy
Definition: Job.cs:21
+
ulong? CancelRight
The Rights required to cancel the Job
Definition: Job.cs:53
-
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
+
DateTimeOffset? StoppedAt
When the Job stopped
Definition: Job.cs:37
+
bool? Cancelled
If the Job was cancelled
Definition: Job.cs:43
+
Func< CancellationToken, Task > PostComplete
A Task to run after the job completes. This will not affect the Api.Models.Internal....
Definition: Job.cs:34
+
DateTimeOffset? StartedAt
When the Job was started
Definition: Job.cs:32
+ +
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
-
Api.Models.Instance ToApi()
Convert the Instance to it&#39;s API form
- +
Api.Models.Job ToApi()
Convert the Job to it's API form
+
RightsType? CancelRightsType
The RightsType of CancelRight if it can be cancelled
Definition: Job.cs:48
diff --git a/_tgstation_8_server_8_host_2_models_2_repository_settings_8cs.html b/_tgstation_8_server_8_host_2_models_2_repository_settings_8cs.html index 2d4e4ab966..afe77cebf0 100644 --- a/_tgstation_8_server_8_host_2_models_2_repository_settings_8cs.html +++ b/_tgstation_8_server_8_host_2_models_2_repository_settings_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/RepositorySettings.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_tgstation_8_server_8_host_2_models_2_repository_settings_8cs_source.html b/_tgstation_8_server_8_host_2_models_2_repository_settings_8cs_source.html index cff1837085..b35f3894a7 100644 --- a/_tgstation_8_server_8_host_2_models_2_repository_settings_8cs_source.html +++ b/_tgstation_8_server_8_host_2_models_2_repository_settings_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/RepositorySettings.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
RepositorySettings.cs
-Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
3 
4 namespace Tgstation.Server.Host.Models
5 {
7  public sealed class RepositorySettings : Api.Models.Internal.RepositorySettings
8  {
12  public long Id { get; set; }
13 
17  public long InstanceId { get; set; }
18 
22  [Required]
23  public Instance Instance { get; set; }
24 
29  public Repository ToApi() => new Repository
30  {
31  // AccessToken = AccessToken, // never show this
32  AccessUser = AccessUser,
33  AutoUpdatesKeepTestMerges = AutoUpdatesKeepTestMerges,
34  AutoUpdatesSynchronize = AutoUpdatesSynchronize,
35  CommitterEmail = CommitterEmail,
36  CommitterName = CommitterName,
37  PushTestMergeCommits = PushTestMergeCommits,
38  ShowTestMergeCommitters = ShowTestMergeCommitters,
39  PostTestMergeComment = PostTestMergeComment
40 
41  // revision information and the rest retrieved by controller
42  };
43  }
44 }
- - +Go to the documentation of this file.
1 using System.ComponentModel.DataAnnotations;
3 
5 {
7  public sealed class RepositorySettings : Api.Models.Internal.RepositorySettings
8  {
12  public long Id { get; set; }
13 
17  public long InstanceId { get; set; }
18 
22  [Required]
23  public Instance Instance { get; set; }
24 
29  public Repository ToApi() => new Repository
30  {
31  // AccessToken = AccessToken, // never show this
40 
41  // revision information and the rest retrieved by controller
42  };
43  }
44 }
Repository ToApi()
Convert the Repository to it's API form
+ + + +
bool? AutoUpdatesSynchronize
If synchronization should occur when auto updating
+
bool? ShowTestMergeCommitters
If test merge commits are signed with the username of the person who merged it. Note this only affect...
+
bool? AutoUpdatesKeepTestMerges
If test merge commits should be kept when auto updating. May cause merge conflicts which will block t...
-
Represents a git repository
Definition: Repository.cs:8
-
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
- - + +
string AccessUser
The username to access the git repository with
+
Represents a git repository
Definition: Repository.cs:8
+
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
+
bool? PushTestMergeCommits
If commits created from testmerges are pushed to the remote
+
bool? PostTestMergeComment
If test merging should create a comment
+ + + +
diff --git a/_tgstation_8_server_8_host_2_models_2_revision_information_8cs.html b/_tgstation_8_server_8_host_2_models_2_revision_information_8cs.html index f80eb27939..9cad7d48dc 100644 --- a/_tgstation_8_server_8_host_2_models_2_revision_information_8cs.html +++ b/_tgstation_8_server_8_host_2_models_2_revision_information_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/RevisionInformation.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_tgstation_8_server_8_host_2_models_2_revision_information_8cs_source.html b/_tgstation_8_server_8_host_2_models_2_revision_information_8cs_source.html index 95e4f013a5..eb12dfff55 100644 --- a/_tgstation_8_server_8_host_2_models_2_revision_information_8cs_source.html +++ b/_tgstation_8_server_8_host_2_models_2_revision_information_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/RevisionInformation.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
RevisionInformation.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.ComponentModel.DataAnnotations;
3 using System.Linq;
4 
5 namespace Tgstation.Server.Host.Models
6 {
8  public sealed class RevisionInformation : Api.Models.Internal.RevisionInformation
9  {
13  public long Id { get; set; }
14 
18  public long InstanceId { get; set; }
19 
23  [Required]
24  public Instance Instance { get; set; }
25 
29  public TestMerge PrimaryTestMerge { get; set; }
30 
34  public List<RevInfoTestMerge> ActiveTestMerges { get; set; }
35 
39  public List<CompileJob> CompileJobs { get; set; }
40 
45  public Api.Models.RevisionInformation ToApi() => new Api.Models.RevisionInformation
46  {
47  CommitSha = CommitSha,
48  OriginCommitSha = OriginCommitSha,
49  PrimaryTestMerge = PrimaryTestMerge?.ToApi(),
50  ActiveTestMerges = ActiveTestMerges.Select(x => x.TestMerge.ToApi()).ToList(),
51  CompileJobs = CompileJobs.Select(x => new Api.Models.CompileJob
52  {
53  Id = x.Id // anti recursion measure
54  }).ToList()
55  };
56  }
57 }
- +Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.ComponentModel.DataAnnotations;
3 using System.Linq;
4 
6 {
8  public sealed class RevisionInformation : Api.Models.Internal.RevisionInformation
9  {
13  public long Id { get; set; }
14 
18  public long InstanceId { get; set; }
19 
23  [Required]
24  public Instance Instance { get; set; }
25 
29  public TestMerge PrimaryTestMerge { get; set; }
30 
34  public List<RevInfoTestMerge> ActiveTestMerges { get; set; }
35 
39  public List<CompileJob> CompileJobs { get; set; }
40 
45  public Api.Models.RevisionInformation ToApi() => new Api.Models.RevisionInformation
46  {
50  ActiveTestMerges = ActiveTestMerges.Select(x => x.TestMerge.ToApi()).ToList(),
51  CompileJobs = CompileJobs.Select(x => new Api.Models.CompileJob
52  {
53  Id = x.Id // anti recursion measure
54  }).ToList()
55  };
56  }
57 }
+ +
Api.Models.TestMerge ToApi()
Convert the TestMerge to it's API form
-
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
- +
List< CompileJob > CompileJobs
See CompileJobs made from this RevisionInformation
+
Represents an Api.Models.Instance in the database
Definition: Instance.cs:8
+ + +
Api.Models.RevisionInformation ToApi()
Convert the RevisionInformation to it's API form
+
TestMerge PrimaryTestMerge
See Api.Models.RevisionInformation.PrimaryTestMerge
+
List< RevInfoTestMerge > ActiveTestMerges
See Api.Models.RevisionInformation.ActiveTestMerges
+
string OriginCommitSha
The sha of the most recent remote commit
diff --git a/_tgstation_8_server_8_host_2_models_2_test_merge_8cs.html b/_tgstation_8_server_8_host_2_models_2_test_merge_8cs.html index f26301da0b..d291a6f3d3 100644 --- a/_tgstation_8_server_8_host_2_models_2_test_merge_8cs.html +++ b/_tgstation_8_server_8_host_2_models_2_test_merge_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/TestMerge.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_tgstation_8_server_8_host_2_models_2_test_merge_8cs_source.html b/_tgstation_8_server_8_host_2_models_2_test_merge_8cs_source.html index c0aeba91d7..0bf347a4f6 100644 --- a/_tgstation_8_server_8_host_2_models_2_test_merge_8cs_source.html +++ b/_tgstation_8_server_8_host_2_models_2_test_merge_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/TestMerge.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestMerge.cs
-Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.ComponentModel.DataAnnotations;
3 
4 namespace Tgstation.Server.Host.Models
5 {
7  public sealed class TestMerge : Api.Models.Internal.TestMerge
8  {
12  [Required]
13  public User MergedBy { get; set; }
14 
18  [Required]
19  public RevisionInformation PrimaryRevisionInformation { get; set; }
20 
24  public long? PrimaryRevisionInformationId { get; set; }
25 
29  public List<RevInfoTestMerge> RevisonInformations { get; set; }
30 
35  public Api.Models.TestMerge ToApi() => new Api.Models.TestMerge
36  {
37  Author = Author,
38  BodyAtMerge = BodyAtMerge,
39  MergedAt = MergedAt,
40  TitleAtMerge = TitleAtMerge,
41  Comment = Comment,
42  Id = Id,
43  MergedBy = MergedBy.ToApi(false),
44  Number = Number,
45  PullRequestRevision = PullRequestRevision,
46  Url = Url
47  };
48  }
49 }
- +Go to the documentation of this file.
1 using System.Collections.Generic;
2 using System.ComponentModel.DataAnnotations;
3 
5 {
7  public sealed class TestMerge : Api.Models.Internal.TestMerge
8  {
12  [Required]
13  public User MergedBy { get; set; }
14 
18  [Required]
20 
24  public long? PrimaryRevisionInformationId { get; set; }
25 
29  public List<RevInfoTestMerge> RevisonInformations { get; set; }
30 
35  public Api.Models.TestMerge ToApi() => new Api.Models.TestMerge
36  {
37  Author = Author,
41  Comment = Comment,
42  Id = Id,
43  MergedBy = MergedBy.ToApi(false),
44  Number = Number,
46  Url = Url
47  };
48  }
49 }
User MergedBy
See Api.Models.TestMerge.MergedBy
Definition: TestMerge.cs:13
+
RevisionInformation PrimaryRevisionInformation
The initial RevisionInformation the TestMerge was merged with
Definition: TestMerge.cs:19
+
Api.Models.User ToApi(bool recursive, bool showDetails)
See ToApi(bool)
+ +
string TitleAtMerge
The title of the pull request
+
string Author
The author of the pull request
+
Api.Models.TestMerge ToApi()
Convert the TestMerge to it's API form
-
Api.Models.RevisionInformation ToApi()
Convert the RevisionInformation to it&#39;s API form
- +
int? Number
The number of the pull request
+
string BodyAtMerge
The body of the pull request
+
List< RevInfoTestMerge > RevisonInformations
All the RevInfoTestMerge for the TestMerge
Definition: TestMerge.cs:29
+
long? PrimaryRevisionInformationId
Foreign key for PrimaryRevisionInformation
Definition: TestMerge.cs:24
+
DateTimeOffset MergedAt
When the TestMerge was created
Definition: TestMerge.cs:20
+
string Url
The URL of the pull request
+
string PullRequestRevision
The sha of the pull request revision to merge. If not specified, the latest commit shall be used (sem...
+
string Comment
Optional comment about the test
+
diff --git a/_tgstation_8_server_8_host_2_models_2_user_8cs.html b/_tgstation_8_server_8_host_2_models_2_user_8cs.html index a3e693377a..da029ed5a4 100644 --- a/_tgstation_8_server_8_host_2_models_2_user_8cs.html +++ b/_tgstation_8_server_8_host_2_models_2_user_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/User.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_tgstation_8_server_8_host_2_models_2_user_8cs_source.html b/_tgstation_8_server_8_host_2_models_2_user_8cs_source.html index adb1f3435c..d7a4e7904b 100644 --- a/_tgstation_8_server_8_host_2_models_2_user_8cs_source.html +++ b/_tgstation_8_server_8_host_2_models_2_user_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/User.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
User.cs
-Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel.DataAnnotations;
4 
5 namespace Tgstation.Server.Host.Models
6 {
8  public sealed class User : Api.Models.Internal.User
9  {
13  public string PasswordHash { get; set; }
14 
18  public User CreatedBy { get; set; }
19 
23  [Required]
24  public string CanonicalName { get; set; }
25 
29  public DateTimeOffset? LastPasswordUpdate { get; set; }
30 
34  public List<User> CreatedUsers { get; set; }
35 
39  public List<InstanceUser> InstanceUsers { get; set; }
40 
44  public List<TestMerge> TestMerges { get; set; }
45 
52  Api.Models.User ToApi(bool recursive, bool showDetails) => new Api.Models.User
53  {
54  AdministrationRights = showDetails ? AdministrationRights : null,
55  CreatedAt = CreatedAt,
56  CreatedBy = recursive ? CreatedBy?.ToApi(false, false) : null,
57  Enabled = Enabled,
58  Id = Id,
59  InstanceManagerRights = showDetails ? InstanceManagerRights : null,
60  Name = Name,
61  SystemIdentifier = showDetails ? SystemIdentifier : null
62  };
63 
69  public Api.Models.User ToApi(bool showDetails) => ToApi(true, showDetails);
70  }
71 }
- -
AdministrationRights
Rights for Models.Administration
+Go to the documentation of this file.
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel.DataAnnotations;
4 
6 {
8  public sealed class User : Api.Models.Internal.User
9  {
13  public string PasswordHash { get; set; }
14 
18  public User CreatedBy { get; set; }
19 
23  [Required]
24  public string CanonicalName { get; set; }
25 
29  public DateTimeOffset? LastPasswordUpdate { get; set; }
30 
34  public List<User> CreatedUsers { get; set; }
35 
39  public List<InstanceUser> InstanceUsers { get; set; }
40 
44  public List<TestMerge> TestMerges { get; set; }
45 
52  Api.Models.User ToApi(bool recursive, bool showDetails) => new Api.Models.User
53  {
54  AdministrationRights = showDetails ? AdministrationRights : null,
56  CreatedBy = recursive ? CreatedBy?.ToApi(false, false) : null,
57  Enabled = Enabled,
58  Id = Id,
59  InstanceManagerRights = showDetails ? InstanceManagerRights : null,
60  Name = Name,
61  SystemIdentifier = showDetails ? SystemIdentifier : null
62  };
63 
69  public Api.Models.User ToApi(bool showDetails) => ToApi(true, showDetails);
70  }
71 }
string Name
The name of the User
Definition: User.cs:38
+
List< InstanceUser > InstanceUsers
The InstanceUsers for the User
Definition: User.cs:39
+
string PasswordHash
The hash of the user's password
Definition: User.cs:13
+
string CanonicalName
The uppercase invariant of Api.Models.Internal.User.Name
Definition: User.cs:24
+
List< TestMerge > TestMerges
The TestMerges made by the User
Definition: User.cs:44
+
Api.Models.User ToApi(bool recursive, bool showDetails)
See ToApi(bool)
+ +
AdministrationRights? AdministrationRights
The Rights.AdministrationRights for the User
Definition: User.cs:44
-
InstanceManagerRights
Rights for managing Models.Instances
- +
User CreatedBy
See Api.Models.User
Definition: User.cs:18
+
InstanceManagerRights? InstanceManagerRights
The Rights.InstanceManagerRights for the User
Definition: User.cs:50
+
DateTimeOffset? LastPasswordUpdate
When PasswordHash was last changed
Definition: User.cs:29
+
long Id
The ID of the User
Definition: User.cs:15
+
DateTimeOffset? CreatedAt
When the User was created
Definition: User.cs:27
+
List< User > CreatedUsers
Users created by this User
Definition: User.cs:34
+
bool? Enabled
If the User is enabled since users cannot be deleted. System users cannot be disabled
Definition: User.cs:21
+
string SystemIdentifier
The SID/UID of the User on Windows/POSIX respectively
Definition: User.cs:32
diff --git a/_tgstation_8_server_8_host_8_assembly_info_8cs.html b/_tgstation_8_server_8_host_8_assembly_info_8cs.html index df4548a1f4..15bb531ff7 100644 --- a/_tgstation_8_server_8_host_8_assembly_info_8cs.html +++ b/_tgstation_8_server_8_host_8_assembly_info_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Host/obj/Release/netcoreapp2.1/Tgstation.Server.Host.AssemblyInfo.cs File Reference + + +tgstation-server: src/Tgstation.Server.Host/obj/Debug/netcoreapp2.1/Tgstation.Server.Host.AssemblyInfo.cs File Reference - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -99,7 +78,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_tgstation_8_server_8_host_8_assembly_info_8cs_source.html b/_tgstation_8_server_8_host_8_assembly_info_8cs_source.html index c45aa1af40..76746b7072 100644 --- a/_tgstation_8_server_8_host_8_assembly_info_8cs_source.html +++ b/_tgstation_8_server_8_host_8_assembly_info_8cs_source.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Host/obj/Release/netcoreapp2.1/Tgstation.Server.Host.AssemblyInfo.cs Source File + + +tgstation-server: src/Tgstation.Server.Host/obj/Debug/netcoreapp2.1/Tgstation.Server.Host.AssemblyInfo.cs Source File - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,13 +71,12 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
Tgstation.Server.Host.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("Tgstation.Server.Host")]
15 [assembly: System.Reflection.AssemblyConfigurationAttribute("Release")]
16 [assembly: System.Reflection.AssemblyFileVersionAttribute("4.0.1.4")]
17 [assembly: System.Reflection.AssemblyInformationalVersionAttribute("4.0.1.4")]
18 [assembly: System.Reflection.AssemblyProductAttribute("Tgstation.Server.Host")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Host")]
20 [assembly: System.Reflection.AssemblyVersionAttribute("4.0.1.4")]
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("Tgstation.Server.Host")]
15 [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
16 [assembly: System.Reflection.AssemblyFileVersionAttribute("4.0.1.4")]
17 [assembly: System.Reflection.AssemblyInformationalVersionAttribute("4.0.1.4")]
18 [assembly: System.Reflection.AssemblyProductAttribute("Tgstation.Server.Host")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Host")]
20 [assembly: System.Reflection.AssemblyVersionAttribute("4.0.1.4")]
21 
22 // Generated by the MSBuild WriteCodeFragment class.
23 
diff --git a/src_2_tgstation_8_server_8_host_8_console_2_assembly_info_8cs.html b/_tgstation_8_server_8_host_8_console_2_assembly_info_8cs.html similarity index 60% rename from src_2_tgstation_8_server_8_host_8_console_2_assembly_info_8cs.html rename to _tgstation_8_server_8_host_8_console_2_assembly_info_8cs.html index 95000901d9..36a1b7c638 100644 --- a/src_2_tgstation_8_server_8_host_8_console_2_assembly_info_8cs.html +++ b/_tgstation_8_server_8_host_8_console_2_assembly_info_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Console/AssemblyInfo.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
diff --git a/_tgstation_8_server_8_host_8_console_2_assembly_info_8cs_source.html b/_tgstation_8_server_8_host_8_console_2_assembly_info_8cs_source.html new file mode 100644 index 0000000000..039b183d33 --- /dev/null +++ b/_tgstation_8_server_8_host_8_console_2_assembly_info_8cs_source.html @@ -0,0 +1,82 @@ + + + + + + + +tgstation-server: src/Tgstation.Server.Host.Console/AssemblyInfo.cs Source File + + + + + + + + + +
+
+ + + + + + + +
+
tgstation-server +
+
The /tg/station 13 server suite
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
AssemblyInfo.cs
+
+
+Go to the documentation of this file.
1 using System.Runtime.CompilerServices;
2 
3 [assembly: InternalsVisibleTo("Tgstation.Server.Host.Console.Tests")]
+ + + + diff --git a/_tgstation_8_server_8_host_8_console_8_assembly_info_8cs.html b/_tgstation_8_server_8_host_8_console_8_assembly_info_8cs.html index 466f488683..aaf02964c2 100644 --- a/_tgstation_8_server_8_host_8_console_8_assembly_info_8cs.html +++ b/_tgstation_8_server_8_host_8_console_8_assembly_info_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Host.Console/obj/Release/netcoreapp2.1/Tgstation.Server.Host.Console.AssemblyInfo.cs File Reference + + +tgstation-server: src/Tgstation.Server.Host.Console/obj/Debug/netcoreapp2.1/Tgstation.Server.Host.Console.AssemblyInfo.cs File Reference - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -99,7 +78,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_tgstation_8_server_8_host_8_console_8_assembly_info_8cs_source.html b/_tgstation_8_server_8_host_8_console_8_assembly_info_8cs_source.html index 52a84c0f9a..0fc27c552a 100644 --- a/_tgstation_8_server_8_host_8_console_8_assembly_info_8cs_source.html +++ b/_tgstation_8_server_8_host_8_console_8_assembly_info_8cs_source.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Host.Console/obj/Release/netcoreapp2.1/Tgstation.Server.Host.Console.AssemblyInfo.cs Source File + + +tgstation-server: src/Tgstation.Server.Host.Console/obj/Debug/netcoreapp2.1/Tgstation.Server.Host.Console.AssemblyInfo.cs Source File - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,13 +71,12 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
Tgstation.Server.Host.Console.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("Tgstation.Server.Host.Console")]
15 [assembly: System.Reflection.AssemblyConfigurationAttribute("Release")]
16 [assembly: System.Reflection.AssemblyFileVersionAttribute("4.0.1.4")]
17 [assembly: System.Reflection.AssemblyInformationalVersionAttribute("4.0.1.4")]
18 [assembly: System.Reflection.AssemblyProductAttribute("Tgstation.Server.Host.Console")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Host.Console")]
20 [assembly: System.Reflection.AssemblyVersionAttribute("4.0.1.4")]
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("Tgstation.Server.Host.Console")]
15 [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
16 [assembly: System.Reflection.AssemblyFileVersionAttribute("4.0.1.4")]
17 [assembly: System.Reflection.AssemblyInformationalVersionAttribute("4.0.1.4")]
18 [assembly: System.Reflection.AssemblyProductAttribute("Tgstation.Server.Host.Console")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Host.Console")]
20 [assembly: System.Reflection.AssemblyVersionAttribute("4.0.1.4")]
21 
22 // Generated by the MSBuild WriteCodeFragment class.
23 
diff --git a/_tgstation_8_server_8_host_8_console_8_tests_8_assembly_info_8cs.html b/_tgstation_8_server_8_host_8_console_8_tests_8_assembly_info_8cs.html index 526c7344eb..073372c14a 100644 --- a/_tgstation_8_server_8_host_8_console_8_tests_8_assembly_info_8cs.html +++ b/_tgstation_8_server_8_host_8_console_8_tests_8_assembly_info_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Console.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Host.Console.Tests.AssemblyInfo.cs File Reference + + +tgstation-server: tests/Tgstation.Server.Host.Console.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Host.Console.Tests.AssemblyInfo.cs File Reference - @@ -33,41 +31,22 @@ - + - - + + + +
@@ -99,7 +78,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_tgstation_8_server_8_host_8_console_8_tests_8_assembly_info_8cs_source.html b/_tgstation_8_server_8_host_8_console_8_tests_8_assembly_info_8cs_source.html index 76fc39106d..e196eee792 100644 --- a/_tgstation_8_server_8_host_8_console_8_tests_8_assembly_info_8cs_source.html +++ b/_tgstation_8_server_8_host_8_console_8_tests_8_assembly_info_8cs_source.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Console.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Host.Console.Tests.AssemblyInfo.cs Source File + + +tgstation-server: tests/Tgstation.Server.Host.Console.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Host.Console.Tests.AssemblyInfo.cs Source File - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,13 +71,12 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
Tgstation.Server.Host.Console.Tests.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("Tgstation.Server.Host.Console.Tests")]
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("Tgstation.Server.Host.Console.Tests")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Host.Console.Tests")]
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("Tgstation.Server.Host.Console.Tests")]
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("Tgstation.Server.Host.Console.Tests")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Host.Console.Tests")]
20 [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
21 
22 // Generated by the MSBuild WriteCodeFragment class.
23 
diff --git a/_tgstation_8_server_8_host_8_console_8_tests_8_program_8cs.html b/_tgstation_8_server_8_host_8_console_8_tests_8_program_8cs.html index 476178b5d9..a8586ad154 100644 --- a/_tgstation_8_server_8_host_8_console_8_tests_8_program_8cs.html +++ b/_tgstation_8_server_8_host_8_console_8_tests_8_program_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Console.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Host.Console.Tests.Program.cs File Reference + + +tgstation-server: tests/Tgstation.Server.Host.Console.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Host.Console.Tests.Program.cs File Reference - @@ -33,41 +31,22 @@ - + - - + + + +
@@ -107,7 +86,7 @@ Classes diff --git a/_tgstation_8_server_8_host_8_console_8_tests_8_program_8cs_source.html b/_tgstation_8_server_8_host_8_console_8_tests_8_program_8cs_source.html index 37466fca50..6dea9ce810 100644 --- a/_tgstation_8_server_8_host_8_console_8_tests_8_program_8cs_source.html +++ b/_tgstation_8_server_8_host_8_console_8_tests_8_program_8cs_source.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Console.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Host.Console.Tests.Program.cs Source File + + +tgstation-server: tests/Tgstation.Server.Host.Console.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Host.Console.Tests.Program.cs Source File - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,15 +71,14 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
Tgstation.Server.Host.Console.Tests.Program.cs
-Go to the documentation of this file.
1 // <auto-generated> This file has been auto generated. </auto-generated>
2 using System;
3 [Microsoft.VisualStudio.TestPlatform.TestSDKAutoGeneratedCode]
4 class AutoGeneratedProgram {static void Main(string[] args){}}
- +Go to the documentation of this file.
1 // <auto-generated> This file has been auto generated. </auto-generated>
2 using System;
3 [Microsoft.VisualStudio.TestPlatform.TestSDKAutoGeneratedCode]
4 class AutoGeneratedProgram {static void Main(string[] args){}}
diff --git a/_tgstation_8_server_8_host_8_razor_assembly_info_8cs.html b/_tgstation_8_server_8_host_8_razor_assembly_info_8cs.html index 3203ae4cf7..e5342176c6 100644 --- a/_tgstation_8_server_8_host_8_razor_assembly_info_8cs.html +++ b/_tgstation_8_server_8_host_8_razor_assembly_info_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Host/obj/Release/netcoreapp2.1/Tgstation.Server.Host.RazorAssemblyInfo.cs File Reference + + +tgstation-server: src/Tgstation.Server.Host/obj/Debug/netcoreapp2.1/Tgstation.Server.Host.RazorAssemblyInfo.cs File Reference - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -99,7 +78,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_tgstation_8_server_8_host_8_razor_assembly_info_8cs_source.html b/_tgstation_8_server_8_host_8_razor_assembly_info_8cs_source.html index c53270b03d..ec9d358495 100644 --- a/_tgstation_8_server_8_host_8_razor_assembly_info_8cs_source.html +++ b/_tgstation_8_server_8_host_8_razor_assembly_info_8cs_source.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Host/obj/Release/netcoreapp2.1/Tgstation.Server.Host.RazorAssemblyInfo.cs Source File + + +tgstation-server: src/Tgstation.Server.Host/obj/Debug/netcoreapp2.1/Tgstation.Server.Host.RazorAssemblyInfo.cs Source File - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,13 +71,12 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
Tgstation.Server.Host.RazorAssemblyInfo.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: Microsoft.AspNetCore.Mvc.ApplicationParts.RelatedAssemblyAttribute("Tgstation.Server.Host.Views")]
15 [assembly: Microsoft.AspNetCore.Razor.Hosting.RazorLanguageVersionAttribute("2.1")]
16 [assembly: Microsoft.AspNetCore.Razor.Hosting.RazorConfigurationNameAttribute("MVC-2.1")]
17 [assembly: Microsoft.AspNetCore.Razor.Hosting.RazorExtensionAssemblyNameAttribute("MVC-2.1", "Microsoft.AspNetCore.Mvc.Razor.Extensions")]
18 
19 // Generated by the MSBuild WriteCodeFragment class.
20 
-
+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: Microsoft.AspNetCore.Mvc.ApplicationParts.RelatedAssemblyAttribute("Tgstation.Server.Host.Views")]
15 [assembly: Microsoft.AspNetCore.Razor.Hosting.RazorLanguageVersionAttribute("2.1")]
16 [assembly: Microsoft.AspNetCore.Razor.Hosting.RazorConfigurationNameAttribute("MVC-2.1")]
17 [assembly: Microsoft.AspNetCore.Razor.Hosting.RazorExtensionAssemblyNameAttribute("MVC-2.1", "Microsoft.AspNetCore.Mvc.Razor.Extensions")]
18 
19 // Generated by the MSBuild WriteCodeFragment class.
20 
diff --git a/src_2_tgstation_8_server_8_host_8_service_2_properties_2_assembly_info_8cs.html b/_tgstation_8_server_8_host_8_service_2_properties_2_assembly_info_8cs.html similarity index 60% rename from src_2_tgstation_8_server_8_host_8_service_2_properties_2_assembly_info_8cs.html rename to _tgstation_8_server_8_host_8_service_2_properties_2_assembly_info_8cs.html index 8d0a1d8906..4b2781684f 100644 --- a/src_2_tgstation_8_server_8_host_8_service_2_properties_2_assembly_info_8cs.html +++ b/_tgstation_8_server_8_host_8_service_2_properties_2_assembly_info_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Service/Properties/AssemblyInfo.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
diff --git a/_tgstation_8_server_8_host_8_service_2_properties_2_assembly_info_8cs_source.html b/_tgstation_8_server_8_host_8_service_2_properties_2_assembly_info_8cs_source.html new file mode 100644 index 0000000000..6a896fd81e --- /dev/null +++ b/_tgstation_8_server_8_host_8_service_2_properties_2_assembly_info_8cs_source.html @@ -0,0 +1,82 @@ + + + + + + + +tgstation-server: src/Tgstation.Server.Host.Service/Properties/AssemblyInfo.cs Source File + + + + + + + + + +
+
+ + + + + + + +
+
tgstation-server +
+
The /tg/station 13 server suite
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
AssemblyInfo.cs
+
+
+Go to the documentation of this file.
1 using System.Runtime.CompilerServices;
2 
3 [assembly:InternalsVisibleTo("Tgstation.Server.Host.Service.Tests")]
+ + + + diff --git a/_tgstation_8_server_8_host_8_service_8_assembly_info_8cs.html b/_tgstation_8_server_8_host_8_service_8_assembly_info_8cs.html new file mode 100644 index 0000000000..e3c0701522 --- /dev/null +++ b/_tgstation_8_server_8_host_8_service_8_assembly_info_8cs.html @@ -0,0 +1,84 @@ + + + + + + + +tgstation-server: src/Tgstation.Server.Host.Service/obj/Debug/net471/win/Tgstation.Server.Host.Service.AssemblyInfo.cs File Reference + + + + + + + + + +
+
+ + + + + + + +
+
tgstation-server +
+
The /tg/station 13 server suite
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
Tgstation.Server.Host.Service.AssemblyInfo.cs File Reference
+
+ + + + + diff --git a/_tgstation_8_server_8_host_8_service_8_assembly_info_8cs_source.html b/_tgstation_8_server_8_host_8_service_8_assembly_info_8cs_source.html new file mode 100644 index 0000000000..4b8dbb39a3 --- /dev/null +++ b/_tgstation_8_server_8_host_8_service_8_assembly_info_8cs_source.html @@ -0,0 +1,82 @@ + + + + + + + +tgstation-server: src/Tgstation.Server.Host.Service/obj/Debug/net471/win/Tgstation.Server.Host.Service.AssemblyInfo.cs Source File + + + + + + + + + +
+
+ + + + + + + +
+
tgstation-server +
+
The /tg/station 13 server suite
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
Tgstation.Server.Host.Service.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("Tgstation.Server.Host.Service")]
15 [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
16 [assembly: System.Reflection.AssemblyFileVersionAttribute("4.0.1.4")]
17 [assembly: System.Reflection.AssemblyInformationalVersionAttribute("4.0.1.4")]
18 [assembly: System.Reflection.AssemblyProductAttribute("Tgstation.Server.Host.Service")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Host.Service")]
20 [assembly: System.Reflection.AssemblyVersionAttribute("4.0.1.4")]
21 
22 // Generated by the MSBuild WriteCodeFragment class.
23 
+ + + + diff --git a/tests_2_tgstation_8_server_8_host_8_service_8_tests_2_properties_2_assembly_info_8cs.html b/_tgstation_8_server_8_host_8_service_8_tests_8_assembly_info_8cs.html similarity index 56% rename from tests_2_tgstation_8_server_8_host_8_service_8_tests_2_properties_2_assembly_info_8cs.html rename to _tgstation_8_server_8_host_8_service_8_tests_8_assembly_info_8cs.html index df0c806d6a..2f1a8a9f62 100644 --- a/tests_2_tgstation_8_server_8_host_8_service_8_tests_2_properties_2_assembly_info_8cs.html +++ b/_tgstation_8_server_8_host_8_service_8_tests_8_assembly_info_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Service.Tests/Properties/AssemblyInfo.cs File Reference + + +tgstation-server: tests/Tgstation.Server.Host.Service.Tests/obj/Debug/net471/Tgstation.Server.Host.Service.Tests.AssemblyInfo.cs File Reference - @@ -33,41 +31,22 @@
- + - - + + + +
-
AssemblyInfo.cs File Reference
+
Tgstation.Server.Host.Service.Tests.AssemblyInfo.cs File Reference
-

Go to the source code of this file.

+

Go to the source code of this file.

diff --git a/_tgstation_8_server_8_host_8_service_8_tests_8_assembly_info_8cs_source.html b/_tgstation_8_server_8_host_8_service_8_tests_8_assembly_info_8cs_source.html new file mode 100644 index 0000000000..68c6bad30a --- /dev/null +++ b/_tgstation_8_server_8_host_8_service_8_tests_8_assembly_info_8cs_source.html @@ -0,0 +1,82 @@ + + + + + + + +tgstation-server: tests/Tgstation.Server.Host.Service.Tests/obj/Debug/net471/Tgstation.Server.Host.Service.Tests.AssemblyInfo.cs Source File + + + + + + + + + +
+
+ + + + + + + +
+
tgstation-server +
+
The /tg/station 13 server suite
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
Tgstation.Server.Host.Service.Tests.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("Tgstation.Server.Host.Service.Tests")]
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("Tgstation.Server.Host.Service.Tests")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Host.Service.Tests")]
20 [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
21 
22 // Generated by the MSBuild WriteCodeFragment class.
23 
+ + + + diff --git a/_tgstation_8_server_8_host_8_tests_2_components_2_watchdog_2_test_watchdog_8cs.html b/_tgstation_8_server_8_host_8_tests_2_components_2_watchdog_2_test_watchdog_8cs.html index 982b5dad6c..fabce22660 100644 --- a/_tgstation_8_server_8_host_8_tests_2_components_2_watchdog_2_test_watchdog_8cs.html +++ b/_tgstation_8_server_8_host_8_tests_2_components_2_watchdog_2_test_watchdog_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Components/Watchdog/TestWatchdog.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
+ + + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Watchdog
 
namespace  Tgstation.Server.Host.Components.Watchdog.Tests
 
@@ -113,7 +102,7 @@ Namespaces diff --git a/_tgstation_8_server_8_host_8_tests_2_components_2_watchdog_2_test_watchdog_8cs_source.html b/_tgstation_8_server_8_host_8_tests_2_components_2_watchdog_2_test_watchdog_8cs_source.html index 6c12673440..fbce79d1e4 100644 --- a/_tgstation_8_server_8_host_8_tests_2_components_2_watchdog_2_test_watchdog_8cs_source.html +++ b/_tgstation_8_server_8_host_8_tests_2_components_2_watchdog_2_test_watchdog_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Components/Watchdog/TestWatchdog.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestWatchdog.cs
-Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Microsoft.Extensions.Logging;
3 using Microsoft.VisualStudio.TestTools.UnitTesting;
4 using Moq;
5 using System;
6 using System.Collections.Generic;
7 using System.Threading;
8 using System.Threading.Tasks;
13 
14 namespace Tgstation.Server.Host.Components.Watchdog.Tests
15 {
16  [TestClass]
17  public sealed class TestWatchdog
18  {
19  [TestMethod]
20  public void TestConstruction()
21  {
22  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(null, null, null, null, null, null, null, null, null, null, null, null, null, default));
23 
24  var mockChat = new Mock<IChat>();
25  mockChat.Setup(x => x.RegisterCommandHandler(It.IsNotNull<ICustomCommandHandler>())).Verifiable();
26  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, null, null, null, null, null, null, null, null, null, null, null, null, default));
27 
28  var mockSessionControllerFactory = new Mock<ISessionControllerFactory>();
29  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, null, null, null, null, null, null, null, null, null, null, null, default));
30 
31  var mockDmbFactory = new Mock<IDmbFactory>();
32  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, null, null, null, null, null, null, null, null, null, null, default));
33 
34  var mockReattachInfoHandler = new Mock<IReattachInfoHandler>();
35  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, null, null, null, null, null, null, null, null, null, default));
36 
37  var mockDatabaseContextFactory = new Mock<IDatabaseContextFactory>();
38  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, null, null, null, null, null, null, null, null, default));
39 
40  var mockByondTopicSender = new Mock<IByondTopicSender>();
41  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, mockByondTopicSender.Object, null, null, null, null, null, null, null, default));
42 
43  var mockEventConsumer = new Mock<IEventConsumer>();
44  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, mockByondTopicSender.Object, mockEventConsumer.Object, null, null, null, null, null, null, default));
45 
46  var mockJobManager = new Mock<IJobManager>();
47  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, mockByondTopicSender.Object, mockEventConsumer.Object, mockJobManager.Object, null, null, null, null, null, default));
48 
49  var mockRestartRegistration = new Mock<IRestartRegistration>();
50  mockRestartRegistration.Setup(x => x.Dispose()).Verifiable();
51  var mockServerControl = new Mock<IServerControl>();
52  mockServerControl.Setup(x => x.RegisterForRestart(It.IsNotNull<IRestartHandler>())).Returns(mockRestartRegistration.Object).Verifiable();
53  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, mockByondTopicSender.Object, mockEventConsumer.Object, mockJobManager.Object, mockServerControl.Object, null, null, null, null, default));
54 
55  var mockAsyncDelayer = new Mock<IAsyncDelayer>();
56  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, mockByondTopicSender.Object, mockEventConsumer.Object, mockJobManager.Object, mockServerControl.Object, mockAsyncDelayer.Object, null, null, null, default));
57 
58  var mockLogger = new Mock<ILogger<Watchdog>>();
59  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, mockByondTopicSender.Object, mockEventConsumer.Object, mockJobManager.Object, mockServerControl.Object, mockAsyncDelayer.Object, mockLogger.Object, null, null, default));
60 
61  var mockLaunchParameters = new DreamDaemonLaunchParameters();
62  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, mockByondTopicSender.Object, mockEventConsumer.Object, mockJobManager.Object, mockServerControl.Object, mockAsyncDelayer.Object, mockLogger.Object, mockLaunchParameters, null, default));
63 
64  var mockInstance = new Models.Instance();
65  new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, mockByondTopicSender.Object, mockEventConsumer.Object, mockJobManager.Object, mockServerControl.Object, mockAsyncDelayer.Object, mockLogger.Object, mockLaunchParameters, mockInstance, default).Dispose();
66 
67  mockRestartRegistration.VerifyAll();
68  mockServerControl.VerifyAll();
69  mockChat.VerifyAll();
70  }
71 
72  [TestMethod]
73  public async Task TestSuccessfulLaunchAndShutdown()
74  {
75  var mockChat = new Mock<IChat>();
76  mockChat.Setup(x => x.RegisterCommandHandler(It.IsNotNull<ICustomCommandHandler>())).Verifiable();
77  var mockSessionControllerFactory = new Mock<ISessionControllerFactory>();
78  var mockDmbFactory = new Mock<IDmbFactory>();
79  var mockLogger = new Mock<ILogger<Watchdog>>();
80  var mockReattachInfoHandler = new Mock<IReattachInfoHandler>();
81  var mockDatabaseContextFactory = new Mock<IDatabaseContextFactory>();
82  var mockByondTopicSender = new Mock<IByondTopicSender>();
83  var mockEventConsumer = new Mock<IEventConsumer>();
84  var mockJobManager = new Mock<IJobManager>();
85  var mockRestartRegistration = new Mock<IRestartRegistration>();
86  mockRestartRegistration.Setup(x => x.Dispose()).Verifiable();
87  var mockServerControl = new Mock<IServerControl>();
88  mockServerControl.Setup(x => x.RegisterForRestart(It.IsNotNull<IRestartHandler>())).Returns(mockRestartRegistration.Object).Verifiable();
89  var mockLaunchParameters = new DreamDaemonLaunchParameters();
90  var mockInstance = new Models.Instance();
91  var mockAsyncDelayer = new Mock<IAsyncDelayer>();
92 
93  using (var wd = new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, mockByondTopicSender.Object, mockEventConsumer.Object, mockJobManager.Object, mockServerControl.Object, mockAsyncDelayer.Object, mockLogger.Object, mockLaunchParameters, mockInstance, default))
94  using (var cts = new CancellationTokenSource())
95  {
96  var mockCompileJob = new Models.CompileJob();
97  var mockDmbProvider = new Mock<IDmbProvider>();
98  mockDmbProvider.SetupGet(x => x.CompileJob).Returns(mockCompileJob).Verifiable();
99  var mDmbP = mockDmbProvider.Object;
100 
101  var infiniteTask = new TaskCompletionSource<int>().Task;
102 
103  mockDmbFactory.SetupGet(x => x.OnNewerDmb).Returns(infiniteTask);
104  mockDmbFactory.Setup(x => x.LockNextDmb(2)).Returns(mDmbP).Verifiable();
105 
106  var sessionsToVerify = new List<Mock<ISessionController>>();
107 
108  var cancellationToken = cts.Token;
109  mockSessionControllerFactory.Setup(x => x.LaunchNew(mockLaunchParameters, mDmbP, null, It.IsAny<bool>(), It.IsAny<bool>(), false, cancellationToken)).Returns(() =>
110  {
111  var mockSession = new Mock<ISessionController>();
112  mockSession.SetupGet(x => x.Lifetime).Returns(infiniteTask).Verifiable();
113  mockSession.SetupGet(x => x.OnReboot).Returns(infiniteTask).Verifiable();
114  mockSession.SetupGet(x => x.Dmb).Returns(mDmbP).Verifiable();
115  mockSession.SetupGet(x => x.LaunchResult).Returns(Task.FromResult(new LaunchResult
116  {
117  StartupTime = TimeSpan.FromSeconds(1)
118  })).Verifiable();
119  sessionsToVerify.Add(mockSession);
120  return Task.FromResult(mockSession.Object);
121  }).Verifiable();
122  mockAsyncDelayer.Setup(x => x.Delay(It.IsAny<TimeSpan>(), cancellationToken)).Returns(Task.CompletedTask).Verifiable();
123 
124  cts.CancelAfter(TimeSpan.FromSeconds(15));
125 
126  try
127  {
128  await wd.Launch(cancellationToken).ConfigureAwait(false);
129  await wd.Terminate(false, cancellationToken).ConfigureAwait(false);
130  }
131  finally
132  {
133  cts.Cancel();
134  }
135  Assert.AreEqual(2, sessionsToVerify.Count);
136  foreach (var I in sessionsToVerify)
137  I.VerifyAll();
138  mockDmbProvider.VerifyAll();
139  }
140 
141  mockSessionControllerFactory.VerifyAll();
142  mockDmbFactory.VerifyAll();
143  mockRestartRegistration.VerifyAll();
144  mockServerControl.VerifyAll();
145  mockChat.VerifyAll();
146  mockAsyncDelayer.VerifyAll();
147  }
148  }
149 }
+Go to the documentation of this file.
1 using Byond.TopicSender;
2 using Microsoft.Extensions.Logging;
3 using Microsoft.VisualStudio.TestTools.UnitTesting;
4 using Moq;
5 using System;
6 using System.Collections.Generic;
7 using System.Threading;
8 using System.Threading.Tasks;
13 
15 {
16  [TestClass]
17  public sealed class TestWatchdog
18  {
19  [TestMethod]
20  public void TestConstruction()
21  {
22  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(null, null, null, null, null, null, null, null, null, null, null, null, null, default));
23 
24  var mockChat = new Mock<IChat>();
25  mockChat.Setup(x => x.RegisterCommandHandler(It.IsNotNull<ICustomCommandHandler>())).Verifiable();
26  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, null, null, null, null, null, null, null, null, null, null, null, null, default));
27 
28  var mockSessionControllerFactory = new Mock<ISessionControllerFactory>();
29  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, null, null, null, null, null, null, null, null, null, null, null, default));
30 
31  var mockDmbFactory = new Mock<IDmbFactory>();
32  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, null, null, null, null, null, null, null, null, null, null, default));
33 
34  var mockReattachInfoHandler = new Mock<IReattachInfoHandler>();
35  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, null, null, null, null, null, null, null, null, null, default));
36 
37  var mockDatabaseContextFactory = new Mock<IDatabaseContextFactory>();
38  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, null, null, null, null, null, null, null, null, default));
39 
40  var mockByondTopicSender = new Mock<IByondTopicSender>();
41  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, mockByondTopicSender.Object, null, null, null, null, null, null, null, default));
42 
43  var mockEventConsumer = new Mock<IEventConsumer>();
44  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, mockByondTopicSender.Object, mockEventConsumer.Object, null, null, null, null, null, null, default));
45 
46  var mockJobManager = new Mock<IJobManager>();
47  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, mockByondTopicSender.Object, mockEventConsumer.Object, mockJobManager.Object, null, null, null, null, null, default));
48 
49  var mockRestartRegistration = new Mock<IRestartRegistration>();
50  mockRestartRegistration.Setup(x => x.Dispose()).Verifiable();
51  var mockServerControl = new Mock<IServerControl>();
52  mockServerControl.Setup(x => x.RegisterForRestart(It.IsNotNull<IRestartHandler>())).Returns(mockRestartRegistration.Object).Verifiable();
53  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, mockByondTopicSender.Object, mockEventConsumer.Object, mockJobManager.Object, mockServerControl.Object, null, null, null, null, default));
54 
55  var mockAsyncDelayer = new Mock<IAsyncDelayer>();
56  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, mockByondTopicSender.Object, mockEventConsumer.Object, mockJobManager.Object, mockServerControl.Object, mockAsyncDelayer.Object, null, null, null, default));
57 
58  var mockLogger = new Mock<ILogger<Watchdog>>();
59  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, mockByondTopicSender.Object, mockEventConsumer.Object, mockJobManager.Object, mockServerControl.Object, mockAsyncDelayer.Object, mockLogger.Object, null, null, default));
60 
61  var mockLaunchParameters = new DreamDaemonLaunchParameters();
62  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, mockByondTopicSender.Object, mockEventConsumer.Object, mockJobManager.Object, mockServerControl.Object, mockAsyncDelayer.Object, mockLogger.Object, mockLaunchParameters, null, default));
63 
64  var mockInstance = new Models.Instance();
65  new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, mockByondTopicSender.Object, mockEventConsumer.Object, mockJobManager.Object, mockServerControl.Object, mockAsyncDelayer.Object, mockLogger.Object, mockLaunchParameters, mockInstance, default).Dispose();
66 
67  mockRestartRegistration.VerifyAll();
68  mockServerControl.VerifyAll();
69  mockChat.VerifyAll();
70  }
71 
72  [TestMethod]
73  public async Task TestSuccessfulLaunchAndShutdown()
74  {
75  var mockChat = new Mock<IChat>();
76  mockChat.Setup(x => x.RegisterCommandHandler(It.IsNotNull<ICustomCommandHandler>())).Verifiable();
77  var mockSessionControllerFactory = new Mock<ISessionControllerFactory>();
78  var mockDmbFactory = new Mock<IDmbFactory>();
79  var mockLogger = new Mock<ILogger<Watchdog>>();
80  var mockReattachInfoHandler = new Mock<IReattachInfoHandler>();
81  var mockDatabaseContextFactory = new Mock<IDatabaseContextFactory>();
82  var mockByondTopicSender = new Mock<IByondTopicSender>();
83  var mockEventConsumer = new Mock<IEventConsumer>();
84  var mockJobManager = new Mock<IJobManager>();
85  var mockRestartRegistration = new Mock<IRestartRegistration>();
86  mockRestartRegistration.Setup(x => x.Dispose()).Verifiable();
87  var mockServerControl = new Mock<IServerControl>();
88  mockServerControl.Setup(x => x.RegisterForRestart(It.IsNotNull<IRestartHandler>())).Returns(mockRestartRegistration.Object).Verifiable();
89  var mockLaunchParameters = new DreamDaemonLaunchParameters();
90  var mockInstance = new Models.Instance();
91  var mockAsyncDelayer = new Mock<IAsyncDelayer>();
92 
93  using (var wd = new Watchdog(mockChat.Object, mockSessionControllerFactory.Object, mockDmbFactory.Object, mockReattachInfoHandler.Object, mockDatabaseContextFactory.Object, mockByondTopicSender.Object, mockEventConsumer.Object, mockJobManager.Object, mockServerControl.Object, mockAsyncDelayer.Object, mockLogger.Object, mockLaunchParameters, mockInstance, default))
94  using (var cts = new CancellationTokenSource())
95  {
96  var mockCompileJob = new Models.CompileJob();
97  var mockDmbProvider = new Mock<IDmbProvider>();
98  mockDmbProvider.SetupGet(x => x.CompileJob).Returns(mockCompileJob).Verifiable();
99  var mDmbP = mockDmbProvider.Object;
100 
101  var infiniteTask = new TaskCompletionSource<int>().Task;
102 
103  mockDmbFactory.SetupGet(x => x.OnNewerDmb).Returns(infiniteTask);
104  mockDmbFactory.Setup(x => x.LockNextDmb(2)).Returns(mDmbP).Verifiable();
105 
106  var sessionsToVerify = new List<Mock<ISessionController>>();
107 
108  var cancellationToken = cts.Token;
109  mockSessionControllerFactory.Setup(x => x.LaunchNew(mockLaunchParameters, mDmbP, null, It.IsAny<bool>(), It.IsAny<bool>(), false, cancellationToken)).Returns(() =>
110  {
111  var mockSession = new Mock<ISessionController>();
112  mockSession.SetupGet(x => x.Lifetime).Returns(infiniteTask).Verifiable();
113  mockSession.SetupGet(x => x.OnReboot).Returns(infiniteTask).Verifiable();
114  mockSession.SetupGet(x => x.Dmb).Returns(mDmbP).Verifiable();
115  mockSession.SetupGet(x => x.LaunchResult).Returns(Task.FromResult(new LaunchResult
116  {
117  StartupTime = TimeSpan.FromSeconds(1)
118  })).Verifiable();
119  sessionsToVerify.Add(mockSession);
120  return Task.FromResult(mockSession.Object);
121  }).Verifiable();
122  mockAsyncDelayer.Setup(x => x.Delay(It.IsAny<TimeSpan>(), cancellationToken)).Returns(Task.CompletedTask).Verifiable();
123 
124  cts.CancelAfter(TimeSpan.FromSeconds(15));
125 
126  try
127  {
128  await wd.Launch(cancellationToken).ConfigureAwait(false);
129  await wd.Terminate(false, cancellationToken).ConfigureAwait(false);
130  }
131  finally
132  {
133  cts.Cancel();
134  }
135  Assert.AreEqual(2, sessionsToVerify.Count);
136  foreach (var I in sessionsToVerify)
137  I.VerifyAll();
138  mockDmbProvider.VerifyAll();
139  }
140 
141  mockSessionControllerFactory.VerifyAll();
142  mockDmbFactory.VerifyAll();
143  mockRestartRegistration.VerifyAll();
144  mockServerControl.VerifyAll();
145  mockChat.VerifyAll();
146  mockAsyncDelayer.VerifyAll();
147  }
148  }
149 }
-
Represents the result of trying to start a DD process
Definition: LaunchResult.cs:9
+
Represents the result of trying to start a DD process
Definition: LaunchResult.cs:9
- - - + + - + - + - -
Handles Commands.ICommands that map to those defined in a IJsonTrackingContext
- - - - + +
Handles Commands.ICommands that map to those defined in a IJsonTrackingContext
+ + + - +
diff --git a/_tgstation_8_server_8_host_8_tests_8_assembly_info_8cs.html b/_tgstation_8_server_8_host_8_tests_8_assembly_info_8cs.html index b50f09579f..f17b747e5d 100644 --- a/_tgstation_8_server_8_host_8_tests_8_assembly_info_8cs.html +++ b/_tgstation_8_server_8_host_8_tests_8_assembly_info_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Host.Tests.AssemblyInfo.cs File Reference + + +tgstation-server: tests/Tgstation.Server.Host.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Host.Tests.AssemblyInfo.cs File Reference - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -99,7 +78,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_tgstation_8_server_8_host_8_tests_8_assembly_info_8cs_source.html b/_tgstation_8_server_8_host_8_tests_8_assembly_info_8cs_source.html index 4e22852711..022ee71c2f 100644 --- a/_tgstation_8_server_8_host_8_tests_8_assembly_info_8cs_source.html +++ b/_tgstation_8_server_8_host_8_tests_8_assembly_info_8cs_source.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Host.Tests.AssemblyInfo.cs Source File + + +tgstation-server: tests/Tgstation.Server.Host.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Host.Tests.AssemblyInfo.cs Source File - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,13 +71,12 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
Tgstation.Server.Host.Tests.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("Tgstation.Server.Host.Tests")]
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("Tgstation.Server.Host.Tests")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Host.Tests")]
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("Tgstation.Server.Host.Tests")]
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("Tgstation.Server.Host.Tests")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Host.Tests")]
20 [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
21 
22 // Generated by the MSBuild WriteCodeFragment class.
23 
diff --git a/_tgstation_8_server_8_host_8_tests_8_program_8cs.html b/_tgstation_8_server_8_host_8_tests_8_program_8cs.html index 6835fdf4aa..f30a7e6528 100644 --- a/_tgstation_8_server_8_host_8_tests_8_program_8cs.html +++ b/_tgstation_8_server_8_host_8_tests_8_program_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Host.Tests.Program.cs File Reference + + +tgstation-server: tests/Tgstation.Server.Host.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Host.Tests.Program.cs File Reference - @@ -33,41 +31,22 @@ - + - - + + + +
@@ -107,7 +86,7 @@ Classes diff --git a/_tgstation_8_server_8_host_8_tests_8_program_8cs_source.html b/_tgstation_8_server_8_host_8_tests_8_program_8cs_source.html index bd9abbdcce..5b598582f8 100644 --- a/_tgstation_8_server_8_host_8_tests_8_program_8cs_source.html +++ b/_tgstation_8_server_8_host_8_tests_8_program_8cs_source.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Host.Tests.Program.cs Source File + + +tgstation-server: tests/Tgstation.Server.Host.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Host.Tests.Program.cs Source File - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,15 +71,14 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
Tgstation.Server.Host.Tests.Program.cs
-Go to the documentation of this file.
1 // <auto-generated> This file has been auto generated. </auto-generated>
2 using System;
3 [Microsoft.VisualStudio.TestPlatform.TestSDKAutoGeneratedCode]
4 class AutoGeneratedProgram {static void Main(string[] args){}}
- +Go to the documentation of this file.
1 // <auto-generated> This file has been auto generated. </auto-generated>
2 using System;
3 [Microsoft.VisualStudio.TestPlatform.TestSDKAutoGeneratedCode]
4 class AutoGeneratedProgram {static void Main(string[] args){}}
diff --git a/src_2_tgstation_8_server_8_host_8_watchdog_2_assembly_info_8cs.html b/_tgstation_8_server_8_host_8_watchdog_2_assembly_info_8cs.html similarity index 60% rename from src_2_tgstation_8_server_8_host_8_watchdog_2_assembly_info_8cs.html rename to _tgstation_8_server_8_host_8_watchdog_2_assembly_info_8cs.html index ed1928c7ff..b641925e2e 100644 --- a/src_2_tgstation_8_server_8_host_8_watchdog_2_assembly_info_8cs.html +++ b/_tgstation_8_server_8_host_8_watchdog_2_assembly_info_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Watchdog/AssemblyInfo.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
diff --git a/_tgstation_8_server_8_host_8_watchdog_2_assembly_info_8cs_source.html b/_tgstation_8_server_8_host_8_watchdog_2_assembly_info_8cs_source.html new file mode 100644 index 0000000000..f9c2e325f3 --- /dev/null +++ b/_tgstation_8_server_8_host_8_watchdog_2_assembly_info_8cs_source.html @@ -0,0 +1,82 @@ + + + + + + + +tgstation-server: src/Tgstation.Server.Host.Watchdog/AssemblyInfo.cs Source File + + + + + + + + + +
+
+ + + + + + + +
+
tgstation-server +
+
The /tg/station 13 server suite
+
+
+ + + + + + + + +
+
+ + +
+ +
+ + +
+
+
+
AssemblyInfo.cs
+
+
+Go to the documentation of this file.
1 using System.Runtime.CompilerServices;
2 
3 [assembly: InternalsVisibleTo("Tgstation.Server.Host.Watchdog.Tests")]
4 [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
+ + + + diff --git a/_tgstation_8_server_8_host_8_watchdog_8_assembly_info_8cs.html b/_tgstation_8_server_8_host_8_watchdog_8_assembly_info_8cs.html index 33f02c41de..d6e42efe3d 100644 --- a/_tgstation_8_server_8_host_8_watchdog_8_assembly_info_8cs.html +++ b/_tgstation_8_server_8_host_8_watchdog_8_assembly_info_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Host.Watchdog/obj/Release/netstandard2.0/Tgstation.Server.Host.Watchdog.AssemblyInfo.cs File Reference + + +tgstation-server: src/Tgstation.Server.Host.Watchdog/obj/Debug/netstandard2.0/Tgstation.Server.Host.Watchdog.AssemblyInfo.cs File Reference - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -99,7 +78,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_tgstation_8_server_8_host_8_watchdog_8_assembly_info_8cs_source.html b/_tgstation_8_server_8_host_8_watchdog_8_assembly_info_8cs_source.html index 11fec32519..6cd9d41c10 100644 --- a/_tgstation_8_server_8_host_8_watchdog_8_assembly_info_8cs_source.html +++ b/_tgstation_8_server_8_host_8_watchdog_8_assembly_info_8cs_source.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Host.Watchdog/obj/Release/netstandard2.0/Tgstation.Server.Host.Watchdog.AssemblyInfo.cs Source File + + +tgstation-server: src/Tgstation.Server.Host.Watchdog/obj/Debug/netstandard2.0/Tgstation.Server.Host.Watchdog.AssemblyInfo.cs Source File - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,13 +71,12 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
Tgstation.Server.Host.Watchdog.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("Tgstation.Server.Host.Watchdog")]
15 [assembly: System.Reflection.AssemblyConfigurationAttribute("Release")]
16 [assembly: System.Reflection.AssemblyFileVersionAttribute("4.0.1.4")]
17 [assembly: System.Reflection.AssemblyInformationalVersionAttribute("4.0.1.4")]
18 [assembly: System.Reflection.AssemblyProductAttribute("Tgstation.Server.Host.Watchdog")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Host.Watchdog")]
20 [assembly: System.Reflection.AssemblyVersionAttribute("4.0.1.4")]
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("Tgstation.Server.Host.Watchdog")]
15 [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
16 [assembly: System.Reflection.AssemblyFileVersionAttribute("4.0.1.4")]
17 [assembly: System.Reflection.AssemblyInformationalVersionAttribute("4.0.1.4")]
18 [assembly: System.Reflection.AssemblyProductAttribute("Tgstation.Server.Host.Watchdog")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Host.Watchdog")]
20 [assembly: System.Reflection.AssemblyVersionAttribute("4.0.1.4")]
21 
22 // Generated by the MSBuild WriteCodeFragment class.
23 
diff --git a/_tgstation_8_server_8_host_8_watchdog_8_tests_2_test_watchdog_8cs.html b/_tgstation_8_server_8_host_8_watchdog_8_tests_2_test_watchdog_8cs.html index 33aa28d506..ae38b8ab95 100644 --- a/_tgstation_8_server_8_host_8_watchdog_8_tests_2_test_watchdog_8cs.html +++ b/_tgstation_8_server_8_host_8_watchdog_8_tests_2_test_watchdog_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Watchdog.Tests/TestWatchdog.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Watchdog
 
namespace  Tgstation.Server.Host.Watchdog.Tests
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_tgstation_8_server_8_host_8_watchdog_8_tests_2_test_watchdog_8cs_source.html b/_tgstation_8_server_8_host_8_watchdog_8_tests_2_test_watchdog_8cs_source.html index f5fcbf5834..5b7166e354 100644 --- a/_tgstation_8_server_8_host_8_watchdog_8_tests_2_test_watchdog_8cs_source.html +++ b/_tgstation_8_server_8_host_8_watchdog_8_tests_2_test_watchdog_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Watchdog.Tests/TestWatchdog.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TestWatchdog.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 using Moq;
4 using System;
5 using System.Threading;
6 using System.Threading.Tasks;
7 
8 namespace Tgstation.Server.Host.Watchdog.Tests
9 {
10  [TestClass]
11  public sealed class TestWatchdog
12  {
13  [TestMethod]
14  public void TestConstruction()
15  {
16  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(null));
17  var mockLogger = new LoggerFactory().CreateLogger<Watchdog>();
18  var wd = new Watchdog(mockLogger);
19  }
20  }
21 }
- +Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Microsoft.VisualStudio.TestTools.UnitTesting;
3 using Moq;
4 using System;
5 using System.Threading;
6 using System.Threading.Tasks;
7 
9 {
10  [TestClass]
11  public sealed class TestWatchdog
12  {
13  [TestMethod]
14  public void TestConstruction()
15  {
16  Assert.ThrowsException<ArgumentNullException>(() => new Watchdog(null));
17  var mockLogger = new LoggerFactory().CreateLogger<Watchdog>();
18  var wd = new Watchdog(mockLogger);
19  }
20  }
21 }
+ - - -
diff --git a/_tgstation_8_server_8_host_8_watchdog_8_tests_8_assembly_info_8cs.html b/_tgstation_8_server_8_host_8_watchdog_8_tests_8_assembly_info_8cs.html index 88df0617e3..ddcebea7fb 100644 --- a/_tgstation_8_server_8_host_8_watchdog_8_tests_8_assembly_info_8cs.html +++ b/_tgstation_8_server_8_host_8_watchdog_8_tests_8_assembly_info_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Watchdog.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Host.Watchdog.Tests.AssemblyInfo.cs File Reference + + +tgstation-server: tests/Tgstation.Server.Host.Watchdog.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Host.Watchdog.Tests.AssemblyInfo.cs File Reference - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -99,7 +78,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_tgstation_8_server_8_host_8_watchdog_8_tests_8_assembly_info_8cs_source.html b/_tgstation_8_server_8_host_8_watchdog_8_tests_8_assembly_info_8cs_source.html index 6b02753515..8178e6150c 100644 --- a/_tgstation_8_server_8_host_8_watchdog_8_tests_8_assembly_info_8cs_source.html +++ b/_tgstation_8_server_8_host_8_watchdog_8_tests_8_assembly_info_8cs_source.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Watchdog.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Host.Watchdog.Tests.AssemblyInfo.cs Source File + + +tgstation-server: tests/Tgstation.Server.Host.Watchdog.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Host.Watchdog.Tests.AssemblyInfo.cs Source File - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,13 +71,12 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
Tgstation.Server.Host.Watchdog.Tests.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("Tgstation.Server.Host.Watchdog.Tests")]
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("Tgstation.Server.Host.Watchdog.Tests")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Host.Watchdog.Tests")]
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("Tgstation.Server.Host.Watchdog.Tests")]
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("Tgstation.Server.Host.Watchdog.Tests")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Host.Watchdog.Tests")]
20 [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
21 
22 // Generated by the MSBuild WriteCodeFragment class.
23 
diff --git a/_tgstation_8_server_8_host_8_watchdog_8_tests_8_program_8cs.html b/_tgstation_8_server_8_host_8_watchdog_8_tests_8_program_8cs.html index 71a5ad72e5..a462091695 100644 --- a/_tgstation_8_server_8_host_8_watchdog_8_tests_8_program_8cs.html +++ b/_tgstation_8_server_8_host_8_watchdog_8_tests_8_program_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Watchdog.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Host.Watchdog.Tests.Program.cs File Reference + + +tgstation-server: tests/Tgstation.Server.Host.Watchdog.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Host.Watchdog.Tests.Program.cs File Reference - @@ -33,41 +31,22 @@ - + - - + + + +
@@ -107,7 +86,7 @@ Classes diff --git a/_tgstation_8_server_8_host_8_watchdog_8_tests_8_program_8cs_source.html b/_tgstation_8_server_8_host_8_watchdog_8_tests_8_program_8cs_source.html index 05521465ef..a66020f3f9 100644 --- a/_tgstation_8_server_8_host_8_watchdog_8_tests_8_program_8cs_source.html +++ b/_tgstation_8_server_8_host_8_watchdog_8_tests_8_program_8cs_source.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Watchdog.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Host.Watchdog.Tests.Program.cs Source File + + +tgstation-server: tests/Tgstation.Server.Host.Watchdog.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Host.Watchdog.Tests.Program.cs Source File - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,15 +71,14 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
Tgstation.Server.Host.Watchdog.Tests.Program.cs
-Go to the documentation of this file.
1 // <auto-generated> This file has been auto generated. </auto-generated>
2 using System;
3 [Microsoft.VisualStudio.TestPlatform.TestSDKAutoGeneratedCode]
4 class AutoGeneratedProgram {static void Main(string[] args){}}
- +Go to the documentation of this file.
1 // <auto-generated> This file has been auto generated. </auto-generated>
2 using System;
3 [Microsoft.VisualStudio.TestPlatform.TestSDKAutoGeneratedCode]
4 class AutoGeneratedProgram {static void Main(string[] args){}}
diff --git a/_tgstation_8_server_8_tests_8_assembly_info_8cs.html b/_tgstation_8_server_8_tests_8_assembly_info_8cs.html index 6ffe9f992d..ddf0de9471 100644 --- a/_tgstation_8_server_8_tests_8_assembly_info_8cs.html +++ b/_tgstation_8_server_8_tests_8_assembly_info_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Tests.AssemblyInfo.cs File Reference + + +tgstation-server: tests/Tgstation.Server.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Tests.AssemblyInfo.cs File Reference - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -99,7 +78,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/_tgstation_8_server_8_tests_8_assembly_info_8cs_source.html b/_tgstation_8_server_8_tests_8_assembly_info_8cs_source.html index 4ac2885489..615cae8ed2 100644 --- a/_tgstation_8_server_8_tests_8_assembly_info_8cs_source.html +++ b/_tgstation_8_server_8_tests_8_assembly_info_8cs_source.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Tests.AssemblyInfo.cs Source File + + +tgstation-server: tests/Tgstation.Server.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Tests.AssemblyInfo.cs Source File - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,13 +71,12 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
Tgstation.Server.Tests.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("Tgstation.Server.Tests")]
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("Tgstation.Server.Tests")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Tests")]
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("Tgstation.Server.Tests")]
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("Tgstation.Server.Tests")]
19 [assembly: System.Reflection.AssemblyTitleAttribute("Tgstation.Server.Tests")]
20 [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
21 
22 // Generated by the MSBuild WriteCodeFragment class.
23 
diff --git a/_tgstation_8_server_8_tests_8_program_8cs.html b/_tgstation_8_server_8_tests_8_program_8cs.html index a18a31b767..daac586c85 100644 --- a/_tgstation_8_server_8_tests_8_program_8cs.html +++ b/_tgstation_8_server_8_tests_8_program_8cs.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Tests.Program.cs File Reference + + +tgstation-server: tests/Tgstation.Server.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Tests.Program.cs File Reference - @@ -33,41 +31,22 @@ - + - - + + + +
@@ -107,7 +86,7 @@ Classes diff --git a/_tgstation_8_server_8_tests_8_program_8cs_source.html b/_tgstation_8_server_8_tests_8_program_8cs_source.html index ba2161b75f..5026383d4c 100644 --- a/_tgstation_8_server_8_tests_8_program_8cs_source.html +++ b/_tgstation_8_server_8_tests_8_program_8cs_source.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Tests/obj/Release/netcoreapp2.1/Tgstation.Server.Tests.Program.cs Source File + + +tgstation-server: tests/Tgstation.Server.Tests/obj/Debug/netcoreapp2.1/Tgstation.Server.Tests.Program.cs Source File - @@ -33,41 +31,22 @@
- + - - + + + +
@@ -92,15 +71,14 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
Tgstation.Server.Tests.Program.cs
-Go to the documentation of this file.
1 // <auto-generated> This file has been auto generated. </auto-generated>
2 using System;
3 [Microsoft.VisualStudio.TestPlatform.TestSDKAutoGeneratedCode]
4 class AutoGeneratedProgram {static void Main(string[] args){}}
- +Go to the documentation of this file.
1 // <auto-generated> This file has been auto generated. </auto-generated>
2 using System;
3 [Microsoft.VisualStudio.TestPlatform.TestSDKAutoGeneratedCode]
4 class AutoGeneratedProgram {static void Main(string[] args){}}
static void Main(string[] args)
diff --git a/_token_8cs.html b/_token_8cs.html index 803b3f6e78..5f906578dd 100644 --- a/_token_8cs.html +++ b/_token_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Token.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_token_8cs_source.html b/_token_8cs_source.html index fe501e99a6..0514137544 100644 --- a/_token_8cs_source.html +++ b/_token_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/Token.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Token.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Api.Models
4 {
8  public sealed class Token
9  {
13  public string Bearer { get; set; }
14 
18  public DateTimeOffset? ExpiresAt { get; set; }
19  }
20 }
- -
Represents a JWT returned by the API
Definition: Token.cs:8
- +Go to the documentation of this file.
1 using System;
2 
4 {
8  public sealed class Token
9  {
13  public string Bearer { get; set; }
14 
18  public DateTimeOffset? ExpiresAt { get; set; }
19  }
20 }
+
DateTimeOffset? ExpiresAt
When the Token expires
Definition: Token.cs:18
+
Represents a JWT returned by the API
Definition: Token.cs:8
+
string Bearer
The value of the JWT
Definition: Token.cs:13
diff --git a/_token_factory_8cs.html b/_token_factory_8cs.html index 2b486eac68..0d386b2b79 100644 --- a/_token_factory_8cs.html +++ b/_token_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/TokenFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_token_factory_8cs_source.html b/_token_factory_8cs_source.html index 7a89204a0b..b9153e71c6 100644 --- a/_token_factory_8cs_source.html +++ b/_token_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/TokenFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
TokenFactory.cs
-Go to the documentation of this file.
1 using Microsoft.IdentityModel.Tokens;
2 using System;
3 using System.Globalization;
4 using System.IdentityModel.Tokens.Jwt;
5 using System.Reflection;
6 using System.Security.Claims;
7 using System.Threading;
8 using System.Threading.Tasks;
11 
12 namespace Tgstation.Server.Host.Security
13 {
15  sealed class TokenFactory : ITokenFactory
16  {
20  const uint TokenExpiryMinutes = 15;
21 
25  const uint TokenClockSkewMinutes = 1;
26 
30  const uint TokenSigningKeyByteAmount = 256;
31 
33  public TokenValidationParameters ValidationParameters { get; }
34 
39 
45  public TokenFactory(IAsyncDelayer asyncDelayer, ICryptographySuite cryptographySuite)
46  {
47  ValidationParameters = new TokenValidationParameters
48  {
49  ValidateIssuerSigningKey = true,
50  IssuerSigningKey = new SymmetricSecurityKey(cryptographySuite.GetSecureBytes(TokenSigningKeyByteAmount)),
51 
52  ValidateIssuer = true,
53  ValidIssuer = Assembly.GetExecutingAssembly().GetName().Name,
54 
55  ValidateLifetime = true,
56  ValidateAudience = true,
57  ValidAudience = typeof(Token).Assembly.GetName().Name,
58 
59  ClockSkew = TimeSpan.FromMinutes(TokenClockSkewMinutes),
60 
61  RequireSignedTokens = true,
62 
63  RequireExpirationTime = true
64  };
65 
66  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
67  }
68 
70  public async Task<Token> CreateToken(Models.User user, CancellationToken cancellationToken)
71  {
72  if (user == null)
73  throw new ArgumentNullException(nameof(user));
74 
75  var now = DateTimeOffset.Now;
76  var nowUnix = now.ToUnixTimeSeconds();
77 
78  // this prevents validation conflicts down the line
79  // tldr we can (theoretically) send a token the same second we receive it
80  // since unix time rounds down, it looks like it came from before the user changed their password
81  // this happens occasionally in unit tests
82  // just delay a second so we can force a round up
83  var lpuUnix = user.LastPasswordUpdate?.ToUnixTimeSeconds();
84  if (nowUnix == lpuUnix)
85  await asyncDelayer.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
86 
87  var expiry = now.AddMinutes(TokenExpiryMinutes);
88  var claims = new Claim[]
89  {
90  new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString(CultureInfo.InvariantCulture)),
91  new Claim(JwtRegisteredClaimNames.Exp, expiry.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture)),
92  new Claim(JwtRegisteredClaimNames.Nbf, nowUnix.ToString(CultureInfo.InvariantCulture)),
93  new Claim(JwtRegisteredClaimNames.Iss, ValidationParameters.ValidIssuer),
94  new Claim(JwtRegisteredClaimNames.Aud, ValidationParameters.ValidAudience)
95  };
96 
97  var token = new JwtSecurityToken(new JwtHeader(new SigningCredentials(ValidationParameters.IssuerSigningKey, SecurityAlgorithms.HmacSha256)), new JwtPayload(claims));
98  return new Token { Bearer = new JwtSecurityTokenHandler().WriteToken(token), ExpiresAt = expiry };
99  }
100  }
101 }
- -
byte[] GetSecureBytes(uint amount)
Generates a secure set of bytes
- - -
Contains various cryptographic functions
+Go to the documentation of this file.
1 using Microsoft.IdentityModel.Tokens;
2 using System;
3 using System.Globalization;
4 using System.IdentityModel.Tokens.Jwt;
5 using System.Reflection;
6 using System.Security.Claims;
7 using System.Threading;
8 using System.Threading.Tasks;
11 
13 {
15  sealed class TokenFactory : ITokenFactory
16  {
20  const uint TokenExpiryMinutes = 15;
21 
25  const uint TokenClockSkewMinutes = 1;
26 
30  const uint TokenSigningKeyByteAmount = 256;
31 
33  public TokenValidationParameters ValidationParameters { get; }
34 
39 
46  {
47  ValidationParameters = new TokenValidationParameters
48  {
49  ValidateIssuerSigningKey = true,
50  IssuerSigningKey = new SymmetricSecurityKey(cryptographySuite.GetSecureBytes(TokenSigningKeyByteAmount)),
51 
52  ValidateIssuer = true,
53  ValidIssuer = Assembly.GetExecutingAssembly().GetName().Name,
54 
55  ValidateLifetime = true,
56  ValidateAudience = true,
57  ValidAudience = typeof(Token).Assembly.GetName().Name,
58 
59  ClockSkew = TimeSpan.FromMinutes(TokenClockSkewMinutes),
60 
61  RequireSignedTokens = true,
62 
63  RequireExpirationTime = true
64  };
65 
66  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
67  }
68 
70  public async Task<Token> CreateToken(Models.User user, CancellationToken cancellationToken)
71  {
72  if (user == null)
73  throw new ArgumentNullException(nameof(user));
74 
75  var now = DateTimeOffset.Now;
76  var nowUnix = now.ToUnixTimeSeconds();
77 
78  // this prevents validation conflicts down the line
79  // tldr we can (theoretically) send a token the same second we receive it
80  // since unix time rounds down, it looks like it came from before the user changed their password
81  // this happens occasionally in unit tests
82  // just delay a second so we can force a round up
83  var lpuUnix = user.LastPasswordUpdate?.ToUnixTimeSeconds();
84  if (nowUnix == lpuUnix)
85  await asyncDelayer.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false);
86 
87  var expiry = now.AddMinutes(TokenExpiryMinutes);
88  var claims = new Claim[]
89  {
90  new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString(CultureInfo.InvariantCulture)),
91  new Claim(JwtRegisteredClaimNames.Exp, expiry.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture)),
92  new Claim(JwtRegisteredClaimNames.Nbf, nowUnix.ToString(CultureInfo.InvariantCulture)),
93  new Claim(JwtRegisteredClaimNames.Iss, ValidationParameters.ValidIssuer),
94  new Claim(JwtRegisteredClaimNames.Aud, ValidationParameters.ValidAudience)
95  };
96 
97  var token = new JwtSecurityToken(new JwtHeader(new SigningCredentials(ValidationParameters.IssuerSigningKey, SecurityAlgorithms.HmacSha256)), new JwtPayload(claims));
98  return new Token { Bearer = new JwtSecurityTokenHandler().WriteToken(token), ExpiresAt = expiry };
99  }
100  }
101 }
+
byte [] GetSecureBytes(uint amount)
Generates a secure set of bytes
+
const uint TokenClockSkewMinutes
Amount of minutes to skew the clock for Token validation
Definition: TokenFactory.cs:25
+ +
Contains various cryptographic functions
-
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the TokenFactory
Definition: TokenFactory.cs:38
-
Represents a JWT returned by the API
Definition: Token.cs:8
-
TokenFactory(IAsyncDelayer asyncDelayer, ICryptographySuite cryptographySuite)
Construct a TokenFactory
Definition: TokenFactory.cs:45
- - -
async Task< Token > CreateToken(Models.User user, CancellationToken cancellationToken)
Create a Token for a given user
Definition: TokenFactory.cs:70
- - +
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the TokenFactory
Definition: TokenFactory.cs:38
+
Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan
+
Represents a JWT returned by the API
Definition: Token.cs:8
+
const uint TokenSigningKeyByteAmount
Amount of bytes to use in the TokenValidationParameters.IssuerSigningKey
Definition: TokenFactory.cs:30
+ +
TokenFactory(IAsyncDelayer asyncDelayer, ICryptographySuite cryptographySuite)
Construct a TokenFactory
Definition: TokenFactory.cs:45
+
TokenValidationParameters ValidationParameters
Definition: TokenFactory.cs:33
+ + +
async Task< Token > CreateToken(Models.User user, CancellationToken cancellationToken)
Create a Token for a given user
Definition: TokenFactory.cs:70
+
const uint TokenExpiryMinutes
Amount of minutes until generated Tokens expire
Definition: TokenFactory.cs:20
+ +
diff --git a/_unauthorized_exception_8cs.html b/_unauthorized_exception_8cs.html index f1803160c4..4d84b42fc2 100644 --- a/_unauthorized_exception_8cs.html +++ b/_unauthorized_exception_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/UnauthorizedException.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_unauthorized_exception_8cs_source.html b/_unauthorized_exception_8cs_source.html index 7cb97d19d3..50b1c71a9f 100644 --- a/_unauthorized_exception_8cs_source.html +++ b/_unauthorized_exception_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/UnauthorizedException.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
UnauthorizedException.cs
-Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
5 namespace Tgstation.Server.Client
6 {
10  public sealed class UnauthorizedException : ClientException
11  {
15  public UnauthorizedException() : base(new ErrorMessage
16  {
17  Message = "Invalid credentials!",
18  SeverApiVersion = null
19  }, HttpStatusCode.Unauthorized)
20  { }
21 
26  public UnauthorizedException(string message) : base(message) { }
27 
33  public UnauthorizedException(string message, Exception innerException) : base(message, innerException) { }
34  }
35 }
- - -
UnauthorizedException(string message)
Construct an UnauthorizedException with a message
-
UnauthorizedException(string message, Exception innerException)
Construct an UnauthorizedException with a message and innerException
+Go to the documentation of this file.
1 using System;
2 using System.Net;
4 
6 {
10  public sealed class UnauthorizedException : ClientException
11  {
15  public UnauthorizedException() : base(new ErrorMessage
16  {
17  Message = "Invalid credentials!",
18  SeverApiVersion = null
19  }, HttpStatusCode.Unauthorized)
20  { }
21 
26  public UnauthorizedException(string message) : base(message) { }
27 
33  public UnauthorizedException(string message, Exception innerException) : base(message, innerException) { }
34  }
35 }
+ +
UnauthorizedException(string message)
Construct an UnauthorizedException with a message
+
UnauthorizedException(string message, Exception innerException)
Construct an UnauthorizedException with a message and innerException
-
UnauthorizedException()
Construct an UnauthorizedException
-
Occurs when the client provides invalid credentials
- -
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- -
Exceptions thrown by IServerClients
+
UnauthorizedException()
Construct an UnauthorizedException
+
Occurs when the client provides invalid credentials
+ +
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+ +
Exceptions thrown by IServerClients
diff --git a/_unrecognized_response_exception_8cs.html b/_unrecognized_response_exception_8cs.html index 0df6d9fc82..dd064bd41a 100644 --- a/_unrecognized_response_exception_8cs.html +++ b/_unrecognized_response_exception_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/UnrecognizedResponseException.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -114,7 +97,7 @@ Namespaces diff --git a/_unrecognized_response_exception_8cs_source.html b/_unrecognized_response_exception_8cs_source.html index f6a6bab804..3c2358637e 100644 --- a/_unrecognized_response_exception_8cs_source.html +++ b/_unrecognized_response_exception_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/UnrecognizedResponseException.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
UnrecognizedResponseException.cs
-Go to the documentation of this file.
1 using System;
2 using System.Globalization;
3 using System.Net;
5 
6 namespace Tgstation.Server.Client
7 {
12  {
18  public UnrecognizedResponseException(string data, HttpStatusCode statusCode) : base(new ErrorMessage
19  {
20  Message = String.Format(CultureInfo.InvariantCulture, "Unrecognized response body: {0}", data),
21  SeverApiVersion = null
22  }, statusCode)
23  { }
24 
29 
34  public UnrecognizedResponseException(string message) : base(message) { }
35 
41  public UnrecognizedResponseException(string message, Exception innerException) : base(message, innerException) { }
42  }
43 }
Occurs when a response is received that did not deserialize to one of the expected Api...
+Go to the documentation of this file.
1 using System;
2 using System.Globalization;
3 using System.Net;
5 
7 {
12  {
18  public UnrecognizedResponseException(string data, HttpStatusCode statusCode) : base(new ErrorMessage
19  {
20  Message = String.Format(CultureInfo.InvariantCulture, "Unrecognized response body: {0}", data),
21  SeverApiVersion = null
22  }, statusCode)
23  { }
24 
29 
34  public UnrecognizedResponseException(string message) : base(message) { }
35 
41  public UnrecognizedResponseException(string message, Exception innerException) : base(message, innerException) { }
42  }
43 }
Occurs when a response is received that did not deserialize to one of the expected Api....
- - -
UnrecognizedResponseException(string message)
Construct an UnrecognizedResponseException with a message
+ +
UnrecognizedResponseException(string message)
Construct an UnrecognizedResponseException with a message
-
UnrecognizedResponseException()
Construct a UnrecognizedResponseException
-
UnrecognizedResponseException(string data, HttpStatusCode statusCode)
Construct an UnrecognizedResponseException with the data of a response body and the statusCode ...
-
UnrecognizedResponseException(string message, Exception innerException)
Construct an UnrecognizedResponseException with a message and innerException
- -
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- -
Exceptions thrown by IServerClients
+
UnrecognizedResponseException()
Construct a UnrecognizedResponseException
+
UnrecognizedResponseException(string data, HttpStatusCode statusCode)
Construct an UnrecognizedResponseException with the data of a response body and the statusCode
+
UnrecognizedResponseException(string message, Exception innerException)
Construct an UnrecognizedResponseException with a message and innerException
+ +
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+ +
Exceptions thrown by IServerClients
diff --git a/_updates_configuration_8cs.html b/_updates_configuration_8cs.html index 4eb0745508..31569d631c 100644 --- a/_updates_configuration_8cs.html +++ b/_updates_configuration_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Configuration/UpdatesConfiguration.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Configuration
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_updates_configuration_8cs_source.html b/_updates_configuration_8cs_source.html index e33c1f3dc9..efc922740f 100644 --- a/_updates_configuration_8cs_source.html +++ b/_updates_configuration_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Configuration/UpdatesConfiguration.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
UpdatesConfiguration.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Host.Configuration
2 {
6  public sealed class UpdatesConfiguration
7  {
11  public const string Section = "Updates";
12 
16  const long DefaultGitHubRepositoryId = 92952846;
17 
21  const string DefaultGitTagPrefix = "tgstation-server-v";
22 
26  const string DefaultUpdatePackageAssetName = "ServerUpdatePackage.zip";
27 
31  public long GitHubRepositoryId { get; set; } = DefaultGitHubRepositoryId;
32 
36  public string GitTagPrefix { get; set; } = DefaultGitTagPrefix;
37 
41  public string UpdatePackageAssetName { get; set; } = DefaultUpdatePackageAssetName;
42  }
43 }
-
Configuration for the automatic update system
- - +Go to the documentation of this file.
2 {
6  public sealed class UpdatesConfiguration
7  {
11  public const string Section = "Updates";
12 
16  const long DefaultGitHubRepositoryId = 92952846;
17 
21  const string DefaultGitTagPrefix = "tgstation-server-v";
22 
26  const string DefaultUpdatePackageAssetName = "ServerUpdatePackage.zip";
27 
31  public long GitHubRepositoryId { get; set; } = DefaultGitHubRepositoryId;
32 
36  public string GitTagPrefix { get; set; } = DefaultGitTagPrefix;
37 
42  }
43 }
string GitTagPrefix
Prefix before the System.Version of TGS published in git tags
+
long GitHubRepositoryId
The Octokit.Repository.Id of the tgstation-server fork to recieve updates from
+
string UpdatePackageAssetName
Asset package containing the new Host assembly in zip form
+
const long DefaultGitHubRepositoryId
The tgstation/tgstation-server Octokit.Repository.Id
+
const string DefaultGitTagPrefix
The default value of GitTagPrefix
+
Configuration for the automatic update system
+
const string Section
The key for the Microsoft.Extensions.Configuration.IConfigurationSection the UpdatesConfiguration res...
+ +
const string DefaultUpdatePackageAssetName
The default value of UpdatePackageAssetName
diff --git a/_user_controller_8cs.html b/_user_controller_8cs.html index 47de77cd57..1e75ea6460 100644 --- a/_user_controller_8cs.html +++ b/_user_controller_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/UserController.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Controllers
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_user_controller_8cs_source.html b/_user_controller_8cs_source.html index 92706aca06..54d957e0d3 100644 --- a/_user_controller_8cs_source.html +++ b/_user_controller_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Controllers/UserController.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
UserController.cs
-Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.EntityFrameworkCore;
3 using Microsoft.Extensions.Logging;
4 using Microsoft.Extensions.Options;
5 using System;
6 using System.Collections.Generic;
7 using System.Globalization;
8 using System.Linq;
9 using System.Net;
10 using System.Threading;
11 using System.Threading.Tasks;
12 using Tgstation.Server.Api;
18 
19 namespace Tgstation.Server.Host.Controllers
20 {
24  [Route(Routes.User)]
25  public sealed class UserController : ModelController<UserUpdate>
26  {
31 
36 
40  readonly ILogger<UserController> logger;
41 
46 
56  public UserController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ISystemIdentityFactory systemIdentityFactory, ICryptographySuite cryptographySuite, ILogger<UserController> logger, IOptions<GeneralConfiguration> generalConfigurationOptions) : base(databaseContext, authenticationContextFactory, logger, false)
57  {
58  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
59  this.systemIdentityFactory = systemIdentityFactory ?? throw new ArgumentNullException(nameof(systemIdentityFactory));
60  this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite));
61  generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
62  }
63 
65  [TgsAuthorize(AdministrationRights.WriteUsers)]
66  public override async Task<IActionResult> Create([FromBody] UserUpdate model, CancellationToken cancellationToken)
67  {
68  if (model == null)
69  throw new ArgumentNullException(nameof(model));
70 
71  if (!(model.Password == null ^ model.SystemIdentifier == null))
72  return BadRequest(new ErrorMessage { Message = "User must have exactly one of either a password or system identifier!" });
73 
74  model.Name = model.Name?.Trim();
75  if (model.Name?.Length == 0)
76  model.Name = null;
77 
78  if (!(model.Name == null ^ model.SystemIdentifier == null))
79  return BadRequest(new ErrorMessage { Message = "User must have a name if and only if user has no system identifier!" });
80 
81  var dbUser = new Models.User
82  {
83  AdministrationRights = model.AdministrationRights ?? AdministrationRights.None,
84  CreatedAt = DateTimeOffset.Now,
85  CreatedBy = AuthenticationContext.User,
86  Enabled = model.Enabled ?? false,
87  InstanceManagerRights = model.InstanceManagerRights ?? InstanceManagerRights.None,
88  Name = model.Name,
89  SystemIdentifier = model.SystemIdentifier,
90  InstanceUsers = new List<Models.InstanceUser>()
91  };
92 
93  if (model.SystemIdentifier != null)
94  try
95  {
96  using (var sysIdentity = await systemIdentityFactory.CreateSystemIdentity(dbUser, cancellationToken).ConfigureAwait(false))
97  {
98  if (sysIdentity == null)
99  return StatusCode((int)HttpStatusCode.Gone);
100  dbUser.Name = sysIdentity.Username;
101  dbUser.SystemIdentifier = sysIdentity.Uid;
102  }
103  }
104  catch (NotImplementedException)
105  {
106  return StatusCode((int)HttpStatusCode.NotImplemented);
107  }
108  else
109  {
110  if (model.Password.Length < generalConfiguration.MinimumPasswordLength)
111  return BadRequest(new ErrorMessage { Message = String.Format(CultureInfo.InvariantCulture, "Password must be at least {0} characters long!", generalConfiguration.MinimumPasswordLength) });
112  cryptographySuite.SetUserPassword(dbUser, model.Password, true);
113  }
114 
115  dbUser.CanonicalName = dbUser.Name.ToUpperInvariant();
116 
117  DatabaseContext.Users.Add(dbUser);
118 
119  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
120 
121  return StatusCode((int)HttpStatusCode.Created, dbUser.ToApi(true));
122  }
123 
125  [TgsAuthorize(AdministrationRights.WriteUsers | AdministrationRights.EditOwnPassword)]
126  public override async Task<IActionResult> Update([FromBody] UserUpdate model, CancellationToken cancellationToken)
127  {
128  if (model == null)
129  throw new ArgumentNullException(nameof(model));
130 
131  var passwordEditOnly = !AuthenticationContext.User.AdministrationRights.Value.HasFlag(AdministrationRights.WriteUsers);
132 
133  var originalUser = passwordEditOnly ? AuthenticationContext.User : await DatabaseContext.Users.Where(x => x.Id == model.Id)
134  .Include(x => x.CreatedBy)
135  .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
136  if (originalUser == default)
137  return NotFound();
138 
139  if (passwordEditOnly && (model.Id != originalUser.Id || model.InstanceManagerRights.HasValue || model.AdministrationRights.HasValue || model.Enabled.HasValue || model.SystemIdentifier != null || model.Name != null))
140  return Forbid();
141 
142  if (model.Password != null)
143  {
144  if (originalUser.PasswordHash == null)
145  return BadRequest(new ErrorMessage { Message = "Cannot convert a system user to a password user!" });
146  cryptographySuite.SetUserPassword(originalUser, model.Password, false);
147  }
148  else if (model.SystemIdentifier != null && model.SystemIdentifier != originalUser.SystemIdentifier)
149  return BadRequest(new ErrorMessage { Message = "Cannot change a user's system identifier!" });
150 
151  if (model.Name != null && model.Name.ToUpperInvariant() != originalUser.CanonicalName)
152  return BadRequest(new ErrorMessage { Message = "Can only change capitalization of a user's name!" });
153 
154  originalUser.InstanceManagerRights = model.InstanceManagerRights ?? originalUser.InstanceManagerRights;
155  originalUser.AdministrationRights = model.AdministrationRights ?? originalUser.AdministrationRights;
156  originalUser.Enabled = model.Enabled ?? originalUser.Enabled;
157  originalUser.Name = model.Name ?? originalUser.Name;
158 
159  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
160 
161  return Json(model.Id == originalUser.Id || (AuthenticationContext.GetRight(RightsType.Administration) & (ulong)AdministrationRights.ReadUsers) != 0 ? originalUser.ToApi(true) : new Api.Models.User
162  {
163  Id = originalUser.Id
164  });
165  }
166 
168  [TgsAuthorize]
169  public override Task<IActionResult> Read(CancellationToken cancellationToken) => Task.FromResult<IActionResult>(Json(AuthenticationContext.User.ToApi(true)));
170 
172  [TgsAuthorize(AdministrationRights.ReadUsers)]
173  public override async Task<IActionResult> List(CancellationToken cancellationToken)
174  {
175  var users = await DatabaseContext.Users
176  .Include(x => x.CreatedBy)
177  .ToListAsync(cancellationToken).ConfigureAwait(false);
178  return Json(users.Select(x => x.ToApi(true)));
179  }
180 
182  [TgsAuthorize]
183  public override async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
184  {
185  if (id == AuthenticationContext.User.Id)
186  return await Read(cancellationToken).ConfigureAwait(false);
187 
188  if (!((AdministrationRights)AuthenticationContext.GetRight(RightsType.Administration)).HasFlag(AdministrationRights.ReadUsers))
189  return Forbid();
190 
191  var user = await DatabaseContext.Users
192  .Where(x => x.Id == id)
193  .Include(x => x.CreatedBy)
194  .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
195  if (user == default)
196  return NotFound();
197  return Json(user.ToApi(true));
198  }
199  }
200 }
- - -
const string User
The Models.User controller
Definition: Routes.cs:24
-
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
+Go to the documentation of this file.
1 using Microsoft.AspNetCore.Mvc;
2 using Microsoft.EntityFrameworkCore;
3 using Microsoft.Extensions.Logging;
4 using Microsoft.Extensions.Options;
5 using System;
6 using System.Collections.Generic;
7 using System.Globalization;
8 using System.Linq;
9 using System.Net;
10 using System.Threading;
11 using System.Threading.Tasks;
12 using Tgstation.Server.Api;
18 
20 {
24  [Route(Routes.User)]
25  public sealed class UserController : ModelController<UserUpdate>
26  {
31 
36 
40  readonly ILogger<UserController> logger;
41 
46 
56  public UserController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ISystemIdentityFactory systemIdentityFactory, ICryptographySuite cryptographySuite, ILogger<UserController> logger, IOptions<GeneralConfiguration> generalConfigurationOptions) : base(databaseContext, authenticationContextFactory, logger, false)
57  {
58  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
59  this.systemIdentityFactory = systemIdentityFactory ?? throw new ArgumentNullException(nameof(systemIdentityFactory));
60  this.cryptographySuite = cryptographySuite ?? throw new ArgumentNullException(nameof(cryptographySuite));
61  generalConfiguration = generalConfigurationOptions?.Value ?? throw new ArgumentNullException(nameof(generalConfigurationOptions));
62  }
63 
65  [TgsAuthorize(AdministrationRights.WriteUsers)]
66  public override async Task<IActionResult> Create([FromBody] UserUpdate model, CancellationToken cancellationToken)
67  {
68  if (model == null)
69  throw new ArgumentNullException(nameof(model));
70 
71  if (!(model.Password == null ^ model.SystemIdentifier == null))
72  return BadRequest(new ErrorMessage { Message = "User must have exactly one of either a password or system identifier!" });
73 
74  model.Name = model.Name?.Trim();
75  if (model.Name?.Length == 0)
76  model.Name = null;
77 
78  if (!(model.Name == null ^ model.SystemIdentifier == null))
79  return BadRequest(new ErrorMessage { Message = "User must have a name if and only if user has no system identifier!" });
80 
81  var dbUser = new Models.User
82  {
83  AdministrationRights = model.AdministrationRights ?? AdministrationRights.None,
84  CreatedAt = DateTimeOffset.Now,
85  CreatedBy = AuthenticationContext.User,
86  Enabled = model.Enabled ?? false,
87  InstanceManagerRights = model.InstanceManagerRights ?? InstanceManagerRights.None,
88  Name = model.Name,
89  SystemIdentifier = model.SystemIdentifier,
90  InstanceUsers = new List<Models.InstanceUser>()
91  };
92 
93  if (model.SystemIdentifier != null)
94  try
95  {
96  using (var sysIdentity = await systemIdentityFactory.CreateSystemIdentity(dbUser, cancellationToken).ConfigureAwait(false))
97  {
98  if (sysIdentity == null)
99  return StatusCode((int)HttpStatusCode.Gone);
100  dbUser.Name = sysIdentity.Username;
101  dbUser.SystemIdentifier = sysIdentity.Uid;
102  }
103  }
104  catch (NotImplementedException)
105  {
106  return StatusCode((int)HttpStatusCode.NotImplemented);
107  }
108  else
109  {
110  if (model.Password.Length < generalConfiguration.MinimumPasswordLength)
111  return BadRequest(new ErrorMessage { Message = String.Format(CultureInfo.InvariantCulture, "Password must be at least {0} characters long!", generalConfiguration.MinimumPasswordLength) });
112  cryptographySuite.SetUserPassword(dbUser, model.Password, true);
113  }
114 
115  dbUser.CanonicalName = dbUser.Name.ToUpperInvariant();
116 
117  DatabaseContext.Users.Add(dbUser);
118 
119  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
120 
121  return StatusCode((int)HttpStatusCode.Created, dbUser.ToApi(true));
122  }
123 
125  [TgsAuthorize(AdministrationRights.WriteUsers | AdministrationRights.EditOwnPassword)]
126  public override async Task<IActionResult> Update([FromBody] UserUpdate model, CancellationToken cancellationToken)
127  {
128  if (model == null)
129  throw new ArgumentNullException(nameof(model));
130 
131  var passwordEditOnly = !AuthenticationContext.User.AdministrationRights.Value.HasFlag(AdministrationRights.WriteUsers);
132 
133  var originalUser = passwordEditOnly ? AuthenticationContext.User : await DatabaseContext.Users.Where(x => x.Id == model.Id)
134  .Include(x => x.CreatedBy)
135  .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
136  if (originalUser == default)
137  return NotFound();
138 
139  if (passwordEditOnly && (model.Id != originalUser.Id || model.InstanceManagerRights.HasValue || model.AdministrationRights.HasValue || model.Enabled.HasValue || model.SystemIdentifier != null || model.Name != null))
140  return Forbid();
141 
142  if (model.Password != null)
143  {
144  if (originalUser.PasswordHash == null)
145  return BadRequest(new ErrorMessage { Message = "Cannot convert a system user to a password user!" });
146  cryptographySuite.SetUserPassword(originalUser, model.Password, false);
147  }
148  else if (model.SystemIdentifier != null && model.SystemIdentifier != originalUser.SystemIdentifier)
149  return BadRequest(new ErrorMessage { Message = "Cannot change a user's system identifier!" });
150 
151  if (model.Name != null && model.Name.ToUpperInvariant() != originalUser.CanonicalName)
152  return BadRequest(new ErrorMessage { Message = "Can only change capitalization of a user's name!" });
153 
154  originalUser.InstanceManagerRights = model.InstanceManagerRights ?? originalUser.InstanceManagerRights;
155  originalUser.AdministrationRights = model.AdministrationRights ?? originalUser.AdministrationRights;
156  originalUser.Enabled = model.Enabled ?? originalUser.Enabled;
157  originalUser.Name = model.Name ?? originalUser.Name;
158 
159  await DatabaseContext.Save(cancellationToken).ConfigureAwait(false);
160 
161  return Json(model.Id == originalUser.Id || (AuthenticationContext.GetRight(RightsType.Administration) & (ulong)AdministrationRights.ReadUsers) != 0 ? originalUser.ToApi(true) : new Api.Models.User
162  {
163  Id = originalUser.Id
164  });
165  }
166 
168  [TgsAuthorize]
169  public override Task<IActionResult> Read(CancellationToken cancellationToken) => Task.FromResult<IActionResult>(Json(AuthenticationContext.User.ToApi(true)));
170 
172  [TgsAuthorize(AdministrationRights.ReadUsers)]
173  public override async Task<IActionResult> List(CancellationToken cancellationToken)
174  {
175  var users = await DatabaseContext.Users
176  .Include(x => x.CreatedBy)
177  .ToListAsync(cancellationToken).ConfigureAwait(false);
178  return Json(users.Select(x => x.ToApi(true)));
179  }
180 
182  [TgsAuthorize]
183  public override async Task<IActionResult> GetId(long id, CancellationToken cancellationToken)
184  {
185  if (id == AuthenticationContext.User.Id)
186  return await Read(cancellationToken).ConfigureAwait(false);
187 
188  if (!((AdministrationRights)AuthenticationContext.GetRight(RightsType.Administration)).HasFlag(AdministrationRights.ReadUsers))
189  return Forbid();
190 
191  var user = await DatabaseContext.Users
192  .Where(x => x.Id == id)
193  .Include(x => x.CreatedBy)
194  .FirstOrDefaultAsync(cancellationToken).ConfigureAwait(false);
195  if (user == default)
196  return NotFound();
197  return Json(user.ToApi(true));
198  }
199  }
200 }
+ + + +
const string User
The Models.User controller
Definition: Routes.cs:24
+
RightsType
The type of rights a model uses
Definition: RightsType.cs:6
- - +
Task< ISystemIdentity > CreateSystemIdentity(User user, CancellationToken cancellationToken)
Create a ISystemIdentity for a given user
+ - -
UserController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ISystemIdentityFactory systemIdentityFactory, ICryptographySuite cryptographySuite, ILogger< UserController > logger, IOptions< GeneralConfiguration > generalConfigurationOptions)
Construct a UserController
-
readonly ICryptographySuite cryptographySuite
The ICryptographySuite for the UserController
- +
UserController(IDatabaseContext databaseContext, IAuthenticationContextFactory authenticationContextFactory, ISystemIdentityFactory systemIdentityFactory, ICryptographySuite cryptographySuite, ILogger< UserController > logger, IOptions< GeneralConfiguration > generalConfigurationOptions)
Construct a UserController
+
readonly ICryptographySuite cryptographySuite
The ICryptographySuite for the UserController
override async Task< IActionResult > Create([FromBody] UserUpdate model, CancellationToken cancellationToken)
-
readonly ISystemIdentityFactory systemIdentityFactory
The ISystemIdentityFactory for the UserController
-
AdministrationRights
Rights for Models.Administration
-
readonly ILogger< UserController > logger
The ILogger for the UserController
-
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
-
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
-
Contains various cryptographic functions
+
override Task< IActionResult > Read(CancellationToken cancellationToken)
Attempt to read a TModel
+
AdministrationRights? AdministrationRights
The Rights.AdministrationRights for the User
Definition: User.cs:44
+
readonly ISystemIdentityFactory systemIdentityFactory
The ISystemIdentityFactory for the UserController
+
AdministrationRights
Rights for Models.Administration
+
readonly ILogger< UserController > logger
The ILogger for the UserController
+
Task Save(CancellationToken cancellationToken)
Saves changes made to the IDatabaseContext
+
ulong GetRight(RightsType rightsType)
Get the value of a given rightsType
+
Contains various cryptographic functions
-
Routes to a server actions
Definition: Routes.cs:9
-
readonly GeneralConfiguration generalConfiguration
The GeneralConfiguration for the UserController
-
override async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Attempt to get a specific a TModel
-
InstanceManagerRights
Rights for managing Models.Instances
+
Routes to a server actions
Definition: Routes.cs:9
+
readonly GeneralConfiguration generalConfiguration
The GeneralConfiguration for the UserController
+
override async Task< IActionResult > GetId(long id, CancellationToken cancellationToken)
Attempt to get a specific a TModel
+
InstanceManagerRights
Rights for managing Models.Instances
- +
override async Task< IActionResult > Update([FromBody] UserUpdate model, CancellationToken cancellationToken)
-
An ApiController representing a TModel
+
An ApiController representing a TModel
-
long Id
The ID of the User
Definition: User.cs:15
- -
override async Task< IActionResult > List(CancellationToken cancellationToken)
Attempt to list entries of the TModel
- -
For editing a given User. Will never be returned by the API
Definition: UserUpdate.cs:6
-
User can read all chat settings except Models.Internal.ChatBot.ConnectionString
-
bool Enabled
If the User is enabled since users cannot be deleted. System users cannot be disabled ...
Definition: User.cs:21
-
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
+
long Id
The ID of the User
Definition: User.cs:15
+ +
override async Task< IActionResult > List(CancellationToken cancellationToken)
Attempt to list entries of the TModel
+
void SetUserPassword(User user, string newPassword, bool newUser)
Sets a User.PasswordHash for a given user
+ +
For editing a given User. Will never be returned by the API
Definition: UserUpdate.cs:6
+
Represents an error message returned by the server
Definition: ErrorMessage.cs:8
- - -
AdministrationRights AdministrationRights
The Rights.AdministrationRights for the User
Definition: User.cs:44
+ +
bool? Enabled
If the User is enabled since users cannot be deleted. System users cannot be disabled
Definition: User.cs:21
+
uint MinimumPasswordLength
Minimum length of database user passwords
+
diff --git a/_user_update_8cs.html b/_user_update_8cs.html index 8c418e1bc8..32f862a093 100644 --- a/_user_update_8cs.html +++ b/_user_update_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/UserUpdate.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Api
 
namespace  Tgstation.Server.Api.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_user_update_8cs_source.html b/_user_update_8cs_source.html index de77efa232..efc649a225 100644 --- a/_user_update_8cs_source.html +++ b/_user_update_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models/UserUpdate.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
UserUpdate.cs
-Go to the documentation of this file.
1 namespace Tgstation.Server.Api.Models
2 {
6  public sealed class UserUpdate : User
7  {
11  public string Password { get; set; }
12  }
13 }
+Go to the documentation of this file.
2 {
6  public sealed class UserUpdate : User
7  {
11  public string Password { get; set; }
12  }
13 }
+
string Password
Cleartext password of the User
Definition: UserUpdate.cs:11
-
For editing a given User. Will never be returned by the API
Definition: UserUpdate.cs:6
- +
For editing a given User. Will never be returned by the API
Definition: UserUpdate.cs:6
diff --git a/_users_client_8cs.html b/_users_client_8cs.html index 97b4180d60..62240732d5 100644 --- a/_users_client_8cs.html +++ b/_users_client_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/UsersClient.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Client
 
@@ -113,7 +96,7 @@ Namespaces diff --git a/_users_client_8cs_source.html b/_users_client_8cs_source.html index 191249b8ad..7f41d7da34 100644 --- a/_users_client_8cs_source.html +++ b/_users_client_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/UsersClient.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
UsersClient.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 using Tgstation.Server.Api;
7 
8 namespace Tgstation.Server.Client
9 {
11  sealed class UsersClient : IUsersClient
12  {
17 
22  public UsersClient(IApiClient apiClient)
23  {
24  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
25  }
26 
28  public Task<User> Create(UserUpdate user, CancellationToken cancellationToken) => apiClient.Create<UserUpdate, User>(Routes.User, user ?? throw new ArgumentNullException(nameof(user)), cancellationToken);
29 
31  public Task<User> GetId(User user, CancellationToken cancellationToken) => apiClient.Read<User>(Routes.SetID(Routes.User, user?.Id ?? throw new ArgumentNullException(nameof(user))), cancellationToken);
32 
34  public Task<IReadOnlyList<User>> List(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<User>>(Routes.List(Routes.User), cancellationToken);
35 
37  public Task<User> Read(CancellationToken cancellationToken) => apiClient.Read<User>(Routes.User, cancellationToken);
38 
40  public Task<User> Update(UserUpdate user, CancellationToken cancellationToken) => apiClient.Update<UserUpdate, User>(Routes.User, user ?? throw new ArgumentNullException(nameof(user)), cancellationToken);
41  }
42 }
readonly IApiClient apiClient
The apiClient for the UsersClient
Definition: UsersClient.cs:16
-
const string User
The Models.User controller
Definition: Routes.cs:24
+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 using Tgstation.Server.Api;
7 
9 {
11  sealed class UsersClient : IUsersClient
12  {
17 
23  {
24  this.apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
25  }
26 
28  public Task<User> Create(UserUpdate user, CancellationToken cancellationToken) => apiClient.Create<UserUpdate, User>(Routes.User, user ?? throw new ArgumentNullException(nameof(user)), cancellationToken);
29 
31  public Task<User> GetId(User user, CancellationToken cancellationToken) => apiClient.Read<User>(Routes.SetID(Routes.User, user?.Id ?? throw new ArgumentNullException(nameof(user))), cancellationToken);
32 
34  public Task<IReadOnlyList<User>> List(CancellationToken cancellationToken) => apiClient.Read<IReadOnlyList<User>>(Routes.List(Routes.User), cancellationToken);
35 
37  public Task<User> Read(CancellationToken cancellationToken) => apiClient.Read<User>(Routes.User, cancellationToken);
38 
40  public Task<User> Update(UserUpdate user, CancellationToken cancellationToken) => apiClient.Update<UserUpdate, User>(Routes.User, user ?? throw new ArgumentNullException(nameof(user)), cancellationToken);
41  }
42 }
readonly IApiClient apiClient
The apiClient for the UsersClient
Definition: UsersClient.cs:16
+
const string User
The Models.User controller
Definition: Routes.cs:24
+
Task< IReadOnlyList< User > > List(CancellationToken cancellationToken)
List all Users
- - + +
Task< User > Read(CancellationToken cancellationToken)
Read the current user's information and general rights
+
Task< User > Create(UserUpdate user, CancellationToken cancellationToken)
Create a new user
-
Routes to a server actions
Definition: Routes.cs:9
- +
Routes to a server actions
Definition: Routes.cs:9
+
Task< User > Update(UserUpdate user, CancellationToken cancellationToken)
Update a user
+ -
long Id
The ID of the User
Definition: User.cs:15
-
static string SetID(string route, long id)
Apply an id postfix to a route
-
static string List(string route)
Get the /List postfix for a route
- -
For editing a given User. Will never be returned by the API
Definition: UserUpdate.cs:6
-
Web interface for the API
Definition: IApiClient.cs:11
-
UsersClient(IApiClient apiClient)
Construct an UsersClient
Definition: UsersClient.cs:22
- +
static string SetID(string route, long id)
Apply an id postfix to a route
+
static string List(string route)
Get the /List postfix for a route
+ +
For editing a given User. Will never be returned by the API
Definition: UserUpdate.cs:6
+
Web interface for the API
Definition: IApiClient.cs:11
+
UsersClient(IApiClient apiClient)
Construct an UsersClient
Definition: UsersClient.cs:22
+
Task< User > GetId(User user, CancellationToken cancellationToken)
Get a specific user
+
diff --git a/_version_command_8cs.html b/_version_command_8cs.html index a712cce6ac..c0cdcc0385 100644 --- a/_version_command_8cs.html +++ b/_version_command_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/VersionCommand.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Components.Chat.Commands.VersionCommandICommand to return the IApplication.VersionString More...
ICommand to return the IApplication.VersionString More...
  + + + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Chat
 
namespace  Tgstation.Server.Host.Components.Chat.Commands
 
@@ -114,7 +103,7 @@ Namespaces diff --git a/_version_command_8cs_source.html b/_version_command_8cs_source.html index e61ede237e..6c68a81a8f 100644 --- a/_version_command_8cs_source.html +++ b/_version_command_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands/VersionCommand.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
VersionCommand.cs
-Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
6 namespace Tgstation.Server.Host.Components.Chat.Commands
7 {
11  sealed class VersionCommand : ICommand
12  {
14  public string Name => "version";
15 
17  public string HelpText => "Displays the tgstation server version";
18 
20  public bool AdminOnly => false;
21 
26 
31  public VersionCommand(IApplication application)
32  {
33  this.application = application ?? throw new ArgumentNullException(nameof(application));
34  }
35 
37  public Task<string> Invoke(string arguments, User user, CancellationToken cancellationToken) => Task.FromResult(application.VersionString);
38  }
39 }
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
- - -
ICommand to return the IApplication.VersionString
-
readonly IApplication application
The IApplication for the VersionCommand
+Go to the documentation of this file.
1 using System;
2 using System.Threading;
3 using System.Threading.Tasks;
5 
7 {
11  sealed class VersionCommand : ICommand
12  {
14  public string Name => "version";
15 
17  public string HelpText => "Displays the tgstation server version";
18 
20  public bool AdminOnly => false;
21 
26 
32  {
33  this.application = application ?? throw new ArgumentNullException(nameof(application));
34  }
35 
37  public Task<string> Invoke(string arguments, User user, CancellationToken cancellationToken) => Task.FromResult(application.VersionString);
38  }
39 }
Configures the ASP.NET Core web application
Definition: IApplication.cs:8
+ +
ICommand to return the IApplication.VersionString
+
readonly IApplication application
The IApplication for the VersionCommand
-
VersionCommand(IApplication application)
Construct a VersionCommand
-
Represents a tgs_chat_user datum
Definition: User.cs:10
- - -
Represents a command that can be invoked by talking to chat bots
Definition: ICommand.cs:9
- + + +
VersionCommand(IApplication application)
Construct a VersionCommand
+
Task< string > Invoke(string arguments, User user, CancellationToken cancellationToken)
Invoke the ICommand
+
Represents a tgs_chat_user datum
Definition: User.cs:10
+
string VersionString
A more verbose version of Version
Definition: IApplication.cs:18
+ + +
Represents a command that can be invoked by talking to chat bots
Definition: ICommand.cs:9
+ +
diff --git a/_watchdog_2_i_watchdog_8cs.html b/_watchdog_2_i_watchdog_8cs.html index aa3e8ad079..a13f8d24e5 100644 --- a/_watchdog_2_i_watchdog_8cs.html +++ b/_watchdog_2_i_watchdog_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Watchdog/IWatchdog.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Watchdog
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_watchdog_2_i_watchdog_8cs_source.html b/_watchdog_2_i_watchdog_8cs_source.html index 83abcefe8b..188dbbea55 100644 --- a/_watchdog_2_i_watchdog_8cs_source.html +++ b/_watchdog_2_i_watchdog_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Watchdog/IWatchdog.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IWatchdog.cs
-Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
4 namespace Tgstation.Server.Host.Watchdog
5 {
9  public interface IWatchdog
10  {
18  Task RunAsync(bool runConfigure, string[] args, CancellationToken cancellationToken);
19  }
20 }
- -
The watchdog for a Host
Definition: IWatchdog.cs:9
- - +Go to the documentation of this file.
1 using System.Threading;
2 using System.Threading.Tasks;
3 
5 {
9  public interface IWatchdog
10  {
18  Task RunAsync(bool runConfigure, string[] args, CancellationToken cancellationToken);
19  }
20 }
+
Task RunAsync(bool runConfigure, string[] args, CancellationToken cancellationToken)
Run the IWatchdog
+
diff --git a/_watchdog_2_i_watchdog_factory_8cs.html b/_watchdog_2_i_watchdog_factory_8cs.html index 2fda7cf915..9343504d1c 100644 --- a/_watchdog_2_i_watchdog_factory_8cs.html +++ b/_watchdog_2_i_watchdog_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Watchdog/IWatchdogFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

interface  Tgstation.Server.Host.Watchdog.IWatchdogFactory - Factory for creating IWatchdogs More...
+ Factory for creating IWatchdogs More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Watchdog
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_watchdog_2_i_watchdog_factory_8cs_source.html b/_watchdog_2_i_watchdog_factory_8cs_source.html index 2a91771db1..aa189edfea 100644 --- a/_watchdog_2_i_watchdog_factory_8cs_source.html +++ b/_watchdog_2_i_watchdog_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Watchdog/IWatchdogFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
IWatchdogFactory.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 
3 namespace Tgstation.Server.Host.Watchdog
4 {
8  public interface IWatchdogFactory
9  {
15  IWatchdog CreateWatchdog(ILoggerFactory loggerFactory);
16  }
17 }
-
The watchdog for a Host
Definition: IWatchdog.cs:9
- - +Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 
4 {
8  public interface IWatchdogFactory
9  {
15  IWatchdog CreateWatchdog(ILoggerFactory loggerFactory);
16  }
17 }
IWatchdog CreateWatchdog(ILoggerFactory loggerFactory)
Create a IWatchdog
+ + +
diff --git a/_watchdog_2_watchdog_8cs.html b/_watchdog_2_watchdog_8cs.html index b59fe13fe0..8797dd217a 100644 --- a/_watchdog_2_watchdog_8cs.html +++ b/_watchdog_2_watchdog_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Watchdog/Watchdog.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Watchdog
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_watchdog_2_watchdog_8cs_source.html b/_watchdog_2_watchdog_8cs_source.html index e2a8d815d2..0897f29ea5 100644 --- a/_watchdog_2_watchdog_8cs_source.html +++ b/_watchdog_2_watchdog_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Watchdog/Watchdog.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
Watchdog.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using System;
3 using System.Collections.Generic;
4 using System.Diagnostics;
5 using System.Globalization;
6 using System.IO;
7 using System.Linq;
8 using System.Reflection;
9 using System.Runtime.InteropServices;
10 using System.Threading;
11 using System.Threading.Tasks;
12 
13 namespace Tgstation.Server.Host.Watchdog
14 {
16  sealed class Watchdog : IWatchdog
17  {
21  readonly ILogger<Watchdog> logger;
22 
27  public Watchdog(ILogger<Watchdog> logger)
28  {
29  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
30  }
31 
33  #pragma warning disable CA1502 // TODO: Decomplexify
34  public async Task RunAsync(bool runConfigure, string[] args, CancellationToken cancellationToken)
35  {
36  logger.LogInformation("Host watchdog starting...");
37  logger.LogDebug("PID: {0}", Process.GetCurrentProcess().Id);
38  string updateDirectory = null;
39  try
40  {
41  var enviromentPath = Environment.GetEnvironmentVariable("PATH");
42  var paths = enviromentPath.Split(';');
43  var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
44 
45  var exeName = "dotnet";
46  IEnumerable<string> enumerator;
47  if (isWindows)
48  {
49  exeName += ".exe";
50  enumerator = paths;
51  }
52  else
53  enumerator = paths.Select(x => x.Split(':')).SelectMany(x => x);
54 
55  enumerator = enumerator.Select(x => Path.Combine(x, exeName));
56 
57  var dotnetPath = enumerator
58  .Where(x =>
59  {
60  logger.LogTrace("Checking for dotnet at {0}", x);
61  return File.Exists(x);
62  })
63  .FirstOrDefault();
64 
65  if (dotnetPath == default)
66  {
67  logger.LogCritical("Unable to locate dotnet executable in PATH! Please ensure the .NET Core runtime is installed and is in your PATH!");
68  return;
69  }
70 
71  logger.LogInformation("Detected dotnet executable at {0}", dotnetPath);
72 
73  var rootLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
74 
75  var assemblyStoragePath = Path.Combine(rootLocation, "lib"); // always always next to watchdog
76 #if DEBUG
77  Directory.CreateDirectory(assemblyStoragePath);
78 #endif
79  var defaultAssemblyPath = Path.GetFullPath(Path.Combine(assemblyStoragePath, "Default"));
80 #if DEBUG
81  // just copy the shit where it belongs
82  Directory.Delete(assemblyStoragePath, true);
83  Directory.CreateDirectory(defaultAssemblyPath);
84 
85  var sourcePath = "../../../Tgstation.Server.Host/bin/Debug/netcoreapp2.1";
86  foreach (string dirPath in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories))
87  Directory.CreateDirectory(dirPath.Replace(sourcePath, defaultAssemblyPath));
88 
89  foreach (string newPath in Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories))
90  File.Copy(newPath, newPath.Replace(sourcePath, defaultAssemblyPath), true);
91 
92  const string AppSettingsJson = "appsettings.json";
93  var rootJson = Path.Combine(rootLocation, AppSettingsJson);
94  File.Delete(rootJson);
95  File.Move(Path.Combine(defaultAssemblyPath, AppSettingsJson), rootJson);
96 #endif
97 
98  var assemblyName = String.Join(".", nameof(Tgstation), nameof(Server), nameof(Host), "dll");
99  var assemblyPath = Path.Combine(defaultAssemblyPath, assemblyName);
100 
101  if (assemblyPath.Contains("\""))
102  {
103  logger.LogCritical("Running from paths with \"'s in the name is not supported!");
104  return;
105  }
106 
107  if (!File.Exists(assemblyPath))
108  {
109  logger.LogCritical("Unable to locate host assembly!");
110  return;
111  }
112 
113  while (!cancellationToken.IsCancellationRequested)
114  using (logger.BeginScope("Host invocation"))
115  {
116  updateDirectory = Path.GetFullPath(Path.Combine(assemblyStoragePath, Guid.NewGuid().ToString()));
117  logger.LogInformation("Update path set to {0}", updateDirectory);
118  using (var process = new Process())
119  {
120  process.StartInfo.FileName = dotnetPath;
121  process.StartInfo.WorkingDirectory = rootLocation; // for appsettings
122 
123  var arguments = new List<string>
124  {
125  '"' + assemblyPath + '"',
126  '"' + updateDirectory + '"'
127  };
128 
129  if (Environment.GetCommandLineArgs().Any(x => x == "--attach-host-debugger"))
130  arguments.Add("--attach-debugger");
131 
132  if (runConfigure)
133  {
134  logger.LogInformation("Running configuration check and wizard if necessary...");
135  arguments.Add("General:SetupWizardMode=Only");
136  }
137 
138  arguments.AddRange(args);
139 
140  process.StartInfo.Arguments = String.Join(" ", arguments);
141 
142  process.StartInfo.UseShellExecute = false; // runs in the same console
143 
144  var tcs = new TaskCompletionSource<object>();
145  process.Exited += (a, b) =>
146  {
147  tcs.TrySetResult(null);
148  };
149  process.EnableRaisingEvents = true;
150 
151  logger.LogInformation("Launching host...");
152 
153  var killedHostProcess = false;
154  try
155  {
156  process.Start();
157 
158  using (var processCts = new CancellationTokenSource())
159  using (processCts.Token.Register(() => tcs.TrySetResult(null)))
160  using (cancellationToken.Register(() =>
161  {
162  if (!Directory.Exists(updateDirectory))
163  {
164  logger.LogInformation("Cancellation requested! Writing shutdown lock file...");
165  File.WriteAllBytes(updateDirectory, Array.Empty<byte>());
166  }
167  else
168  logger.LogWarning("Cancellation requested while update directory exists!");
169 
170  logger.LogInformation("Will force close host process if it doesn't exit in 10 seconds...");
171 
172  try
173  {
174  processCts.CancelAfter(TimeSpan.FromSeconds(10));
175  }
176  catch (ObjectDisposedException) { } // race conditions
177  }))
178  await tcs.Task.ConfigureAwait(false);
179  }
180  catch (InvalidOperationException) { }
181  finally
182  {
183  try
184  {
185  if (!process.HasExited)
186  {
187  killedHostProcess = true;
188  process.Kill();
189  process.WaitForExit();
190  }
191  }
192  catch (InvalidOperationException) { }
193  logger.LogInformation("Host exited!");
194  }
195 
196  if (runConfigure)
197  {
198  logger.LogInformation("Exiting due to configuration check...");
199  return;
200  }
201 
202  switch (process.ExitCode)
203  {
204  case 0:
205  return;
206  case 1:
207  if (!cancellationToken.IsCancellationRequested)
208  logger.LogInformation("Watchdog will restart host..."); // just a restart
209  else
210  logger.LogWarning("Host requested restart but watchdog shutdown is in progress!");
211  break;
212  case 2:
213  // update path is now an exception document
214  logger.LogCritical("Host crashed, propagating exception dump...");
215  var data = File.ReadAllText(updateDirectory);
216  try
217  {
218  File.Delete(updateDirectory);
219  }
220  catch (Exception e)
221  {
222  logger.LogWarning("Unable to delete exception dump file at {0}! Exception: {1}", updateDirectory, e);
223  }
224 
225 #pragma warning disable CA2201 // Do not raise reserved exception types
226  throw new Exception(String.Format(CultureInfo.InvariantCulture, "Host propagated exception: {0}", data));
227 #pragma warning restore CA2201 // Do not raise reserved exception types
228  default:
229  if (killedHostProcess)
230  {
231  logger.LogWarning("Watchdog forced to kill host process!");
232  cancellationToken.ThrowIfCancellationRequested();
233  }
234 
235 #pragma warning disable CA2201 // Do not raise reserved exception types
236  throw new Exception(String.Format(CultureInfo.InvariantCulture, "Host crashed with exit code {0}!", process.ExitCode));
237 #pragma warning restore CA2201 // Do not raise reserved exception types
238  }
239  }
240 
241  // HEY YOU
242  // BE WARNED THAT IF YOU DEBUGGED THE HOST PROCESS THAT JUST LAUNCHED THE DEBUGGER WILL HOLD A LOCK ON THE DIRECTORY
243  // THIS MEANS THE FIRST DIRECTORY.MOVE WILL THROW
244  if (Directory.Exists(updateDirectory))
245  {
246  logger.LogInformation("Applying server update...");
247  if (isWindows)
248  {
249  // windows dick sucking resource unlocking
250  GC.Collect(Int32.MaxValue, GCCollectionMode.Default, true);
251  await Task.Delay(TimeSpan.FromSeconds(5), cancellationToken).ConfigureAwait(false);
252  }
253 
254  var tempPath = Path.Combine(assemblyStoragePath, Guid.NewGuid().ToString());
255  try
256  {
257  Directory.Move(defaultAssemblyPath, tempPath);
258  try
259  {
260  Directory.Move(updateDirectory, defaultAssemblyPath);
261  logger.LogInformation("Server update complete, deleting old server...");
262  try
263  {
264  Directory.Delete(tempPath, true);
265  }
266  catch (Exception e)
267  {
268  logger.LogWarning("Error deleting old server at {0}! Exception: {1}", tempPath, e);
269  }
270  }
271  catch (Exception e)
272  {
273  logger.LogError("Error moving updated server directory, attempting revert! Exception: {0}", e);
274  Directory.Delete(defaultAssemblyPath, true);
275  Directory.Move(tempPath, defaultAssemblyPath);
276  logger.LogInformation("Revert successful!");
277  }
278  }
279  catch (Exception e)
280  {
281  logger.LogWarning("Failed to move out active host assembly! Exception: {0}", e);
282  }
283  }
284  }
285  }
286  catch (OperationCanceledException)
287  {
288  logger.LogDebug("Exiting due to cancellation...");
289  if (!Directory.Exists(updateDirectory))
290  File.Delete(updateDirectory);
291  else
292  Directory.Delete(updateDirectory, true);
293  }
294  catch (Exception e)
295  {
296  logger.LogCritical("Watchdog error! Exception: {0}", e);
297  }
298  finally
299  {
300  logger.LogInformation("Host watchdog exiting...");
301  }
302  }
303  #pragma warning restore CA1502
304  }
305 }
- - -
async Task RunAsync(bool runConfigure, string[] args, CancellationToken cancellationToken)
Run the IWatchdog
Definition: Watchdog.cs:34
-
readonly ILogger< Watchdog > logger
The ILogger for the Watchdog
Definition: Watchdog.cs:21
-
The watchdog for a Host
Definition: IWatchdog.cs:9
+Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using System;
3 using System.Collections.Generic;
4 using System.Diagnostics;
5 using System.Globalization;
6 using System.IO;
7 using System.Linq;
8 using System.Reflection;
9 using System.Runtime.InteropServices;
10 using System.Threading;
11 using System.Threading.Tasks;
12 
14 {
16  sealed class Watchdog : IWatchdog
17  {
21  readonly ILogger<Watchdog> logger;
22 
27  public Watchdog(ILogger<Watchdog> logger)
28  {
29  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
30  }
31 
32  string GetDotnetPath(bool isWindows)
33  {
34  var enviromentPath = Environment.GetEnvironmentVariable("PATH");
35  var paths = enviromentPath.Split(';');
36 
37  var exeName = "dotnet";
38  IEnumerable<string> enumerator;
39  if (isWindows)
40  {
41  exeName += ".exe";
42  enumerator = paths;
43  }
44  else
45  enumerator = paths.Select(x => x.Split(':')).SelectMany(x => x);
46 
47  enumerator = enumerator.Select(x => Path.Combine(x, exeName));
48 
49  return enumerator
50  .Where(x =>
51  {
52  logger.LogTrace("Checking for dotnet at {0}", x);
53  return File.Exists(x);
54  })
55  .FirstOrDefault();
56  }
57 
59  #pragma warning disable CA1502 // TODO: Decomplexify
60  public async Task RunAsync(bool runConfigure, string[] args, CancellationToken cancellationToken)
61  {
62  logger.LogInformation("Host watchdog starting...");
63  logger.LogDebug("PID: {0}", Process.GetCurrentProcess().Id);
64  string updateDirectory = null;
65  try
66  {
67  var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
68  var dotnetPath = GetDotnetPath(isWindows);
69  if (dotnetPath == default)
70  {
71  logger.LogCritical("Unable to locate dotnet executable in PATH! Please ensure the .NET Core runtime is installed and is in your PATH!");
72  return;
73  }
74 
75  logger.LogInformation("Detected dotnet executable at {0}", dotnetPath);
76 
77  var rootLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
78 
79  var assemblyStoragePath = Path.Combine(rootLocation, "lib"); // always always next to watchdog
80 #if DEBUG
81  Directory.CreateDirectory(assemblyStoragePath);
82 #endif
83  var defaultAssemblyPath = Path.GetFullPath(Path.Combine(assemblyStoragePath, "Default"));
84 #if DEBUG
85  // just copy the shit where it belongs
86  Directory.Delete(assemblyStoragePath, true);
87  Directory.CreateDirectory(defaultAssemblyPath);
88 
89  var sourcePath = "../../../Tgstation.Server.Host/bin/Debug/netcoreapp2.1";
90  foreach (string dirPath in Directory.GetDirectories(sourcePath, "*", SearchOption.AllDirectories))
91  Directory.CreateDirectory(dirPath.Replace(sourcePath, defaultAssemblyPath));
92 
93  foreach (string newPath in Directory.GetFiles(sourcePath, "*.*", SearchOption.AllDirectories))
94  File.Copy(newPath, newPath.Replace(sourcePath, defaultAssemblyPath), true);
95 
96  const string AppSettingsJson = "appsettings.json";
97  var rootJson = Path.Combine(rootLocation, AppSettingsJson);
98  File.Delete(rootJson);
99  File.Move(Path.Combine(defaultAssemblyPath, AppSettingsJson), rootJson);
100 #endif
101 
102  var assemblyName = String.Join(".", nameof(Tgstation), nameof(Server), nameof(Host), "dll");
103  var assemblyPath = Path.Combine(defaultAssemblyPath, assemblyName);
104 
105  if (assemblyPath.Contains("\""))
106  {
107  logger.LogCritical("Running from paths with \"'s in the name is not supported!");
108  return;
109  }
110 
111  if (!File.Exists(assemblyPath))
112  {
113  logger.LogCritical("Unable to locate host assembly!");
114  return;
115  }
116 
117  while (!cancellationToken.IsCancellationRequested)
118  using (logger.BeginScope("Host invocation"))
119  {
120  updateDirectory = Path.GetFullPath(Path.Combine(assemblyStoragePath, Guid.NewGuid().ToString()));
121  logger.LogInformation("Update path set to {0}", updateDirectory);
122  using (var process = new Process())
123  {
124  process.StartInfo.FileName = dotnetPath;
125  process.StartInfo.WorkingDirectory = rootLocation; // for appsettings
126 
127  var arguments = new List<string>
128  {
129  '"' + assemblyPath + '"',
130  '"' + updateDirectory + '"'
131  };
132 
133  if (Environment.GetCommandLineArgs().Any(x => x.Equals("--attach-host-debugger", StringComparison.OrdinalIgnoreCase)))
134  arguments.Add("--attach-debugger");
135 
136  if (runConfigure)
137  {
138  logger.LogInformation("Running configuration check and wizard if necessary...");
139  arguments.Add("General:SetupWizardMode=Only");
140  }
141 
142  arguments.AddRange(args);
143 
144  process.StartInfo.Arguments = String.Join(" ", arguments);
145 
146  process.StartInfo.UseShellExecute = false; // runs in the same console
147 
148  var tcs = new TaskCompletionSource<object>();
149  process.Exited += (a, b) =>
150  {
151  tcs.TrySetResult(null);
152  };
153  process.EnableRaisingEvents = true;
154 
155  logger.LogInformation("Launching host...");
156 
157  var killedHostProcess = false;
158  try
159  {
160  process.Start();
161 
162  using (var processCts = new CancellationTokenSource())
163  using (processCts.Token.Register(() => tcs.TrySetResult(null)))
164  using (cancellationToken.Register(() =>
165  {
166  if (!Directory.Exists(updateDirectory))
167  {
168  logger.LogInformation("Cancellation requested! Writing shutdown lock file...");
169  File.WriteAllBytes(updateDirectory, Array.Empty<byte>());
170  }
171  else
172  logger.LogWarning("Cancellation requested while update directory exists!");
173 
174  logger.LogInformation("Will force close host process if it doesn't exit in 10 seconds...");
175 
176  try
177  {
178  processCts.CancelAfter(TimeSpan.FromSeconds(10));
179  }
180  catch (ObjectDisposedException) { } // race conditions
181  }))
182  await tcs.Task.ConfigureAwait(false);
183  }
184  catch (InvalidOperationException) { }
185  finally
186  {
187  try
188  {
189  if (!process.HasExited)
190  {
191  killedHostProcess = true;
192  process.Kill();
193  process.WaitForExit();
194  }
195  }
196  catch (InvalidOperationException) { }
197  logger.LogInformation("Host exited!");
198  }
199 
200  if (runConfigure)
201  {
202  logger.LogInformation("Exiting due to configuration check...");
203  return;
204  }
205 
206  switch (process.ExitCode)
207  {
208  case 0:
209  return;
210  case 1:
211  if (!cancellationToken.IsCancellationRequested)
212  logger.LogInformation("Watchdog will restart host..."); // just a restart
213  else
214  logger.LogWarning("Host requested restart but watchdog shutdown is in progress!");
215  break;
216  case 2:
217  // update path is now an exception document
218  logger.LogCritical("Host crashed, propagating exception dump...");
219  var data = File.ReadAllText(updateDirectory);
220  try
221  {
222  File.Delete(updateDirectory);
223  }
224  catch (Exception e)
225  {
226  logger.LogWarning("Unable to delete exception dump file at {0}! Exception: {1}", updateDirectory, e);
227  }
228 
229 #pragma warning disable CA2201 // Do not raise reserved exception types
230  throw new Exception(String.Format(CultureInfo.InvariantCulture, "Host propagated exception: {0}", data));
231 #pragma warning restore CA2201 // Do not raise reserved exception types
232  default:
233  if (killedHostProcess)
234  {
235  logger.LogWarning("Watchdog forced to kill host process!");
236  cancellationToken.ThrowIfCancellationRequested();
237  }
238 
239 #pragma warning disable CA2201 // Do not raise reserved exception types
240  throw new Exception(String.Format(CultureInfo.InvariantCulture, "Host crashed with exit code {0}!", process.ExitCode));
241 #pragma warning restore CA2201 // Do not raise reserved exception types
242  }
243  }
244 
245  // HEY YOU
246  // BE WARNED THAT IF YOU DEBUGGED THE HOST PROCESS THAT JUST LAUNCHED THE DEBUGGER WILL HOLD A LOCK ON THE DIRECTORY
247  // THIS MEANS THE FIRST DIRECTORY.MOVE WILL THROW
248  if (Directory.Exists(updateDirectory))
249  {
250  logger.LogInformation("Applying server update...");
251  if (isWindows)
252  {
253  // windows dick sucking resource unlocking
254  GC.Collect(Int32.MaxValue, GCCollectionMode.Default, true);
255  await Task.Delay(TimeSpan.FromSeconds(5), cancellationToken).ConfigureAwait(false);
256  }
257 
258  var tempPath = Path.Combine(assemblyStoragePath, Guid.NewGuid().ToString());
259  try
260  {
261  Directory.Move(defaultAssemblyPath, tempPath);
262  try
263  {
264  Directory.Move(updateDirectory, defaultAssemblyPath);
265  logger.LogInformation("Server update complete, deleting old server...");
266  try
267  {
268  Directory.Delete(tempPath, true);
269  }
270  catch (Exception e)
271  {
272  logger.LogWarning("Error deleting old server at {0}! Exception: {1}", tempPath, e);
273  }
274  }
275  catch (Exception e)
276  {
277  logger.LogError("Error moving updated server directory, attempting revert! Exception: {0}", e);
278  Directory.Delete(defaultAssemblyPath, true);
279  Directory.Move(tempPath, defaultAssemblyPath);
280  logger.LogInformation("Revert successful!");
281  }
282  }
283  catch (Exception e)
284  {
285  logger.LogWarning("Failed to move out active host assembly! Exception: {0}", e);
286  }
287  }
288  }
289  }
290  catch (OperationCanceledException)
291  {
292  logger.LogDebug("Exiting due to cancellation...");
293  if (!Directory.Exists(updateDirectory))
294  File.Delete(updateDirectory);
295  else
296  Directory.Delete(updateDirectory, true);
297  }
298  catch (Exception e)
299  {
300  logger.LogCritical("Watchdog error! Exception: {0}", e);
301  }
302  finally
303  {
304  logger.LogInformation("Host watchdog exiting...");
305  }
306  }
307  #pragma warning restore CA1502
308  }
309 }
+
async Task RunAsync(bool runConfigure, string[] args, CancellationToken cancellationToken)
Run the IWatchdog
Definition: Watchdog.cs:60
+ +
readonly ILogger< Watchdog > logger
The ILogger for the Watchdog
Definition: Watchdog.cs:21
+ +
string GetDotnetPath(bool isWindows)
Definition: Watchdog.cs:32
- -
Watchdog(ILogger< Watchdog > logger)
Construct a Watchdog
Definition: Watchdog.cs:27
+ +
Watchdog(ILogger< Watchdog > logger)
Construct a Watchdog
Definition: Watchdog.cs:27
diff --git a/_watchdog_2_watchdog_factory_8cs.html b/_watchdog_2_watchdog_factory_8cs.html index 2a177c00c6..9103362a26 100644 --- a/_watchdog_2_watchdog_factory_8cs.html +++ b/_watchdog_2_watchdog_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Watchdog/WatchdogFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Watchdog
 
@@ -113,7 +98,7 @@ Namespaces diff --git a/_watchdog_2_watchdog_factory_8cs_source.html b/_watchdog_2_watchdog_factory_8cs_source.html index 7d0289d563..47ec9afa56 100644 --- a/_watchdog_2_watchdog_factory_8cs_source.html +++ b/_watchdog_2_watchdog_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Watchdog/WatchdogFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
WatchdogFactory.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using System;
3 
4 namespace Tgstation.Server.Host.Watchdog
5 {
7  public sealed class WatchdogFactory : IWatchdogFactory
8  {
10  public IWatchdog CreateWatchdog(ILoggerFactory loggerFactory) => new Watchdog(loggerFactory?.CreateLogger<Watchdog>() ?? throw new ArgumentNullException(nameof(loggerFactory)));
11  }
12 }
- - -
The watchdog for a Host
Definition: IWatchdog.cs:9
- +Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using System;
3 
5 {
7  public sealed class WatchdogFactory : IWatchdogFactory
8  {
10  public IWatchdog CreateWatchdog(ILoggerFactory loggerFactory) => new Watchdog(loggerFactory?.CreateLogger<Watchdog>() ?? throw new ArgumentNullException(nameof(loggerFactory)));
11  }
12 }
+
IWatchdog CreateWatchdog(ILoggerFactory loggerFactory)
Create a IWatchdog
+ + + -
diff --git a/_watchdog_reattach_information_base_8cs.html b/_watchdog_reattach_information_base_8cs.html index 51e9a5e0c2..d12352fd3b 100644 --- a/_watchdog_reattach_information_base_8cs.html +++ b/_watchdog_reattach_information_base_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/WatchdogReattachInformationBase.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Models.WatchdogReattachInformationBase - Base class for WatchdogReattachInformation More...
+ Base class for WatchdogReattachInformation More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Models
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_watchdog_reattach_information_base_8cs_source.html b/_watchdog_reattach_information_base_8cs_source.html index 7f4da40ca0..6d5d0fc217 100644 --- a/_watchdog_reattach_information_base_8cs_source.html +++ b/_watchdog_reattach_information_base_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/WatchdogReattachInformationBase.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
WatchdogReattachInformationBase.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Host.Models
4 {
8  public abstract class WatchdogReattachInformationBase
9  {
13  public bool AlphaIsActive { get; set; }
14 
19 
25  {
26  AlphaIsActive = copy?.AlphaIsActive ?? throw new ArgumentNullException(nameof(copy));
27  }
28  }
29 }
WatchdogReattachInformationBase()
Construct a WatchdogReattachInformationBase
- - -
WatchdogReattachInformationBase(WatchdogReattachInformationBase copy)
Construct a WatchdogReattachInformation from a given copy
- - - +Go to the documentation of this file.
1 using System;
2 
4 {
8  public abstract class WatchdogReattachInformationBase
9  {
13  public bool AlphaIsActive { get; set; }
14 
19 
25  {
26  AlphaIsActive = copy?.AlphaIsActive ?? throw new ArgumentNullException(nameof(copy));
27  }
28  }
29 }
WatchdogReattachInformationBase()
Construct a WatchdogReattachInformationBase
+ +
WatchdogReattachInformationBase(WatchdogReattachInformationBase copy)
Construct a WatchdogReattachInformation from a given copy
+ +
diff --git a/_windows_byond_installer_8cs.html b/_windows_byond_installer_8cs.html index e87d0213b9..3547473228 100644 --- a/_windows_byond_installer_8cs.html +++ b/_windows_byond_installer_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Components.Byond.WindowsByondInstallerIByondInstaller for windows systems More...
IByondInstaller for windows systems More...
  + + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Byond
 
@@ -114,7 +101,7 @@ Namespaces diff --git a/_windows_byond_installer_8cs_source.html b/_windows_byond_installer_8cs_source.html index 81848d5389..8979a5955f 100644 --- a/_windows_byond_installer_8cs_source.html +++ b/_windows_byond_installer_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Byond/WindowsByondInstaller.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
WindowsByondInstaller.cs
-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;
8 using Tgstation.Server.Host.IO;
9 
10 namespace Tgstation.Server.Host.Components.Byond
11 {
16  {
20  const string ByondRevisionsURLTemplate = "https://secure.byond.com/download/build/{0}/{0}.{1}_byond.zip";
21 
25  const string ByondConfigDir = "byond/cfg";
26 
30  const string ByondDDConfig = "daemon.txt";
31 
35  const string ByondNoPromptTrustedMode = "trusted-check 0";
36 
40  const string ByondDXDir = "byond/directx";
41 
43  public string DreamDaemonName => "dreamdaemon.exe";
44 
46  public string DreamMakerName => "dm.exe";
47 
52 
57 
61  readonly ILogger<WindowsByondInstaller> logger;
62 
66  readonly SemaphoreSlim semaphore;
67 
72 
79  public WindowsByondInstaller(IIOManager ioManager, IProcessExecutor processExecutor, ILogger<WindowsByondInstaller> logger)
80  {
81  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
82  this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor));
83  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
84 
85  semaphore = new SemaphoreSlim(1);
86  installedDirectX = false;
87  }
88 
90  public void Dispose() => semaphore.Dispose();
91 
93  public async Task CleanCache(CancellationToken cancellationToken)
94  {
95  try
96  {
97  await ioManager.DeleteDirectory(ioManager.ConcatPath(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "byond/cache"), cancellationToken).ConfigureAwait(false);
98  }
99  catch(OperationCanceledException)
100  {
101  throw;
102  }
103  catch (Exception e)
104  {
105  logger.LogWarning("Error deleting BYOND cache! Exception: {0}", e);
106  }
107  }
108 
110  public Task<byte[]> DownloadVersion(Version version, CancellationToken cancellationToken)
111  {
112  var url = String.Format(CultureInfo.InvariantCulture, ByondRevisionsURLTemplate, version.Major, version.Minor);
113 
114  return ioManager.DownloadFile(new Uri(url), cancellationToken);
115  }
116 
118  public async Task InstallByond(string path, Version version, CancellationToken cancellationToken)
119  {
120  async Task SetNoPromptTrusted()
121  {
122  var configPath = ioManager.ConcatPath(path, ByondConfigDir);
123  await ioManager.CreateDirectory(configPath, cancellationToken).ConfigureAwait(false);
124  await ioManager.WriteAllBytes(ioManager.ConcatPath(configPath, ByondDDConfig), Encoding.UTF8.GetBytes(ByondNoPromptTrustedMode), cancellationToken).ConfigureAwait(false);
125  }
126 
127  var setNoPromptTrustedModeTask = SetNoPromptTrusted();
128 
129  // after this version lummox made DD depend of directx lol
130  // but then he became amazing and not only fixed it but also gave us 30s compiles \[T]/
131  // then he readded it again so -_-
132  if (!installedDirectX)
133  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
134  if (!installedDirectX)
135  {
136  // ^check again because race conditions
137  // always install it, it's pretty fast and will do better redundancy checking than us
138  var rbdx = ioManager.ConcatPath(path, ByondDXDir);
139 
140  // noShellExecute because we aren't doing runas shennanigans
141  IProcess directXInstaller;
142  try
143  {
144  directXInstaller = processExecutor.LaunchProcess(ioManager.ConcatPath(rbdx, "DXSETUP.exe"), rbdx, "/silent", noShellExecute: true);
145  }
146  catch (Exception e)
147  {
148  throw new JobException("Unable to start DirectX installer process! Is the server running with admin privileges?", e);
149  }
150 
151  using (directXInstaller)
152  {
153  int exitCode;
154  using (cancellationToken.Register(() => directXInstaller.Terminate()))
155  exitCode = await directXInstaller.Lifetime.ConfigureAwait(false);
156  cancellationToken.ThrowIfCancellationRequested();
157 
158  if (exitCode != 0)
159  throw new JobException(String.Format(CultureInfo.InvariantCulture, "Failed to install included DirectX! Exit code: {0}", exitCode));
160  installedDirectX = true;
161  }
162  }
163 
164  await setNoPromptTrustedModeTask.ConfigureAwait(false);
165  }
166  }
167 }
readonly SemaphoreSlim semaphore
The SemaphoreSlim for the WindowsByondInstaller
-
Task< byte[]> DownloadVersion(Version version, CancellationToken cancellationToken)
Download a given BYOND version
-
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
-
readonly ILogger< WindowsByondInstaller > logger
The ILogger for the WindowsByondInstaller
- - - - +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;
8 using Tgstation.Server.Host.IO;
9 
11 {
16  {
20  const string ByondRevisionsURLTemplate = "https://secure.byond.com/download/build/{0}/{0}.{1}_byond.zip";
21 
25  const string ByondConfigDir = "byond/cfg";
26 
30  const string ByondDDConfig = "daemon.txt";
31 
35  const string ByondNoPromptTrustedMode = "trusted-check 0";
36 
40  const string ByondDXDir = "byond/directx";
41 
43  public string DreamDaemonName => "dreamdaemon.exe";
44 
46  public string DreamMakerName => "dm.exe";
47 
52 
57 
61  readonly ILogger<WindowsByondInstaller> logger;
62 
66  readonly SemaphoreSlim semaphore;
67 
72 
80  {
81  this.ioManager = ioManager ?? throw new ArgumentNullException(nameof(ioManager));
82  this.processExecutor = processExecutor ?? throw new ArgumentNullException(nameof(processExecutor));
83  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
84 
85  semaphore = new SemaphoreSlim(1);
86  installedDirectX = false;
87  }
88 
90  public void Dispose() => semaphore.Dispose();
91 
93  public async Task CleanCache(CancellationToken cancellationToken)
94  {
95  try
96  {
97  await ioManager.DeleteDirectory(ioManager.ConcatPath(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "byond/cache"), cancellationToken).ConfigureAwait(false);
98  }
99  catch(OperationCanceledException)
100  {
101  throw;
102  }
103  catch (Exception e)
104  {
105  logger.LogWarning("Error deleting BYOND cache! Exception: {0}", e);
106  }
107  }
108 
110  public Task<byte[]> DownloadVersion(Version version, CancellationToken cancellationToken)
111  {
112  var url = String.Format(CultureInfo.InvariantCulture, ByondRevisionsURLTemplate, version.Major, version.Minor);
113 
114  return ioManager.DownloadFile(new Uri(url), cancellationToken);
115  }
116 
118  public async Task InstallByond(string path, Version version, CancellationToken cancellationToken)
119  {
120  async Task SetNoPromptTrusted()
121  {
122  var configPath = ioManager.ConcatPath(path, ByondConfigDir);
123  await ioManager.CreateDirectory(configPath, cancellationToken).ConfigureAwait(false);
124  await ioManager.WriteAllBytes(ioManager.ConcatPath(configPath, ByondDDConfig), Encoding.UTF8.GetBytes(ByondNoPromptTrustedMode), cancellationToken).ConfigureAwait(false);
125  }
126 
127  var setNoPromptTrustedModeTask = SetNoPromptTrusted();
128 
129  // after this version lummox made DD depend of directx lol
130  // but then he became amazing and not only fixed it but also gave us 30s compiles \[T]/
131  // then he readded it again so -_-
132  if (!installedDirectX)
133  using (await SemaphoreSlimContext.Lock(semaphore, cancellationToken).ConfigureAwait(false))
134  if (!installedDirectX)
135  {
136  // ^check again because race conditions
137  // always install it, it's pretty fast and will do better redundancy checking than us
138  var rbdx = ioManager.ConcatPath(path, ByondDXDir);
139 
140  // noShellExecute because we aren't doing runas shennanigans
141  IProcess directXInstaller;
142  try
143  {
144  directXInstaller = processExecutor.LaunchProcess(ioManager.ConcatPath(rbdx, "DXSETUP.exe"), rbdx, "/silent", noShellExecute: true);
145  }
146  catch (Exception e)
147  {
148  throw new JobException("Unable to start DirectX installer process! Is the server running with admin privileges?", e);
149  }
150 
151  using (directXInstaller)
152  {
153  int exitCode;
154  using (cancellationToken.Register(() => directXInstaller.Terminate()))
155  exitCode = await directXInstaller.Lifetime.ConfigureAwait(false);
156  cancellationToken.ThrowIfCancellationRequested();
157 
158  if (exitCode != 0)
159  throw new JobException(String.Format(CultureInfo.InvariantCulture, "Failed to install included DirectX! Exit code: {0}", exitCode));
160  installedDirectX = true;
161  }
162  }
163 
164  await setNoPromptTrustedModeTask.ConfigureAwait(false);
165  }
166  }
167 }
readonly SemaphoreSlim semaphore
The SemaphoreSlim for the WindowsByondInstaller
+
Task DeleteDirectory(string path, CancellationToken cancellationToken)
Recursively delete a directory
+
Task< byte[]> DownloadVersion(Version version, CancellationToken cancellationToken)
Download a given BYOND version
+
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
+
readonly ILogger< WindowsByondInstaller > logger
The ILogger for the WindowsByondInstaller
+
Task< byte[]> DownloadFile(Uri url, CancellationToken cancellationToken)
Downloads a file from url
+ + +
const string ByondRevisionsURLTemplate
The URL format string for getting BYOND windows version {0}.{1} zipfile
+
Task CreateDirectory(string path, CancellationToken cancellationToken)
Create a directory at path
-
For downloading and installing BYOND extractions for a given system
- -
async Task CleanCache(CancellationToken cancellationToken)
Attempts to cleans the BYOND cache folder for the system
-
void Terminate()
Terminates the process
-
Abstraction over a System.Diagnostics.Process
Definition: IProcess.cs:9
-
WindowsByondInstaller(IIOManager ioManager, IProcessExecutor processExecutor, ILogger< WindowsByondInstaller > logger)
Construct a WindowsByondInstaller
-
async Task InstallByond(string path, Version version, CancellationToken cancellationToken)
Does actions necessary to get an extracted BYOND installation working
- +
For downloading and installing BYOND extractions for a given system
+ + +
async Task CleanCache(CancellationToken cancellationToken)
Attempts to cleans the BYOND cache folder for the system
+
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
+
WindowsByondInstaller(IIOManager ioManager, IProcessExecutor processExecutor, ILogger< WindowsByondInstaller > logger)
Construct a WindowsByondInstaller
+
async Task InstallByond(string path, Version version, CancellationToken cancellationToken)
Does actions necessary to get an extracted BYOND installation working
+ +
const string ByondDXDir
The directory that contains the BYOND directx redistributable
-
Interface for using filesystems
Definition: IIOManager.cs:11
- -
static async Task< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore
-
readonly IIOManager ioManager
The IIOManager for the WindowsByondInstaller
-
Operation exceptions thrown from the context of a Models.Job
Definition: JobException.cs:8
- - - +
Interface for using filesystems
Definition: IIOManager.cs:11
+ + +
static async Task< SemaphoreSlimContext > Lock(SemaphoreSlim semaphore, CancellationToken cancellationToken)
Asyncronously locks a semaphore
+
readonly IIOManager ioManager
The IIOManager for the WindowsByondInstaller
+
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
+ + +
diff --git a/_windows_network_prompt_reaper_8cs.html b/_windows_network_prompt_reaper_8cs.html index 261e00db0b..93fadcef2b 100644 --- a/_windows_network_prompt_reaper_8cs.html +++ b/_windows_network_prompt_reaper_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/WindowsNetworkPromptReaper.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
+ + + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Components
 
namespace  Tgstation.Server.Host.Components.Watchdog
 
@@ -113,7 +100,7 @@ Namespaces diff --git a/_windows_network_prompt_reaper_8cs_source.html b/_windows_network_prompt_reaper_8cs_source.html index 0e42df07ce..a381361482 100644 --- a/_windows_network_prompt_reaper_8cs_source.html +++ b/_windows_network_prompt_reaper_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Watchdog/WindowsNetworkPromptReaper.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
WindowsNetworkPromptReaper.cs
-Go to the documentation of this file.
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.Runtime.InteropServices;
8 using System.Text;
9 using System.Threading;
10 using System.Threading.Tasks;
12 
13 namespace Tgstation.Server.Host.Components.Watchdog
14 {
17  {
21  const int SendMessageCount = 5;
22 
26  const int RecheckDelayMs = 250;
27 
32 
36  readonly ILogger<WindowsNetworkPromptReaper> logger;
37 
41  readonly CancellationTokenSource cancellationTokenSource;
42 
46  readonly List<IProcess> registeredProcesses;
47 
51  Task runTask;
52 
53  static bool EnumWindow(IntPtr hWnd, IntPtr lParam)
54  {
55  var gcChildhandlesList = GCHandle.FromIntPtr(lParam);
56 
57  if (gcChildhandlesList.Target == null)
58  return false;
59 
60  var childHandles = (List<IntPtr>)gcChildhandlesList.Target;
61  childHandles.Add(hWnd);
62 
63  return true;
64  }
65 
66  static List<IntPtr> GetAllChildHandles(IntPtr main)
67  {
68  var childHandles = new List<IntPtr>();
69  var gcChildhandlesList = GCHandle.Alloc(childHandles);
70  try
71  {
72  var pointerChildHandlesList = GCHandle.ToIntPtr(gcChildhandlesList);
73  NativeMethods.EnumWindowProc childProc = new NativeMethods.EnumWindowProc(EnumWindow);
74  NativeMethods.EnumChildWindows(main, childProc, pointerChildHandlesList);
75  }
76  finally
77  {
78  gcChildhandlesList.Free();
79  }
80 
81  return childHandles;
82  }
83 
89  public WindowsNetworkPromptReaper(IAsyncDelayer asyncDelayer, ILogger<WindowsNetworkPromptReaper> logger)
90  {
91  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
92  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
93 
94  registeredProcesses = new List<IProcess>();
95  cancellationTokenSource = new CancellationTokenSource();
96  }
97 
99  public void Dispose() => cancellationTokenSource.Dispose();
100 
101  async Task Run(CancellationToken cancellationToken)
102  {
103  logger.LogDebug("Starting network prompt reaper...");
104  try
105  {
106  while (!cancellationToken.IsCancellationRequested)
107  {
108  await asyncDelayer.Delay(TimeSpan.FromMilliseconds(RecheckDelayMs), cancellationToken).ConfigureAwait(false);
109 
110  IntPtr window;
111  int processId;
112  lock (registeredProcesses)
113  {
114  if (registeredProcesses.Count == 0)
115  continue;
116 
117  window = NativeMethods.FindWindow(null, "Network Accessibility");
118  if (window == IntPtr.Zero)
119  continue;
120 
121  // found a bitch
122  var threadId = NativeMethods.GetWindowThreadProcessId(window, out processId);
123  if (!registeredProcesses.Any(x => x.Id == processId))
124  continue; // not our bitch
125  }
126 
127  logger.LogTrace("Identified \"Network Accessibility\" window in owned process {0}", processId);
128 
129  var found = false;
130  foreach (var I in GetAllChildHandles(window))
131  {
132  const int MaxLength = 10;
133  var stringBuilder = new StringBuilder(MaxLength + 1);
134 
135  if (NativeMethods.GetWindowText(I, stringBuilder, MaxLength) == 0)
136  {
137  logger.LogWarning("Error calling GetWindowText! Exception: {0}", new Win32Exception());
138  continue;
139  }
140 
141  var windowText = stringBuilder.ToString();
142  if (windowText == "Yes")
143  {
144  // smash_button_meme.jpg
145  logger.LogTrace("Sending \"Yes\" button clicks...");
146  for (var J = 0; J < SendMessageCount; ++J)
147  {
148  const int BM_CLICK = 0x00F5;
149  var result = NativeMethods.SendMessage(I, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
150  }
151 
152  found = true;
153  break;
154  }
155  }
156 
157  if (!found)
158  logger.LogDebug("Unable to find \"Yes\" button for \"Network Accessibility\" window in owned process {0}!", processId);
159  }
160  }
161  catch (OperationCanceledException)
162  {
163  logger.LogTrace("Cancelled!");
164  }
165  finally
166  {
167  logger.LogDebug("Exiting network prompt reaper...");
168  }
169  }
170 
172  public Task StartAsync(CancellationToken cancellationToken)
173  {
174  runTask = Run(cancellationTokenSource.Token);
175  return Task.CompletedTask;
176  }
177 
179  public async Task StopAsync(CancellationToken cancellationToken)
180  {
181  logger.LogTrace("Stopping network prompt reaper...");
182  cancellationTokenSource.Cancel();
183  await runTask.ConfigureAwait(false);
184  registeredProcesses.Clear();
185  }
186 
188  public void RegisterProcess(IProcess process)
189  {
190  if (process == null)
191  throw new ArgumentNullException(nameof(process));
192 
193  lock (registeredProcesses)
194  {
195  if (registeredProcesses.Contains(process))
196  throw new InvalidOperationException("This process has already been registered for network prompt reaping!");
197  logger.LogTrace("Registering process {0}...", process.Id);
198  registeredProcesses.Add(process);
199  }
200 
201  process.Lifetime.ContinueWith(x =>
202  {
203  logger.LogTrace("Unregistering process {0}...", process.Id);
204  lock (registeredProcesses)
205  registeredProcesses.Remove(process);
206  }, TaskScheduler.Current);
207  }
208  }
209 }
Task< int > Lifetime
The Task<TResult> resulting in the exit code of the process
Definition: IProcessBase.cs:14
-
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 BetterWin32Errors;
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.Runtime.InteropServices;
8 using System.Text;
9 using System.Threading;
10 using System.Threading.Tasks;
12 
14 {
17  {
21  const int SendMessageCount = 5;
22 
26  const int RecheckDelayMs = 250;
27 
32 
36  readonly ILogger<WindowsNetworkPromptReaper> logger;
37 
41  readonly CancellationTokenSource cancellationTokenSource;
42 
46  readonly List<IProcess> registeredProcesses;
47 
51  Task runTask;
52 
53  static bool EnumWindow(IntPtr hWnd, IntPtr lParam)
54  {
55  var gcChildhandlesList = GCHandle.FromIntPtr(lParam);
56 
57  if (gcChildhandlesList.Target == null)
58  return false;
59 
60  var childHandles = (List<IntPtr>)gcChildhandlesList.Target;
61  childHandles.Add(hWnd);
62 
63  return true;
64  }
65 
66  static List<IntPtr> GetAllChildHandles(IntPtr main)
67  {
68  var childHandles = new List<IntPtr>();
69  var gcChildhandlesList = GCHandle.Alloc(childHandles);
70  try
71  {
72  var pointerChildHandlesList = GCHandle.ToIntPtr(gcChildhandlesList);
74  NativeMethods.EnumChildWindows(main, childProc, pointerChildHandlesList);
75  }
76  finally
77  {
78  gcChildhandlesList.Free();
79  }
80 
81  return childHandles;
82  }
83 
89  public WindowsNetworkPromptReaper(IAsyncDelayer asyncDelayer, ILogger<WindowsNetworkPromptReaper> logger)
90  {
91  this.asyncDelayer = asyncDelayer ?? throw new ArgumentNullException(nameof(asyncDelayer));
92  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
93 
94  registeredProcesses = new List<IProcess>();
95  cancellationTokenSource = new CancellationTokenSource();
96  }
97 
99  public void Dispose() => cancellationTokenSource.Dispose();
100 
101  async Task Run(CancellationToken cancellationToken)
102  {
103  logger.LogDebug("Starting network prompt reaper...");
104  try
105  {
106  while (!cancellationToken.IsCancellationRequested)
107  {
108  await asyncDelayer.Delay(TimeSpan.FromMilliseconds(RecheckDelayMs), cancellationToken).ConfigureAwait(false);
109 
110  IntPtr window;
111  int processId;
112  lock (registeredProcesses)
113  {
114  if (registeredProcesses.Count == 0)
115  continue;
116 
117  window = NativeMethods.FindWindow(null, "Network Accessibility");
118  if (window == IntPtr.Zero)
119  continue;
120 
121  // found a bitch
122  var threadId = NativeMethods.GetWindowThreadProcessId(window, out processId);
123  if (!registeredProcesses.Any(x => x.Id == processId))
124  continue; // not our bitch
125  }
126 
127  logger.LogTrace("Identified \"Network Accessibility\" window in owned process {0}", processId);
128 
129  var found = false;
130  foreach (var I in GetAllChildHandles(window))
131  {
132  const int MaxLength = 10;
133  var stringBuilder = new StringBuilder(MaxLength + 1);
134 
135  if (NativeMethods.GetWindowText(I, stringBuilder, MaxLength) == 0)
136  {
137  logger.LogWarning("Error calling GetWindowText! Exception: {0}", new Win32Exception());
138  continue;
139  }
140 
141  var windowText = stringBuilder.ToString();
142  if (windowText == "Yes")
143  {
144  // smash_button_meme.jpg
145  logger.LogTrace("Sending \"Yes\" button clicks...");
146  for (var J = 0; J < SendMessageCount; ++J)
147  {
148  const int BM_CLICK = 0x00F5;
149  var result = NativeMethods.SendMessage(I, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
150  }
151 
152  found = true;
153  break;
154  }
155  }
156 
157  if (!found)
158  logger.LogDebug("Unable to find \"Yes\" button for \"Network Accessibility\" window in owned process {0}!", processId);
159  }
160  }
161  catch (OperationCanceledException)
162  {
163  logger.LogTrace("Cancelled!");
164  }
165  finally
166  {
167  logger.LogDebug("Exiting network prompt reaper...");
168  }
169  }
170 
172  public Task StartAsync(CancellationToken cancellationToken)
173  {
175  return Task.CompletedTask;
176  }
177 
179  public async Task StopAsync(CancellationToken cancellationToken)
180  {
181  logger.LogTrace("Stopping network prompt reaper...");
182  cancellationTokenSource.Cancel();
183  await runTask.ConfigureAwait(false);
184  registeredProcesses.Clear();
185  }
186 
188  public void RegisterProcess(IProcess process)
189  {
190  if (process == null)
191  throw new ArgumentNullException(nameof(process));
192 
193  lock (registeredProcesses)
194  {
195  if (registeredProcesses.Contains(process))
196  throw new InvalidOperationException("This process has already been registered for network prompt reaping!");
197  logger.LogTrace("Registering process {0}...", process.Id);
198  registeredProcesses.Add(process);
199  }
200 
201  process.Lifetime.ContinueWith(x =>
202  {
203  logger.LogTrace("Unregistering process {0}...", process.Id);
204  lock (registeredProcesses)
205  registeredProcesses.Remove(process);
206  }, TaskScheduler.Current);
207  }
208  }
209 }
+
Task< int > Lifetime
The Task<TResult> resulting in the exit code of the process
Definition: IProcessBase.cs:14
+ +
static int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount)
See https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getwindowtextw
+
const int SendMessageCount
Number of times to send the button click message. Should be at least 2 or it may fail to focus the wi...
- - + -
readonly List< IProcess > registeredProcesses
The list of IProcesss registered
+
readonly List< IProcess > registeredProcesses
The list of IProcesss registered
-
static IntPtr FindWindow(string lpClassName, string lpWindowName)
See https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-findwindoww ...
-
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 ...
-
readonly CancellationTokenSource cancellationTokenSource
The CancellationTokenSource for the WindowsNetworkPromptReaper
-
delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam)
See https://msdn.microsoft.com/en-us/library/ms633493(v=VS.85).aspx
-
Task runTask
The Task representing the lifetime of the WindowsNetworkPromptReaper
-
Abstraction over a System.Diagnostics.Process
Definition: IProcess.cs:9
-
Native methods used by the code
-
readonly ILogger< WindowsNetworkPromptReaper > logger
The ILogger for the WindowsNetworkPromptReaper
+
static IntPtr FindWindow(string lpClassName, string lpWindowName)
See https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-findwindoww
+
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
+
readonly CancellationTokenSource cancellationTokenSource
The CancellationTokenSource for the WindowsNetworkPromptReaper
+
Task Delay(TimeSpan timeSpan, CancellationToken cancellationToken)
Create a Task that completes after a given timeSpan
+
delegate bool EnumWindowProc(IntPtr hwnd, IntPtr lParam)
See https://msdn.microsoft.com/en-us/library/ms633493(v=VS.85).aspx
+
Task runTask
The Task representing the lifetime of the WindowsNetworkPromptReaper
+
const int RecheckDelayMs
Check for prompts each time this amount of milliseconds pass
+
Abstraction over a System.Diagnostics.Process
Definition: IProcess.cs:9
+
Native methods used by the code
+
readonly ILogger< WindowsNetworkPromptReaper > logger
The ILogger for the WindowsNetworkPromptReaper
-
static int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId)
See https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getwindowthreadprocessid ...
-
void RegisterProcess(IProcess process)
Register a given process for network prompt reaping
- - +
static int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId)
See https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getwindowthreadprocessid
+
void RegisterProcess(IProcess process)
Register a given process for network prompt reaping
+ -
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the WindowsNetworkPromptReaper
+
readonly IAsyncDelayer asyncDelayer
The IAsyncDelayer for the WindowsNetworkPromptReaper
-
static bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam)
See https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-enumchildwindows ...
-
int Id
The IProcess&#39; ID
Definition: IProcess.cs:14
-
On Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort(). This looks out for those prompts and immediately clicks "Yes" if the owning process has registered for it
-
WindowsNetworkPromptReaper(IAsyncDelayer asyncDelayer, ILogger< WindowsNetworkPromptReaper > logger)
Construct a WindowsNetworkPromptReaper
- +
static bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam)
See https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-enumchildwindows
+ +
On Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort()....
+
WindowsNetworkPromptReaper(IAsyncDelayer asyncDelayer, ILogger< WindowsNetworkPromptReaper > logger)
Construct a WindowsNetworkPromptReaper
+ - +
diff --git a/_windows_post_write_handler_8cs.html b/_windows_post_write_handler_8cs.html index ed901f8987..0070b761f1 100644 --- a/_windows_post_write_handler_8cs.html +++ b/_windows_post_write_handler_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/WindowsPostWriteHandler.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.IO.WindowsPostWriteHandlerIPostWriteHandler for Windows systems More...
IPostWriteHandler for Windows systems More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.IO
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_windows_post_write_handler_8cs_source.html b/_windows_post_write_handler_8cs_source.html index 9ab48fae3d..2749ddab80 100644 --- a/_windows_post_write_handler_8cs_source.html +++ b/_windows_post_write_handler_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/WindowsPostWriteHandler.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
WindowsPostWriteHandler.cs
-Go to the documentation of this file.
1 using System;
2 
3 namespace Tgstation.Server.Host.IO
4 {
9  {
11  public void HandleWrite(string filePath)
12  {
13  if (filePath == null)
14  throw new ArgumentNullException(nameof(filePath));
15  }
16  }
17 }
Handles changing file modes/permissions after writing
- - -
IPostWriteHandler for Windows systems
-
void HandleWrite(string filePath)
For handling system specific necessities after a write
- +Go to the documentation of this file.
1 using System;
2 
4 {
9  {
11  public void HandleWrite(string filePath)
12  {
13  if (filePath == null)
14  throw new ArgumentNullException(nameof(filePath));
15  }
16  }
17 }
Handles changing file modes/permissions after writing
+
IPostWriteHandler for Windows systems
+
void HandleWrite(string filePath)
For handling system specific necessities after a write
+
diff --git a/_windows_symlink_factory_8cs.html b/_windows_symlink_factory_8cs.html index cc69bc99bb..0c64d8ee31 100644 --- a/_windows_symlink_factory_8cs.html +++ b/_windows_symlink_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/WindowsSymlinkFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.IO.WindowsSymlinkFactoryISymlinkFactory for windows systems More...
ISymlinkFactory for windows systems More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.IO
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_windows_symlink_factory_8cs_source.html b/_windows_symlink_factory_8cs_source.html index f7a292aa02..6215159211 100644 --- a/_windows_symlink_factory_8cs_source.html +++ b/_windows_symlink_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO/WindowsSymlinkFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
WindowsSymlinkFactory.cs
-Go to the documentation of this file.
2 using System;
3 using System.IO;
4 using System.Threading;
5 using System.Threading.Tasks;
6 
7 namespace Tgstation.Server.Host.IO
8 {
13  {
15  public Task CreateSymbolicLink(string targetPath, string linkPath, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
16  {
17  if (targetPath == null)
18  throw new ArgumentNullException(nameof(targetPath));
19  if (linkPath == null)
20  throw new ArgumentNullException(nameof(linkPath));
21 
22  // check if its not a file
23  var flags = File.Exists(targetPath) ? NativeMethods.CreateSymbolicLinkFlags.None : NativeMethods.CreateSymbolicLinkFlags.Directory;
24 
25  /*
26  * no don't fucking use this
27  * sure it works in SOME cases
28  * i.e. win10 1803+ and IN DEVELOPER MODE
29  * other times it throws ERROR_INVALID_PARAMETER
30  * but the fucking worst is there is some configuration of windows that accept the argument and allow the function to succeed
31  * BUT IT DOESN'T CREATE THE FUCKING LINK
32  * I AM NOT DEBUGGING THAT SHIT AGAIN AHHH
33 
34  flags |= NativeMethods.CreateSymbolicLinkFlags.AllowUnprivilegedCreate;
35  */
36 
37  cancellationToken.ThrowIfCancellationRequested();
38  if (!NativeMethods.CreateSymbolicLink(linkPath, targetPath, flags))
39  throw new Win32Exception();
40  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
41  }
42 }
- - +Go to the documentation of this file.
1 using BetterWin32Errors;
2 using System;
3 using System.IO;
4 using System.Threading;
5 using System.Threading.Tasks;
6 
8 {
13  {
15  public Task CreateSymbolicLink(string targetPath, string linkPath, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
16  {
17  if (targetPath == null)
18  throw new ArgumentNullException(nameof(targetPath));
19  if (linkPath == null)
20  throw new ArgumentNullException(nameof(linkPath));
21 
22  // check if its not a file
23  var flags = File.Exists(targetPath) ? NativeMethods.CreateSymbolicLinkFlags.None : NativeMethods.CreateSymbolicLinkFlags.Directory;
24 
25  /*
26  * no don't fucking use this
27  * sure it works in SOME cases
28  * i.e. win10 1803+ and IN DEVELOPER MODE
29  * other times it throws ERROR_INVALID_PARAMETER
30  * but the fucking worst is there is some configuration of windows that accept the argument and allow the function to succeed
31  * BUT IT DOESN'T CREATE THE FUCKING LINK
32  * I AM NOT DEBUGGING THAT SHIT AGAIN AHHH
33 
34  flags |= NativeMethods.CreateSymbolicLinkFlags.AllowUnprivilegedCreate;
35  */
36 
37  cancellationToken.ThrowIfCancellationRequested();
38  if (!NativeMethods.CreateSymbolicLink(linkPath, targetPath, flags))
39  throw new Win32Exception();
40  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
41  }
42 }
CreateSymbolicLinkFlags
See https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createsymboliclinka#param...
- -
static bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, CreateSymbolicLinkFlags dwFlags)
See https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createsymboliclinkw ...
-
Native methods used by the code
- - + +
static bool CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, CreateSymbolicLinkFlags dwFlags)
See https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createsymboliclinkw
+ +
Native methods used by the code
+
diff --git a/_windows_system_identity_8cs.html b/_windows_system_identity_8cs.html index ecfa55dc63..cccd247780 100644 --- a/_windows_system_identity_8cs.html +++ b/_windows_system_identity_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/WindowsSystemIdentity.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Security.WindowsSystemIdentityISystemIdentity for windows systems More...
ISystemIdentity for windows systems More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_windows_system_identity_8cs_source.html b/_windows_system_identity_8cs_source.html index 21bb24c01c..b262302280 100644 --- a/_windows_system_identity_8cs_source.html +++ b/_windows_system_identity_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/WindowsSystemIdentity.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
WindowsSystemIdentity.cs
-Go to the documentation of this file.
1 using System;
2 using System.DirectoryServices.AccountManagement;
3 using System.Security.Principal;
4 using System.Threading;
5 using System.Threading.Tasks;
6 
7 namespace Tgstation.Server.Host.Security
8 {
13  {
15  public string Uid => (userPrincipal?.Sid ?? identity.User).ToString();
16 
18  public string Username => userPrincipal?.Name ?? identity.Name;
19 
23  readonly WindowsIdentity identity;
24 
28  readonly UserPrincipal userPrincipal;
29 
34  public WindowsSystemIdentity(WindowsIdentity identity)
35  {
36  this.identity = identity ?? throw new ArgumentNullException(nameof(identity));
37  }
38 
43  public WindowsSystemIdentity(UserPrincipal userPrincipal)
44  {
45  this.userPrincipal = userPrincipal ?? throw new ArgumentNullException(nameof(userPrincipal));
46  }
47 
49  public void Dispose()
50  {
51  if (identity != null)
52  identity.Dispose();
53  else
54  {
55  var context = userPrincipal.Context;
56  userPrincipal.Dispose();
57  context.Dispose();
58  }
59  }
60 
63  {
64  if (identity != null)
65  {
66  // var newIdentity = (WindowsIdentity)identity.Clone(); //doesn't work because of https://github.com/dotnet/corefx/issues/31841
67  var newIdentity = new WindowsIdentity(identity.Token); // the handle is cloned internally
68 
69  return new WindowsSystemIdentity(newIdentity);
70  }
71 
72  // can't clone a UP, shouldn't be trying to anyway, cloning is for impersonation
73  throw new InvalidOperationException("Cannot clone a UserPrincipal based WindowsSystemIdentity!");
74  }
75 
77  public Task RunImpersonated(Action action, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
78  {
79  if (action == null)
80  throw new ArgumentNullException(nameof(action));
81  if (identity == null)
82  throw new InvalidOperationException("Impersonate using a UserPrincipal based WindowsSystemIdentity!");
83  WindowsIdentity.RunImpersonated(identity.AccessToken, action);
84  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
85  }
86 }
- - -
Represents a user on the current System.Runtime.InteropServices.OSPlatform
- -
WindowsSystemIdentity(WindowsIdentity identity)
Construct a WindowsSystemIdentity using a WindowsIdentity
-
WindowsSystemIdentity(UserPrincipal userPrincipal)
Construct a WindowsSystemIdentity using a UserPrincipal
-
ISystemIdentity Clone()
Clone the ISystemIdentity creating another copy that must have IDisposable.Dispose called on it ...
-
readonly WindowsIdentity identity
The WindowsIdentity for the WindowsSystemIdentity
-
readonly UserPrincipal userPrincipal
The UserPrincipal for the WindowsSystemIdentity
- +Go to the documentation of this file.
1 using System;
2 using System.DirectoryServices.AccountManagement;
3 using System.Security.Principal;
4 using System.Threading;
5 using System.Threading.Tasks;
6 
8 {
13  {
15  public string Uid => (userPrincipal?.Sid ?? identity.User).ToString();
16 
18  public string Username => userPrincipal?.Name ?? identity.Name;
19 
23  readonly WindowsIdentity identity;
24 
28  readonly UserPrincipal userPrincipal;
29 
34  public WindowsSystemIdentity(WindowsIdentity identity)
35  {
36  this.identity = identity ?? throw new ArgumentNullException(nameof(identity));
37  }
38 
43  public WindowsSystemIdentity(UserPrincipal userPrincipal)
44  {
45  this.userPrincipal = userPrincipal ?? throw new ArgumentNullException(nameof(userPrincipal));
46  }
47 
49  public void Dispose()
50  {
51  if (identity != null)
52  identity.Dispose();
53  else
54  {
55  var context = userPrincipal.Context;
56  userPrincipal.Dispose();
57  context.Dispose();
58  }
59  }
60 
63  {
64  if (identity != null)
65  {
66  // var newIdentity = (WindowsIdentity)identity.Clone(); //doesn't work because of https://github.com/dotnet/corefx/issues/31841
67  var newIdentity = new WindowsIdentity(identity.Token); // the handle is cloned internally
68 
69  return new WindowsSystemIdentity(newIdentity);
70  }
71 
72  // can't clone a UP, shouldn't be trying to anyway, cloning is for impersonation
73  throw new InvalidOperationException("Cannot clone a UserPrincipal based WindowsSystemIdentity!");
74  }
75 
77  public Task RunImpersonated(Action action, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
78  {
79  if (action == null)
80  throw new ArgumentNullException(nameof(action));
81  if (identity == null)
82  throw new InvalidOperationException("Impersonate using a UserPrincipal based WindowsSystemIdentity!");
83  WindowsIdentity.RunImpersonated(identity.AccessToken, action);
84  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
85  }
86 }
+ +
Represents a user on the current System.Runtime.InteropServices.OSPlatform
+
WindowsSystemIdentity(WindowsIdentity identity)
Construct a WindowsSystemIdentity using a WindowsIdentity
+ +
WindowsSystemIdentity(UserPrincipal userPrincipal)
Construct a WindowsSystemIdentity using a UserPrincipal
+ +
ISystemIdentity Clone()
Clone the ISystemIdentity creating another copy that must have IDisposable.Dispose called on it
+
readonly WindowsIdentity identity
The WindowsIdentity for the WindowsSystemIdentity
+ +
readonly UserPrincipal userPrincipal
The UserPrincipal for the WindowsSystemIdentity
+
Task RunImpersonated(Action action, CancellationToken cancellationToken)
Runs a given action in the context of the ISystemIdentity
diff --git a/_windows_system_identity_factory_8cs.html b/_windows_system_identity_factory_8cs.html index 093d93f6aa..0eab32d0b8 100644 --- a/_windows_system_identity_factory_8cs.html +++ b/_windows_system_identity_factory_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/WindowsSystemIdentityFactory.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +

Classes

class  Tgstation.Server.Host.Security.WindowsSystemIdentityFactoryISystemIdentityFactory for windows systems. Uses long running tasks due to potential networked domains More...
ISystemIdentityFactory for windows systems. Uses long running tasks due to potential networked domains More...
  + + + + + +

Namespaces

namespace  Tgstation
 
namespace  Tgstation.Server
 
namespace  Tgstation.Server.Host
 
namespace  Tgstation.Server.Host.Security
 
@@ -114,7 +99,7 @@ Namespaces diff --git a/_windows_system_identity_factory_8cs_source.html b/_windows_system_identity_factory_8cs_source.html index 6d90699ce0..6f69e4205b 100644 --- a/_windows_system_identity_factory_8cs_source.html +++ b/_windows_system_identity_factory_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security/WindowsSystemIdentityFactory.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
- + - - + + + +
WindowsSystemIdentityFactory.cs
-Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Microsoft.Win32.SafeHandles;
3 using System;
4 using System.DirectoryServices.AccountManagement;
5 using System.Security.Principal;
6 using System.Threading;
7 using System.Threading.Tasks;
9 
10 namespace Tgstation.Server.Host.Security
11 {
16  {
20  readonly ILogger<WindowsSystemIdentityFactory> logger;
21 
28  static void GetUserAndDomainName(string input, out string username, out string domainName)
29  {
30  var splits = input.Split('\\');
31  username = splits.Length > 1 ? splits[1] : splits[0];
32  domainName = splits.Length > 1 ? splits[0] : null;
33  }
34 
39  public WindowsSystemIdentityFactory(ILogger<WindowsSystemIdentityFactory> logger)
40  {
41  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
42  }
43 
45  public Task<ISystemIdentity> CreateSystemIdentity(User user, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
46  {
47  if (user == null)
48  throw new ArgumentNullException(nameof(user));
49 
50  if (user.SystemIdentifier == null)
51  throw new InvalidOperationException("User's SystemIdentifier must not be null!");
52 
53  PrincipalContext pc = null;
54  UserPrincipal principal = null;
55 
56  bool TryGetPrincipalFromContextType(ContextType contextType)
57  {
58  try
59  {
60  pc = new PrincipalContext(contextType);
61  cancellationToken.ThrowIfCancellationRequested();
62  principal = UserPrincipal.FindByIdentity(pc, user.SystemIdentifier);
63  }
64  catch (OperationCanceledException)
65  {
66  throw;
67  }
68  catch (Exception e)
69  {
70  logger.LogWarning("Error loading user for context type {0}! Exception: {1}", contextType, e);
71  }
72  finally
73  {
74  if (principal == null)
75  {
76  pc?.Dispose();
77  cancellationToken.ThrowIfCancellationRequested();
78  }
79  }
80 
81  return principal != null;
82  }
83 
84  if (!TryGetPrincipalFromContextType(ContextType.Machine) && !TryGetPrincipalFromContextType(ContextType.Domain))
85  return null;
86  return (ISystemIdentity)new WindowsSystemIdentity(principal);
87  },
88  cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
89 
91  public Task<ISystemIdentity> CreateSystemIdentity(string username, string password, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
92  {
93  if (username == null)
94  throw new ArgumentNullException(nameof(username));
95  if (password == null)
96  throw new ArgumentNullException(nameof(password));
97 
98  var originalUsername = username;
99  GetUserAndDomainName(originalUsername, out username, out var domainName);
100 
101  var res = NativeMethods.LogonUser(username, domainName, password, 3 /*LOGON32_LOGON_NETWORK*/, 0 /*LOGON32_PROVIDER_DEFAULT*/, out var token);
102  if (!res)
103  {
104  logger.LogTrace("Failed to log in username {0}!", originalUsername);
105  return null;
106  }
107 
108  logger.LogTrace("Successfully logged in username {0}!", originalUsername);
109 
110  using (var handle = new SafeAccessTokenHandle(token)) // checked internally, windows identity always duplicates the handle when constructed with a userToken
111  return (ISystemIdentity)new WindowsSystemIdentity(new WindowsIdentity(handle.DangerousGetHandle())); // https://github.com/dotnet/corefx/blob/6ed61acebe3214fcf79b4274f2bb9b55c0604a4d/src/System.Security.Principal.Windows/src/System/Security/Principal/WindowsIdentity.cs#L271
112  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
113  }
114 }
- -
Represents a user on the current System.Runtime.InteropServices.OSPlatform
+Go to the documentation of this file.
1 using Microsoft.Extensions.Logging;
2 using Microsoft.Win32.SafeHandles;
3 using System;
4 using System.DirectoryServices.AccountManagement;
5 using System.Security.Principal;
6 using System.Threading;
7 using System.Threading.Tasks;
9 
11 {
16  {
20  readonly ILogger<WindowsSystemIdentityFactory> logger;
21 
28  static void GetUserAndDomainName(string input, out string username, out string domainName)
29  {
30  var splits = input.Split('\\');
31  username = splits.Length > 1 ? splits[1] : splits[0];
32  domainName = splits.Length > 1 ? splits[0] : null;
33  }
34 
39  public WindowsSystemIdentityFactory(ILogger<WindowsSystemIdentityFactory> logger)
40  {
41  this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
42  }
43 
45  public Task<ISystemIdentity> CreateSystemIdentity(User user, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
46  {
47  if (user == null)
48  throw new ArgumentNullException(nameof(user));
49 
50  if (user.SystemIdentifier == null)
51  throw new InvalidOperationException("User's SystemIdentifier must not be null!");
52 
53  PrincipalContext pc = null;
54  UserPrincipal principal = null;
55 
56  bool TryGetPrincipalFromContextType(ContextType contextType)
57  {
58  try
59  {
60  pc = new PrincipalContext(contextType);
61  cancellationToken.ThrowIfCancellationRequested();
62  principal = UserPrincipal.FindByIdentity(pc, user.SystemIdentifier);
63  }
64  catch (OperationCanceledException)
65  {
66  throw;
67  }
68  catch (Exception e)
69  {
70  logger.LogWarning("Error loading user for context type {0}! Exception: {1}", contextType, e);
71  }
72  finally
73  {
74  if (principal == null)
75  {
76  pc?.Dispose();
77  cancellationToken.ThrowIfCancellationRequested();
78  }
79  }
80 
81  return principal != null;
82  }
83 
84  if (!TryGetPrincipalFromContextType(ContextType.Machine) && !TryGetPrincipalFromContextType(ContextType.Domain))
85  return null;
86  return (ISystemIdentity)new WindowsSystemIdentity(principal);
87  },
88  cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
89 
91  public Task<ISystemIdentity> CreateSystemIdentity(string username, string password, CancellationToken cancellationToken) => Task.Factory.StartNew(() =>
92  {
93  if (username == null)
94  throw new ArgumentNullException(nameof(username));
95  if (password == null)
96  throw new ArgumentNullException(nameof(password));
97 
98  var originalUsername = username;
99  GetUserAndDomainName(originalUsername, out username, out var domainName);
100 
101  var res = NativeMethods.LogonUser(username, domainName, password, 3 /*LOGON32_LOGON_NETWORK*/, 0 /*LOGON32_PROVIDER_DEFAULT*/, out var token);
102  if (!res)
103  {
104  logger.LogTrace("Failed to log in username {0}!", originalUsername);
105  return null;
106  }
107 
108  logger.LogTrace("Successfully logged in username {0}!", originalUsername);
109 
110  using (var handle = new SafeAccessTokenHandle(token)) // checked internally, windows identity always duplicates the handle when constructed with a userToken
111  return (ISystemIdentity)new WindowsSystemIdentity(new WindowsIdentity(handle.DangerousGetHandle())); // https://github.com/dotnet/corefx/blob/6ed61acebe3214fcf79b4274f2bb9b55c0604a4d/src/System.Security.Principal.Windows/src/System/Security/Principal/WindowsIdentity.cs#L271
112  }, cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current);
113  }
114 }
Task< ISystemIdentity > CreateSystemIdentity(User user, CancellationToken cancellationToken)
Create a ISystemIdentity for a given user
- -
readonly ILogger< WindowsSystemIdentityFactory > logger
The ILogger for the WindowsSystemIdentityFactory
-
WindowsSystemIdentityFactory(ILogger< WindowsSystemIdentityFactory > logger)
Construct a WindowsSystemIdentityFactory
+
readonly ILogger< WindowsSystemIdentityFactory > logger
The ILogger for the WindowsSystemIdentityFactory
+
WindowsSystemIdentityFactory(ILogger< WindowsSystemIdentityFactory > logger)
Construct a WindowsSystemIdentityFactory
ISystemIdentityFactory for windows systems. Uses long running tasks due to potential networked domain...
-
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 ...
- -
Native methods used by the code
- -
static void GetUserAndDomainName(string input, out string username, out string domainName)
Extract the username and domain name from a string in the format "username\\domainname" ...
- -
string SystemIdentifier
The SID/UID of the User on Windows/POSIX respectively
Definition: User.cs:32
- + + + +
static void GetUserAndDomainName(string input, out string username, out string domainName)
Extract the username and domain name from a string in the format "username\\domainname"
+ +
diff --git a/annotated.html b/annotated.html index f28dc79e13..310b99e399 100644 --- a/annotated.html +++ b/annotated.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
- + - - + + + +
 NModels  NInternal  CChatBotManage the server chat bots - CChatConnectionStringBuilderHelper for building ChatBot.ConnectionStrings - CCompileJobRepresents a run of DreamMaker - CDreamDaemonLaunchParametersLaunch settings for DreamDaemon - CDreamDaemonSettingsConfigurable settings for DreamDaemon + CChatConnectionStringBuilderHelper for building ChatBot.ConnectionStrings + CCompileJobRepresents a run of DreamMaker + CDreamDaemonLaunchParametersLaunch settings for DreamDaemon + CDreamDaemonSettingsConfigurable settings for DreamDaemon  CJobRepresents a long running job - CRepositorySettingsRepresents configurable settings for a Repository + CRepositorySettingsRepresents configurable settings for a Repository  CRevisionInformationRepresents information about a current git revison  CTestMergeRepresents a merge of a GitHub pull request  CTestMergeBaseLayer of test merge data required internally - CUserRepresents a server User + CUserRepresents a server User  NTests  CTestIrcConnectionStringBuilder  CAdministrationRepresents administrative server information @@ -119,13 +95,13 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CChatChannelIndicates a chat channel  CCompileJob  CConfigurationFileRepresents a game configuration file. Create and delete actions uncerimonuously overwrite/delete files - CDiscordConnectionStringBuilderChatConnectionStringBuilder for ChatProvider.Discord - CDreamDaemonRepresents an instance of BYOND's DreamDaemon game server. Create action starts the server. Delete action shuts down the server - CDreamMakerRepresents the state of the DreamMaker compiler. Create action starts a new compile. Delete action cancels the current compile + CDiscordConnectionStringBuilderChatConnectionStringBuilder for ChatProvider.Discord + CDreamDaemonRepresents an instance of BYOND's DreamDaemon game server. Create action starts the server. Delete action shuts down the server + CDreamMakerRepresents the state of the DreamMaker compiler. Create action starts a new compile. Delete action cancels the current compile  CErrorMessageRepresents an error message returned by the server  CInstanceMetadata about a server instance - CInstanceUserRepresents a Users permissions in an Instance - CIrcConnectionStringBuilderChatConnectionStringBuilder for ChatProvider.Irc + CInstanceUserRepresents a Users permissions in an Instance + CIrcConnectionStringBuilderChatConnectionStringBuilder for ChatProvider.Irc  CJobRepresents a long running job on the server. Model is read-only, updates attempt to cancel the job  CRepositoryRepresents a git repository  CRevisionInformation @@ -138,11 +114,11 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  NRights  NTests  CTestRightsTests for Rights - CRightsHelperHelper for RightsTypes + CRightsHelperHelper for RightsTypes  NTests - CTestApiHeadersTests for ApiHeaders + CTestApiHeadersTests for ApiHeaders  CApiHeadersRepresents the header that must be present for every server request - CRoutesRoutes to a server actions + CRoutesRoutes to a server actions  NClient  NComponents  NTests @@ -173,19 +149,19 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CApiClientFactory  CApiConflictExceptionOccurs when the server returns an unknown response  CApiMismatchExceptionOccurs when the API version of the client is not compatible with the server's - CClientExceptionExceptions thrown by IServerClients + CClientExceptionExceptions thrown by IServerClients  CConflictExceptionOccurs when the client performs an action that would result in data conflict  CHttpClient  CIAdministrationClientFor managing server administration  CIApiClientWeb interface for the API - CIApiClientFactoryFor creating IApiClients + CIApiClientFactoryFor creating IApiClients  CIHttpClientFor sending HTTP requests  CIInstanceManagerClientFor managing Instances  CInstanceManagerClient  CInsufficientPermissionsExceptionOccurs when the client attempts to perform an action they do not have the rights for  CIRequestLoggerFor logging HTTP requests and responses  CIServerClientMain client for communicating with a server - CIServerClientFactoryFactory for creating IServerClients + CIServerClientFactoryFactory for creating IServerClients  CIUsersClientFor managing Users  CMethodNotSupportedExceptionOccurs when the client tries to use a currently unsupported API  CRateLimitExceptionOccurs when a GitHub rate limit occurs @@ -207,8 +183,8 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CIByondExecutableLockRepresents usage of the two primary BYOND server executables  CIByondInstallerFor downloading and installing BYOND extractions for a given system  CIByondManagerFor managing the BYOND installation - CPosixByondInstallerIByondInstaller for Posix systems - CWindowsByondInstallerIByondInstaller for windows systems + CPosixByondInstallerIByondInstaller for Posix systems + CWindowsByondInstallerIByondInstaller for windows systems  NChat  NCommands  CBoolConverterJsonConverter for decoding bools returned by BYOND @@ -216,26 +192,26 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CCommandFactory  CCustomCommandRepresents a command made from DM code  CICommandRepresents a command that can be invoked by talking to chat bots - CICommandFactoryFactory for built in ICommands + CICommandFactoryFactory for built in ICommands  CKekCommandkek  CPullRequestsCommandCommand for reading the active Api.Models.TestMerges - CRevisionCommandFor displaying Api.Models.Internal.RevisionInformation - CVersionCommandICommand to return the IApplication.VersionString + CRevisionCommandFor displaying Api.Models.Internal.RevisionInformation + CVersionCommandICommand to return the IApplication.VersionString  NProviders  NTests  CTestDiscordProvider - CDiscordProviderIProvider for the Discord app + CDiscordProviderIProvider for the Discord app  CIProviderFor interacting with a chat service - CIrcProviderIProvider for internet relay chat - CMessageRepresents a message recieved by a IProvider + CIrcProviderIProvider for internet relay chat + CMessageRepresents a message recieved by a IProvider  CProvider - CChannelRepresents a Providers.IProvider channel - CChannelMappingRepresents a mapping of a Channel.RealId + CChannelRepresents a Providers.IProvider channel + CChannelMappingRepresents a mapping of a Channel.RealId  CChat  CChatFactory  CIChatFor managing connected chat services - CIChatFactoryFor creating IChats - CICustomCommandHandlerHandles Commands.ICommands that map to those defined in a IJsonTrackingContext + CIChatFactoryFor creating IChats + CICustomCommandHandlerHandles Commands.ICommands that map to those defined in a IJsonTrackingContext  CIJsonTrackingContextRepresents a tracking of dynamic chat json files  CIProviderFactoryFactory for IProviders  CJsonTrackingContext @@ -243,21 +219,21 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CResponseRepresents a chat message requested by DD  CUserRepresents a tgs_chat_user datum  NCompiler - CDmbFactoryStandard IDmbFactory + CDmbFactoryStandard IDmbFactory  CDmbProvider  CDreamMaker  CICompileJobConsumerSink for CompileJobs - CIDmbFactoryFactory for IDmbProviders + CIDmbFactoryFactory for IDmbProviders  CIDreamMakerFor managing the compiler - CTemporaryDmbProviderTemporary IDmbProvider + CTemporaryDmbProviderTemporary IDmbProvider  NInterop  CChatCommandRepresents a chat command to be handled by DD  CCommCommandRepresents a command from DD  CCommContext - CConstantsConstants used for communication with the DMAPI - CEventNotificationFor notifying DD of EventTypes + CConstantsConstants used for communication with the DMAPI + CEventNotificationFor notifying DD of EventTypes  CICommContextRepresents a registration of an interop session - CICommHandlerHandles CommCommands + CICommHandlerHandles CommCommands  CJsonFileRepresentation of the initial json passed to DreamDaemon  CJsonSubFileListInformation used in for reattaching and interop  CTestMergeThis model mirrors /datum/tgs_revision_information/test_merge @@ -265,7 +241,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CCredentialsProvider  CICredentialsProviderFor generating CredentialsHandlers  CIRepositoryRepresents an on-disk git repository - CIRepositoryManagerFactory for creating and loading IRepositorys + CIRepositoryManagerFactory for creating and loading IRepositorys  CRepository  CRepositoryManager  NStaticFiles @@ -275,29 +251,29 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  NWatchdog  NTests  CTestWatchdog - CDeadSessionControllerImplements a fake "dead" ISessionController + CDeadSessionControllerImplements a fake "dead" ISessionController  CINetworkPromptReaperOn Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort(). This looks out for those prompts and immediately clicks "Yes" if the owning process has registered for it - CIReattachInfoHandlerHandles saving and loading WatchdogReattachInformation + CIReattachInfoHandlerHandles saving and loading WatchdogReattachInformation  CISessionControllerHandles communication with a DreamDaemon IProcess - CISessionControllerFactoryFactory for ISessionControllers + CISessionControllerFactoryFactory for ISessionControllers  CIWatchdogRuns and monitors the twin server controllers - CIWatchdogFactoryFor creating IWatchdogs + CIWatchdogFactoryFor creating IWatchdogs  CLaunchResultRepresents the result of trying to start a DD process  CMonitorStateThe (absolute) state of the Watchdog  CPosixNetworkPromptReaper - CReattachInformationParameters necessary for duplicating a ISessionController session + CReattachInformationParameters necessary for duplicating a ISessionController session  CSessionController  CSessionControllerFactory  CWatchdog  CWatchdogFactory - CWatchdogReattachInformationReattach information for a IWatchdog + CWatchdogReattachInformationReattach information for a IWatchdog  CWindowsNetworkPromptReaper  CEventConsumer  CIDmbProviderProvides absolute paths to the latest compiled .dmbs - CIEventConsumerConsumes EventTypes and takes the appropriate actions + CIEventConsumerConsumes EventTypes and takes the appropriate actions  CIInstanceFor interacting with the instance services - CIInstanceFactoryFactory for creating IInstances - CIInstanceManagerFor managing IInstances + CIInstanceFactoryFactory for creating IInstances + CIInstanceManagerFor managing IInstances  CInstance  CInstanceFactory  CInstanceManager @@ -313,18 +289,18 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CTestProgram  CProgramContains the entrypoint for the application  NControllers - CAdministrationControllerModelController<TModel> for Administration + CAdministrationControllerModelController<TModel> for Administration  CApiControllerA Controller for API functions - CByondControllerController for managing Api.Models.Byond.Versions - CChatControllerModelController<TModel> for managing Api.Models.ChatBots - CConfigurationControllerThe ModelController<TModel> for ConfigurationFiles - CDreamDaemonControllerModelController<TModel> for managing the DreamDaemon + CByondControllerController for managing Api.Models.Byond.Versions + CChatControllerModelController<TModel> for managing Api.Models.ChatBots + CConfigurationControllerThe ModelController<TModel> for ConfigurationFiles + CDreamDaemonControllerModelController<TModel> for managing the DreamDaemon  CDreamMakerControllerController for managing the compiler - CHomeControllerMain ApiController for the Application + CHomeControllerMain ApiController for the Application  CInstanceControllerController for managing Components.Instances  CInstanceUserControllerFor managing Users - CJobControllerModelController<TModel> for Api.Models.Jobs - CModelControllerAn ApiController representing a TModel + CJobControllerModelController<TModel> for Api.Models.Jobs + CModelControllerAn ApiController representing a TModel  CRepositoryControllerController for managing the Repositorys  CTgsAuthorizeAttributeHelper for using the AuthorizeAttribute with the Api.Rights system  CUserControllerFor managing Users @@ -361,9 +337,9 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CIPlatformIdentifierFor identifying the current platform  CIProcessAbstraction over a System.Diagnostics.Process  CIProcessBaseRepresents process lifetime - CIProcessExecutorFor launching IProcess' + CIProcessExecutorFor launching IProcess'  CIRestartHandlerHandler for server restarts - CIRestartRegistrationRepresents the lifetime of a IRestartHandler registration + CIRestartRegistrationRepresents the lifetime of a IRestartHandler registration  CIServerControlRepresents a service that may take an updated Host assembly and run it, stopping the current assembly in the process  CISetupWizardThe command line Configuration setup wizard  CJobExceptionOperation exceptions thrown from the context of a Models.Job @@ -376,41 +352,42 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CSemaphoreSlimContextAsync lock context helper  CServiceCollectionExtensionsExtensions for IServiceCollection  CSetupWizard + CTaskExtensionsExtensions for the Task class  NIO  NTests  CTestConsole  CTestPostWriteHandler  CTestSymlinkFactory  CConsole - CDefaultIOManagerIIOManager that resolves paths to Environment.CurrentDirectory + CDefaultIOManagerIIOManager that resolves paths to Environment.CurrentDirectory  CIConsoleAbstraction for System.Console  CIIOManagerInterface for using filesystems  CIPostWriteHandlerHandles changing file modes/permissions after writing  CISymlinkFactoryFor creating filesystem symbolic links  CISynchronousIOManagerFor accessing the disk in a synchronous manner - CPosixPostWriteHandlerIPostWriteHandler for POSIX systems - CPosixSymlinkFactoryISymlinkFactory for posix systems - CResolvingIOManagerAn IIOManager that resolve relative paths from another IIOManager to a subdirectory of that + CPosixPostWriteHandlerIPostWriteHandler for POSIX systems + CPosixSymlinkFactoryISymlinkFactory for posix systems + CResolvingIOManagerAn IIOManager that resolve relative paths from another IIOManager to a subdirectory of that  CSynchronousIOManager - CWindowsPostWriteHandlerIPostWriteHandler for Windows systems - CWindowsSymlinkFactoryISymlinkFactory for windows systems + CWindowsPostWriteHandlerIPostWriteHandler for Windows systems + CWindowsSymlinkFactoryISymlinkFactory for windows systems  NModels  NMigrations - CDesignTimeDbContextFactoryHelpersContains helpers for creating design time Models.DatabaseContext<TParentContext>s - CMSAddMinimumSecurityAdd the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel columns for MSSQL - CMSFixRevInfoIndexMake commit shas non-unique per Instance for MSSQL + CDesignTimeDbContextFactoryHelpersContains helpers for creating design time DatabaseContext<TParentContext>s + CMSAddMinimumSecurityAdd the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel columns for MSSQL + CMSFixRevInfoIndexMake commit shas non-unique per Instance for MSSQL  CMSInitialCreateThe initial database migration for MSSQL  CMSNullableAndForeignKeyCleanupCleans up of nullable columns and foreign keys MSSQL - CMSReattachCompileJobRequiredMarks the CompileJobs of ReattachInformations as non-nullable for MSSQL - CMSToggleTestmergeCommentsAdd the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MSSQL - CMYAddMinimumSecurityAdd the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel columns for MySQL/MariaDB - CMYFixRevInfoIndexMake commit shas non-unique per Instance for MSSQL + CMSReattachCompileJobRequiredMarks the CompileJobs of ReattachInformations as non-nullable for MSSQL + CMSToggleTestmergeCommentsAdd the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MSSQL + CMYAddMinimumSecurityAdd the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel columns for MySQL/MariaDB + CMYFixRevInfoIndexMake commit shas non-unique per Instance for MSSQL  CMYInitialCreateThe initial database migration for MySQL/MariaDB  CMYNullableAndForeignKeyCleanupCleans up of nullable columns and foreign keys MySQL/MariaDB - CMYReattachCompileJobRequiredMarks the CompileJobs of ReattachInformations as non-nullable for MySQL/MariaDB + CMYReattachCompileJobRequiredMarks the CompileJobs of ReattachInformations as non-nullable for MySQL/MariaDB  CMySqlDatabaseContextModelSnapshot  CMySqlDesignTimeDbContextFactory - CMYToggleTestmergeCommentsAdd the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MySQL/MariaDB + CMYToggleTestmergeCommentsAdd the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MySQL/MariaDB  CSqlServerDatabaseContextModelSnapshot  CSqlServerDesignTimeDbContextFactory  CChatBot @@ -422,44 +399,44 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CDreamMakerSettings  CIDatabaseContextRepresents the database  CIDatabaseSeederFor initially seeding a database - CInstanceRepresents an Api.Models.Instance in the database + CInstanceRepresents an Api.Models.Instance in the database  CInstanceUser  CJob - CMySqlDatabaseContextDatabaseContext<TParentContext> for MySQL - CReattachInformationDatabase representation of Components.Watchdog.ReattachInformation - CReattachInformationBaseBase class for ReattachInformation + CMySqlDatabaseContextDatabaseContext<TParentContext> for MySQL + CReattachInformationDatabase representation of Components.Watchdog.ReattachInformation + CReattachInformationBaseBase class for ReattachInformation  CRepositorySettings  CRevInfoTestMergeMany to many relationship for Models.RevisionInformation and Models.TestMerge  CRevisionInformation - CSqlServerDatabaseContextDatabaseContext<TParentContext> for Sqlserver + CSqlServerDatabaseContextDatabaseContext<TParentContext> for Sqlserver  CTestMerge  CUser - CWatchdogReattachInformationDatabase representation of Components.Watchdog.WatchdogReattachInformation - CWatchdogReattachInformationBaseBase class for WatchdogReattachInformation + CWatchdogReattachInformationDatabase representation of Components.Watchdog.WatchdogReattachInformation + CWatchdogReattachInformationBaseBase class for WatchdogReattachInformation  NSecurity  NTests - CTestAuthenticationContextTests for AuthenticationContext + CTestAuthenticationContextTests for AuthenticationContext  CAuthenticationContextManages Api.Models.Users for a scope  CAuthenticationContextFactory  CClaimsInjector  CCryptographySuite  CIAuthenticationContextRepresents the currently authenticated Api.Models.User  CIAuthenticationContextFactoryFor creating and accessing authentication contexts - CIClaimsInjectorFor injecting System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look for + CIClaimsInjectorFor injecting System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look for  CICryptographySuiteContains various cryptographic functions  CIdentityCache - CIdentityCacheObjectFor keeping a specific ISystemIdentity alive for a period of time - CIIdentityCacheFor caching ISystemIdentitys + CIdentityCacheObjectFor keeping a specific ISystemIdentity alive for a period of time + CIIdentityCacheFor caching ISystemIdentitys  CISystemIdentityRepresents a user on the current System.Runtime.InteropServices.OSPlatform - CISystemIdentityFactoryFactory for ISystemIdentitys + CISystemIdentityFactoryFactory for ISystemIdentitys  CITokenFactoryFor creating Tokens - CPosixSystemIdentityFactoryISystemIdentityFactory for posix systems + CPosixSystemIdentityFactoryISystemIdentityFactory for posix systems  CTokenFactory - CWindowsSystemIdentityISystemIdentity for windows systems - CWindowsSystemIdentityFactoryISystemIdentityFactory for windows systems. Uses long running tasks due to potential networked domains + CWindowsSystemIdentityISystemIdentity for windows systems + CWindowsSystemIdentityFactoryISystemIdentityFactory for windows systems. Uses long running tasks due to potential networked domains  NService  NTests - CTestServerServiceTests for ServerService + CTestServerServiceTests for ServerService  CProgramContains the entrypoint for the application  CServerServiceRepresents a IWatchdog as a ServiceBase  NTests @@ -469,11 +446,11 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CTestWatchdog  CTestWatchdogFactoryTests for WatchdogFactory  CIWatchdogThe watchdog for a Host - CIWatchdogFactoryFactory for creating IWatchdogs + CIWatchdogFactoryFactory for creating IWatchdogs  CWatchdog  CWatchdogFactory  CIServerRepresents the host - CIServerFactoryFor creating IServers + CIServerFactoryFor creating IServers  CNativeMethodsNative methods used by the code  CProgramEntrypoint for the Process  CServer @@ -494,12 +471,11 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CIApplicationLifetime  CIDesignTimeDbContextFactory  CIDisposable - CIEventLog - CIHostedService - CJsonConverter - CMigration - CModelSnapshot - CServiceBase + CIHostedService + CJsonConverter + CMigration + CModelSnapshot + CServiceBase
@@ -507,7 +483,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/api.html b/api.html index 7f2b59fc18..b98aa400fc 100644 --- a/api.html +++ b/api.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: API @@ -11,9 +12,6 @@ - @@ -33,36 +31,22 @@ - + - + + + +
-
+
API
@@ -181,7 +165,7 @@ Authentication
  • Username: <your username>
  • Authorization:Password <your password>
  • -

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

    1 {
    2  "bearer": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwiZXhwIjoiMTUzMzIzNjk0MSIsIm5iZiI6IjE1MzMyMzYwNDEiLCJpc3MiOiJUZ3N0YXRpb24uU2VydmVyLkhvc3QiLCJhdWQiOiJUZ3N0YXRpb24uU2VydmVyLkFwaSJ9.QWFSWNi9mgol582zaK4MQ5XDK2gZF-Nx3z9_ToHjKW4"
    3 }

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

    +

    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>
    • @@ -220,7 +204,7 @@ Version

      The versions of the TGS host can be retireved with this request

      GET "/" => Tgstation.Server.Api.Models.ServerInformation

      The Version model fields are based on the C# one and looks like this:

      -
      1 {
      2  "version": "<major>.<minor>.<patch>.<revision>"
      3 }

      Other fields may be present in the Version model but should be ignored. See a description of these version numbers here.

      +
      {
      "version": "<major>.<minor>.<patch>.<revision>"
      }

      Other fields may be present in the Version model but should be ignored. See a description of these version numbers here.

      Server-wide Administrative Actions

      You can retrieve server update information with this

      @@ -291,17 +275,17 @@ Repository Management

      Repository Commands for Git Aliases

      All these actions are done with the POST method

      -

      git pull (Only if Tgstation.Server.Api.Models.Repository.Reference is set):

      1 {
      2  "updateFromOrigin": true
      3 }

      git checkout <commit sha> (Unsets Tgstation.Server.Api.Models.Repository.Reference):

      1 {
      2  "checkoutSha": "<commit sha>"
      3 }

      git checkout -f <branch or tag> && git clean -fxd (Sets Tgstation.Server.Api.Models.Repository.Reference):

      1 {
      2  "reference": "<branch or tag>"
      3 }

      git fetch && git checkout -f branch && git clean -fxd && git reset –hard origin/branch (Sets Tgstation.Server.Api.Models.Repository.Reference);

      1 {
      2  "updateFromOrigin": true,
      3  "reference": "branch"
      4 }

      +

      git pull (Only if Tgstation.Server.Api.Models.Repository.Reference is set):

      {
      "updateFromOrigin": true
      }

      git checkout <commit sha> (Unsets Tgstation.Server.Api.Models.Repository.Reference):

      {
      "checkoutSha": "<commit sha>"
      }

      git checkout -f <branch or tag> && git clean -fxd (Sets Tgstation.Server.Api.Models.Repository.Reference):

      {
      "reference": "<branch or tag>"
      }

      git fetch && git checkout -f branch && git clean -fxd && git reset –hard origin/branch (Sets Tgstation.Server.Api.Models.Repository.Reference);

      {
      "updateFromOrigin": true,
      "reference": "branch"
      }

      Test Merging

      Any of the above POST methods can be combined with the Tgstation.Server.Api.Models.Repository.NewTestMerges field to add test merges on top of the checked out commit.

      -
      1 {
      2  "newTestMerges": [
      3  {
      4  "number": 12345,
      5  "comment": "I'm merging this for x reason"
      6  },
      7  {
      8  "number": 12346,
      9  "pullRequestRevision": "abcdef1"
      10  }
      11  ]
      12 }

      If the server detects a set of Tgstation.Server.Api.Models.TestMergeParameters being applied that it has seen before, it'll instead attempt to checkout the commit that was created then.

      +
      {
      "newTestMerges": [
      {
      "number": 12345,
      "comment": "I'm merging this for x reason"
      },
      {
      "number": 12346,
      "pullRequestRevision": "abcdef1"
      }
      ]
      }

      If the server detects a set of Tgstation.Server.Api.Models.TestMergeParameters being applied that it has seen before, it'll instead attempt to checkout the commit that was created then.

      Unsetting Authentication

      The repository uses the Tgstation.Server.Api.Models.Repository.AccessUser and Tgstation.Server.Api.Models.Repository.AccessToken credentials to access the remote repository if these fields are set. To unset them you must set both of them to an empty string like so

      -
      1 {
      2  "accessUser": "",
      3  "accessToken": ""
      4 }

      This will remove both fields from the database

      +
      {
      "accessUser": "",
      "accessToken": ""
      }

      This will remove both fields from the database

      Compiler Handling

      -

      The DM compiler can run one job at a time for an Instance. Instead of using standard Tgstation.Server.Api.Models.Job.Progress it uses the Tgstation.Server.Api.Models.DreamMaker.Status field to denote it's current stage. It can be retrieved like this:

      +

      The DM compiler can run one job at a time for an Instance. Instead of using standard Tgstation.Server.Api.Models.Job.Progress it uses the Tgstation.Server.Api.Models.DreamMaker.Status field to denote it's current stage. It can be retrieved like this:

      I GET "/DreamMaker" => Tgstation.Server.Api.Models.DreamMaker

      This will also return the last successful Tgstation.Server.Api.Models.CompileJob as well as the Tgstation.Server.Api.Models.Internal.DreamMakerSettings.ProjectName

      The ProjectName field can be changed with this method:

      @@ -310,7 +294,7 @@ Compiler Handling

      I PUT "/DreamMaker" Empty => Tgstation.Server.Api.Models.Job

      The job object returned represents the compile job

      "Empty" refers to an empty json object like so:

      -
      1 {}

      The compiler endpoint is also used to read compile jobs

      +
      {}

      The compiler endpoint is also used to read compile jobs

      To list successful compile jobs ids use:

      I GET "/DreamMaker/List" => Array of Tgstation.Server.Api.Models.CompileJob

      To get a specific compile job use:

      @@ -350,12 +334,13 @@ Watchdog

      The returned jobs represents the startup process for the watchdog

      To stop the watchdog use the following request:

      I DELETE "/DreamDaemon" => OK

      -
    + + diff --git a/architecture.html b/architecture.html index c6c3d932d2..66ec57fd98 100644 --- a/architecture.html +++ b/architecture.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Server Architecture @@ -11,9 +12,6 @@ - @@ -33,36 +31,22 @@ - + - + + + +
    -
    +
    Server Architecture
    @@ -169,7 +153,7 @@ Jobs

    Long running operations create Tgstation.Server.Host.Models.Job objects which represent information about long running tasks. These objects can be queried to find out who started them, if they've been completed, canceled, who cancelled them, their error message if any, and get their progress percentage in some cases. The job will be created and supplied by the request that started it, but active/all jobs may also be queried.

    Instances

    -

    Instances exist in two forms: Their database metadata and their actual class. The class only exists if the instance is set to be Tgstation.Server.Api.Models.Instance.Online . This is where all the actual server management code lives. A single instance is made up of individual components that work with each other through their intefaces

    +

    Instances exist in two forms: Their database metadata and their actual class. The class only exists if the instance is set to be Tgstation.Server.Api.Models.Instance.Online . This is where all the actual server management code lives. A single instance is made up of individual components that work with each other through their intefaces

    Instance Factory

    This is responsible for creating the components and weaving them into the final Tgstation.Server.Host.Components.Instance. This happens automatically at server startup if an instance is configured to be online

    @@ -295,12 +279,13 @@ Host Update Process

    The Host.Watchdog launches the Host with a designated path in the /lib folder. When the Host process wants to update, it extracts the new Host package to this directory and exits with code 1. The watchdog then attempts to rename the current /lib/Default directory to something unique, rename the update directory to /lib/Default and the launch the new Host process.

    The Host.Watchdog serves an additional purpose of automatically restarting the the Host in the case of a fatal crash (which should never happen, but the additional layer of safety is nice).

    -
    + + diff --git a/arrowdown.png b/arrowdown.png deleted file mode 100644 index 0b63f6d38c4b9ec907b820192ebe9724ed6eca22..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 246 zcmVkw!R34#Lv2LOS^S2tZA31X++9RY}n zChwn@Z)Wz*WWHH{)HDtJnq&A2hk$b-y(>?@z0iHr41EKCGp#T5?07*qoM6N<$f(V3Pvj6}9 diff --git a/arrowright.png b/arrowright.png deleted file mode 100644 index c6ee22f937a07d1dbfc27c669d11f8ed13e2f152..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 229 zcmV^P)R?RzRoKvklcaQ%HF6%rK2&ZgO(-ihJ_C zzrKgp4jgO( fd_(yg|3PpEQb#9`a?Pz_00000NkvXXu0mjftR`5K diff --git a/class_authorize_attribute.html b/class_authorize_attribute.html index 08a9d762fc..8dbc228174 100644 --- a/class_authorize_attribute.html +++ b/class_authorize_attribute.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: AuthorizeAttribute Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + +
    -Tgstation.Server.Host.Controllers.TgsAuthorizeAttribute - -
    +Tgstation.Server.Host.Controllers.TgsAuthorizeAttribute + +
    The documentation for this class was generated from the following file: @@ -108,7 +84,7 @@ Inheritance diagram for AuthorizeAttribute: diff --git a/class_auto_generated_program-members.html b/class_auto_generated_program-members.html index 38523d2d11..f54017b6ee 100644 --- a/class_auto_generated_program-members.html +++ b/class_auto_generated_program-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +

    Detailed Description

    -

    Definition at line 4 of file Tgstation.Server.Api.Tests.Program.cs.

    +

    Definition at line 4 of file Tgstation.Server.Api.Tests.Program.cs.

    Member Function Documentation

    - + +

    ◆ Main() [1/6]

    +
    @@ -124,7 +102,7 @@ Static Private Member Functions - + @@ -136,15 +114,17 @@ Static Private Member Functions
    static void AutoGeneratedProgram.Main (string[] string []  args)
    -

    Definition at line 4 of file Tgstation.Server.Api.Tests.Program.cs.

    +

    Definition at line 4 of file Tgstation.Server.Api.Tests.Program.cs.

    -

    References Main().

    +

    References Main().

    + +

    Referenced by Main().

    -

    Referenced by Main().

    -
    4 {
    - + +

    ◆ Main() [2/6]

    +
    @@ -154,7 +134,7 @@ Static Private Member Functions - + @@ -166,15 +146,17 @@ Static Private Member Functions
    static void AutoGeneratedProgram.Main (string[] string []  args)
    -

    Definition at line 4 of file Tgstation.Server.Tests.Program.cs.

    +

    Definition at line 4 of file Tgstation.Server.Tests.Program.cs.

    -

    References Main().

    +

    References Main().

    + +

    Referenced by Main().

    -

    Referenced by Main().

    -
    4 {
    - + +

    ◆ Main() [3/6]

    +
    @@ -184,7 +166,7 @@ Static Private Member Functions - + @@ -196,15 +178,17 @@ Static Private Member Functions
    static void AutoGeneratedProgram.Main (string[] string []  args)
    -

    Definition at line 4 of file Tgstation.Server.Host.Watchdog.Tests.Program.cs.

    +

    Definition at line 4 of file Tgstation.Server.Host.Watchdog.Tests.Program.cs.

    -

    References Main().

    +

    References Main().

    + +

    Referenced by Main().

    -

    Referenced by Main().

    -
    4 {
    - + +

    ◆ Main() [4/6]

    +
    @@ -214,7 +198,7 @@ Static Private Member Functions - + @@ -226,15 +210,17 @@ Static Private Member Functions
    static void AutoGeneratedProgram.Main (string[] string []  args)
    -

    Definition at line 4 of file Tgstation.Server.Host.Tests.Program.cs.

    +

    Definition at line 4 of file Tgstation.Server.Host.Tests.Program.cs.

    -

    References Main().

    +

    References Main().

    + +

    Referenced by Main().

    -

    Referenced by Main().

    -
    4 {
    - + +

    ◆ Main() [5/6]

    +
    @@ -244,7 +230,7 @@ Static Private Member Functions - + @@ -256,15 +242,17 @@ Static Private Member Functions
    static void AutoGeneratedProgram.Main (string[] string []  args)
    -

    Definition at line 4 of file Tgstation.Server.Host.Console.Tests.Program.cs.

    +

    Definition at line 4 of file Tgstation.Server.Host.Console.Tests.Program.cs.

    -

    References Main().

    +

    References Main().

    + +

    Referenced by Main().

    -

    Referenced by Main().

    -
    4 {
    - + +

    ◆ Main() [6/6]

    +
    @@ -274,7 +262,7 @@ Static Private Member Functions - + @@ -286,28 +274,28 @@ Static Private Member Functions
    static void AutoGeneratedProgram.Main (string[] string []  args)
    -

    Definition at line 4 of file Tgstation.Server.Client.Tests.Program.cs.

    +

    Definition at line 4 of file Tgstation.Server.Client.Tests.Program.cs.

    -

    References Main().

    +

    References Main().

    + +

    Referenced by Main().

    -

    Referenced by Main().

    -
    4 {

    The documentation for this class was generated from the following files:
    diff --git a/class_controller.html b/class_controller.html index 7f85372588..5b8b581f90 100644 --- a/class_controller.html +++ b/class_controller.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Controller Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + +
    -Tgstation.Server.Host.Controllers.ApiController -Tgstation.Server.Host.Controllers.HomeController -Tgstation.Server.Host.Controllers.ModelController< TModel > - -
    +Tgstation.Server.Host.Controllers.ApiController +Tgstation.Server.Host.Controllers.HomeController +Tgstation.Server.Host.Controllers.ModelController< TModel > + +

    The documentation for this class was generated from the following file: @@ -110,7 +86,7 @@ Inheritance diagram for Controller:
    diff --git a/class_db_context.html b/class_db_context.html index b660abd296..7fe2ce8d1a 100644 --- a/class_db_context.html +++ b/class_db_context.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: DbContext Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + +
    Tgstation.Server.Host.Models.DatabaseContext< TParentContext > - -
    + +
    The documentation for this class was generated from the following file: @@ -108,7 +84,7 @@ Inheritance diagram for DbContext: diff --git a/class_i_application_lifetime.html b/class_i_application_lifetime.html index 0ed5b3cf6b..26bd0b6747 100644 --- a/class_i_application_lifetime.html +++ b/class_i_application_lifetime.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: IApplicationLifetime Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + +
    Tgstation.Server.Host.Core.Tests.TestApplication.MockApplicationLifetime - -
    + +
    The documentation for this class was generated from the following file: @@ -108,7 +84,7 @@ Inheritance diagram for IApplicationLifetime: diff --git a/class_i_design_time_db_context_factory.html b/class_i_design_time_db_context_factory.html index 86ec6d20dd..7e7b85a494 100644 --- a/class_i_design_time_db_context_factory.html +++ b/class_i_design_time_db_context_factory.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: IDesignTimeDbContextFactory Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + +
    Tgstation.Server.Host.Models.Migrations.MySqlDesignTimeDbContextFactory Tgstation.Server.Host.Models.Migrations.SqlServerDesignTimeDbContextFactory - -
    + +
    The documentation for this class was generated from the following file: @@ -109,7 +85,7 @@ Inheritance diagram for IDesignTimeDbContextFactory: diff --git a/class_i_disposable.html b/class_i_disposable.html index b937679991..7fb30b2cde 100644 --- a/class_i_disposable.html +++ b/class_i_disposable.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: IDisposable Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + +
    -Tgstation.Server.Client.IApiClient -Tgstation.Server.Client.IHttpClient -Tgstation.Server.Client.IServerClient -Tgstation.Server.Host.Components.Byond.IByondExecutableLock -Tgstation.Server.Host.Components.Byond.IByondManager -Tgstation.Server.Host.Components.Byond.WindowsByondInstaller -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.IInstance +Tgstation.Server.Client.IApiClient +Tgstation.Server.Client.IHttpClient +Tgstation.Server.Client.IServerClient +Tgstation.Server.Host.Components.Byond.IByondExecutableLock +Tgstation.Server.Host.Components.Byond.IByondManager +Tgstation.Server.Host.Components.Byond.WindowsByondInstaller +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.IInstance Tgstation.Server.Host.Components.InstanceManager -Tgstation.Server.Host.Components.Interop.ICommContext -Tgstation.Server.Host.Components.Repository.IRepository -Tgstation.Server.Host.Components.Repository.IRepositoryManager -Tgstation.Server.Host.Components.StaticFiles.IConfiguration -Tgstation.Server.Host.Components.Watchdog.IWatchdog +Tgstation.Server.Host.Components.Interop.ICommContext +Tgstation.Server.Host.Components.Repository.IRepository +Tgstation.Server.Host.Components.Repository.IRepositoryManager +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.IProcessBase +Tgstation.Server.Host.Core.IRestartRegistration +Tgstation.Server.Host.Core.JobHandler Tgstation.Server.Host.Core.JobManager -Tgstation.Server.Host.Core.SemaphoreSlimContext +Tgstation.Server.Host.Core.SemaphoreSlimContext Tgstation.Server.Host.Security.AuthenticationContextFactory -Tgstation.Server.Host.Security.IAuthenticationContext +Tgstation.Server.Host.Security.IAuthenticationContext Tgstation.Server.Host.Security.IdentityCache -Tgstation.Server.Host.Security.IdentityCacheObject -Tgstation.Server.Host.Security.ISystemIdentity - -
    +Tgstation.Server.Host.Security.IdentityCacheObject +Tgstation.Server.Host.Security.ISystemIdentity + +
    The documentation for this class was generated from the following file: @@ -136,7 +112,7 @@ Inheritance diagram for IDisposable: diff --git a/class_i_event_log.html b/class_i_event_log.html deleted file mode 100644 index 1a203d181a..0000000000 --- a/class_i_event_log.html +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - -tgstation-server: IEventLog Class Reference - - - - - - - - - - -
    -
    - - - - - - - -
    -
    tgstation-server -
    -
    The /tg/station 13 server suite
    -
    -
    - - - - - - -
    -
    - - -
    - -
    - -
    -
    -
    -
    IEventLog Class Reference
    -
    -
    -
    -Inheritance diagram for IEventLog:
    -
    -
    - - -Tgstation.Server.Host.Service.ServerService - -
    -
    The documentation for this class was generated from the following file: -
    - - - - diff --git a/class_i_event_log.png b/class_i_event_log.png deleted file mode 100644 index 50855341d44e53a1667e070c602d8c835ca73776..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 731 zcmeAS@N?(olHy`uVBq!ia0y~yVB`g|12~w0q{-?F%Yl?cfKQ0)|NsAi%olIImi8Z- z0AzvjfddCvJMYK?xf~@ye!&btMIdnXREQA+15=i#i(^OyFwMY4GputXH-${K>Y|gU- zrVn~Khs_w2z=W8z=F*gH+z-SHm<_fuUMSuj*`CY5qhquNsDkOuA(%3R2BKMy&2OEs ze15+8G>~wfrULfzB#}hvZHk_PN8N7ed7fQe7yGWPc4_jDi7Ku+hrczS{{GmaermZ< z&StY?|IW3k@UD3qf4ML#S?S!FA2&BN_a1%v_u0CVufJ+;M_vEEb^H7~kL`Ex-)<}M z-P?O9aMAqZFY63vmYcn~ckEY7P*$ARs`Y6O6Ti<%nVC3wUEd0`wh8)=-zfP#nad-6 zV+DWY^THn?s;ie=xm@>FD|pHy8^6cJR_{Y@FiZPRFltto?tdC&cCk3W#P{H>6`FBJ zGS#kKKeGPmT+Zs0$0f^quCAY5bobERl^eHj{9oVqxTHE)?S0OT{Hwh;+{{lWET40= z_p`N{!O;SFZLHtBkbE8WtZRN@N^Y!%HzW;xE2l*FVhpXY3Q%|F4|EJ0A&Oct0D O89ZJ6T-G@yGywn^|4&B% diff --git a/class_i_hosted_service.html b/class_i_hosted_service.html index d4f0f458f5..0daeee66ca 100644 --- a/class_i_hosted_service.html +++ b/class_i_hosted_service.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: IHostedService Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + +
    -Tgstation.Server.Host.Components.Byond.IByondManager -Tgstation.Server.Host.Components.Chat.IChat -Tgstation.Server.Host.Components.Compiler.ICompileJobConsumer -Tgstation.Server.Host.Components.IInstance -Tgstation.Server.Host.Components.IInstanceFactory +Tgstation.Server.Host.Components.Byond.IByondManager +Tgstation.Server.Host.Components.Chat.IChat +Tgstation.Server.Host.Components.Compiler.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.StaticFiles.IConfiguration +Tgstation.Server.Host.Components.Watchdog.IWatchdog Tgstation.Server.Host.Components.Watchdog.WindowsNetworkPromptReaper -Tgstation.Server.Host.Core.IJobManager - -
    +Tgstation.Server.Host.Core.IJobManager + +
    The documentation for this class was generated from the following file: @@ -117,7 +93,7 @@ Inheritance diagram for IHostedService: diff --git a/class_json_converter.html b/class_json_converter.html index fbfa30db95..47dfc090bd 100644 --- a/class_json_converter.html +++ b/class_json_converter.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: JsonConverter Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + +
    -Tgstation.Server.Host.Components.Chat.Commands.BoolConverter - -
    +Tgstation.Server.Host.Components.Chat.Commands.BoolConverter + +
    The documentation for this class was generated from the following file: @@ -108,7 +84,7 @@ Inheritance diagram for JsonConverter: diff --git a/class_migration.html b/class_migration.html index 56d0ff863c..3e4e636a39 100644 --- a/class_migration.html +++ b/class_migration.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Migration Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + +
    Tgstation.Server.Host.Models.Migrations.MSAddMinimumSecurity -Tgstation.Server.Host.Models.Migrations.MSFixRevInfoIndex -Tgstation.Server.Host.Models.Migrations.MSInitialCreate -Tgstation.Server.Host.Models.Migrations.MSNullableAndForeignKeyCleanup -Tgstation.Server.Host.Models.Migrations.MSReattachCompileJobRequired -Tgstation.Server.Host.Models.Migrations.MSToggleTestmergeComments +Tgstation.Server.Host.Models.Migrations.MSFixRevInfoIndex +Tgstation.Server.Host.Models.Migrations.MSInitialCreate +Tgstation.Server.Host.Models.Migrations.MSNullableAndForeignKeyCleanup +Tgstation.Server.Host.Models.Migrations.MSReattachCompileJobRequired +Tgstation.Server.Host.Models.Migrations.MSToggleTestmergeComments Tgstation.Server.Host.Models.Migrations.MYAddMinimumSecurity -Tgstation.Server.Host.Models.Migrations.MYFixRevInfoIndex -Tgstation.Server.Host.Models.Migrations.MYInitialCreate -Tgstation.Server.Host.Models.Migrations.MYNullableAndForeignKeyCleanup -Tgstation.Server.Host.Models.Migrations.MYReattachCompileJobRequired -Tgstation.Server.Host.Models.Migrations.MYToggleTestmergeComments - -
    +Tgstation.Server.Host.Models.Migrations.MYFixRevInfoIndex +Tgstation.Server.Host.Models.Migrations.MYInitialCreate +Tgstation.Server.Host.Models.Migrations.MYNullableAndForeignKeyCleanup +Tgstation.Server.Host.Models.Migrations.MYReattachCompileJobRequired +Tgstation.Server.Host.Models.Migrations.MYToggleTestmergeComments + +
    The documentation for this class was generated from the following file: @@ -119,7 +95,7 @@ Inheritance diagram for Migration: diff --git a/class_model_snapshot.html b/class_model_snapshot.html index 79ca3ba92d..0e18a0fe99 100644 --- a/class_model_snapshot.html +++ b/class_model_snapshot.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: ModelSnapshot Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + +
    Tgstation.Server.Host.Models.Migrations.MySqlDatabaseContextModelSnapshot Tgstation.Server.Host.Models.Migrations.SqlServerDatabaseContextModelSnapshot - -
    + +
    The documentation for this class was generated from the following file: @@ -109,7 +85,7 @@ Inheritance diagram for ModelSnapshot: diff --git a/class_release_notes_1_1_program-members.html b/class_release_notes_1_1_program-members.html index 1e92fc9d35..eb1781b708 100644 --- a/class_release_notes_1_1_program-members.html +++ b/class_release_notes_1_1_program-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +

    Static Private Member Functions

    static async Task< int > Main (string[] args) - The entrypoint for the Program More...
    + The entrypoint for the Program More...
     

    Detailed Description

    Contains the application entrypoint

    -

    Definition at line 15 of file Program.cs.

    +

    Definition at line 15 of file Program.cs.

    Member Function Documentation

    - + +

    ◆ Main()

    +
    @@ -123,7 +101,7 @@ Static Private Member Functions - + @@ -135,10 +113,10 @@ Static Private Member Functions
    static async Task<int> ReleaseNotes.Program.Main (string[] string []  args)
    -

    The entrypoint for the Program

    +

    The entrypoint for the Program

    -

    Definition at line 20 of file Program.cs.

    -
    21  {
    22  if (args.Length < 1)
    23  {
    24  Console.WriteLine("Missing version argument!");
    25  return 1;
    26  }
    27 
    28  var versionString = args[0];
    29  if (!Version.TryParse(versionString, out var version))
    30  {
    31  Console.WriteLine("Invalid version: " + versionString);
    32  return 2;
    33  }
    34 
    35  var doNotCloseMilestone = args.Length >= 2 && args[1].ToUpperInvariant() == "--NO-CLOSE";
    36 
    37  const string ReleaseNotesEnvVar = "TGS_RELEASE_NOTES_TOKEN";
    38  var githubToken = Environment.GetEnvironmentVariable(ReleaseNotesEnvVar);
    39  if (String.IsNullOrWhiteSpace(githubToken))
    40  {
    41  Console.WriteLine("Missing " + ReleaseNotesEnvVar + " environment variable!");
    42  return 3;
    43  }
    44 
    45  try
    46  {
    47  var client = new GitHubClient(new ProductHeaderValue("tgs_release_notes"));
    48  client.Credentials = new Credentials(githubToken);
    49 
    50  const string RepoOwner = "tgstation";
    51  const string RepoName = "tgstation-server";
    52 
    53  var releasesTask = client.Repository.Release.GetAll(RepoOwner, RepoName);
    54 
    55  Console.WriteLine("Getting pull requests in milestone " + versionString + "...");
    56  var milestonePRs = await client.Search.SearchIssues(new SearchIssuesRequest
    57  {
    58  Milestone = versionString,
    59  Type = IssueTypeQualifier.PullRequest,
    60  Repos = { { RepoOwner, RepoName } }
    61  }).ConfigureAwait(false);
    62 
    63  if (milestonePRs.IncompleteResults)
    64  {
    65  Console.WriteLine("Incomplete results for milestone PRs query!");
    66  return 5;
    67  }
    68  Console.WriteLine(milestonePRs.Items.Count + " total pull requests");
    69 
    70  Task<Milestone> milestoneTask = null;
    71  var milestoneTaskLock = new object();
    72  var releaseDictionary = new Dictionary<int, List<string>>();
    73  var authorizedUsers = new Dictionary<long, Task<bool>>();
    74 
    75  async Task GetReleaseNotesFromPR(Issue pullRequest)
    76  {
    77  //need to check it was merged
    78  var fullPR = await client.Repository.PullRequest.Get(RepoOwner, RepoName, pullRequest.Number).ConfigureAwait(false);
    79 
    80  async Task<Milestone> GetMilestone()
    81  {
    82  if (fullPR.Milestone == null)
    83  return null;
    84  return await client.Issue.Milestone.Get(RepoOwner, RepoName, fullPR.Milestone.Number);
    85  };
    86 
    87  lock (milestoneTaskLock)
    88  if (milestoneTask == null)
    89  milestoneTask = GetMilestone();
    90 
    91  if (!fullPR.Merged)
    92  return;
    93 
    94  async Task BuildNotesFromComment(string comment, User user)
    95  {
    96  var commentSplits = comment.Split('\n');
    97  var notesOpen = false;
    98  var notesClosed = false;
    99  var notes = new List<string>();
    100  foreach (var line in commentSplits)
    101  {
    102  var trimmedLine = line.Trim();
    103  if (!notesOpen)
    104  {
    105  notesOpen = trimmedLine.StartsWith(":cl:", StringComparison.Ordinal);
    106  notesClosed = false;
    107  continue;
    108  }
    109  if (trimmedLine.StartsWith("/:cl:", StringComparison.Ordinal))
    110  {
    111  notesClosed = true;
    112  notesOpen = false;
    113  continue;
    114  }
    115  if (trimmedLine.Length == 0)
    116  continue;
    117  notes.Add(trimmedLine);
    118  }
    119  if (!notesClosed || notes.Count == 0)
    120  return;
    121 
    122  Task<bool> authTask;
    123  TaskCompletionSource<bool> ourTcs = null;
    124  lock (authorizedUsers)
    125  {
    126  if (!authorizedUsers.TryGetValue(user.Id, out authTask))
    127  {
    128  ourTcs = new TaskCompletionSource<bool>();
    129  authTask = ourTcs.Task;
    130  authorizedUsers.Add(user.Id, authTask);
    131  }
    132  }
    133 
    134  if (ourTcs != null)
    135  try
    136  {
    137  //check if the user has access
    138  var perm = await client.Repository.Collaborator.ReviewPermission(RepoOwner, RepoName, user.Login).ConfigureAwait(false);
    139  ourTcs.SetResult(perm.Permission == PermissionLevel.Write || perm.Permission == PermissionLevel.Admin);
    140  }
    141  catch
    142  {
    143  ourTcs.SetResult(false);
    144  throw;
    145  }
    146 
    147  var authorized = await authTask.ConfigureAwait(false);
    148  if (!authorized)
    149  return;
    150 
    151  lock (releaseDictionary)
    152  {
    153  foreach (var I in notes)
    154  Console.WriteLine("#" + fullPR.Number + " - " + I + " (@" + user.Login + ")");
    155  if (releaseDictionary.TryGetValue(fullPR.Number, out var currentValues))
    156  currentValues.AddRange(notes);
    157  else
    158  releaseDictionary.Add(fullPR.Number, notes);
    159  }
    160  }
    161 
    162  var comments = await client.Issue.Comment.GetAllForIssue(RepoOwner, RepoName, fullPR.Number).ConfigureAwait(false);
    163  await Task.WhenAll(BuildNotesFromComment(fullPR.Body, fullPR.User), Task.WhenAll(comments.Select(x => BuildNotesFromComment(x.Body, x.User)))).ConfigureAwait(false);
    164  }
    165 
    166  var tasks = new List<Task>();
    167  foreach (var I in milestonePRs.Items)
    168  tasks.Add(GetReleaseNotesFromPR(I));
    169 
    170  var releases = await releasesTask.ConfigureAwait(false);
    171 
    172  var releasingSuite = version.Major;
    173 
    174  Version highestReleaseVersion = null;
    175  Release highestRelease = null;
    176  foreach (var I in releases)
    177  {
    178  if (!Version.TryParse(I.TagName.Replace("tgstation-server-v", String.Empty), out var currentReleaseVersion))
    179  {
    180  Console.WriteLine("WARNING: Unable to determine version of release " + I.HtmlUrl);
    181  continue;
    182  }
    183 
    184  if (currentReleaseVersion.Major == releasingSuite && (highestReleaseVersion == null || currentReleaseVersion > highestReleaseVersion))
    185  {
    186  highestReleaseVersion = currentReleaseVersion;
    187  highestRelease = I;
    188  }
    189  }
    190 
    191  if (highestReleaseVersion == null)
    192  {
    193  Console.WriteLine("Unable to determine highest release version for suite " + releasingSuite + "!");
    194  return 6;
    195  }
    196 
    197  var oldNotes = highestRelease.Body;
    198 
    199  var splits = new List<string>(oldNotes.Split('\n'));
    200  //trim away all the lines that don't start with #
    201 
    202  string keepThisRelease;
    203  if (version.Revision == 0)
    204  if (version.Build == 0)
    205  keepThisRelease = "# ";
    206  else
    207  keepThisRelease = "## ";
    208  else
    209  keepThisRelease = "### ";
    210 
    211  for (; !splits[0].StartsWith(keepThisRelease, StringComparison.Ordinal); splits.RemoveAt(0))
    212  if (splits.Count == 1)
    213  {
    214  Console.WriteLine("Error formatting release notes: Can't detemine notes start!");
    215  return 7;
    216  }
    217 
    218  oldNotes = String.Join('\n', splits);
    219 
    220  string prefix;
    221  switch (releasingSuite)
    222  {
    223  case 3:
    224  prefix = "The /tg/station server suite";
    225  break;
    226  default:
    227  prefix = "See https://tgstation.github.io/tgstation-server for installation instructions";
    228  break;
    229  }
    230 
    231  var newNotes = new StringBuilder(prefix);
    232  newNotes.Append(Environment.NewLine);
    233  newNotes.Append(Environment.NewLine);
    234  if (version.Revision == 0)
    235  if (version.Build == 0)
    236  {
    237  newNotes.Append("# [Version ");
    238  newNotes.Append(version.Minor);
    239  }
    240  else
    241  {
    242  newNotes.Append("## [Changelog for ");
    243  newNotes.Append(version.Build);
    244  newNotes.Append(".x");
    245  }
    246  else
    247  {
    248  newNotes.Append("### [Patch ");
    249  newNotes.Append(version.Revision);
    250  }
    251  newNotes.Append("](");
    252  var milestone = await milestoneTask.ConfigureAwait(false);
    253  if (milestone == null)
    254  {
    255  Console.WriteLine("Unable to detemine milestone!");
    256  return 9;
    257  }
    258  newNotes.Append(milestone.HtmlUrl);
    259  newNotes.Append("?closed=1)");
    260  newNotes.Append(Environment.NewLine);
    261 
    262  await Task.WhenAll(tasks).ConfigureAwait(false);
    263 
    264  if (releaseDictionary.Count == 0)
    265  {
    266  Console.WriteLine("No release notes for this milestone!");
    267  return 8;
    268  }
    269 
    270  foreach (var I in releaseDictionary)
    271  foreach (var note in I.Value)
    272  {
    273  newNotes.Append(Environment.NewLine);
    274  newNotes.Append("- ");
    275  newNotes.Append(note);
    276  newNotes.Append(" (#");
    277  newNotes.Append(I.Key);
    278  newNotes.Append(')');
    279  }
    280 
    281  newNotes.Append(Environment.NewLine);
    282  newNotes.Append(Environment.NewLine);
    283  newNotes.Append(oldNotes);
    284 
    285  Console.WriteLine("Writing out new release notes...");
    286  var releaseNotes = newNotes.ToString();
    287  await File.WriteAllTextAsync("release_notes.md", releaseNotes).ConfigureAwait(false);
    288 
    289  if (doNotCloseMilestone)
    290  Console.WriteLine("Not closing milestone due to parameter!");
    291  else
    292  {
    293  Console.WriteLine("Closing milestone...");
    294  await client.Issue.Milestone.Update(RepoOwner, RepoName, milestone.Number, new MilestoneUpdate
    295  {
    296  State = ItemState.Closed
    297  }).ConfigureAwait(false);
    298  }
    299 
    300  return 0;
    301  }
    302  catch (Exception e)
    303  {
    304  Console.WriteLine(e);
    305  return 4;
    306  }
    307  }
    +

    Definition at line 20 of file Program.cs.

    +
    21  {
    22  if (args.Length < 1)
    23  {
    24  Console.WriteLine("Missing version argument!");
    25  return 1;
    26  }
    27 
    28  var versionString = args[0];
    29  if (!Version.TryParse(versionString, out var version))
    30  {
    31  Console.WriteLine("Invalid version: " + versionString);
    32  return 2;
    33  }
    34 
    35  var doNotCloseMilestone = args.Length >= 2 && args[1].ToUpperInvariant() == "--NO-CLOSE";
    36 
    37  const string ReleaseNotesEnvVar = "TGS_RELEASE_NOTES_TOKEN";
    38  var githubToken = Environment.GetEnvironmentVariable(ReleaseNotesEnvVar);
    39  if (String.IsNullOrWhiteSpace(githubToken))
    40  {
    41  Console.WriteLine("Missing " + ReleaseNotesEnvVar + " environment variable!");
    42  return 3;
    43  }
    44 
    45  try
    46  {
    47  var client = new GitHubClient(new ProductHeaderValue("tgs_release_notes"));
    48  client.Credentials = new Credentials(githubToken);
    49 
    50  const string RepoOwner = "tgstation";
    51  const string RepoName = "tgstation-server";
    52 
    53  var releasesTask = client.Repository.Release.GetAll(RepoOwner, RepoName);
    54 
    55  Console.WriteLine("Getting pull requests in milestone " + versionString + "...");
    56  var milestonePRs = await client.Search.SearchIssues(new SearchIssuesRequest
    57  {
    58  Milestone = versionString,
    59  Type = IssueTypeQualifier.PullRequest,
    60  Repos = { { RepoOwner, RepoName } }
    61  }).ConfigureAwait(false);
    62 
    63  if (milestonePRs.IncompleteResults)
    64  {
    65  Console.WriteLine("Incomplete results for milestone PRs query!");
    66  return 5;
    67  }
    68  Console.WriteLine(milestonePRs.Items.Count + " total pull requests");
    69 
    70  Task<Milestone> milestoneTask = null;
    71  var milestoneTaskLock = new object();
    72  var releaseDictionary = new Dictionary<int, List<string>>();
    73  var authorizedUsers = new Dictionary<long, Task<bool>>();
    74 
    75  async Task GetReleaseNotesFromPR(Issue pullRequest)
    76  {
    77  //need to check it was merged
    78  var fullPR = await client.Repository.PullRequest.Get(RepoOwner, RepoName, pullRequest.Number).ConfigureAwait(false);
    79 
    80  async Task<Milestone> GetMilestone()
    81  {
    82  if (fullPR.Milestone == null)
    83  return null;
    84  return await client.Issue.Milestone.Get(RepoOwner, RepoName, fullPR.Milestone.Number);
    85  };
    86 
    87  lock (milestoneTaskLock)
    88  if (milestoneTask == null)
    89  milestoneTask = GetMilestone();
    90 
    91  if (!fullPR.Merged)
    92  return;
    93 
    94  async Task BuildNotesFromComment(string comment, User user)
    95  {
    96  var commentSplits = comment.Split('\n');
    97  var notesOpen = false;
    98  var notesClosed = false;
    99  var notes = new List<string>();
    100  foreach (var line in commentSplits)
    101  {
    102  var trimmedLine = line.Trim();
    103  if (!notesOpen)
    104  {
    105  notesOpen = trimmedLine.StartsWith(":cl:", StringComparison.Ordinal);
    106  notesClosed = false;
    107  continue;
    108  }
    109  if (trimmedLine.StartsWith("/:cl:", StringComparison.Ordinal))
    110  {
    111  notesClosed = true;
    112  notesOpen = false;
    113  continue;
    114  }
    115  if (trimmedLine.Length == 0)
    116  continue;
    117  notes.Add(trimmedLine);
    118  }
    119  if (!notesClosed || notes.Count == 0)
    120  return;
    121 
    122  Task<bool> authTask;
    123  TaskCompletionSource<bool> ourTcs = null;
    124  lock (authorizedUsers)
    125  {
    126  if (!authorizedUsers.TryGetValue(user.Id, out authTask))
    127  {
    128  ourTcs = new TaskCompletionSource<bool>();
    129  authTask = ourTcs.Task;
    130  authorizedUsers.Add(user.Id, authTask);
    131  }
    132  }
    133 
    134  if (ourTcs != null)
    135  try
    136  {
    137  //check if the user has access
    138  var perm = await client.Repository.Collaborator.ReviewPermission(RepoOwner, RepoName, user.Login).ConfigureAwait(false);
    139  ourTcs.SetResult(perm.Permission == PermissionLevel.Write || perm.Permission == PermissionLevel.Admin);
    140  }
    141  catch
    142  {
    143  ourTcs.SetResult(false);
    144  throw;
    145  }
    146 
    147  var authorized = await authTask.ConfigureAwait(false);
    148  if (!authorized)
    149  return;
    150 
    151  lock (releaseDictionary)
    152  {
    153  foreach (var I in notes)
    154  Console.WriteLine("#" + fullPR.Number + " - " + I + " (@" + user.Login + ")");
    155  if (releaseDictionary.TryGetValue(fullPR.Number, out var currentValues))
    156  currentValues.AddRange(notes);
    157  else
    158  releaseDictionary.Add(fullPR.Number, notes);
    159  }
    160  }
    161 
    162  var comments = await client.Issue.Comment.GetAllForIssue(RepoOwner, RepoName, fullPR.Number).ConfigureAwait(false);
    163  await Task.WhenAll(BuildNotesFromComment(fullPR.Body, fullPR.User), Task.WhenAll(comments.Select(x => BuildNotesFromComment(x.Body, x.User)))).ConfigureAwait(false);
    164  }
    165 
    166  var tasks = new List<Task>();
    167  foreach (var I in milestonePRs.Items)
    168  tasks.Add(GetReleaseNotesFromPR(I));
    169 
    170  var releases = await releasesTask.ConfigureAwait(false);
    171 
    172  var releasingSuite = version.Major;
    173 
    174  Version highestReleaseVersion = null;
    175  Release highestRelease = null;
    176  foreach (var I in releases)
    177  {
    178  if (!Version.TryParse(I.TagName.Replace("tgstation-server-v", String.Empty), out var currentReleaseVersion))
    179  {
    180  Console.WriteLine("WARNING: Unable to determine version of release " + I.HtmlUrl);
    181  continue;
    182  }
    183 
    184  if (currentReleaseVersion.Major == releasingSuite && (highestReleaseVersion == null || currentReleaseVersion > highestReleaseVersion))
    185  {
    186  highestReleaseVersion = currentReleaseVersion;
    187  highestRelease = I;
    188  }
    189  }
    190 
    191  if (highestReleaseVersion == null)
    192  {
    193  Console.WriteLine("Unable to determine highest release version for suite " + releasingSuite + "!");
    194  return 6;
    195  }
    196 
    197  var oldNotes = highestRelease.Body;
    198 
    199  var splits = new List<string>(oldNotes.Split('\n'));
    200  //trim away all the lines that don't start with #
    201 
    202  string keepThisRelease;
    203  if (version.Revision == 0)
    204  if (version.Build == 0)
    205  keepThisRelease = "# ";
    206  else
    207  keepThisRelease = "## ";
    208  else
    209  keepThisRelease = "### ";
    210 
    211  for (; !splits[0].StartsWith(keepThisRelease, StringComparison.Ordinal); splits.RemoveAt(0))
    212  if (splits.Count == 1)
    213  {
    214  Console.WriteLine("Error formatting release notes: Can't detemine notes start!");
    215  return 7;
    216  }
    217 
    218  oldNotes = String.Join('\n', splits);
    219 
    220  string prefix;
    221  switch (releasingSuite)
    222  {
    223  case 3:
    224  prefix = "The /tg/station server suite";
    225  break;
    226  default:
    227  prefix = "See https://tgstation.github.io/tgstation-server for installation instructions";
    228  break;
    229  }
    230 
    231  var newNotes = new StringBuilder(prefix);
    232  newNotes.Append(Environment.NewLine);
    233  newNotes.Append(Environment.NewLine);
    234  if (version.Revision == 0)
    235  if (version.Build == 0)
    236  {
    237  newNotes.Append("# [Version ");
    238  newNotes.Append(version.Minor);
    239  }
    240  else
    241  {
    242  newNotes.Append("## [Changelog for ");
    243  newNotes.Append(version.Build);
    244  newNotes.Append(".x");
    245  }
    246  else
    247  {
    248  newNotes.Append("### [Patch ");
    249  newNotes.Append(version.Revision);
    250  }
    251  newNotes.Append("](");
    252  var milestone = await milestoneTask.ConfigureAwait(false);
    253  if (milestone == null)
    254  {
    255  Console.WriteLine("Unable to detemine milestone!");
    256  return 9;
    257  }
    258  newNotes.Append(milestone.HtmlUrl);
    259  newNotes.Append("?closed=1)");
    260  newNotes.Append(Environment.NewLine);
    261 
    262  await Task.WhenAll(tasks).ConfigureAwait(false);
    263 
    264  if (releaseDictionary.Count == 0)
    265  {
    266  Console.WriteLine("No release notes for this milestone!");
    267  return 8;
    268  }
    269 
    270  foreach (var I in releaseDictionary)
    271  foreach (var note in I.Value)
    272  {
    273  newNotes.Append(Environment.NewLine);
    274  newNotes.Append("- ");
    275  newNotes.Append(note);
    276  newNotes.Append(" (#");
    277  newNotes.Append(I.Key);
    278  newNotes.Append(')');
    279  }
    280 
    281  newNotes.Append(Environment.NewLine);
    282  newNotes.Append(Environment.NewLine);
    283  newNotes.Append(oldNotes);
    284 
    285  Console.WriteLine("Writing out new release notes...");
    286  var releaseNotes = newNotes.ToString();
    287  await File.WriteAllTextAsync("release_notes.md", releaseNotes).ConfigureAwait(false);
    288 
    289  if (doNotCloseMilestone)
    290  Console.WriteLine("Not closing milestone due to parameter!");
    291  else
    292  {
    293  Console.WriteLine("Closing milestone...");
    294  await client.Issue.Milestone.Update(RepoOwner, RepoName, milestone.Number, new MilestoneUpdate
    295  {
    296  State = ItemState.Closed
    297  }).ConfigureAwait(false);
    298  }
    299 
    300  return 0;
    301  }
    302  catch (Exception e)
    303  {
    304  Console.WriteLine(e);
    305  return 4;
    306  }
    307  }

    The documentation for this class was generated from the following file:
      @@ -149,7 +127,7 @@ Static Private Member Functions diff --git a/class_service_base.html b/class_service_base.html index 86446e36f7..3a8f58df75 100644 --- a/class_service_base.html +++ b/class_service_base.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: ServiceBase Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + +
    -Tgstation.Server.Host.Service.ServerService - -
    +Tgstation.Server.Host.Service.ServerService + +
    The documentation for this class was generated from the following file: @@ -108,7 +84,7 @@ Inheritance diagram for ServiceBase: diff --git a/class_tgstation_1_1_server_1_1_api_1_1_api_headers-members.html b/class_tgstation_1_1_server_1_1_api_1_1_api_headers-members.html index 6bea50901f..2b84cfba8b 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_api_headers-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_api_headers-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + +
    AssemblyNameTgstation.Server.Api.ApiHeadersprivatestatic CheckCompatibility(Version otherVersion)Tgstation.Server.Api.ApiHeadersstatic Compatible()Tgstation.Server.Api.ApiHeaders - InstanceIdTgstation.Server.Api.ApiHeaders + InstanceIdTgstation.Server.Api.ApiHeaders InstanceIdHeaderTgstation.Server.Api.ApiHeadersprivate IsTokenAuthenticationTgstation.Server.Api.ApiHeaders JwtAuthenticationSchemeTgstation.Server.Api.ApiHeadersprivate PasswordTgstation.Server.Api.ApiHeaders PasswordAuthenticationSchemeTgstation.Server.Api.ApiHeadersprivate RawUserAgentTgstation.Server.Api.ApiHeaders - SetRequestHeaders(HttpRequestHeaders headers, long?instanceId=null)Tgstation.Server.Api.ApiHeaders + SetRequestHeaders(HttpRequestHeaders headers, long? instanceId=null)Tgstation.Server.Api.ApiHeaders TokenTgstation.Server.Api.ApiHeaders UserAgentTgstation.Server.Api.ApiHeaders UsernameTgstation.Server.Api.ApiHeaders @@ -126,7 +102,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); 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 6d146d1dc8..3dbdea01e8 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 @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Api.ApiHeaders Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + +

    Public Member Functions

     ApiHeaders (ProductHeaderValue userAgent, string token) - Construct ApiHeaders for JWT authentication More...
    + Construct ApiHeaders for JWT authentication More...
       ApiHeaders (ProductHeaderValue userAgent, string username, string password) - Construct ApiHeaders for password authentication More...
    + Construct ApiHeaders for password authentication More...
       ApiHeaders (RequestHeaders requestHeaders) - Construct and validates ApiHeaders from a set of requestHeaders More...
    + Construct and validates ApiHeaders from a set of requestHeaders More...
      bool Compatible () - Checks if the ApiVersion is compatible with Version More...
    + Checks if the ApiVersion is compatible with Version More...
      -void SetRequestHeaders (HttpRequestHeaders headers, long?instanceId=null) - Set HttpRequestHeaders using the ApiHeaders. This initially clears headers More...
    -  +void SetRequestHeaders (HttpRequestHeaders headers, long? instanceId=null) + Set HttpRequestHeaders using the ApiHeaders. This initially clears headers More...
    +  @@ -153,9 +129,9 @@ Static Public Attributes

    Static Public Member Functions

    - - - + + + @@ -175,19 +151,19 @@ Properties - +

    Properties

    long InstanceId [get, set]
     The Models.Instance.Id being accessed More...
     
    long? InstanceId [get, set]
     The Models.Instance.Id being accessed More...
     
    string RawUserAgent [get]
     The client's raw user agent More...
     

    Private Member Functions

     ApiHeaders (ProductHeaderValue userAgent, string token, string username, string password)
     Construct ApiHeaders More...
     Construct ApiHeaders More...
     
    - + - + - + @@ -205,9 +181,11 @@ Static Private Attributes

    Detailed Description

    Represents the header that must be present for every server request

    -

    Definition at line 16 of file ApiHeaders.cs.

    +

    Definition at line 16 of file ApiHeaders.cs.

    Constructor & Destructor Documentation

    - + +

    ◆ ApiHeaders() [1/4]

    +

    Private Attributes

    const string ApiVersionHeader = "Api"
     The ApiVersion header key More...
     The ApiVersion header key More...
     
    const string UsernameHeader = "Username"
     The Username header key More...
     The Username header key More...
     
    const string InstanceIdHeader = "Instance"
     The InstanceId header key More...
     The InstanceId header key More...
     
    const string JwtAuthenticationScheme = "Bearer"
     The JWT authentication header scheme More...
    @@ -231,20 +209,22 @@ Static Private Attributes
    -

    Construct ApiHeaders for JWT authentication

    +

    Construct ApiHeaders for JWT authentication

    Parameters
    - - + +
    userAgentThe value of UserAgent
    tokenThe value of Token
    userAgentThe value of UserAgent
    tokenThe value of Token
    -

    Definition at line 110 of file ApiHeaders.cs.

    -
    110  : this(userAgent, token, null, null)
    111  {
    112  if (userAgent == null)
    113  throw new ArgumentNullException(nameof(userAgent));
    114  if (token == null)
    115  throw new ArgumentNullException(nameof(token));
    116  }
    +

    Definition at line 110 of file ApiHeaders.cs.

    +
    110  : this(userAgent, token, null, null)
    111  {
    112  if (userAgent == null)
    113  throw new ArgumentNullException(nameof(userAgent));
    114  if (token == null)
    115  throw new ArgumentNullException(nameof(token));
    116  }
    - + +

    ◆ ApiHeaders() [2/4]

    +
    @@ -274,21 +254,23 @@ Static Private Attributes
    -

    Construct ApiHeaders for password authentication

    +

    Construct ApiHeaders for password authentication

    Parameters
    - - - + + +
    userAgentThe value of UserAgent
    usernameThe value of Username
    passwordThe value of Password
    userAgentThe value of UserAgent
    usernameThe value of Username
    passwordThe value of Password
    -

    Definition at line 124 of file ApiHeaders.cs.

    -
    124  : this(userAgent, null, username, password)
    125  {
    126  if (userAgent == null)
    127  throw new ArgumentNullException(nameof(userAgent));
    128  if (username == null)
    129  throw new ArgumentNullException(nameof(username));
    130  if (password == null)
    131  throw new ArgumentNullException(nameof(password));
    132  }
    +

    Definition at line 124 of file ApiHeaders.cs.

    +
    124  : this(userAgent, null, username, password)
    125  {
    126  if (userAgent == null)
    127  throw new ArgumentNullException(nameof(userAgent));
    128  if (username == null)
    129  throw new ArgumentNullException(nameof(username));
    130  if (password == null)
    131  throw new ArgumentNullException(nameof(password));
    132  }
    - + +

    ◆ ApiHeaders() [3/4]

    +
    @@ -302,33 +284,37 @@ Static Private Attributes
    -

    Construct and validates ApiHeaders from a set of requestHeaders

    +

    Construct and validates ApiHeaders from a set of requestHeaders

    Parameters
    - +
    requestHeadersThe RequestHeaders containing the ApiHeaders
    requestHeadersThe RequestHeaders containing the ApiHeaders
    -

    Definition at line 138 of file ApiHeaders.cs.

    -
    139  {
    140  var jsonAccept = new Microsoft.Net.Http.Headers.MediaTypeHeaderValue(ApplicationJson);
    141  if (!requestHeaders.Accept.Any(x => x.MediaType == jsonAccept.MediaType))
    142  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Client does not accept {0}!", ApplicationJson));
    143 
    144  if (!requestHeaders.Headers.TryGetValue(HeaderNames.UserAgent, out var userAgentValues) || userAgentValues.Count == 0)
    145  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Missing {0} headers!", HeaderNames.UserAgent));
    146 
    147  RawUserAgent = userAgentValues.First();
    148  if (String.IsNullOrWhiteSpace(RawUserAgent))
    149  throw new InvalidOperationException("Malformed client User-Agent!");
    150 
    151  // make sure the api header matches ours
    152  if (!requestHeaders.Headers.TryGetValue(ApiVersionHeader, out var apiUserAgentHeaderValues) || !ProductInfoHeaderValue.TryParse(apiUserAgentHeaderValues.FirstOrDefault(), out var apiUserAgent) || apiUserAgent.Product.Name != AssemblyName.Name)
    153  throw new InvalidOperationException("Missing API version!");
    154 
    155  if (!Version.TryParse(apiUserAgent.Product.Version, out var apiVersion))
    156  throw new InvalidOperationException("Malformed API version!");
    157 
    158  ApiVersion = apiVersion;
    159 
    160  if (!requestHeaders.Headers.TryGetValue(HeaderNames.Authorization, out StringValues authorization))
    161  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Missing {0} header!", HeaderNames.Authorization));
    162  var auth = authorization.First();
    163  var splits = new List<string>(auth.Split(' '));
    164  var scheme = splits.First();
    165  if (String.IsNullOrWhiteSpace(scheme))
    166  throw new InvalidOperationException("Missing authentication scheme!");
    167 
    168  splits.RemoveAt(0);
    169  var parameter = String.Concat(splits);
    170  if (String.IsNullOrEmpty(parameter))
    171  throw new InvalidOperationException("Missing authentication parameter!");
    172 
    173  if (requestHeaders.Headers.TryGetValue(InstanceIdHeader, out var instanceIdValues))
    174  {
    175  var instanceIdString = instanceIdValues.FirstOrDefault();
    176  if (instanceIdString != default && Int64.TryParse(instanceIdString, out var instanceId))
    177  InstanceId = instanceId;
    178  }
    179 
    180  switch (scheme)
    181  {
    183  Token = parameter;
    184  break;
    186  Password = parameter;
    187  var fail = !requestHeaders.Headers.TryGetValue(UsernameHeader, out var values);
    188  if (!fail)
    189  {
    190  Username = values.FirstOrDefault();
    191  fail = String.IsNullOrWhiteSpace(Username);
    192  }
    193 
    194  if (fail)
    195  throw new InvalidOperationException("Missing Username header!");
    196  break;
    197  default:
    198  throw new InvalidOperationException("Invalid authentication scheme!");
    199  }
    200  }
    static readonly AssemblyName AssemblyName
    The current System.Reflection.AssemblyName
    Definition: ApiHeaders.cs:51
    -
    const string ApplicationJson
    TODO: Remove this when https://github.com/dotnet/corefx/pull/26701 makes it into the sdk ...
    Definition: ApiHeaders.cs:21
    -
    Version ApiVersion
    The client&#39;s API version
    Definition: ApiHeaders.cs:76
    -
    const string PasswordAuthenticationScheme
    The password authentication header scheme
    Definition: ApiHeaders.cs:46
    -
    string Username
    The client&#39;s username
    Definition: ApiHeaders.cs:86
    -
    string Password
    The client&#39;s password
    Definition: ApiHeaders.cs:91
    -
    string RawUserAgent
    The client&#39;s raw user agent
    Definition: ApiHeaders.cs:71
    -
    const string JwtAuthenticationScheme
    The JWT authentication header scheme
    Definition: ApiHeaders.cs:41
    -
    const string ApiVersionHeader
    The ApiVersion header key
    Definition: ApiHeaders.cs:26
    -
    const string InstanceIdHeader
    The InstanceId header key
    Definition: ApiHeaders.cs:36
    -
    string Token
    The client&#39;s JWT
    Definition: ApiHeaders.cs:81
    -
    long InstanceId
    The Models.Instance.Id being accessed
    Definition: ApiHeaders.cs:61
    -
    const string UsernameHeader
    The Username header key
    Definition: ApiHeaders.cs:31
    -
    static Version Version
    Get the version of the Api the caller is using
    Definition: ApiHeaders.cs:56
    +

    Definition at line 138 of file ApiHeaders.cs.

    +
    139  {
    140  if (requestHeaders == null)
    141  throw new ArgumentNullException(nameof(requestHeaders));
    142 
    143  var jsonAccept = new Microsoft.Net.Http.Headers.MediaTypeHeaderValue(ApplicationJson);
    144  if (!requestHeaders.Accept.Any(x => x.MediaType == jsonAccept.MediaType))
    145  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Client does not accept {0}!", ApplicationJson));
    146 
    147  if (!requestHeaders.Headers.TryGetValue(HeaderNames.UserAgent, out var userAgentValues) || userAgentValues.Count == 0)
    148  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Missing {0} headers!", HeaderNames.UserAgent));
    149 
    150  RawUserAgent = userAgentValues.First();
    151  if (String.IsNullOrWhiteSpace(RawUserAgent))
    152  throw new InvalidOperationException("Malformed client User-Agent!");
    153 
    154  // make sure the api header matches ours
    155  if (!requestHeaders.Headers.TryGetValue(ApiVersionHeader, out var apiUserAgentHeaderValues) || !ProductInfoHeaderValue.TryParse(apiUserAgentHeaderValues.FirstOrDefault(), out var apiUserAgent) || apiUserAgent.Product.Name != AssemblyName.Name)
    156  throw new InvalidOperationException("Missing API version!");
    157 
    158  if (!Version.TryParse(apiUserAgent.Product.Version, out var apiVersion))
    159  throw new InvalidOperationException("Malformed API version!");
    160 
    161  ApiVersion = apiVersion;
    162 
    163  if (!requestHeaders.Headers.TryGetValue(HeaderNames.Authorization, out StringValues authorization))
    164  throw new InvalidOperationException(String.Format(CultureInfo.InvariantCulture, "Missing {0} header!", HeaderNames.Authorization));
    165  var auth = authorization.First();
    166  var splits = new List<string>(auth.Split(' '));
    167  var scheme = splits.First();
    168  if (String.IsNullOrWhiteSpace(scheme))
    169  throw new InvalidOperationException("Missing authentication scheme!");
    170 
    171  splits.RemoveAt(0);
    172  var parameter = String.Concat(splits);
    173  if (String.IsNullOrEmpty(parameter))
    174  throw new InvalidOperationException("Missing authentication parameter!");
    175 
    176  if (requestHeaders.Headers.TryGetValue(InstanceIdHeader, out var instanceIdValues))
    177  {
    178  var instanceIdString = instanceIdValues.FirstOrDefault();
    179  if (instanceIdString != default && Int64.TryParse(instanceIdString, out var instanceId))
    180  InstanceId = instanceId;
    181  }
    182 
    183  switch (scheme)
    184  {
    186  Token = parameter;
    187  break;
    189  Password = parameter;
    190  var fail = !requestHeaders.Headers.TryGetValue(UsernameHeader, out var values);
    191  if (!fail)
    192  {
    193  Username = values.FirstOrDefault();
    194  fail = String.IsNullOrWhiteSpace(Username);
    195  }
    196 
    197  if (fail)
    198  throw new InvalidOperationException("Missing Username header!");
    199  break;
    200  default:
    201  throw new InvalidOperationException("Invalid authentication scheme!");
    202  }
    203  }
    static readonly AssemblyName AssemblyName
    The current System.Reflection.AssemblyName
    Definition: ApiHeaders.cs:51
    +
    const string ApplicationJson
    TODO: Remove this when https://github.com/dotnet/corefx/pull/26701 makes it into the sdk
    Definition: ApiHeaders.cs:21
    +
    Version ApiVersion
    The client's API version
    Definition: ApiHeaders.cs:76
    +
    const string PasswordAuthenticationScheme
    The password authentication header scheme
    Definition: ApiHeaders.cs:46
    +
    string Username
    The client's username
    Definition: ApiHeaders.cs:86
    +
    string Password
    The client's password
    Definition: ApiHeaders.cs:91
    +
    string RawUserAgent
    The client's raw user agent
    Definition: ApiHeaders.cs:71
    +
    long? InstanceId
    The Models.Instance.Id being accessed
    Definition: ApiHeaders.cs:61
    +
    const string JwtAuthenticationScheme
    The JWT authentication header scheme
    Definition: ApiHeaders.cs:41
    +
    const string ApiVersionHeader
    The ApiVersion header key
    Definition: ApiHeaders.cs:26
    +
    const string InstanceIdHeader
    The InstanceId header key
    Definition: ApiHeaders.cs:36
    +
    string Token
    The client's JWT
    Definition: ApiHeaders.cs:81
    +
    const string UsernameHeader
    The Username header key
    Definition: ApiHeaders.cs:31
    +
    static Version Version
    Get the version of the Api the caller is using
    Definition: ApiHeaders.cs:56
    +

    References Tgstation.Server.Api.ApiHeaders.ApiVersion, Tgstation.Server.Api.ApiHeaders.ApiVersionHeader, Tgstation.Server.Api.ApiHeaders.ApplicationJson, Tgstation.Server.Api.ApiHeaders.AssemblyName, Tgstation.Server.Api.ApiHeaders.InstanceId, Tgstation.Server.Api.ApiHeaders.InstanceIdHeader, Tgstation.Server.Api.ApiHeaders.JwtAuthenticationScheme, Tgstation.Server.Api.ApiHeaders.Password, Tgstation.Server.Api.ApiHeaders.PasswordAuthenticationScheme, Tgstation.Server.Api.ApiHeaders.RawUserAgent, Tgstation.Server.Api.ApiHeaders.Token, Tgstation.Server.Api.ApiHeaders.Username, Tgstation.Server.Api.ApiHeaders.UsernameHeader, and Tgstation.Server.Api.ApiHeaders.Version.

    +
    - + +

    ◆ ApiHeaders() [4/4]

    +
    @@ -372,29 +358,33 @@ Static Private Attributes
    -

    Construct ApiHeaders

    +

    Construct ApiHeaders

    Parameters
    - - - - + + + +
    userAgentThe value of UserAgent
    tokenThe value of Token
    usernameThe value of Username
    passwordThe value of Password
    userAgentThe value of UserAgent
    tokenThe value of Token
    usernameThe value of Username
    passwordThe value of Password
    -

    Definition at line 209 of file ApiHeaders.cs.

    -
    210  {
    211  RawUserAgent = userAgent?.ToString();
    212  Token = token;
    213  Username = username;
    214  Password = password;
    216  }
    Version ApiVersion
    The client&#39;s API version
    Definition: ApiHeaders.cs:76
    -
    string Username
    The client&#39;s username
    Definition: ApiHeaders.cs:86
    -
    string Password
    The client&#39;s password
    Definition: ApiHeaders.cs:91
    -
    string RawUserAgent
    The client&#39;s raw user agent
    Definition: ApiHeaders.cs:71
    -
    string Token
    The client&#39;s JWT
    Definition: ApiHeaders.cs:81
    -
    static Version Version
    Get the version of the Api the caller is using
    Definition: ApiHeaders.cs:56
    +

    Definition at line 212 of file ApiHeaders.cs.

    +
    213  {
    214  RawUserAgent = userAgent?.ToString();
    215  Token = token;
    216  Username = username;
    217  Password = password;
    219  }
    Version ApiVersion
    The client's API version
    Definition: ApiHeaders.cs:76
    +
    string Username
    The client's username
    Definition: ApiHeaders.cs:86
    +
    string Password
    The client's password
    Definition: ApiHeaders.cs:91
    +
    string RawUserAgent
    The client's raw user agent
    Definition: ApiHeaders.cs:71
    +
    string Token
    The client's JWT
    Definition: ApiHeaders.cs:81
    +
    static Version Version
    Get the version of the Api the caller is using
    Definition: ApiHeaders.cs:56
    +

    References Tgstation.Server.Api.ApiHeaders.ApiVersion, Tgstation.Server.Api.ApiHeaders.Password, Tgstation.Server.Api.ApiHeaders.RawUserAgent, Tgstation.Server.Api.ApiHeaders.Token, Tgstation.Server.Api.ApiHeaders.Username, and Tgstation.Server.Api.ApiHeaders.Version.

    +

    Member Function Documentation

    - + +

    ◆ CheckCompatibility()

    +
    @@ -419,15 +409,17 @@ Static Private Attributes

    Checks if a given otherVersion is compatible with our own

    Parameters
    - +
    otherVersionThe Version to test
    otherVersionThe Version to test
    -
    Returns
    if the given version is compatible with the API. otherwise
    +
    Returns
    true if the given version is compatible with the API. false otherwise
    - + +

    ◆ Compatible()

    +
    @@ -440,14 +432,16 @@ Static Private Attributes
    -

    Checks if the ApiVersion is compatible with Version

    -
    Returns
    if the API is compatible, otherwise
    +

    Checks if the ApiVersion is compatible with Version

    +
    Returns
    true if the API is compatible, false otherwise
    -

    Referenced by Tgstation.Server.Host.Controllers.ApiController.OnActionExecutionAsync().

    +

    Referenced by Tgstation.Server.Host.Controllers.ApiController.OnActionExecutionAsync().

    - + +

    ◆ SetRequestHeaders()

    +
    @@ -471,37 +465,41 @@ Static Private Attributes
    -

    Set HttpRequestHeaders using the ApiHeaders. This initially clears headers

    +

    Set HttpRequestHeaders using the ApiHeaders. This initially clears headers

    Parameters
    - +
    headersThe HttpRequestHeaders to set
    instanceIdThe Models.Instance.Id for the request
    instanceIdThe Models.Instance.Id for the request
    -

    Definition at line 229 of file ApiHeaders.cs.

    - -

    Referenced by Tgstation.Server.Client.ApiClient.RunRequest< TResult >().

    -
    230  {
    231  if (headers == null)
    232  throw new ArgumentNullException(nameof(headers));
    233  if (instanceId.HasValue && InstanceId.HasValue && instanceId != InstanceId)
    234  throw new InvalidOperationException("Specified instance ID in constructor and SetRequestHeaders!");
    235 
    236  headers.Clear();
    237  headers.Accept.Add(new MediaTypeWithQualityHeaderValue(ApplicationJson));
    239  headers.Authorization = new AuthenticationHeaderValue(JwtAuthenticationScheme, Token);
    240  else
    241  {
    242  headers.Authorization = new AuthenticationHeaderValue(PasswordAuthenticationScheme, Password);
    243  headers.Add(UsernameHeader, Username);
    244  }
    245 
    246  headers.UserAgent.Add(new ProductInfoHeaderValue(UserAgent));
    247  headers.Add(ApiVersionHeader, new ProductHeaderValue(AssemblyName.Name, ApiVersion.ToString()).ToString());
    248  instanceId = instanceId ?? InstanceId;
    249  if (instanceId.HasValue)
    250  headers.Add(InstanceIdHeader, instanceId.ToString());
    251  }
    static readonly AssemblyName AssemblyName
    The current System.Reflection.AssemblyName
    Definition: ApiHeaders.cs:51
    -
    const string ApplicationJson
    TODO: Remove this when https://github.com/dotnet/corefx/pull/26701 makes it into the sdk ...
    Definition: ApiHeaders.cs:21
    -
    Version ApiVersion
    The client&#39;s API version
    Definition: ApiHeaders.cs:76
    -
    const string PasswordAuthenticationScheme
    The password authentication header scheme
    Definition: ApiHeaders.cs:46
    -
    string Username
    The client&#39;s username
    Definition: ApiHeaders.cs:86
    -
    ProductHeaderValue UserAgent
    The client&#39;s user agent as a ProductHeaderValue if valid
    Definition: ApiHeaders.cs:66
    -
    string Password
    The client&#39;s password
    Definition: ApiHeaders.cs:91
    -
    bool IsTokenAuthentication
    If the header uses password or JWT authentication
    Definition: ApiHeaders.cs:96
    -
    const string JwtAuthenticationScheme
    The JWT authentication header scheme
    Definition: ApiHeaders.cs:41
    -
    const string ApiVersionHeader
    The ApiVersion header key
    Definition: ApiHeaders.cs:26
    -
    const string InstanceIdHeader
    The InstanceId header key
    Definition: ApiHeaders.cs:36
    -
    string Token
    The client&#39;s JWT
    Definition: ApiHeaders.cs:81
    -
    long InstanceId
    The Models.Instance.Id being accessed
    Definition: ApiHeaders.cs:61
    -
    const string UsernameHeader
    The Username header key
    Definition: ApiHeaders.cs:31
    +

    Definition at line 232 of file ApiHeaders.cs.

    +
    233  {
    234  if (headers == null)
    235  throw new ArgumentNullException(nameof(headers));
    236  if (instanceId.HasValue && InstanceId.HasValue && instanceId != InstanceId)
    237  throw new InvalidOperationException("Specified instance ID in constructor and SetRequestHeaders!");
    238 
    239  headers.Clear();
    240  headers.Accept.Add(new MediaTypeWithQualityHeaderValue(ApplicationJson));
    242  headers.Authorization = new AuthenticationHeaderValue(JwtAuthenticationScheme, Token);
    243  else
    244  {
    245  headers.Authorization = new AuthenticationHeaderValue(PasswordAuthenticationScheme, Password);
    246  headers.Add(UsernameHeader, Username);
    247  }
    248 
    249  headers.UserAgent.Add(new ProductInfoHeaderValue(UserAgent));
    250  headers.Add(ApiVersionHeader, new ProductHeaderValue(AssemblyName.Name, ApiVersion.ToString()).ToString());
    251  instanceId = instanceId ?? InstanceId;
    252  if (instanceId.HasValue)
    253  headers.Add(InstanceIdHeader, instanceId.ToString());
    254  }
    static readonly AssemblyName AssemblyName
    The current System.Reflection.AssemblyName
    Definition: ApiHeaders.cs:51
    +
    const string ApplicationJson
    TODO: Remove this when https://github.com/dotnet/corefx/pull/26701 makes it into the sdk
    Definition: ApiHeaders.cs:21
    +
    Version ApiVersion
    The client's API version
    Definition: ApiHeaders.cs:76
    +
    const string PasswordAuthenticationScheme
    The password authentication header scheme
    Definition: ApiHeaders.cs:46
    +
    string Username
    The client's username
    Definition: ApiHeaders.cs:86
    +
    ProductHeaderValue UserAgent
    The client's user agent as a ProductHeaderValue if valid
    Definition: ApiHeaders.cs:66
    +
    string Password
    The client's password
    Definition: ApiHeaders.cs:91
    +
    bool IsTokenAuthentication
    If the header uses password or JWT authentication
    Definition: ApiHeaders.cs:96
    +
    long? InstanceId
    The Models.Instance.Id being accessed
    Definition: ApiHeaders.cs:61
    +
    const string JwtAuthenticationScheme
    The JWT authentication header scheme
    Definition: ApiHeaders.cs:41
    +
    const string ApiVersionHeader
    The ApiVersion header key
    Definition: ApiHeaders.cs:26
    +
    const string InstanceIdHeader
    The InstanceId header key
    Definition: ApiHeaders.cs:36
    +
    string Token
    The client's JWT
    Definition: ApiHeaders.cs:81
    +
    const string UsernameHeader
    The Username header key
    Definition: ApiHeaders.cs:31
    +

    References Tgstation.Server.Api.ApiHeaders.ApiVersion, Tgstation.Server.Api.ApiHeaders.ApiVersionHeader, Tgstation.Server.Api.ApiHeaders.ApplicationJson, Tgstation.Server.Api.ApiHeaders.AssemblyName, Tgstation.Server.Api.ApiHeaders.InstanceId, Tgstation.Server.Api.ApiHeaders.InstanceIdHeader, Tgstation.Server.Api.ApiHeaders.IsTokenAuthentication, Tgstation.Server.Api.ApiHeaders.JwtAuthenticationScheme, Tgstation.Server.Api.ApiHeaders.Password, Tgstation.Server.Api.ApiHeaders.PasswordAuthenticationScheme, Tgstation.Server.Api.ApiHeaders.Token, Tgstation.Server.Api.ApiHeaders.UserAgent, Tgstation.Server.Api.ApiHeaders.Username, and Tgstation.Server.Api.ApiHeaders.UsernameHeader.

    + +

    Referenced by Tgstation.Server.Client.ApiClient.RunRequest< TResult >().

    +

    Member Data Documentation

    - + +

    ◆ ApiVersionHeader

    +
    @@ -519,13 +517,17 @@ Static Private Attributes
    -

    The ApiVersion header key

    +

    The ApiVersion header key

    -

    Definition at line 26 of file ApiHeaders.cs.

    +

    Definition at line 26 of file ApiHeaders.cs.

    + +

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

    - + +

    ◆ ApplicationJson

    +
    @@ -537,13 +539,15 @@ Static Private Attributes

    TODO: Remove this when https://github.com/dotnet/corefx/pull/26701 makes it into the sdk

    -

    Definition at line 21 of file ApiHeaders.cs.

    +

    Definition at line 21 of file ApiHeaders.cs.

    -

    Referenced by Tgstation.Server.Client.ApiClient.RunRequest< TResult >(), and Tgstation.Server.Api.Tests.TestApiHeaders.TestUserAgentsAreValid().

    +

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

    - + +

    ◆ AssemblyName

    +
    @@ -563,11 +567,15 @@ Static Private Attributes

    The current System.Reflection.AssemblyName

    -

    Definition at line 51 of file ApiHeaders.cs.

    +

    Definition at line 51 of file ApiHeaders.cs.

    + +

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

    - + +

    ◆ InstanceIdHeader

    +
    @@ -585,13 +593,17 @@ Static Private Attributes
    -

    The InstanceId header key

    +

    The InstanceId header key

    -

    Definition at line 36 of file ApiHeaders.cs.

    +

    Definition at line 36 of file ApiHeaders.cs.

    + +

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

    - + +

    ◆ IsTokenAuthentication

    +
    @@ -603,13 +615,15 @@ Static Private Attributes

    If the header uses password or JWT authentication

    -

    Definition at line 96 of file ApiHeaders.cs.

    +

    Definition at line 96 of file ApiHeaders.cs.

    -

    Referenced by Tgstation.Server.Host.Controllers.HomeController.CreateToken().

    +

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

    - + +

    ◆ JwtAuthenticationScheme

    +
    @@ -629,11 +643,15 @@ Static Private Attributes

    The JWT authentication header scheme

    -

    Definition at line 41 of file ApiHeaders.cs.

    +

    Definition at line 41 of file ApiHeaders.cs.

    + +

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

    - + +

    ◆ PasswordAuthenticationScheme

    +
    @@ -653,11 +671,15 @@ Static Private Attributes

    The password authentication header scheme

    -

    Definition at line 46 of file ApiHeaders.cs.

    +

    Definition at line 46 of file ApiHeaders.cs.

    + +

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

    - + +

    ◆ UserAgent

    +
    @@ -669,11 +691,15 @@ Static Private Attributes

    The client's user agent as a ProductHeaderValue if valid

    -

    Definition at line 66 of file ApiHeaders.cs.

    +

    Definition at line 66 of file ApiHeaders.cs.

    + +

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

    - + +

    ◆ UsernameHeader

    +
    @@ -691,13 +717,17 @@ Static Private Attributes
    -

    The Username header key

    +

    The Username header key

    -

    Definition at line 31 of file ApiHeaders.cs.

    +

    Definition at line 31 of file ApiHeaders.cs.

    + +

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

    - + +

    ◆ Version

    +
    @@ -717,14 +747,16 @@ Static Private Attributes

    Get the version of the Api the caller is using

    -

    Definition at line 56 of file ApiHeaders.cs.

    +

    Definition at line 56 of file ApiHeaders.cs.

    -

    Referenced by Tgstation.Server.Tests.IntegrationTest.TestStandardOperation().

    +

    Referenced by Tgstation.Server.Api.ApiHeaders.ApiHeaders(), and Tgstation.Server.Tests.IntegrationTest.TestStandardOperation().

    Property Documentation

    - + +

    ◆ ApiVersion

    +
    @@ -744,13 +776,15 @@ Static Private Attributes

    The client's API version

    -

    Definition at line 76 of file ApiHeaders.cs.

    - -

    Referenced by Tgstation.Server.Host.Controllers.ApiController.OnActionExecutionAsync().

    +

    Definition at line 76 of file ApiHeaders.cs.

    +
    76 { get; }
    +

    Referenced by Tgstation.Server.Api.ApiHeaders.ApiHeaders(), Tgstation.Server.Host.Controllers.ApiController.OnActionExecutionAsync(), and Tgstation.Server.Api.ApiHeaders.SetRequestHeaders().

    - + +

    ◆ InstanceId

    +
    @@ -758,7 +792,7 @@ Static Private Attributes @@ -768,15 +802,17 @@ Static Private Attributes
    - +
    long Tgstation.Server.Api.ApiHeaders.InstanceIdlong? Tgstation.Server.Api.ApiHeaders.InstanceId
    - + +

    ◆ Password

    +
    @@ -796,13 +832,15 @@ Static Private Attributes

    The client's password

    -

    Definition at line 91 of file ApiHeaders.cs.

    - -

    Referenced by Tgstation.Server.Host.Controllers.HomeController.CreateToken().

    +

    Definition at line 91 of file ApiHeaders.cs.

    +
    91 { get; }
    +

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

    - + +

    ◆ RawUserAgent

    +
    @@ -822,13 +860,15 @@ Static Private Attributes

    The client's raw user agent

    -

    Definition at line 71 of file ApiHeaders.cs.

    - -

    Referenced by Tgstation.Server.Host.Controllers.ApiController.OnActionExecutionAsync().

    +

    Definition at line 71 of file ApiHeaders.cs.

    +
    71 { get; }
    +

    Referenced by Tgstation.Server.Api.ApiHeaders.ApiHeaders(), and Tgstation.Server.Host.Controllers.ApiController.OnActionExecutionAsync().

    - + +

    ◆ Token

    +
    @@ -848,13 +888,15 @@ Static Private Attributes

    The client's JWT

    -

    Definition at line 81 of file ApiHeaders.cs.

    - -

    Referenced by Tgstation.Server.Client.ServerClient.ServerClient().

    +

    Definition at line 81 of file ApiHeaders.cs.

    +
    81 { get; }
    +

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

    - + +

    ◆ Username

    +
    @@ -874,9 +916,9 @@ Static Private Attributes

    The client's username

    -

    Definition at line 86 of file ApiHeaders.cs.

    - -

    Referenced by Tgstation.Server.Host.Controllers.HomeController.CreateToken().

    +

    Definition at line 86 of file ApiHeaders.cs.

    +
    86 { get; }
    +

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

    @@ -888,7 +930,7 @@ Static Private Attributes diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_administration-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_administration-members.html index 12c00bd82b..7f1f7701a0 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_administration-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_administration-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + + - + - - + + + +
     The GitHub repository the server is built to recieve updates from More...
      Version LatestVersion [get, set] - The latest available version of the Tgstation.Server.Host assembly from the upstream repository. If Version.Minor is higher than NewVersion's the update cannot be applied due to API changes More...
    + The latest available version of the Tgstation.Server.Host assembly from the upstream repository. If Version.Minor is higher than NewVersion's the update cannot be applied due to API changes More...
      Version NewVersion [get, set]  Changes the version of Tgstation.Server.Host to the given version from the upstream repository More...
    @@ -120,9 +96,11 @@ Properties

    Detailed Description

    Represents administrative server information

    -

    Definition at line 8 of file Administration.cs.

    +

    Definition at line 8 of file Administration.cs.

    Property Documentation

    - + +

    ◆ LatestVersion

    +
    @@ -140,15 +118,17 @@ Properties
    -

    The latest available version of the Tgstation.Server.Host assembly from the upstream repository. If Version.Minor is higher than NewVersion's the update cannot be applied due to API changes

    +

    The latest available version of the Tgstation.Server.Host assembly from the upstream repository. If Version.Minor is higher than NewVersion's the update cannot be applied due to API changes

    -

    Definition at line 23 of file Administration.cs.

    - -

    Referenced by Tgstation.Server.Tests.AdministrationTest.TestRead().

    +

    Definition at line 23 of file Administration.cs.

    +
    23 { get; set; }
    +

    Referenced by Tgstation.Server.Tests.AdministrationTest.TestRead().

    - + +

    ◆ NewVersion

    +
    @@ -168,11 +148,13 @@ Properties

    Changes the version of Tgstation.Server.Host to the given version from the upstream repository

    -

    Definition at line 28 of file Administration.cs.

    +

    Definition at line 28 of file Administration.cs.

    +
    28 { get; set; }
    + + + +

    ◆ TrackedRepositoryUrl

    - - -
    @@ -192,11 +174,13 @@ Properties

    The GitHub repository the server is built to recieve updates from

    -

    Definition at line 18 of file Administration.cs.

    +

    Definition at line 18 of file Administration.cs.

    +
    18 { get; set; }
    + + + +

    ◆ WindowsHost

    - - -
    @@ -216,9 +200,9 @@ Properties

    If the server is running on a windows operating system

    -

    Definition at line 13 of file Administration.cs.

    - -

    Referenced by Tgstation.Server.Tests.AdministrationTest.TestRead().

    +

    Definition at line 13 of file Administration.cs.

    +
    13 { get; set; }
    +

    Referenced by Tgstation.Server.Tests.AdministrationTest.TestRead().

    @@ -230,7 +214,7 @@ Properties diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_byond-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_byond-members.html index ab0b467399..88bde46b92 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_byond-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_byond-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + + - + - - + + + +

    Properties

    Version Version [get, set] - The System.Version of the Byond installation used for new compiles. Will be if the user does not have permission to view it or there is no BYOND version installed. Only considers the Version.Major and Version.Minor numbers More...
    + The System.Version of the Byond installation used for new compiles. Will be null if the user does not have permission to view it or there is no BYOND version installed. Only considers the Version.Major and Version.Minor numbers More...
      Job InstallJob [get, set] - The Job being used to install a new Version More...
    + The Job being used to install a new Version More...
     

    Detailed Description

    Represents a BYOND installation

    -

    Definition at line 8 of file Byond.cs.

    +

    Definition at line 8 of file Byond.cs.

    Property Documentation

    - + +

    ◆ InstallJob

    +
    @@ -134,13 +112,15 @@ Properties
    -

    The Job being used to install a new Version

    - -

    Definition at line 18 of file Byond.cs.

    +

    The Job being used to install a new Version

    +

    Definition at line 18 of file Byond.cs.

    +
    18 { get; set; }
    - + +

    ◆ Version

    +
    @@ -158,10 +138,10 @@ Properties
    -

    The System.Version of the Byond installation used for new compiles. Will be if the user does not have permission to view it or there is no BYOND version installed. Only considers the Version.Major and Version.Minor numbers

    - -

    Definition at line 13 of file Byond.cs.

    +

    The System.Version of the Byond installation used for new compiles. Will be null if the user does not have permission to view it or there is no BYOND version installed. Only considers the Version.Major and Version.Minor numbers

    +

    Definition at line 13 of file Byond.cs.

    +
    13 { get; set; }

    The documentation for this class was generated from the following file:
      @@ -172,7 +152,7 @@ Properties diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_chat_bot-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_chat_bot-members.html index dc09db9f99..156e97d4fe 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_chat_bot-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_chat_bot-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + + diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_chat_bot.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_chat_bot.html index b967043b66..69bccb2574 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_chat_bot.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_chat_bot.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Api.Models.ChatBot Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + +
    -Tgstation.Server.Api.Models.Internal.ChatBot - -
    +Tgstation.Server.Api.Models.Internal.ChatBot + +
    - + + + + + + + +

    Public Member Functions

    bool ValidateProviderChannelTypes ()
     Validates Channels are correct for the Internal.ChatBot.Provider More...
     Validates Channels are correct for the Internal.ChatBot.Provider More...
     
    - Public Member Functions inherited from Tgstation.Server.Api.Models.Internal.ChatBot
    ChatConnectionStringBuilder CreateConnectionStringBuilder ()
     Get the ChatConnectionStringBuilder which maps to the ConnectionString. More...
     
    void SetConnectionStringBuilder (ChatConnectionStringBuilder stringBuilder)
     Set the ChatConnectionStringBuilder for the ChatBot. Also updates the ConnectionString. More...
     
    @@ -125,29 +108,28 @@ Properties - + - + - - - - - - + + + + + + - + - - -

    Properties

     
    - Properties inherited from Tgstation.Server.Api.Models.Internal.ChatBot
    long Id [get, set]
     The settings id More...
     The settings id More...
     
    string Name [get, set]
     The name of the connection More...
     The name of the connection More...
     
    bool Enabled [get, set]
     If the connection is enabled More...
     
    ChatProvider Provider [get, set]
     The ChatProvider used for the connection More...
     
    bool? Enabled [get, set]
     If the connection is enabled More...
     
    ChatProviderProvider [get, set]
     The ChatProvider used for the connection More...
     
    string ConnectionString [get, set]
     The information used to connect to the Provider More...
     The information used to connect to the Provider More...
     
    ChatConnectionStringBuilder ConnectionStringBuilder [get, set]
     The ChatConnectionStringBuilder which maps to the ConnectionString More...
     

    Detailed Description

    -

    Definition at line 8 of file ChatBot.cs.

    +

    Definition at line 8 of file ChatBot.cs.

    Member Function Documentation

    - + +

    ◆ ValidateProviderChannelTypes()

    +
    @@ -160,18 +142,22 @@ Properties
    -

    Validates Channels are correct for the Internal.ChatBot.Provider

    -
    Returns
    if the Channels are valid for the Internal.ChatBot.Provider, otherwise
    +

    Validates Channels are correct for the Internal.ChatBot.Provider

    +
    Returns
    true if the Channels are valid for the Internal.ChatBot.Provider, false otherwise
    -

    Definition at line 19 of file ChatBot.cs.

    -
    20  {
    21  switch (Provider)
    22  {
    23  case ChatProvider.Discord:
    24  return Channels?.Select(x => x.DiscordChannelId.HasValue && x.IrcChannel == null).All(x => x) ?? true;
    25  case ChatProvider.Irc:
    26  return Channels?.Select(x => !x.DiscordChannelId.HasValue && x.IrcChannel != null).All(x => x) ?? true;
    27  default:
    28  throw new InvalidOperationException("Invalid provider type!");
    29  }
    30  }
    List< ChatChannel > Channels
    Channels the Discord bot should listen/announce in
    Definition: ChatBot.cs:13
    -
    ChatProvider Provider
    The ChatProvider used for the connection
    Definition: ChatBot.cs:31
    -
    ChatProvider
    Represents a chat service provider
    Definition: ChatProvider.cs:6
    +

    Definition at line 19 of file ChatBot.cs.

    +
    20  {
    21  switch (Provider)
    22  {
    23  case ChatProvider.Discord:
    24  return Channels?.Select(x => x.DiscordChannelId.HasValue && x.IrcChannel == null).All(x => x) ?? true;
    25  case ChatProvider.Irc:
    26  return Channels?.Select(x => !x.DiscordChannelId.HasValue && x.IrcChannel != null).All(x => x) ?? true;
    27  default:
    28  throw new InvalidOperationException("Invalid provider type!");
    29  }
    30  }
    List< ChatChannel > Channels
    Channels the Discord bot should listen/announce in
    Definition: ChatBot.cs:13
    +
    ChatProvider
    Represents a chat service provider
    Definition: ChatProvider.cs:6
    +
    ChatProvider? Provider
    The ChatProvider used for the connection
    Definition: ChatBot.cs:30
    +

    References Tgstation.Server.Api.Models.ChatBot.Channels, and Tgstation.Server.Api.Models.Internal.ChatBot.Provider.

    +

    Property Documentation

    - + +

    ◆ Channels

    +
    @@ -191,7 +177,9 @@ Properties

    Channels the Discord bot should listen/announce in

    -

    Definition at line 13 of file ChatBot.cs.

    +

    Definition at line 13 of file ChatBot.cs.

    +
    13 { get; set; }
    +

    Referenced by Tgstation.Server.Api.Models.ChatBot.ValidateProviderChannelTypes().

    @@ -203,7 +191,7 @@ Properties diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_chat_channel-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_chat_channel-members.html index 605fe272c6..d2e017b503 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_chat_channel-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_chat_channel-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + + diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_chat_channel.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_chat_channel.html index a5f4834394..68c6737387 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_chat_channel.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_chat_channel.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Api.Models.ChatChannel Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + +
    Tgstation.Server.Host.Models.ChatChannel - -
    + +
    - - - - - - - - - - - - + + + + + + + + + + + + @@ -135,9 +111,11 @@ Properties

    Detailed Description

    Indicates a chat channel

    -

    Definition at line 8 of file ChatChannel.cs.

    +

    Definition at line 8 of file ChatChannel.cs.

    Property Documentation

    - + +

    ◆ DiscordChannelId

    +

    Properties

    string IrcChannel [get, set]
     The IRC channel name More...
     
    ulong DiscordChannelId [get, set]
     The Discord channel ID More...
     
    bool IsAdminChannel [get, set]
     If the ChatChannel is an admin channel More...
     
    bool IsWatchdogChannel [get, set]
     If the ChatChannel is a watchdog channel More...
     
    bool IsUpdatesChannel [get, set]
     If the ChatChannel is an updates channel More...
     
    ulong? DiscordChannelId [get, set]
     The Discord channel ID More...
     
    bool? IsAdminChannel [get, set]
     If the ChatChannel is an admin channel More...
     
    bool? IsWatchdogChannel [get, set]
     If the ChatChannel is a watchdog channel More...
     
    bool? IsUpdatesChannel [get, set]
     If the ChatChannel is an updates channel More...
     
    string Tag [get, set]
     A custom tag users can define to group channels together More...
     
    @@ -145,7 +123,7 @@ Properties @@ -157,13 +135,15 @@ Properties

    The Discord channel ID

    -

    Definition at line 18 of file ChatChannel.cs.

    - -

    Referenced by Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.MapChannels().

    +

    Definition at line 18 of file ChatChannel.cs.

    +
    18 { get; set; }
    +

    Referenced by Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.MapChannels().

    - + +

    ◆ IrcChannel

    +
    - +
    ulong Tgstation.Server.Api.Models.ChatChannel.DiscordChannelIdulong? Tgstation.Server.Api.Models.ChatChannel.DiscordChannelId
    @@ -183,11 +163,13 @@ Properties

    The IRC channel name

    -

    Definition at line 13 of file ChatChannel.cs.

    +

    Definition at line 13 of file ChatChannel.cs.

    +
    13 { get; set; }
    + + + +

    ◆ IsAdminChannel

    - - -
    @@ -195,7 +177,7 @@ Properties @@ -205,15 +187,17 @@ Properties
    - +
    bool Tgstation.Server.Api.Models.ChatChannel.IsAdminChannelbool? Tgstation.Server.Api.Models.ChatChannel.IsAdminChannel
    -

    If the ChatChannel is an admin channel

    +

    If the ChatChannel is an admin channel

    -

    Definition at line 24 of file ChatChannel.cs.

    - -

    Referenced by Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.MapChannels().

    +

    Definition at line 24 of file ChatChannel.cs.

    +
    24 { get; set; }
    +

    Referenced by Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.MapChannels().

    - + +

    ◆ IsUpdatesChannel

    +
    @@ -221,7 +205,7 @@ Properties @@ -231,13 +215,15 @@ Properties
    - +
    bool Tgstation.Server.Api.Models.ChatChannel.IsUpdatesChannelbool? Tgstation.Server.Api.Models.ChatChannel.IsUpdatesChannel
    -

    If the ChatChannel is an updates channel

    - -

    Definition at line 36 of file ChatChannel.cs.

    +

    If the ChatChannel is an updates channel

    +

    Definition at line 36 of file ChatChannel.cs.

    +
    36 { get; set; }
    - + +

    ◆ IsWatchdogChannel

    +
    @@ -245,7 +231,7 @@ Properties @@ -255,13 +241,15 @@ Properties
    - +
    bool Tgstation.Server.Api.Models.ChatChannel.IsWatchdogChannelbool? Tgstation.Server.Api.Models.ChatChannel.IsWatchdogChannel
    -

    If the ChatChannel is a watchdog channel

    - -

    Definition at line 30 of file ChatChannel.cs.

    +

    If the ChatChannel is a watchdog channel

    +

    Definition at line 30 of file ChatChannel.cs.

    +
    30 { get; set; }
    - + +

    ◆ Tag

    +
    @@ -281,9 +269,9 @@ Properties

    A custom tag users can define to group channels together

    -

    Definition at line 41 of file ChatChannel.cs.

    - -

    Referenced by Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.MapChannels().

    +

    Definition at line 41 of file ChatChannel.cs.

    +
    41 { get; set; }
    +

    Referenced by Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider.MapChannels().

    @@ -295,7 +283,7 @@ Properties diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_compile_job-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_compile_job-members.html index 2fbbb24bf2..817af30340 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_compile_job-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_compile_job-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + + @@ -111,7 +87,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); 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 ee4fa9f8cc..405c61f60b 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 @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Api.Models.CompileJob Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + +
    -Tgstation.Server.Api.Models.Internal.CompileJob - -
    +Tgstation.Server.Api.Models.Internal.CompileJob + + - + - + - + - + - + - - - - - - + + + + + +

    Properties

    Job Job [get, set]
     The Job relating to this job More...
     The Job relating to this job More...
     
    RevisionInformation RevisionInformation [get, set]
     Git revision the compiler ran on. Not modifiable More...
     
    Version ByondVersion [get, set]
     The Byond.Version the CompileJob was made with More...
     The Byond.Version the CompileJob was made with More...
     
    - Properties inherited from Tgstation.Server.Api.Models.Internal.CompileJob
    long Id [get, set]
     The ID of the job More...
     The ID of the job More...
     
    string DmeName [get, set]
     The .dme file used for compilation More...
     The .dme file used for compilation More...
     
    string Output [get, set]
     Textual output of DM More...
     Textual output of DM More...
     
    Guid DirectoryName [get, set]
     The Game folder the results were compiled into More...
     
    DreamDaemonSecurity MinimumSecurityLevel [get, set]
     The minimum DreamDaemonSecurity required to run the CompileJob's output More...
     
    Guid? DirectoryName [get, set]
     The Game folder the results were compiled into More...
     
    DreamDaemonSecurityMinimumSecurityLevel [get, set]
     The minimum DreamDaemonSecurity required to run the CompileJob's output More...
     

    Detailed Description

    -

    Definition at line 6 of file CompileJob.cs.

    +

    Definition at line 6 of file CompileJob.cs.

    Property Documentation

    - + +

    ◆ ByondVersion

    + - + +

    ◆ Job

    +
    @@ -187,13 +167,15 @@ Properties
    -

    The Job relating to this job

    - -

    Definition at line 11 of file CompileJob.cs.

    +

    The Job relating to this job

    +

    Definition at line 11 of file CompileJob.cs.

    +
    11 { get; set; }
    - + +

    ◆ RevisionInformation

    +
    @@ -213,9 +195,9 @@ Properties

    Git revision the compiler ran on. Not modifiable

    -

    Definition at line 16 of file CompileJob.cs.

    - -

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

    +

    Definition at line 16 of file CompileJob.cs.

    +
    16 { get; set; }
    +

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

    @@ -227,7 +209,7 @@ Properties diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_configuration_file-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_configuration_file-members.html index 39723078b9..7f911ad921 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_configuration_file-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_configuration_file-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + + @@ -108,7 +84,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); 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 af1cc8632b..df3a4843de 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 @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Api.Models.ConfigurationFile Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + +
    string Path [get, set]  The path to the ConfigurationFile file More...
      -bool AccessDenied [get, set] - If access to the ConfigurationFile file was denied for the operation More...
    -  -bool IsDirectory [get, set] - If Path represents a directory More...
    -  +bool? AccessDenied [get, set] + If access to the ConfigurationFile file was denied for the operation More...
    +  +bool? IsDirectory [get, set] + If Path represents a directory More...
    +  string LastReadHash [get, set]  The MD5 hash of the file when last read by the user. If this doesn't match during update actions, the write will be denied with System.Net.HttpStatusCode.Conflict More...
      -byte[] Content [get, set] - The content of the ConfigurationFile. Will be if AccessDenied is or during listing and write operations More...
    +byte [] Content [get, set] + The content of the ConfigurationFile. Will be null if AccessDenied is true or during listing and write operations More...
     

    Detailed Description

    Represents a game configuration file. Create and delete actions uncerimonuously overwrite/delete files

    -

    Definition at line 6 of file ConfigurationFile.cs.

    +

    Definition at line 6 of file ConfigurationFile.cs.

    Property Documentation

    - + +

    ◆ AccessDenied

    +
    @@ -133,7 +111,7 @@ Properties @@ -145,13 +123,15 @@ Properties

    If access to the ConfigurationFile file was denied for the operation

    -

    Definition at line 16 of file ConfigurationFile.cs.

    - -

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

    +

    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().

    - + +

    ◆ Content

    +
    - +
    bool Tgstation.Server.Api.Models.ConfigurationFile.AccessDeniedbool? Tgstation.Server.Api.Models.ConfigurationFile.AccessDenied
    @@ -169,13 +149,15 @@ Properties
    -

    The content of the ConfigurationFile. Will be if AccessDenied is or during listing and write operations

    - -

    Definition at line 32 of file ConfigurationFile.cs.

    +

    The content of the ConfigurationFile. Will be null if AccessDenied is true or during listing and write operations

    +

    Definition at line 32 of file ConfigurationFile.cs.

    +
    32 { get; set; }
    - + +

    ◆ IsDirectory

    +
    @@ -183,7 +165,7 @@ Properties @@ -193,15 +175,17 @@ Properties
    - +
    bool Tgstation.Server.Api.Models.ConfigurationFile.IsDirectorybool? Tgstation.Server.Api.Models.ConfigurationFile.IsDirectory
    - + +

    ◆ LastReadHash

    +
    @@ -221,11 +205,13 @@ Properties

    The MD5 hash of the file when last read by the user. If this doesn't match during update actions, the write will be denied with System.Net.HttpStatusCode.Conflict

    -

    Definition at line 26 of file ConfigurationFile.cs.

    +

    Definition at line 26 of file ConfigurationFile.cs.

    +
    26 { get; set; }
    + + + +

    ◆ Path

    - - -
    @@ -245,9 +231,9 @@ Properties

    The path to the ConfigurationFile file

    -

    Definition at line 11 of file ConfigurationFile.cs.

    - -

    Referenced by Tgstation.Server.Tests.Instance.ConfigurationTest.FileExists(), Tgstation.Server.Client.Components.ConfigurationClient.Read(), and Tgstation.Server.Tests.Instance.ConfigurationTest.TestDeleteDirectory().

    +

    Definition at line 11 of file ConfigurationFile.cs.

    +
    11 { get; set; }
    +

    Referenced by Tgstation.Server.Tests.Instance.ConfigurationTest.FileExists(), Tgstation.Server.Client.Components.ConfigurationClient.Read(), and Tgstation.Server.Tests.Instance.ConfigurationTest.TestDeleteDirectory().

    @@ -259,7 +245,7 @@ Properties diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_discord_connection_string_builder-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_discord_connection_string_builder-members.html index a65c7affbe..6bf11708e0 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_discord_connection_string_builder-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_discord_connection_string_builder-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + + - + - - + + + +
    -

    ChatConnectionStringBuilder for ChatProvider.Discord +

    ChatConnectionStringBuilder for ChatProvider.Discord More...

    Inheritance diagram for Tgstation.Server.Api.Models.DiscordConnectionStringBuilder:
    @@ -109,20 +85,20 @@ Inheritance diagram for Tgstation.Server.Api.Models.DiscordConnectionStringBuild
    -Tgstation.Server.Api.Models.Internal.ChatConnectionStringBuilder - -
    +Tgstation.Server.Api.Models.Internal.ChatConnectionStringBuilder + +
    - + - + - +

    Public Member Functions

     DiscordConnectionStringBuilder ()
     Construct a DiscordConnectionStringBuilder More...
     Construct a DiscordConnectionStringBuilder More...
     
     DiscordConnectionStringBuilder (string connectionString)
     Construct a DiscordConnectionStringBuilder from a connectionString More...
     Construct a DiscordConnectionStringBuilder from a connectionString More...
     
    override string ToString ()
     Gets the ChatBot.ConnectionString associated with the ChatConnectionStringBuilder More...
     Gets the ChatBot.ConnectionString associated with the ChatConnectionStringBuilder More...
     
    - +

    @@ -137,15 +113,17 @@ Properties

     
    - Properties inherited from Tgstation.Server.Api.Models.Internal.ChatConnectionStringBuilder
    abstract bool Valid [get]
     If the ChatConnectionStringBuilder evaluates to a valid ChatBot.ConnectionString More...
     If the ChatConnectionStringBuilder evaluates to a valid ChatBot.ConnectionString More...
     

    Detailed Description

    -

    ChatConnectionStringBuilder for ChatProvider.Discord

    +

    ChatConnectionStringBuilder for ChatProvider.Discord

    -

    Definition at line 9 of file DiscordConnectionStringBuilder.cs.

    +

    Definition at line 9 of file DiscordConnectionStringBuilder.cs.

    Constructor & Destructor Documentation

    - + +

    ◆ DiscordConnectionStringBuilder() [1/2]

    +
    @@ -158,13 +136,15 @@ Properties
    -

    Construct a DiscordConnectionStringBuilder

    +

    Construct a DiscordConnectionStringBuilder

    -

    Definition at line 23 of file DiscordConnectionStringBuilder.cs.

    +

    Definition at line 23 of file DiscordConnectionStringBuilder.cs.

    23 { }
    - + +

    ◆ DiscordConnectionStringBuilder() [2/2]

    +
    @@ -178,7 +158,7 @@ Properties
    -

    Construct a DiscordConnectionStringBuilder from a connectionString

    +

    Construct a DiscordConnectionStringBuilder from a connectionString

    Parameters
    @@ -186,13 +166,17 @@ Properties -

    Definition at line 29 of file DiscordConnectionStringBuilder.cs.

    -
    30  {
    31  BotToken = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
    32  }
    +

    Definition at line 29 of file DiscordConnectionStringBuilder.cs.

    +
    30  {
    31  BotToken = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
    32  }
    +

    References Tgstation.Server.Api.Models.DiscordConnectionStringBuilder.BotToken.

    +

    Member Function Documentation

    - + +

    ◆ ToString()

    +
    connectionStringThe connection string
    @@ -213,14 +197,16 @@ Properties

    Member Data Documentation

    - + +

    ◆ Valid

    +
    @@ -232,12 +218,14 @@ Properties

    -

    Definition at line 12 of file DiscordConnectionStringBuilder.cs.

    +

    Definition at line 12 of file DiscordConnectionStringBuilder.cs.

    Property Documentation

    - + +

    ◆ BotToken

    +
    @@ -258,7 +246,9 @@ Properties

    The Discord bot token

    See https://discordapp.com/developers/docs/topics/oauth2#bots

    -

    Definition at line 18 of file DiscordConnectionStringBuilder.cs.

    +

    Definition at line 18 of file DiscordConnectionStringBuilder.cs.

    +
    18 { get; set; }
    +

    Referenced by Tgstation.Server.Api.Models.DiscordConnectionStringBuilder.DiscordConnectionStringBuilder().

    @@ -270,7 +260,7 @@ Properties diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_dream_daemon-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_dream_daemon-members.html index 90f97f6836..6c7d5a10f0 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_dream_daemon-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_dream_daemon-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + +
    This is the complete list of members for Tgstation.Server.Api.Models.DreamDaemon, including all inherited members.

    - - - - - + + + + + - - - - - - + + + + + + - +
    ActiveCompileJobTgstation.Server.Api.Models.DreamDaemon
    AllowWebClientTgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters
    AutoStartTgstation.Server.Api.Models.Internal.DreamDaemonSettings
    CurrentAllowWebclientTgstation.Server.Api.Models.DreamDaemon
    CurrentPortTgstation.Server.Api.Models.DreamDaemon
    CurrentSecurityTgstation.Server.Api.Models.DreamDaemon
    AllowWebClientTgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters
    AutoStartTgstation.Server.Api.Models.Internal.DreamDaemonSettings
    CurrentAllowWebclientTgstation.Server.Api.Models.DreamDaemon
    CurrentPortTgstation.Server.Api.Models.DreamDaemon
    CurrentSecurityTgstation.Server.Api.Models.DreamDaemon
    Match(DreamDaemonLaunchParameters otherParameters)Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters
    PrimaryPortTgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters
    RunningTgstation.Server.Api.Models.DreamDaemon
    SecondaryPortTgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters
    SecurityLevelTgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters
    SoftRestartTgstation.Server.Api.Models.Internal.DreamDaemonSettings
    SoftShutdownTgstation.Server.Api.Models.Internal.DreamDaemonSettings
    PrimaryPortTgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters
    RunningTgstation.Server.Api.Models.DreamDaemon
    SecondaryPortTgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters
    SecurityLevelTgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters
    SoftRestartTgstation.Server.Api.Models.Internal.DreamDaemonSettings
    SoftShutdownTgstation.Server.Api.Models.Internal.DreamDaemonSettings
    StagedCompileJobTgstation.Server.Api.Models.DreamDaemon
    StartupTimeoutTgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters
    StartupTimeoutTgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters
    diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_dream_daemon.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_dream_daemon.html index 1f356304be..6f393e9203 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_dream_daemon.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_dream_daemon.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Api.Models.DreamDaemon Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + +
    -

    Represents an instance of BYOND's DreamDaemon game server. Create action starts the server. Delete action shuts down the server +

    Represents an instance of BYOND's DreamDaemon game server. Create action starts the server. Delete action shuts down the server More...

    Inheritance diagram for Tgstation.Server.Api.Models.DreamDaemon:
    @@ -107,10 +83,10 @@ Inheritance diagram for Tgstation.Server.Api.Models.DreamDaemon:
    -Tgstation.Server.Api.Models.Internal.DreamDaemonSettings -Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters - -
    +Tgstation.Server.Api.Models.Internal.DreamDaemonSettings +Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters + +
    @@ -120,58 +96,60 @@ Properties - - - - - - - - - - - - + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + +

    Properties

    CompileJob StagedCompileJob [get, set]
     The next revision to go live More...
     
    bool Running [get, set]
     The current status of DreamDaemon More...
     
    DreamDaemonSecurity CurrentSecurity [get, set]
     The current DreamDaemonSecurity of DreamDaemon. May be downgraded due to requirements of ActiveCompileJob More...
     
    ushort CurrentPort [get, set]
     The port the running DreamDaemon instance is set to More...
     
    bool CurrentAllowWebclient [get, set]
     The webclient status the running DreamDaemon instance is set to More...
     
    bool? Running [get, set]
     The current status of DreamDaemon More...
     
    DreamDaemonSecurityCurrentSecurity [get, set]
     The current DreamDaemonSecurity of DreamDaemon. May be downgraded due to requirements of ActiveCompileJob More...
     
    ushort? CurrentPort [get, set]
     The port the running DreamDaemon instance is set to More...
     
    bool? CurrentAllowWebclient [get, set]
     The webclient status the running DreamDaemon instance is set to More...
     
    - Properties inherited from Tgstation.Server.Api.Models.Internal.DreamDaemonSettings
    bool AutoStart [get, set]
     If DreamDaemon starts when it's Instance starts More...
     
    bool SoftRestart [get, set]
     If the server is undergoing a soft reset. This may be automatically set by changes to other fields More...
     
    bool SoftShutdown [get, set]
     If the server is undergoing a soft shutdown More...
     
    bool? AutoStart [get, set]
     If DreamDaemon starts when it's Instance starts More...
     
    bool? SoftRestart [get, set]
     If the server is undergoing a soft reset. This may be automatically set by changes to other fields More...
     
    bool? SoftShutdown [get, set]
     If the server is undergoing a soft shutdown More...
     
    - Properties inherited from Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters
    bool AllowWebClient [get, set]
     If the BYOND web client can be used to connect to the game server More...
     
    DreamDaemonSecurity SecurityLevel [get, set]
     The DreamDaemonSecurity level of DreamDaemon More...
     
    ushort PrimaryPort [get, set]
     The first port DreamDaemon uses. This should be the publically advertised port More...
     
    ushort SecondaryPort [get, set]
     The second port DreamDaemon uses More...
     
    uint StartupTimeout [get, set]
     The DreamDaemon startup timeout in seconds More...
     
    bool? AllowWebClient [get, set]
     If the BYOND web client can be used to connect to the game server More...
     
    DreamDaemonSecuritySecurityLevel [get, set]
     The DreamDaemonSecurity level of DreamDaemon More...
     
    ushort? PrimaryPort [get, set]
     The first port DreamDaemon uses. This should be the publically advertised port More...
     
    ushort? SecondaryPort [get, set]
     The second port DreamDaemon uses More...
     
    uint? StartupTimeout [get, set]
     The DreamDaemon startup timeout in seconds More...
     
    - +

    Additional Inherited Members

    - Public Member Functions inherited from Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters
    bool Match (DreamDaemonLaunchParameters otherParameters)
     Check if we match a given set of otherParameters More...
     Check if we match a given set of otherParameters More...
     

    Detailed Description

    -

    Represents an instance of BYOND's DreamDaemon game server. Create action starts the server. Delete action shuts down the server

    +

    Represents an instance of BYOND's DreamDaemon game server. Create action starts the server. Delete action shuts down the server

    -

    Definition at line 8 of file DreamDaemon.cs.

    +

    Definition at line 8 of file DreamDaemon.cs.

    Property Documentation

    - + +

    ◆ ActiveCompileJob

    +
    @@ -191,11 +169,13 @@ Additional Inherited Members

    The live revision

    -

    Definition at line 13 of file DreamDaemon.cs.

    +

    Definition at line 13 of file DreamDaemon.cs.

    +
    13 { get; set; }
    + + + +

    ◆ CurrentAllowWebclient

    - - -
    @@ -203,7 +183,7 @@ Additional Inherited Members @@ -213,13 +193,15 @@ Additional Inherited Members
    - +
    bool Tgstation.Server.Api.Models.DreamDaemon.CurrentAllowWebclientbool? Tgstation.Server.Api.Models.DreamDaemon.CurrentAllowWebclient
    -

    The webclient status the running DreamDaemon instance is set to

    - -

    Definition at line 38 of file DreamDaemon.cs.

    +

    The webclient status the running DreamDaemon instance is set to

    +

    Definition at line 38 of file DreamDaemon.cs.

    +
    38 { get; set; }
    - + +

    ◆ CurrentPort

    +
    @@ -227,7 +209,7 @@ Additional Inherited Members @@ -237,13 +219,15 @@ Additional Inherited Members
    - +
    ushort Tgstation.Server.Api.Models.DreamDaemon.CurrentPortushort? Tgstation.Server.Api.Models.DreamDaemon.CurrentPort
    -

    The port the running DreamDaemon instance is set to

    - -

    Definition at line 33 of file DreamDaemon.cs.

    +

    The port the running DreamDaemon instance is set to

    +

    Definition at line 33 of file DreamDaemon.cs.

    +
    33 { get; set; }
    - + +

    ◆ CurrentSecurity

    +
    @@ -251,7 +235,7 @@ Additional Inherited Members @@ -261,13 +245,15 @@ Additional Inherited Members
    - +
    DreamDaemonSecurity Tgstation.Server.Api.Models.DreamDaemon.CurrentSecurityDreamDaemonSecurity? Tgstation.Server.Api.Models.DreamDaemon.CurrentSecurity
    -

    The current DreamDaemonSecurity of DreamDaemon. May be downgraded due to requirements of ActiveCompileJob

    - -

    Definition at line 28 of file DreamDaemon.cs.

    +

    The current DreamDaemonSecurity of DreamDaemon. May be downgraded due to requirements of ActiveCompileJob

    +

    Definition at line 28 of file DreamDaemon.cs.

    +
    28 { get; set; }
    - + +

    ◆ Running

    +
    @@ -275,7 +261,7 @@ Additional Inherited Members @@ -285,13 +271,15 @@ Additional Inherited Members
    - +
    bool Tgstation.Server.Api.Models.DreamDaemon.Runningbool? Tgstation.Server.Api.Models.DreamDaemon.Running
    -

    The current status of DreamDaemon

    - -

    Definition at line 23 of file DreamDaemon.cs.

    +

    The current status of DreamDaemon

    +

    Definition at line 23 of file DreamDaemon.cs.

    +
    23 { get; set; }
    - + +

    ◆ StagedCompileJob

    +
    @@ -311,8 +299,8 @@ Additional Inherited Members

    The next revision to go live

    -

    Definition at line 18 of file DreamDaemon.cs.

    - +

    Definition at line 18 of file DreamDaemon.cs.

    +
    18 { get; set; }

    The documentation for this class was generated from the following file:
      @@ -323,7 +311,7 @@ Additional Inherited Members diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_dream_maker-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_dream_maker-members.html index ae7ab360b7..38302f2534 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_dream_maker-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_dream_maker-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + + diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_dream_maker.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_dream_maker.html index fe6a1858fc..318a7e67f4 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_dream_maker.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_dream_maker.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Api.Models.DreamMaker Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + +
    -

    Represents the state of the DreamMaker compiler. Create action starts a new compile. Delete action cancels the current compile +

    Represents the state of the DreamMaker compiler. Create action starts a new compile. Delete action cancels the current compile More...

    Inheritance diagram for Tgstation.Server.Api.Models.DreamMaker:
    @@ -108,27 +84,29 @@ Inheritance diagram for Tgstation.Server.Api.Models.DreamMaker:
    Tgstation.Server.Host.Models.DreamMakerSettings - -
    + + - + - - - - - - + + + + + +

    Properties

    string ProjectName [get, set]
     The .dme file DreamMaker tries to compile with without the extension More...
     The .dme file DreamMaker tries to compile with without the extension More...
     
    ushort ApiValidationPort [get, set]
     The port used during compilation to validate the DMAPI More...
     
    DreamDaemonSecurity ApiValidationSecurityLevel [get, set]
     The DreamDaemonSecurity level used to validate the DMAPI More...
     
    ushort? ApiValidationPort [get, set]
     The port used during compilation to validate the DMAPI More...
     
    DreamDaemonSecurityApiValidationSecurityLevel [get, set]
     The DreamDaemonSecurity level used to validate the DMAPI More...
     

    Detailed Description

    -

    Represents the state of the DreamMaker compiler. Create action starts a new compile. Delete action cancels the current compile

    +

    Represents the state of the DreamMaker compiler. Create action starts a new compile. Delete action cancels the current compile

    -

    Definition at line 8 of file DreamMaker.cs.

    +

    Definition at line 8 of file DreamMaker.cs.

    Property Documentation

    - + +

    ◆ ApiValidationPort

    +
    @@ -136,7 +114,7 @@ Properties @@ -148,11 +126,13 @@ Properties

    The port used during compilation to validate the DMAPI

    -

    Definition at line 19 of file DreamMaker.cs.

    +

    Definition at line 19 of file DreamMaker.cs.

    +
    19 { get; set; }
    + + + +

    ◆ ApiValidationSecurityLevel

    - - -
    - +
    ushort Tgstation.Server.Api.Models.DreamMaker.ApiValidationPortushort? Tgstation.Server.Api.Models.DreamMaker.ApiValidationPort
    @@ -160,7 +140,7 @@ Properties @@ -170,13 +150,15 @@ Properties
    - +
    DreamDaemonSecurity Tgstation.Server.Api.Models.DreamMaker.ApiValidationSecurityLevelDreamDaemonSecurity? Tgstation.Server.Api.Models.DreamMaker.ApiValidationSecurityLevel
    -

    The DreamDaemonSecurity level used to validate the DMAPI

    - -

    Definition at line 25 of file DreamMaker.cs.

    +

    The DreamDaemonSecurity level used to validate the DMAPI

    +

    Definition at line 25 of file DreamMaker.cs.

    +
    25 { get; set; }
    - + +

    ◆ ProjectName

    +
    @@ -194,10 +176,10 @@ Properties
    -

    The .dme file DreamMaker tries to compile with without the extension

    - -

    Definition at line 13 of file DreamMaker.cs.

    +

    The .dme file DreamMaker tries to compile with without the extension

    +

    Definition at line 13 of file DreamMaker.cs.

    +
    13 { get; set; }

    The documentation for this class was generated from the following file:
      @@ -208,7 +190,7 @@ Properties diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_error_message-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_error_message-members.html index 983fadf8ff..a8c01390d4 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_error_message-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_error_message-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + + - + - - + + + +
    string Message [get, set]  A human readable description of the error More...
      -Version SeverApiVersion [get, set] +Version SeverApiVersion = ApiHeaders.Version [get, set]  The version of the API the server is using More...
     

    Detailed Description

    Represents an error message returned by the server

    -

    Definition at line 8 of file ErrorMessage.cs.

    +

    Definition at line 8 of file ErrorMessage.cs.

    Property Documentation

    - + +

    ◆ Message

    +
    @@ -136,13 +114,15 @@ Properties

    A human readable description of the error

    -

    Definition at line 13 of file ErrorMessage.cs.

    - -

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

    +

    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.File(), Tgstation.Server.Host.Controllers.ApiController.OnActionExecutionAsync(), and Tgstation.Server.Host.Controllers.ConfigurationController.Update().

    - + +

    ◆ SeverApiVersion

    +
    @@ -150,7 +130,7 @@ Properties @@ -162,9 +142,9 @@ Properties

    The version of the API the server is using

    -

    Definition at line 18 of file ErrorMessage.cs.

    - -

    Referenced by Tgstation.Server.Client.ClientException.ClientException().

    +

    Definition at line 18 of file ErrorMessage.cs.

    +
    18 { get; set; } = ApiHeaders.Version;
    +

    Referenced by Tgstation.Server.Client.ClientException.ClientException???().

    @@ -176,7 +156,7 @@ Properties diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance-members.html index 94e488e338..15a5c5de1c 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - +
    Version Tgstation.Server.Api.Models.ErrorMessage.SeverApiVersionVersion Tgstation.Server.Api.Models.ErrorMessage.SeverApiVersion = ApiHeaders.Version
    - + - - + + + + 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 3200308845..bcc91f8ba5 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 @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Api.Models.Instance Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + +
    -Tgstation.Server.Host.Models.Instance - -
    +Tgstation.Server.Host.Models.Instance + +
    - +

    Public Member Functions

    Instance CloneMetadata ()
     Create a clone of the essential Instance metadata More...
     Create a clone of the essential Instance metadata More...
     
    - + - + - + - - - - - - - - - + + + + + + + + + - +

    Properties

    long Id [get, set]
     The id of the Instance. Not modifiable More...
     The id of the Instance. Not modifiable More...
     
    string Name [get, set]
     The name of the Instance More...
     The name of the Instance More...
     
    string Path [get, set]
     The path to where the Instance is located. Can only be changed while the Instance is offline. Must not exist when the instance is created More...
     The path to where the Instance is located. Can only be changed while the Instance is offline. Must not exist when the instance is created More...
     
    bool Online [get, set]
     If the Instance is online More...
     
    ConfigurationType ConfigurationType [get, set]
     If ConfigurationFile can be used on the Instance More...
     
    uint AutoUpdateInterval [get, set]
     The time interval in minutes the repository is automatically pulled and compiles. 0 disables More...
     
    bool? Online [get, set]
     If the Instance is online More...
     
    ConfigurationTypeConfigurationType [get, set]
     If ConfigurationFile can be used on the Instance More...
     
    uint? AutoUpdateInterval [get, set]
     The time interval in minutes the repository is automatically pulled and compiles. 0 disables More...
     
    Job MoveJob [get, set]
     The Job representing a change of Path More...
     The Job representing a change of Path More...
     

    Detailed Description

    Metadata about a server instance

    -

    Definition at line 9 of file Instance.cs.

    +

    Definition at line 9 of file Instance.cs.

    Member Function Documentation

    - + +

    ◆ CloneMetadata()

    +
    @@ -160,13 +138,15 @@ Properties
    -

    Create a clone of the essential Instance metadata

    -
    Returns
    A clone of the essential Instance metadata
    +

    Create a clone of the essential Instance metadata

    +
    Returns
    A clone of the essential Instance metadata

    Property Documentation

    - + +

    ◆ AutoUpdateInterval

    +
    @@ -174,7 +154,7 @@ Properties @@ -186,11 +166,13 @@ Properties

    The time interval in minutes the repository is automatically pulled and compiles. 0 disables

    -

    Definition at line 44 of file Instance.cs.

    +

    Definition at line 44 of file Instance.cs.

    +
    44 { get; set; }
    + + + +

    ◆ ConfigurationType

    - - -
    - +
    uint Tgstation.Server.Api.Models.Instance.AutoUpdateIntervaluint? Tgstation.Server.Api.Models.Instance.AutoUpdateInterval
    @@ -198,7 +180,7 @@ Properties @@ -208,15 +190,17 @@ Properties
    - +
    ConfigurationType Tgstation.Server.Api.Models.Instance.ConfigurationTypeConfigurationType? Tgstation.Server.Api.Models.Instance.ConfigurationType
    -

    If ConfigurationFile can be used on the Instance

    +

    If ConfigurationFile can be used on the Instance

    -

    Definition at line 38 of file Instance.cs.

    - -

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

    +

    Definition at line 38 of file Instance.cs.

    +
    38 { get; set; }
    +

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

    - + +

    ◆ Id

    +
    @@ -234,15 +218,17 @@ Properties
    -

    The id of the Instance. Not modifiable

    +

    The id of the Instance. Not modifiable

    -

    Definition at line 14 of file Instance.cs.

    - -

    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.InstanceUserController.Delete(), Tgstation.Server.Host.Controllers.RepositoryController.Delete(), Tgstation.Server.Host.Controllers.DreamMakerController.GetId(), Tgstation.Server.Host.Controllers.InstanceUserController.GetId(), Tgstation.Server.Client.InstanceManagerClient.InstanceManagerClient(), 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.Host.Controllers.DreamMakerController.Read(), Tgstation.Server.Host.Controllers.RepositoryController.Read(), Tgstation.Server.Host.Controllers.DreamDaemonController.ReadImpl(), Tgstation.Server.Host.Core.JobManager.RunJob(), Tgstation.Server.Host.Components.Instance.TimerLoop(), 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().

    +

    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.InstanceUserController.Delete(), Tgstation.Server.Host.Controllers.RepositoryController.Delete(), Tgstation.Server.Host.Controllers.DreamMakerController.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.Host.Controllers.DreamMakerController.Read(), Tgstation.Server.Client.Components.ConfigurationClient.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().

    - + +

    ◆ MoveJob

    +
    @@ -260,14 +246,16 @@ Properties
    -

    The Job representing a change of Path

    -

    Due to how Jobs are children of Instances but moving one requires the Instance to be offline, interactions with this Job are performed in a non-standard fashion. The Job is read by querying the Instance again (either via list or ID lookup) and cancelled by making any sort of update to the Instance. Once the Instance comes back Online it can be queried like a normal job

    - -

    Definition at line 51 of file Instance.cs.

    +

    The Job representing a change of Path

    +

    Due to how Jobs are children of Instances but moving one requires the Instance to be offline, interactions with this Job are performed in a non-standard fashion. The Job is read by querying the Instance again (either via list or ID lookup) and cancelled by making any sort of update to the Instance. Once the Instance comes back Online it can be queried like a normal job

    +

    Definition at line 51 of file Instance.cs.

    +
    51 { get; set; }
    - + +

    ◆ Name

    +
    @@ -285,13 +273,15 @@ Properties
    -

    The name of the Instance

    - -

    Definition at line 20 of file Instance.cs.

    +

    The name of the Instance

    +

    Definition at line 20 of file Instance.cs.

    +
    20 { get; set; }
    - + +

    ◆ Online

    +
    @@ -299,7 +289,7 @@ Properties @@ -309,13 +299,15 @@ Properties
    - +
    bool Tgstation.Server.Api.Models.Instance.Onlinebool? Tgstation.Server.Api.Models.Instance.Online
    -

    If the Instance is online

    - -

    Definition at line 32 of file Instance.cs.

    +

    If the Instance is online

    +

    Definition at line 32 of file Instance.cs.

    +
    32 { get; set; }
    - + +

    ◆ Path

    +
    @@ -333,9 +325,11 @@ Properties
    -

    The path to where the Instance is located. Can only be changed while the Instance is offline. Must not exist when the instance is created

    +

    The path to where the Instance is located. Can only be changed while the Instance is offline. Must not exist when the instance is created

    -

    Definition at line 26 of file Instance.cs.

    +

    Definition at line 26 of file Instance.cs.

    +
    26 { get; set; }
    +

    Referenced by Tgstation.Server.Tests.Instance.ConfigurationTest.FileExists().

    @@ -347,7 +341,7 @@ Properties diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance_user-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance_user-members.html index 6051296567..1d1c2c96be 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance_user-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_instance_user-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + 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 64a740c286..c883edcc2b 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 @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Api.Models.InstanceUser Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + +
    -

    Represents a Users permissions in an Instance +

    Represents a Users permissions in an Instance More...

    Inheritance diagram for Tgstation.Server.Api.Models.InstanceUser:
    @@ -108,42 +84,44 @@ Inheritance diagram for Tgstation.Server.Api.Models.InstanceUser:
    Tgstation.Server.Host.Models.InstanceUser - -
    + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + +

    Properties

    long UserId [get, set]
     The Internal.User.Id of the User the InstanceUser belongs to More...
     
    InstanceUserRights InstanceUserRights [get, set]
     The Rights.InstanceUserRights of the InstanceUser More...
     
    ByondRights ByondRights [get, set]
     The Rights.ByondRights of the InstanceUser More...
     
    DreamDaemonRights DreamDaemonRights [get, set]
     The Rights.DreamDaemonRights of the InstanceUser More...
     
    DreamMakerRights DreamMakerRights [get, set]
     The Rights.DreamMakerRights of the InstanceUser More...
     
    RepositoryRights RepositoryRights [get, set]
     The Rights.RepositoryRights of the InstanceUser More...
     
    ChatBotRights ChatBotRights [get, set]
     The Rights.ChatBotRights of the InstanceUser More...
     
    ConfigurationRights ConfigurationRights [get, set]
     The Rights.ConfigurationRights of the InstanceUser More...
     
    long? UserId [get, set]
     The Internal.User.Id of the User the InstanceUser belongs to More...
     
    InstanceUserRightsInstanceUserRights [get, set]
     The Rights.InstanceUserRights of the InstanceUser More...
     
    ByondRightsByondRights [get, set]
     The Rights.ByondRights of the InstanceUser More...
     
    DreamDaemonRightsDreamDaemonRights [get, set]
     The Rights.DreamDaemonRights of the InstanceUser More...
     
    DreamMakerRightsDreamMakerRights [get, set]
     The Rights.DreamMakerRights of the InstanceUser More...
     
    RepositoryRightsRepositoryRights [get, set]
     The Rights.RepositoryRights of the InstanceUser More...
     
    ChatBotRightsChatBotRights [get, set]
     The Rights.ChatBotRights of the InstanceUser More...
     
    ConfigurationRightsConfigurationRights [get, set]
     The Rights.ConfigurationRights of the InstanceUser More...
     

    Detailed Description

    -

    Represents a Users permissions in an Instance

    +

    Represents a Users permissions in an Instance

    -

    Definition at line 9 of file InstanceUser.cs.

    +

    Definition at line 9 of file InstanceUser.cs.

    Property Documentation

    - + +

    ◆ ByondRights

    +
    @@ -151,7 +129,7 @@ Properties @@ -161,13 +139,15 @@ Properties
    - +
    ByondRights Tgstation.Server.Api.Models.InstanceUser.ByondRightsByondRights? Tgstation.Server.Api.Models.InstanceUser.ByondRights
    -

    The Rights.ByondRights of the InstanceUser

    - -

    Definition at line 27 of file InstanceUser.cs.

    +

    The Rights.ByondRights of the InstanceUser

    +

    Definition at line 27 of file InstanceUser.cs.

    +
    27 { get; set; }
    - + +

    ◆ ChatBotRights

    +
    @@ -175,7 +155,7 @@ Properties @@ -185,13 +165,15 @@ Properties
    - +
    ChatBotRights Tgstation.Server.Api.Models.InstanceUser.ChatBotRightsChatBotRights? Tgstation.Server.Api.Models.InstanceUser.ChatBotRights
    -

    The Rights.ChatBotRights of the InstanceUser

    - -

    Definition at line 51 of file InstanceUser.cs.

    +

    The Rights.ChatBotRights of the InstanceUser

    +

    Definition at line 51 of file InstanceUser.cs.

    +
    51 { get; set; }
    - + +

    ◆ ConfigurationRights

    +
    @@ -199,7 +181,7 @@ Properties @@ -209,13 +191,15 @@ Properties
    - +
    ConfigurationRights Tgstation.Server.Api.Models.InstanceUser.ConfigurationRightsConfigurationRights? Tgstation.Server.Api.Models.InstanceUser.ConfigurationRights
    -

    The Rights.ConfigurationRights of the InstanceUser

    - -

    Definition at line 57 of file InstanceUser.cs.

    +

    The Rights.ConfigurationRights of the InstanceUser

    +

    Definition at line 57 of file InstanceUser.cs.

    +
    57 { get; set; }
    - + +

    ◆ DreamDaemonRights

    +
    @@ -223,7 +207,7 @@ Properties @@ -233,13 +217,15 @@ Properties
    - +
    DreamDaemonRights Tgstation.Server.Api.Models.InstanceUser.DreamDaemonRightsDreamDaemonRights? Tgstation.Server.Api.Models.InstanceUser.DreamDaemonRights
    -

    The Rights.DreamDaemonRights of the InstanceUser

    - -

    Definition at line 33 of file InstanceUser.cs.

    +

    The Rights.DreamDaemonRights of the InstanceUser

    +

    Definition at line 33 of file InstanceUser.cs.

    +
    33 { get; set; }
    - + +

    ◆ DreamMakerRights

    +
    @@ -247,7 +233,7 @@ Properties @@ -257,15 +243,17 @@ Properties
    - +
    DreamMakerRights Tgstation.Server.Api.Models.InstanceUser.DreamMakerRightsDreamMakerRights? Tgstation.Server.Api.Models.InstanceUser.DreamMakerRights
    - + +

    ◆ InstanceUserRights

    +
    @@ -273,7 +261,7 @@ Properties @@ -283,13 +271,15 @@ Properties
    - +
    InstanceUserRights Tgstation.Server.Api.Models.InstanceUser.InstanceUserRightsInstanceUserRights? Tgstation.Server.Api.Models.InstanceUser.InstanceUserRights
    -

    The Rights.InstanceUserRights of the InstanceUser

    - -

    Definition at line 21 of file InstanceUser.cs.

    +

    The Rights.InstanceUserRights of the InstanceUser

    +

    Definition at line 21 of file InstanceUser.cs.

    +
    21 { get; set; }
    - + +

    ◆ RepositoryRights

    +
    @@ -297,7 +287,7 @@ Properties @@ -307,13 +297,15 @@ Properties
    - +
    RepositoryRights Tgstation.Server.Api.Models.InstanceUser.RepositoryRightsRepositoryRights? Tgstation.Server.Api.Models.InstanceUser.RepositoryRights
    -

    The Rights.RepositoryRights of the InstanceUser

    - -

    Definition at line 45 of file InstanceUser.cs.

    +

    The Rights.RepositoryRights of the InstanceUser

    +

    Definition at line 45 of file InstanceUser.cs.

    +
    45 { get; set; }
    - + +

    ◆ UserId

    +
    @@ -321,7 +313,7 @@ Properties @@ -331,12 +323,10 @@ Properties
    - +
    long Tgstation.Server.Api.Models.InstanceUser.UserIdlong? Tgstation.Server.Api.Models.InstanceUser.UserId
    -

    The Internal.User.Id of the User the InstanceUser belongs to

    - -

    Definition at line 15 of file InstanceUser.cs.

    - -

    Referenced by Tgstation.Server.Client.Components.InstanceUserClient.InstanceUserClient().

    +

    The Internal.User.Id of the User the InstanceUser belongs to

    +

    Definition at line 15 of file InstanceUser.cs.

    +
    15 { get; set; }

    The documentation for this class was generated from the following file:
      @@ -347,7 +337,7 @@ Properties diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_chat_bot-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_chat_bot-members.html index fe3fda1f4b..410b264810 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_chat_bot-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_chat_bot-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + + diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_chat_bot.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_chat_bot.html index de431772ee..58c3f88cad 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_chat_bot.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_chat_bot.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Api.Models.Internal.ChatBot Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + +
    @@ -109,9 +86,18 @@ Inheritance diagram for Tgstation.Server.Api.Models.Internal.ChatBot:
    Tgstation.Server.Api.Models.ChatBot Tgstation.Server.Host.Models.ChatBot - -
    + + + + + + + + + +

    +Public Member Functions

    ChatConnectionStringBuilder CreateConnectionStringBuilder ()
     Get the ChatConnectionStringBuilder which maps to the ConnectionString. More...
     
    void SetConnectionStringBuilder (ChatConnectionStringBuilder stringBuilder)
     Set the ChatConnectionStringBuilder for the ChatBot. Also updates the ConnectionString. More...
     
    @@ -120,25 +106,83 @@ Properties - - - - - - + + + + + + - + - - -

    Properties

    long Id [get, set]
    string Name [get, set]
     The name of the connection More...
     
    bool Enabled [get, set]
     If the connection is enabled More...
     
    ChatProvider Provider [get, set]
     The ChatProvider used for the connection More...
     
    bool? Enabled [get, set]
     If the connection is enabled More...
     
    ChatProviderProvider [get, set]
     The ChatProvider used for the connection More...
     
    string ConnectionString [get, set]
     The information used to connect to the Provider More...
     The information used to connect to the Provider More...
     
    ChatConnectionStringBuilder ConnectionStringBuilder [get, set]
     The ChatConnectionStringBuilder which maps to the ConnectionString More...
     

    Detailed Description

    Manage the server chat bots

    -

    Definition at line 10 of file ChatBot.cs.

    -

    Property Documentation

    - +

    Definition at line 9 of file ChatBot.cs.

    +

    Member Function Documentation

    + +

    ◆ CreateConnectionStringBuilder()

    + +
    +
    + + + + + + + +
    ChatConnectionStringBuilder Tgstation.Server.Api.Models.Internal.ChatBot.CreateConnectionStringBuilder ()
    +
    + +

    Get the ChatConnectionStringBuilder which maps to the ConnectionString.

    +
    Returns
    A ChatConnectionStringBuilder for the ChatBot.
    + +

    Definition at line 42 of file ChatBot.cs.

    +
    43  {
    44  if (ConnectionString == null)
    45  return null;
    46  switch (Provider)
    47  {
    48  case ChatProvider.Discord:
    49  return new DiscordConnectionStringBuilder(ConnectionString);
    50  case ChatProvider.Irc:
    51  return new IrcConnectionStringBuilder(ConnectionString);
    52  default:
    53  throw new InvalidOperationException("Invalid Provider!");
    54  }
    55  }
    string ConnectionString
    The information used to connect to the Provider
    Definition: ChatBot.cs:36
    +
    ChatProvider
    Represents a chat service provider
    Definition: ChatProvider.cs:6
    +
    ChatProvider? Provider
    The ChatProvider used for the connection
    Definition: ChatBot.cs:30
    +
    +

    References Tgstation.Server.Api.Models.Internal.ChatBot.ConnectionString, and Tgstation.Server.Api.Models.Internal.ChatBot.Provider.

    + +
    +
    + +

    ◆ SetConnectionStringBuilder()

    + +
    +
    + + + + + + + + +
    void Tgstation.Server.Api.Models.Internal.ChatBot.SetConnectionStringBuilder (ChatConnectionStringBuilder stringBuilder)
    +
    + +

    Set the ChatConnectionStringBuilder for the ChatBot. Also updates the ConnectionString.

    +
    Parameters
    + + +
    stringBuilderThe optional ChatConnectionStringBuilder.
    +
    +
    + +

    Definition at line 61 of file ChatBot.cs.

    +
    62  {
    63  ConnectionString = stringBuilder?.ToString();
    64  }
    string ConnectionString
    The information used to connect to the Provider
    Definition: ChatBot.cs:36
    +
    +

    References Tgstation.Server.Api.Models.Internal.ChatBot.ConnectionString, and Tgstation.Server.Api.Models.Internal.ChatConnectionStringBuilder.ToString().

    + +
    +
    +

    Property Documentation

    + +

    ◆ ConnectionString

    +
    @@ -156,13 +200,17 @@ Properties
    -

    The information used to connect to the Provider

    +

    The information used to connect to the Provider

    -

    Definition at line 37 of file ChatBot.cs.

    +

    Definition at line 36 of file ChatBot.cs.

    +
    36 { get; set; }
    +

    Referenced by Tgstation.Server.Api.Models.Internal.ChatBot.CreateConnectionStringBuilder(), and Tgstation.Server.Api.Models.Internal.ChatBot.SetConnectionStringBuilder().

    - + +

    ◆ Enabled

    +
    @@ -170,31 +218,7 @@ Properties - - -
    - - -
    ChatConnectionStringBuilder Tgstation.Server.Api.Models.Internal.ChatBot.ConnectionStringBuilder
    -
    -getset
    -
    - -

    The ChatConnectionStringBuilder which maps to the ConnectionString

    - -

    Definition at line 44 of file ChatBot.cs.

    - -
    -
    - -
    -
    - - - @@ -206,13 +230,15 @@ Properties

    If the connection is enabled

    -

    Definition at line 26 of file ChatBot.cs.

    - -

    Referenced by Tgstation.Server.Host.Components.Chat.Chat.ChangeSettings().

    +

    Definition at line 25 of file ChatBot.cs.

    +
    25 { get; set; }
    +

    Referenced by Tgstation.Server.Host.Components.Chat.Chat.ChangeSettings().

    - + +

    ◆ Id

    +
    - - - +
    bool Tgstation.Server.Api.Models.Internal.ChatBot.Enabledbool? Tgstation.Server.Api.Models.Internal.ChatBot.Enabled
    @@ -232,13 +258,15 @@ Properties

    The settings id

    -

    Definition at line 15 of file ChatBot.cs.

    - -

    Referenced by Tgstation.Server.Host.Components.Chat.Chat.ChangeSettings(), and Tgstation.Server.Client.Components.ChatBotsClient.ChatBotsClient().

    +

    Definition at line 14 of file ChatBot.cs.

    +
    14 { get; set; }
    +

    Referenced by Tgstation.Server.Host.Components.Chat.Chat.ChangeSettings().

    - + +

    ◆ Name

    +
    @@ -258,11 +286,13 @@ Properties

    The name of the connection

    -

    Definition at line 21 of file ChatBot.cs.

    +

    Definition at line 20 of file ChatBot.cs.

    +
    20 { get; set; }
    + + + +

    ◆ Provider

    - - -
    @@ -270,7 +300,7 @@ Properties @@ -280,9 +310,11 @@ Properties
    - +
    ChatProvider Tgstation.Server.Api.Models.Internal.ChatBot.ProviderChatProvider? Tgstation.Server.Api.Models.Internal.ChatBot.Provider
    -

    The ChatProvider used for the connection

    +

    The ChatProvider used for the connection

    -

    Definition at line 31 of file ChatBot.cs.

    +

    Definition at line 30 of file ChatBot.cs.

    +
    30 { get; set; }
    +

    Referenced by Tgstation.Server.Api.Models.Internal.ChatBot.CreateConnectionStringBuilder(), and Tgstation.Server.Api.Models.ChatBot.ValidateProviderChannelTypes().

    @@ -294,7 +326,7 @@ Properties diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_chat_connection_string_builder-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_chat_connection_string_builder-members.html index 32f72415e5..8e73c59191 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_chat_connection_string_builder-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_chat_connection_string_builder-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
    -

    Helper for building ChatBot.ConnectionStrings +

    Helper for building ChatBot.ConnectionStrings More...

    Inheritance diagram for Tgstation.Server.Api.Models.Internal.ChatConnectionStringBuilder:
    @@ -108,29 +84,31 @@ Inheritance diagram for Tgstation.Server.Api.Models.Internal.ChatConnectionStrin
    -Tgstation.Server.Api.Models.DiscordConnectionStringBuilder -Tgstation.Server.Api.Models.IrcConnectionStringBuilder - -
    +Tgstation.Server.Api.Models.DiscordConnectionStringBuilder +Tgstation.Server.Api.Models.IrcConnectionStringBuilder + +
    - +

    Public Member Functions

    abstract override string ToString ()
     Gets the ChatBot.ConnectionString associated with the ChatConnectionStringBuilder More...
     Gets the ChatBot.ConnectionString associated with the ChatConnectionStringBuilder More...
     
    - +

    Properties

    abstract bool Valid [get]
     If the ChatConnectionStringBuilder evaluates to a valid ChatBot.ConnectionString More...
     If the ChatConnectionStringBuilder evaluates to a valid ChatBot.ConnectionString More...
     

    Detailed Description

    -

    Helper for building ChatBot.ConnectionStrings

    +

    Helper for building ChatBot.ConnectionStrings

    -

    Definition at line 6 of file ChatConnectionStringBuilder.cs.

    +

    Definition at line 6 of file ChatConnectionStringBuilder.cs.

    Member Function Documentation

    - + +

    ◆ ToString()

    +

    Property Documentation

    - + +

    ◆ Valid

    +
    @@ -177,10 +159,10 @@ Properties
    -

    If the ChatConnectionStringBuilder evaluates to a valid ChatBot.ConnectionString

    - -

    Definition at line 11 of file ChatConnectionStringBuilder.cs.

    +

    If the ChatConnectionStringBuilder evaluates to a valid ChatBot.ConnectionString

    +

    Definition at line 11 of file ChatConnectionStringBuilder.cs.

    +
    11 { get; }

    The documentation for this class was generated from the following file:
      @@ -191,7 +173,7 @@ Properties diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_compile_job-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_compile_job-members.html index c374debeb1..c44b2d1443 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_compile_job-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_compile_job-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + + 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 34f2b3f80e..5aa89d807c 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 @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Api.Models.Internal.CompileJob Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + +
    -

    Represents a run of DreamMaker +

    Represents a run of DreamMaker More...

    Inheritance diagram for Tgstation.Server.Api.Models.Internal.CompileJob:
    @@ -109,8 +85,8 @@ Inheritance diagram for Tgstation.Server.Api.Models.Internal.CompileJob:
    Tgstation.Server.Api.Models.CompileJob Tgstation.Server.Host.Models.CompileJob - -
    + + @@ -123,19 +99,21 @@ Properties - - - - - - + + + + + +

    Properties

    string Output [get, set]
     Textual output of DM More...
     
    Guid DirectoryName [get, set]
     The Game folder the results were compiled into More...
     
    DreamDaemonSecurity MinimumSecurityLevel [get, set]
     The minimum DreamDaemonSecurity required to run the CompileJob's output More...
     
    Guid? DirectoryName [get, set]
     The Game folder the results were compiled into More...
     
    DreamDaemonSecurityMinimumSecurityLevel [get, set]
     The minimum DreamDaemonSecurity required to run the CompileJob's output More...
     

    Detailed Description

    -

    Represents a run of DreamMaker

    +

    Represents a run of DreamMaker

    -

    Definition at line 9 of file CompileJob.cs.

    +

    Definition at line 9 of file CompileJob.cs.

    Property Documentation

    - + +

    ◆ DirectoryName

    +
    @@ -143,7 +121,7 @@ Properties @@ -155,13 +133,15 @@ Properties

    The Game folder the results were compiled into

    -

    Definition at line 32 of file CompileJob.cs.

    - -

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

    +

    Definition at line 32 of file CompileJob.cs.

    +
    32 { get; set; }
    +

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

    - + +

    ◆ DmeName

    +
    - +
    Guid Tgstation.Server.Api.Models.Internal.CompileJob.DirectoryNameGuid? Tgstation.Server.Api.Models.Internal.CompileJob.DirectoryName
    @@ -181,11 +161,13 @@ Properties

    The .dme file used for compilation

    -

    Definition at line 20 of file CompileJob.cs.

    +

    Definition at line 20 of file CompileJob.cs.

    +
    20 { get; set; }
    + + + +

    ◆ Id

    - - -
    @@ -205,13 +187,15 @@ Properties

    The ID of the job

    -

    Definition at line 14 of file CompileJob.cs.

    - -

    Referenced by Tgstation.Server.Host.Components.Compiler.DmbFactory.CleanJob(), Tgstation.Server.Client.Components.DreamMakerClient.DreamMakerClient(), Tgstation.Server.Host.Components.Compiler.DmbFactory.FromCompileJob(), Tgstation.Server.Host.Components.Watchdog.Watchdog.HandlerMonitorWakeup(), and Tgstation.Server.Host.Components.Compiler.DmbFactory.LockNextDmb().

    +

    Definition at line 14 of file CompileJob.cs.

    +
    14 { get; set; }
    +

    Referenced by Tgstation.Server.Host.Components.Compiler.DmbFactory.CleanJob(), Tgstation.Server.Host.Components.Compiler.DmbFactory.FromCompileJob(), Tgstation.Server.Host.Components.Watchdog.Watchdog.HandlerMonitorWakeup(), and Tgstation.Server.Host.Components.Compiler.DmbFactory.LockNextDmb().

    - + +

    ◆ MinimumSecurityLevel

    +
    @@ -219,7 +203,7 @@ Properties @@ -229,15 +213,17 @@ Properties
    - +
    DreamDaemonSecurity Tgstation.Server.Api.Models.Internal.CompileJob.MinimumSecurityLevelDreamDaemonSecurity? Tgstation.Server.Api.Models.Internal.CompileJob.MinimumSecurityLevel
    -

    The minimum DreamDaemonSecurity required to run the CompileJob's output

    +

    The minimum DreamDaemonSecurity required to run the CompileJob's output

    -

    Definition at line 38 of file CompileJob.cs.

    - -

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

    +

    Definition at line 38 of file CompileJob.cs.

    +
    38 { get; set; }
    +

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

    - + +

    ◆ Output

    +
    @@ -257,8 +243,8 @@ Properties

    Textual output of DM

    -

    Definition at line 26 of file CompileJob.cs.

    - +

    Definition at line 26 of file CompileJob.cs.

    +
    26 { get; set; }

    The documentation for this class was generated from the following file:
      @@ -269,7 +255,7 @@ Properties diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_dream_daemon_launch_parameters-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_dream_daemon_launch_parameters-members.html index 9c8698386c..8ca2c60fd5 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_dream_daemon_launch_parameters-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_dream_daemon_launch_parameters-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + + 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 5ae8eb6ec3..1df74457bf 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 @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + +
    -

    Launch settings for DreamDaemon +

    Launch settings for DreamDaemon More...

    Inheritance diagram for Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters:
    @@ -108,11 +84,11 @@ Inheritance diagram for Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchPa
    -Tgstation.Server.Api.Models.Internal.DreamDaemonSettings -Tgstation.Server.Api.Models.DreamDaemon +Tgstation.Server.Api.Models.Internal.DreamDaemonSettings +Tgstation.Server.Api.Models.DreamDaemon Tgstation.Server.Host.Models.DreamDaemonSettings - -
    + +
    @@ -122,28 +98,30 @@ Public Member Functions

    Public Member Functions

    - - - - - - - - - - - - - - - + + + + + + + + + + + + + + +

    Properties

    bool AllowWebClient [get, set]
     If the BYOND web client can be used to connect to the game server More...
     
    DreamDaemonSecurity SecurityLevel [get, set]
     The DreamDaemonSecurity level of DreamDaemon More...
     
    ushort PrimaryPort [get, set]
     The first port DreamDaemon uses. This should be the publically advertised port More...
     
    ushort SecondaryPort [get, set]
     The second port DreamDaemon uses More...
     
    uint StartupTimeout [get, set]
     The DreamDaemon startup timeout in seconds More...
     
    bool? AllowWebClient [get, set]
     If the BYOND web client can be used to connect to the game server More...
     
    DreamDaemonSecuritySecurityLevel [get, set]
     The DreamDaemonSecurity level of DreamDaemon More...
     
    ushort? PrimaryPort [get, set]
     The first port DreamDaemon uses. This should be the publically advertised port More...
     
    ushort? SecondaryPort [get, set]
     The second port DreamDaemon uses More...
     
    uint? StartupTimeout [get, set]
     The DreamDaemon startup timeout in seconds More...
     

    Detailed Description

    -

    Launch settings for DreamDaemon

    +

    Launch settings for DreamDaemon

    -

    Definition at line 8 of file DreamDaemonLaunchParameters.cs.

    +

    Definition at line 9 of file DreamDaemonLaunchParameters.cs.

    Member Function Documentation

    - + +

    ◆ Match()

    +
    @@ -160,18 +138,20 @@ Properties

    Check if we match a given set of otherParameters

    Parameters
    - +
    otherParametersThe DreamDaemonLaunchParameters to compare against
    otherParametersThe DreamDaemonLaunchParameters to compare against
    -
    Returns
    if they match, otherwise
    +
    Returns
    true if they match, false otherwise
    -

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

    +

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

    Property Documentation

    - + +

    ◆ AllowWebClient

    +
    @@ -179,7 +159,7 @@ Properties @@ -191,13 +171,15 @@ Properties

    If the BYOND web client can be used to connect to the game server

    -

    Definition at line 14 of file DreamDaemonLaunchParameters.cs.

    - -

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

    +

    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().

    - + +

    ◆ PrimaryPort

    +
    - +
    bool Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters.AllowWebClientbool? Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters.AllowWebClient
    @@ -205,7 +187,7 @@ Properties @@ -215,15 +197,17 @@ Properties
    - +
    ushort Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters.PrimaryPortushort? Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters.PrimaryPort
    -

    The first port DreamDaemon uses. This should be the publically advertised port

    +

    The first port DreamDaemon uses. This should be the publically advertised port

    -

    Definition at line 26 of file DreamDaemonLaunchParameters.cs.

    - -

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

    +

    Definition at line 27 of file DreamDaemonLaunchParameters.cs.

    +
    27 { get; set; }
    +

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

    - + +

    ◆ SecondaryPort

    +
    @@ -231,7 +215,7 @@ Properties @@ -241,15 +225,17 @@ Properties
    - +
    ushort Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters.SecondaryPortushort? Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters.SecondaryPort
    - + +

    ◆ SecurityLevel

    +
    @@ -257,7 +243,7 @@ Properties @@ -267,15 +253,17 @@ Properties
    - +
    DreamDaemonSecurity Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters.SecurityLevelDreamDaemonSecurity? Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters.SecurityLevel
    - + +

    ◆ StartupTimeout

    +
    @@ -283,7 +271,7 @@ Properties @@ -293,11 +281,11 @@ Properties
    - +
    uint Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters.StartupTimeoutuint? Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters.StartupTimeout
    @@ -309,7 +297,7 @@ Properties diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_dream_daemon_settings-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_dream_daemon_settings-members.html index ced436326d..653c91e527 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_dream_daemon_settings-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_dream_daemon_settings-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + + 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 a3ac460543..a9bae1bb66 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 @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Api.Models.Internal.DreamDaemonSettings Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + +
    -

    Configurable settings for DreamDaemon +

    Configurable settings for DreamDaemon More...

    Inheritance diagram for Tgstation.Server.Api.Models.Internal.DreamDaemonSettings:
    @@ -107,53 +83,55 @@ Inheritance diagram for Tgstation.Server.Api.Models.Internal.DreamDaemonSettings
    -Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters -Tgstation.Server.Api.Models.DreamDaemon +Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters +Tgstation.Server.Api.Models.DreamDaemon Tgstation.Server.Host.Models.DreamDaemonSettings - -
    + +
    - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + +

    Properties

    bool AutoStart [get, set]
     If DreamDaemon starts when it's Instance starts More...
     
    bool SoftRestart [get, set]
     If the server is undergoing a soft reset. This may be automatically set by changes to other fields More...
     
    bool SoftShutdown [get, set]
     If the server is undergoing a soft shutdown More...
     
    bool? AutoStart [get, set]
     If DreamDaemon starts when it's Instance starts More...
     
    bool? SoftRestart [get, set]
     If the server is undergoing a soft reset. This may be automatically set by changes to other fields More...
     
    bool? SoftShutdown [get, set]
     If the server is undergoing a soft shutdown More...
     
    - Properties inherited from Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters
    bool AllowWebClient [get, set]
     If the BYOND web client can be used to connect to the game server More...
     
    DreamDaemonSecurity SecurityLevel [get, set]
     The DreamDaemonSecurity level of DreamDaemon More...
     
    ushort PrimaryPort [get, set]
     The first port DreamDaemon uses. This should be the publically advertised port More...
     
    ushort SecondaryPort [get, set]
     The second port DreamDaemon uses More...
     
    uint StartupTimeout [get, set]
     The DreamDaemon startup timeout in seconds More...
     
    bool? AllowWebClient [get, set]
     If the BYOND web client can be used to connect to the game server More...
     
    DreamDaemonSecuritySecurityLevel [get, set]
     The DreamDaemonSecurity level of DreamDaemon More...
     
    ushort? PrimaryPort [get, set]
     The first port DreamDaemon uses. This should be the publically advertised port More...
     
    ushort? SecondaryPort [get, set]
     The second port DreamDaemon uses More...
     
    uint? StartupTimeout [get, set]
     The DreamDaemon startup timeout in seconds More...
     
    - +

    Additional Inherited Members

    - Public Member Functions inherited from Tgstation.Server.Api.Models.Internal.DreamDaemonLaunchParameters
    bool Match (DreamDaemonLaunchParameters otherParameters)
     Check if we match a given set of otherParameters More...
     Check if we match a given set of otherParameters More...
     

    Detailed Description

    -

    Configurable settings for DreamDaemon

    +

    Configurable settings for DreamDaemon

    -

    Definition at line 8 of file DreamDaemonSettings.cs.

    +

    Definition at line 8 of file DreamDaemonSettings.cs.

    Property Documentation

    - + +

    ◆ AutoStart

    +
    @@ -161,7 +139,7 @@ Additional Inherited Members @@ -171,15 +149,17 @@ Additional Inherited Members
    - +
    bool Tgstation.Server.Api.Models.Internal.DreamDaemonSettings.AutoStartbool? Tgstation.Server.Api.Models.Internal.DreamDaemonSettings.AutoStart
    - + +

    ◆ SoftRestart

    +
    @@ -187,7 +167,7 @@ Additional Inherited Members @@ -199,11 +179,13 @@ Additional Inherited Members

    If the server is undergoing a soft reset. This may be automatically set by changes to other fields

    -

    Definition at line 20 of file DreamDaemonSettings.cs.

    +

    Definition at line 20 of file DreamDaemonSettings.cs.

    +
    20 { get; set; }
    + + + +

    ◆ SoftShutdown

    - - -
    - +
    bool Tgstation.Server.Api.Models.Internal.DreamDaemonSettings.SoftRestartbool? Tgstation.Server.Api.Models.Internal.DreamDaemonSettings.SoftRestart
    @@ -211,7 +193,7 @@ Additional Inherited Members @@ -223,8 +205,8 @@ Additional Inherited Members

    If the server is undergoing a soft shutdown

    -

    Definition at line 26 of file DreamDaemonSettings.cs.

    - +

    Definition at line 26 of file DreamDaemonSettings.cs.

    +
    26 { get; set; }

    The documentation for this class was generated from the following file:
      @@ -235,7 +217,7 @@ Additional Inherited Members diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_job-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_job-members.html index e69f39f382..2690a2efdb 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_job-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_job-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - +
    bool Tgstation.Server.Api.Models.Internal.DreamDaemonSettings.SoftShutdownbool? Tgstation.Server.Api.Models.Internal.DreamDaemonSettings.SoftShutdown
    - + - - + + + + 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 bcc6b80746..2c9df2e90c 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 @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Api.Models.Internal.Job Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + +
    -Tgstation.Server.Api.Models.Job +Tgstation.Server.Api.Models.Job Tgstation.Server.Host.Models.Job - -
    + +
    - + - + - + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + +

    Properties

    long Id [get, set]
     The Job ID More...
     The Job ID More...
     
    string Description [get, set]
     English description of the Job More...
     English description of the Job More...
     
    string ExceptionDetails [get, set]
     Details of any exceptions caught during the Job More...
     Details of any exceptions caught during the Job More...
     
    DateTimeOffset StartedAt [get, set]
     When the Job was started More...
     
    DateTimeOffset StoppedAt [get, set]
     When the Job stopped More...
     
    bool Cancelled [get, set]
     If the Job was cancelled More...
     
    RightsType CancelRightsType [get, set]
     The RightsType of CancelRight if it can be cancelled More...
     
    ulong CancelRight [get, set]
     The Rights required to cancel the Job More...
     
    DateTimeOffset? StartedAt [get, set]
     When the Job was started More...
     
    DateTimeOffset? StoppedAt [get, set]
     When the Job stopped More...
     
    bool? Cancelled [get, set]
     If the Job was cancelled More...
     
    RightsTypeCancelRightsType [get, set]
     The RightsType of CancelRight if it can be cancelled More...
     
    ulong? CancelRight [get, set]
     The Rights required to cancel the Job More...
     

    Detailed Description

    Represents a long running job

    -

    Definition at line 10 of file Job.cs.

    +

    Definition at line 10 of file Job.cs.

    Property Documentation

    - + +

    ◆ Cancelled

    +
    @@ -152,7 +130,7 @@ Properties @@ -162,15 +140,17 @@ Properties
    - +
    bool Tgstation.Server.Api.Models.Internal.Job.Cancelledbool? Tgstation.Server.Api.Models.Internal.Job.Cancelled
    -

    If the Job was cancelled

    +

    If the Job was cancelled

    -

    Definition at line 43 of file Job.cs.

    - -

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

    +

    Definition at line 43 of file Job.cs.

    +
    43 { get; set; }
    +

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

    - + +

    ◆ CancelRight

    +
    @@ -178,7 +158,7 @@ Properties @@ -188,13 +168,15 @@ Properties
    - +
    ulong Tgstation.Server.Api.Models.Internal.Job.CancelRightulong? Tgstation.Server.Api.Models.Internal.Job.CancelRight
    -

    The Rights required to cancel the Job

    - -

    Definition at line 53 of file Job.cs.

    +

    The Rights required to cancel the Job

    +

    Definition at line 53 of file Job.cs.

    +
    53 { get; set; }
    - + +

    ◆ CancelRightsType

    +
    @@ -202,7 +184,7 @@ Properties @@ -212,13 +194,15 @@ Properties
    - +
    RightsType Tgstation.Server.Api.Models.Internal.Job.CancelRightsTypeRightsType? Tgstation.Server.Api.Models.Internal.Job.CancelRightsType
    -

    The RightsType of CancelRight if it can be cancelled

    - -

    Definition at line 48 of file Job.cs.

    +

    The RightsType of CancelRight if it can be cancelled

    +

    Definition at line 48 of file Job.cs.

    +
    48 { get; set; }
    - + +

    ◆ Description

    +
    @@ -236,15 +220,15 @@ Properties
    -

    English description of the Job

    - -

    Definition at line 21 of file Job.cs.

    - -

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

    +

    English description of the Job

    +

    Definition at line 21 of file Job.cs.

    +
    21 { get; set; }
    - + +

    ◆ ExceptionDetails

    +
    @@ -262,15 +246,17 @@ Properties
    -

    Details of any exceptions caught during the Job

    +

    Details of any exceptions caught during the Job

    -

    Definition at line 26 of file Job.cs.

    - -

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

    +

    Definition at line 26 of file Job.cs.

    +
    26 { get; set; }
    +

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

    - + +

    ◆ Id

    + - + +

    ◆ StartedAt

    +
    @@ -304,7 +292,7 @@ Properties @@ -314,15 +302,15 @@ Properties
    - +
    DateTimeOffset Tgstation.Server.Api.Models.Internal.Job.StartedAtDateTimeOffset? Tgstation.Server.Api.Models.Internal.Job.StartedAt
    -

    When the Job was started

    - -

    Definition at line 32 of file Job.cs.

    - -

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

    +

    When the Job was started

    +

    Definition at line 32 of file Job.cs.

    +
    32 { get; set; }
    - + +

    ◆ StoppedAt

    +
    @@ -330,7 +318,7 @@ Properties @@ -340,11 +328,11 @@ Properties
    - +
    DateTimeOffset Tgstation.Server.Api.Models.Internal.Job.StoppedAtDateTimeOffset? Tgstation.Server.Api.Models.Internal.Job.StoppedAt
    -

    When the Job stopped

    +

    When the Job stopped

    -

    Definition at line 37 of file Job.cs.

    - -

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

    +

    Definition at line 37 of file Job.cs.

    +
    37 { get; set; }
    +

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

    @@ -356,7 +344,7 @@ Properties diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_repository_settings-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_repository_settings-members.html index 0e6c8b7fef..7147b9b978 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_repository_settings-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_repository_settings-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + 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 f0d8855e46..07e1171718 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 @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Api.Models.Internal.RepositorySettings Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + +
    -

    Represents configurable settings for a Repository +

    Represents configurable settings for a Repository More...

    Inheritance diagram for Tgstation.Server.Api.Models.Internal.RepositorySettings:
    @@ -107,10 +83,10 @@ Inheritance diagram for Tgstation.Server.Api.Models.Internal.RepositorySettings:
    -Tgstation.Server.Api.Models.Repository +Tgstation.Server.Api.Models.Repository Tgstation.Server.Host.Models.RepositorySettings - -
    + +
    @@ -126,28 +102,30 @@ Properties - - - - - - - - - - - - - - - + + + + + + + + + + + + + + +

    Properties

    string AccessToken [get, set]
     The token/password to access the git repository with More...
     
    bool PushTestMergeCommits [get, set]
     If commits created from testmerges are pushed to the remote More...
     
    bool ShowTestMergeCommitters [get, set]
     If test merge commits are signed with the username of the person who merged it. Note this only affects future commits More...
     
    bool AutoUpdatesKeepTestMerges [get, set]
     If test merge commits should be kept when auto updating. May cause merge conflicts which will block the update More...
     
    bool AutoUpdatesSynchronize [get, set]
     If synchronization should occur when auto updating More...
     
    bool PostTestMergeComment [get, set]
     If test merging should create a comment More...
     
    bool? PushTestMergeCommits [get, set]
     If commits created from testmerges are pushed to the remote More...
     
    bool? ShowTestMergeCommitters [get, set]
     If test merge commits are signed with the username of the person who merged it. Note this only affects future commits More...
     
    bool? AutoUpdatesKeepTestMerges [get, set]
     If test merge commits should be kept when auto updating. May cause merge conflicts which will block the update More...
     
    bool? AutoUpdatesSynchronize [get, set]
     If synchronization should occur when auto updating More...
     
    bool? PostTestMergeComment [get, set]
     If test merging should create a comment More...
     

    Detailed Description

    -

    Represents configurable settings for a Repository

    +

    Represents configurable settings for a Repository

    -

    Definition at line 8 of file RepositorySettings.cs.

    +

    Definition at line 8 of file RepositorySettings.cs.

    Property Documentation

    - + +

    ◆ AccessToken

    +
    @@ -167,13 +145,15 @@ Properties

    The token/password to access the git repository with

    -

    Definition at line 30 of file RepositorySettings.cs.

    - -

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

    +

    Definition at line 30 of file RepositorySettings.cs.

    +
    30 { get; set; }
    +

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

    - + +

    ◆ AccessUser

    +
    @@ -193,11 +173,13 @@ Properties

    The username to access the git repository with

    -

    Definition at line 25 of file RepositorySettings.cs.

    +

    Definition at line 25 of file RepositorySettings.cs.

    +
    25 { get; set; }
    + + + +

    ◆ AutoUpdatesKeepTestMerges

    - - -
    @@ -205,7 +187,7 @@ Properties @@ -217,11 +199,13 @@ Properties

    If test merge commits should be kept when auto updating. May cause merge conflicts which will block the update

    -

    Definition at line 48 of file RepositorySettings.cs.

    +

    Definition at line 48 of file RepositorySettings.cs.

    +
    48 { get; set; }
    + + + +

    ◆ AutoUpdatesSynchronize

    - - -
    - +
    bool Tgstation.Server.Api.Models.Internal.RepositorySettings.AutoUpdatesKeepTestMergesbool? Tgstation.Server.Api.Models.Internal.RepositorySettings.AutoUpdatesKeepTestMerges
    @@ -229,7 +213,7 @@ Properties @@ -241,11 +225,13 @@ Properties

    If synchronization should occur when auto updating

    -

    Definition at line 54 of file RepositorySettings.cs.

    +

    Definition at line 54 of file RepositorySettings.cs.

    +
    54 { get; set; }
    + + + +

    ◆ CommitterEmail

    - - -
    - +
    bool Tgstation.Server.Api.Models.Internal.RepositorySettings.AutoUpdatesSynchronizebool? Tgstation.Server.Api.Models.Internal.RepositorySettings.AutoUpdatesSynchronize
    @@ -265,11 +251,13 @@ Properties

    The e-mail of the committer

    -

    Definition at line 20 of file RepositorySettings.cs.

    +

    Definition at line 20 of file RepositorySettings.cs.

    +
    20 { get; set; }
    + + + +

    ◆ CommitterName

    - - -
    @@ -289,11 +277,13 @@ Properties

    The name of the committer

    -

    Definition at line 14 of file RepositorySettings.cs.

    +

    Definition at line 14 of file RepositorySettings.cs.

    +
    14 { get; set; }
    + + + +

    ◆ PostTestMergeComment

    - - -
    @@ -301,7 +291,7 @@ Properties @@ -313,11 +303,13 @@ Properties

    If test merging should create a comment

    -

    Definition at line 60 of file RepositorySettings.cs.

    +

    Definition at line 60 of file RepositorySettings.cs.

    +
    60 { get; set; }
    + + + +

    ◆ PushTestMergeCommits

    - - -
    - +
    bool Tgstation.Server.Api.Models.Internal.RepositorySettings.PostTestMergeCommentbool? Tgstation.Server.Api.Models.Internal.RepositorySettings.PostTestMergeComment
    @@ -325,7 +317,7 @@ Properties @@ -337,11 +329,13 @@ Properties

    If commits created from testmerges are pushed to the remote

    -

    Definition at line 36 of file RepositorySettings.cs.

    +

    Definition at line 36 of file RepositorySettings.cs.

    +
    36 { get; set; }
    + + + +

    ◆ ShowTestMergeCommitters

    - - -
    - +
    bool Tgstation.Server.Api.Models.Internal.RepositorySettings.PushTestMergeCommitsbool? Tgstation.Server.Api.Models.Internal.RepositorySettings.PushTestMergeCommits
    @@ -349,7 +343,7 @@ Properties @@ -361,8 +355,8 @@ Properties

    If test merge commits are signed with the username of the person who merged it. Note this only affects future commits

    -

    Definition at line 42 of file RepositorySettings.cs.

    - +

    Definition at line 42 of file RepositorySettings.cs.

    +
    42 { get; set; }

    The documentation for this class was generated from the following file:
      @@ -373,7 +367,7 @@ Properties diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_revision_information-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_revision_information-members.html index 8ceb5bdec6..99c9fd0d35 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_revision_information-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_revision_information-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - +
    bool Tgstation.Server.Api.Models.Internal.RepositorySettings.ShowTestMergeCommittersbool? Tgstation.Server.Api.Models.Internal.RepositorySettings.ShowTestMergeCommitters
    - + - - + + + + - + - - + + + +
    Tgstation.Server.Api.Models.RevisionInformation Tgstation.Server.Host.Models.RevisionInformation - -
    + +
    @@ -124,9 +100,11 @@ Properties

    Detailed Description

    Represents information about a current git revison

    -

    Definition at line 8 of file RevisionInformation.cs.

    +

    Definition at line 8 of file RevisionInformation.cs.

    Property Documentation

    - + +

    ◆ CommitSha

    +

    Properties

    @@ -146,13 +124,15 @@ Properties

    The revision sha

    -

    Definition at line 15 of file RevisionInformation.cs.

    - -

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

    +

    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().

    - + +

    ◆ OriginCommitSha

    +
    @@ -172,9 +152,9 @@ Properties

    The sha of the most recent remote commit

    -

    Definition at line 22 of file RevisionInformation.cs.

    - -

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

    +

    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().

    @@ -186,7 +166,7 @@ Properties diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_test_merge-members.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_test_merge-members.html index 7bf7b324e0..4c5d5de6a6 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_test_merge-members.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_test_merge-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + +
    CommentTgstation.Server.Api.Models.TestMergeParameters IdTgstation.Server.Api.Models.Internal.TestMerge MergedAtTgstation.Server.Api.Models.Internal.TestMerge - NumberTgstation.Server.Api.Models.TestMergeParameters + NumberTgstation.Server.Api.Models.TestMergeParameters PullRequestRevisionTgstation.Server.Api.Models.TestMergeParameters TestMergeBase()Tgstation.Server.Api.Models.Internal.TestMergeBaseprotected TestMergeBase(TestMergeBase copy)Tgstation.Server.Api.Models.Internal.TestMergeBaseprotected @@ -114,7 +90,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_test_merge.html b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_test_merge.html index 46208e99b3..068e0e25e1 100644 --- a/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_test_merge.html +++ b/class_tgstation_1_1_server_1_1_api_1_1_models_1_1_internal_1_1_test_merge.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Api.Models.Internal.TestMerge Class Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + +
    -Tgstation.Server.Api.Models.Internal.TestMergeBase -Tgstation.Server.Api.Models.TestMergeParameters +Tgstation.Server.Api.Models.Internal.TestMergeBase +Tgstation.Server.Api.Models.TestMergeParameters Tgstation.Server.Api.Models.TestMerge Tgstation.Server.Host.Models.TestMerge - -
    + + - + - + - + - + - + - + - - - + + + - + - +

    Properties

    long Id [get, set]
     The ID of the TestMerge More...
     The ID of the TestMerge More...
     
    DateTimeOffset MergedAt [get, set]
     When the TestMerge was created More...
     When the TestMerge was created More...
     
    - Properties inherited from Tgstation.Server.Api.Models.Internal.TestMergeBase
    string TitleAtMerge [get, set]
     The title of the pull request More...
     The title of the pull request More...
     
    string BodyAtMerge [get, set]
     The body of the pull request More...
     The body of the pull request More...
     
    string Url [get, set]
     The URL of the pull request More...
     The URL of the pull request More...
     
    string Author [get, set]
     The author of the pull request More...
     The author of the pull request More...
     
    - Properties inherited from Tgstation.Server.Api.Models.TestMergeParameters
    int Number [get, set]
     The number of the pull request More...
     
    int? Number [get, set]
     The number of the pull request More...
     
    string PullRequestRevision [get, set]
     The sha of the pull request revision to merge. If not specified, the latest commit shall be used (semi-unsafe) More...
     The sha of the pull request revision to merge. If not specified, the latest commit shall be used (semi-unsafe) More...
     
    string Comment [get, set]
     Optional comment about the test More...
     Optional comment about the test More...
     
    - + - +

    Additional Inherited Members

    - Protected Member Functions inherited from Tgstation.Server.Api.Models.Internal.TestMergeBase
     TestMergeBase ()
     Construct a TestMergeBase More...
     Construct a TestMergeBase More...
     
     TestMergeBase (TestMergeBase copy)
     Construct a TestMergeBase from a copy More...
     Construct a TestMergeBase from a copy More...
     

    Detailed Description

    Represents a merge of a GitHub pull request

    -

    Definition at line 9 of file TestMerge.cs.

    +

    Definition at line 9 of file TestMerge.cs.

    Property Documentation

    - + +

    ◆ Id

    +
    @@ -179,13 +157,15 @@ Additional Inherited Members
    -

    The ID of the TestMerge

    - -

    Definition at line 14 of file TestMerge.cs.

    +

    The ID of the TestMerge

    +

    Definition at line 14 of file TestMerge.cs.

    +
    14 { get; set; }
    - + +

    ◆ MergedAt

    +
    @@ -203,10 +183,10 @@ Additional Inherited Members
    -

    When the TestMerge was created

    - -

    Definition at line 20 of file TestMerge.cs.

    +

    When the TestMerge was created

    +

    Definition at line 20 of file TestMerge.cs.

    +
    20 { get; set; }

    The documentation for this class was generated from the following file:
    -
    Release Directory Reference
    +
    Debug Directory Reference
    - +

    Directories

    directory  netcoreapp2.1
    directory  netcoreapp2.1
     
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_0c9add60ab05c04ed8367ecaedf67c01.html b/dir_0c9add60ab05c04ed8367ecaedf67c01.html index c2aff7f542..cabeec09e4 100644 --- a/dir_0c9add60ab05c04ed8367ecaedf67c01.html +++ b/dir_0c9add60ab05c04ed8367ecaedf67c01.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models/Migrations Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
    diff --git a/dir_0de875c2ee7edd4009e892c5045f7b3a.html b/dir_0de875c2ee7edd4009e892c5045f7b3a.html index 0f9a4d8c05..7c52c77709 100644 --- a/dir_0de875c2ee7edd4009e892c5045f7b3a.html +++ b/dir_0de875c2ee7edd4009e892c5045f7b3a.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Core Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
      file  SetupWizard.cs [code]   +file  TaskExtensions.cs [code]
    diff --git a/dir_0f5073360b9ba6d1522457c65eebe36a.html b/dir_0f5073360b9ba6d1522457c65eebe36a.html index d74e7eaf9f..e4597866e7 100644 --- a/dir_0f5073360b9ba6d1522457c65eebe36a.html +++ b/dir_0f5073360b9ba6d1522457c65eebe36a.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Interop Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
    diff --git a/dir_103b33cf1ab7043de6f87dfa61afa23f.html b/dir_103b33cf1ab7043de6f87dfa61afa23f.html index aa10758ae0..dfe8735c5e 100644 --- a/dir_103b33cf1ab7043de6f87dfa61afa23f.html +++ b/dir_103b33cf1ab7043de6f87dfa61afa23f.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Watchdog.Tests/obj Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +

    Directories

    -directory  Release +directory  Debug  
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_b2c89c850c962495793d09ea3a2ee385.html b/dir_1083fcf52a7d94a2efffb6ca88246acf.html similarity index 67% rename from dir_b2c89c850c962495793d09ea3a2ee385.html rename to dir_1083fcf52a7d94a2efffb6ca88246acf.html index 9e631c4d68..e49824d27c 100644 --- a/dir_b2c89c850c962495793d09ea3a2ee385.html +++ b/dir_1083fcf52a7d94a2efffb6ca88246acf.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Console.Tests/obj/Release/netcoreapp2.1 Directory Reference + + +tgstation-server: tests/Tgstation.Server.Host.Console.Tests/obj/Debug/netcoreapp2.1 Directory Reference - @@ -33,41 +31,22 @@ - + - - + + + +
    @@ -105,7 +84,7 @@ Files diff --git a/dir_1302441b003a340c6a16c9bc1b51c94e.html b/dir_1302441b003a340c6a16c9bc1b51c94e.html index aa6d4b621c..91b0981e53 100644 --- a/dir_1302441b003a340c6a16c9bc1b51c94e.html +++ b/dir_1302441b003a340c6a16c9bc1b51c94e.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Core Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_177c182c6d1f29bec543c3fdad3072d5.html b/dir_177c182c6d1f29bec543c3fdad3072d5.html index c5f1f80c35..dbe78e282c 100644 --- a/dir_177c182c6d1f29bec543c3fdad3072d5.html +++ b/dir_177c182c6d1f29bec543c3fdad3072d5.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/obj Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +

    Directories

    -directory  Release +directory  Debug  
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_18f2820c1d411453d7d989b812e41820.html b/dir_18f2820c1d411453d7d989b812e41820.html new file mode 100644 index 0000000000..b4d1bc8c59 --- /dev/null +++ b/dir_18f2820c1d411453d7d989b812e41820.html @@ -0,0 +1,88 @@ + + + + + + + +tgstation-server: src/Tgstation.Server.Host.Service/obj/Debug/net471/win Directory Reference + + + + + + + + + +
    +
    + + + + + + + +
    +
    tgstation-server +
    +
    The /tg/station 13 server suite
    +
    +
    + + + + + + + + +
    +
    + + +
    + +
    + + +
    +
    +
    +
    win Directory Reference
    +
    + + + + + diff --git a/dir_1cebbc1bce26b60bfb2ee26c80f86b02.html b/dir_1cebbc1bce26b60bfb2ee26c80f86b02.html index 89fa3f5688..6ea3acfc41 100644 --- a/dir_1cebbc1bce26b60bfb2ee26c80f86b02.html +++ b/dir_1cebbc1bce26b60bfb2ee26c80f86b02.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Service/Properties Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +

    Files

    -file  AssemblyInfo.cs [code] +file  AssemblyInfo.cs [code]  
    @@ -103,7 +82,7 @@ Files diff --git a/dir_2133157f8312226ef9ea4ce42a802cf8.html b/dir_2133157f8312226ef9ea4ce42a802cf8.html index fd037e722b..c5fb7a5057 100644 --- a/dir_2133157f8312226ef9ea4ce42a802cf8.html +++ b/dir_2133157f8312226ef9ea4ce42a802cf8.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Components Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
    diff --git a/dir_53aae571c66a052729f8e64ccc397130.html b/dir_2553b13cbb871373b0c30fb90d66217c.html similarity index 65% rename from dir_53aae571c66a052729f8e64ccc397130.html rename to dir_2553b13cbb871373b0c30fb90d66217c.html index 41068033a6..1978232120 100644 --- a/dir_53aae571c66a052729f8e64ccc397130.html +++ b/dir_2553b13cbb871373b0c30fb90d66217c.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Tests/obj/Release/netcoreapp2.1 Directory Reference + + +tgstation-server: tests/Tgstation.Server.Host.Tests/obj/Debug/netcoreapp2.1 Directory Reference - @@ -33,41 +31,22 @@
    - + - - + + + +
    @@ -105,7 +84,7 @@ Files diff --git a/dir_26764abc66ddba24c5915db53fd68d23.html b/dir_26764abc66ddba24c5915db53fd68d23.html new file mode 100644 index 0000000000..29c5341f8d --- /dev/null +++ b/dir_26764abc66ddba24c5915db53fd68d23.html @@ -0,0 +1,88 @@ + + + + + + + +tgstation-server: src/Tgstation.Server.Host.Service/obj/Debug Directory Reference + + + + + + + + + +
    +
    + + + + + + + +
    +
    tgstation-server +
    +
    The /tg/station 13 server suite
    +
    +
    + + + + + + + + +
    +
    + + +
    + +
    + + +
    +
    +
    +
    Debug Directory Reference
    +
    +
    + + + + +

    +Directories

    directory  net471
     
    +
    + + + + diff --git a/dir_90400719279795a0c5ea912516a4c874.html b/dir_2b9d136d9ffdab429a63a74fca28b300.html similarity index 59% rename from dir_90400719279795a0c5ea912516a4c874.html rename to dir_2b9d136d9ffdab429a63a74fca28b300.html index 80c2dd4c01..a3a167a310 100644 --- a/dir_90400719279795a0c5ea912516a4c874.html +++ b/dir_2b9d136d9ffdab429a63a74fca28b300.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Host/obj/Release Directory Reference + + +tgstation-server: src/Tgstation.Server.Host/obj/Debug Directory Reference - @@ -33,41 +31,22 @@
    - + - - + + + +
    -
    Release Directory Reference
    +
    Debug Directory Reference
    - +

    Directories

    directory  netcoreapp2.1
    directory  netcoreapp2.1
     
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_ec133cefc1442f53ec97e0d7a57cf129.html b/dir_2e39d68cad3f83629c74ea67329dead9.html similarity index 59% rename from dir_ec133cefc1442f53ec97e0d7a57cf129.html rename to dir_2e39d68cad3f83629c74ea67329dead9.html index c66705fb2e..880d78f25d 100644 --- a/dir_ec133cefc1442f53ec97e0d7a57cf129.html +++ b/dir_2e39d68cad3f83629c74ea67329dead9.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tools/ReleaseNotes/obj/Release Directory Reference + + +tgstation-server: tools/ReleaseNotes/obj/Debug Directory Reference - @@ -33,41 +31,22 @@ - + - - + + + +
    -
    Release Directory Reference
    +
    Debug Directory Reference
    - +

    Directories

    directory  netcoreapp2.1
    directory  netcoreapp2.1
     
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_7ae0efc0613c36c848fa310214e0aee3.html b/dir_2e67631cb23401d696bcfdbe81f86f0f.html similarity index 59% rename from dir_7ae0efc0613c36c848fa310214e0aee3.html rename to dir_2e67631cb23401d696bcfdbe81f86f0f.html index 6f771886e7..62db505c90 100644 --- a/dir_7ae0efc0613c36c848fa310214e0aee3.html +++ b/dir_2e67631cb23401d696bcfdbe81f86f0f.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Api/obj/Release Directory Reference + + +tgstation-server: src/Tgstation.Server.Api/obj/Debug Directory Reference - @@ -33,41 +31,22 @@ - + - - + + + +
    -
    Release Directory Reference
    +
    Debug Directory Reference
    - +

    Directories

    directory  netstandard2.0
    directory  netstandard2.0
     
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_2ea2465064f3ff030c6dd6700a328d91.html b/dir_2ea2465064f3ff030c6dd6700a328d91.html index 649b91cc6b..07d1660ae2 100644 --- a/dir_2ea2465064f3ff030c6dd6700a328d91.html +++ b/dir_2ea2465064f3ff030c6dd6700a328d91.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
    diff --git a/dir_34761767c1c3cd212f9d2f80ea0828a8.html b/dir_34761767c1c3cd212f9d2f80ea0828a8.html index 036daa96c8..6d3c0644e2 100644 --- a/dir_34761767c1c3cd212f9d2f80ea0828a8.html +++ b/dir_34761767c1c3cd212f9d2f80ea0828a8.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    - + @@ -134,7 +113,7 @@ Files diff --git a/dir_38cec1532eaed7aa1de0b599a76e3e80.html b/dir_38cec1532eaed7aa1de0b599a76e3e80.html index 3734c1c544..81c9a59c4c 100644 --- a/dir_38cec1532eaed7aa1de0b599a76e3e80.html +++ b/dir_38cec1532eaed7aa1de0b599a76e3e80.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: src/Tgstation.Server.Host/Controllers Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@

    Files

    file  AssemblyInfo.cs [code]
    file  AssemblyInfo.cs [code]
     
    file  IServer.cs [code]
     
    - + - - + + + +
    diff --git a/dir_446bdfc1cd19b69c11765b5665ebfd45.html b/dir_446bdfc1cd19b69c11765b5665ebfd45.html index e9184ffb05..105e122116 100644 --- a/dir_446bdfc1cd19b69c11765b5665ebfd45.html +++ b/dir_446bdfc1cd19b69c11765b5665ebfd45.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/obj Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +

    Directories

    -directory  Release +directory  Debug  
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_4122b363a9d577bed19bef337e757ff3.html b/dir_48968f849f7ddb061f7130e079fe66a6.html similarity index 59% rename from dir_4122b363a9d577bed19bef337e757ff3.html rename to dir_48968f849f7ddb061f7130e079fe66a6.html index b3a9b1e4ea..2df0e4e0e9 100644 --- a/dir_4122b363a9d577bed19bef337e757ff3.html +++ b/dir_48968f849f7ddb061f7130e079fe66a6.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Client/obj/Release Directory Reference + + +tgstation-server: src/Tgstation.Server.Client/obj/Debug Directory Reference - @@ -33,41 +31,22 @@ - + - - + + + +
    -
    Release Directory Reference
    +
    Debug Directory Reference
    - +

    Directories

    directory  netstandard2.0
    directory  netstandard2.0
     
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_49e56c817e5e54854c35e136979f97ca.html b/dir_49e56c817e5e54854c35e136979f97ca.html new file mode 100644 index 0000000000..c8217ab51c --- /dev/null +++ b/dir_49e56c817e5e54854c35e136979f97ca.html @@ -0,0 +1,82 @@ + + + + + + + +tgstation-server: docs Directory Reference + + + + + + + + + +
    +
    + + + + + + + +
    +
    tgstation-server +
    +
    The /tg/station 13 server suite
    +
    +
    + + + + + + + + +
    +
    + + +
    + +
    + + +
    +
    +
    +
    docs Directory Reference
    +
    +
    +
    + + + + diff --git a/dir_d45f494620bc0048ee4a31fa4f7391e1.html b/dir_4c0c7e2f4fc60f51e2347a2d8dda94ce.html similarity index 65% rename from dir_d45f494620bc0048ee4a31fa4f7391e1.html rename to dir_4c0c7e2f4fc60f51e2347a2d8dda94ce.html index f7d7774036..cd6ab8de8e 100644 --- a/dir_d45f494620bc0048ee4a31fa4f7391e1.html +++ b/dir_4c0c7e2f4fc60f51e2347a2d8dda94ce.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Api.Tests/obj/Release/netcoreapp2.1 Directory Reference + + +tgstation-server: tests/Tgstation.Server.Api.Tests/obj/Debug/netcoreapp2.1 Directory Reference - @@ -33,41 +31,22 @@ - + - - + + + +
    @@ -105,7 +84,7 @@ Files diff --git a/dir_4ddbd20a555bd1f3bf9569744c8989cc.html b/dir_4ddbd20a555bd1f3bf9569744c8989cc.html index f29416300e..d40348233a 100644 --- a/dir_4ddbd20a555bd1f3bf9569744c8989cc.html +++ b/dir_4ddbd20a555bd1f3bf9569744c8989cc.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/StaticFiles Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_4eeb864c4eec08c7d6b9d3b0352cfdde.html b/dir_4eeb864c4eec08c7d6b9d3b0352cfdde.html index 44586d0f15..f7c5864794 100644 --- a/dir_4eeb864c4eec08c7d6b9d3b0352cfdde.html +++ b/dir_4eeb864c4eec08c7d6b9d3b0352cfdde.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tools Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_59425e443f801f1f2fd8bbe4959a3ccf.html b/dir_59425e443f801f1f2fd8bbe4959a3ccf.html index 837d4508e9..aab9cb7b86 100644 --- a/dir_59425e443f801f1f2fd8bbe4959a3ccf.html +++ b/dir_59425e443f801f1f2fd8bbe4959a3ccf.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_5d46d0c3fd1cac5ce1ea23751ad25792.html b/dir_5d46d0c3fd1cac5ce1ea23751ad25792.html index 4127709c2b..2b5bd313b0 100644 --- a/dir_5d46d0c3fd1cac5ce1ea23751ad25792.html +++ b/dir_5d46d0c3fd1cac5ce1ea23751ad25792.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Repository Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_5d5b300b88421e3050db28dd037f6f39.html b/dir_5d5b300b88421e3050db28dd037f6f39.html index cafa89e051..6bc7cb2a7c 100644 --- a/dir_5d5b300b88421e3050db28dd037f6f39.html +++ b/dir_5d5b300b88421e3050db28dd037f6f39.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Watchdog.Tests Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_5e0b464d3b4be546c63c5188ffeb96e4.html b/dir_5e0b464d3b4be546c63c5188ffeb96e4.html index 6a9180c00b..b2f8f7e3b3 100644 --- a/dir_5e0b464d3b4be546c63c5188ffeb96e4.html +++ b/dir_5e0b464d3b4be546c63c5188ffeb96e4.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Providers Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_61d7974a657c30011f457b376d274ee7.html b/dir_61d7974a657c30011f457b376d274ee7.html index a47941bde3..4b257001b3 100644 --- a/dir_61d7974a657c30011f457b376d274ee7.html +++ b/dir_61d7974a657c30011f457b376d274ee7.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Models Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_68267d1309a1af8e8297ef4c3efbcdba.html b/dir_68267d1309a1af8e8297ef4c3efbcdba.html index 91f172fc1b..2b0fa683b4 100644 --- a/dir_68267d1309a1af8e8297ef4c3efbcdba.html +++ b/dir_68267d1309a1af8e8297ef4c3efbcdba.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_685b5aa2d8a661ab5bc3f68b331887b0.html b/dir_685b5aa2d8a661ab5bc3f68b331887b0.html index 218f75929a..a6126c4dcf 100644 --- a/dir_685b5aa2d8a661ab5bc3f68b331887b0.html +++ b/dir_685b5aa2d8a661ab5bc3f68b331887b0.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Console/obj Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +

    Directories

    -directory  Release +directory  Debug  
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_689f0584ee97ae9ca308532531d9c5d2.html b/dir_689f0584ee97ae9ca308532531d9c5d2.html index 6c9954610a..3c5c554b6a 100644 --- a/dir_689f0584ee97ae9ca308532531d9c5d2.html +++ b/dir_689f0584ee97ae9ca308532531d9c5d2.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/obj Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +

    Directories

    -directory  Release +directory  Debug  
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_6c60df807dd2523776d391746c262b4d.html b/dir_6c60df807dd2523776d391746c262b4d.html index 76adc6f8d6..4aa4e0b5d0 100644 --- a/dir_6c60df807dd2523776d391746c262b4d.html +++ b/dir_6c60df807dd2523776d391746c262b4d.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client/Components Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
    diff --git a/dir_71f5cbd840fdd1dea9f035c7b1a066ee.html b/dir_71f5cbd840fdd1dea9f035c7b1a066ee.html index 20d88a7e8e..b4d5bff78a 100644 --- a/dir_71f5cbd840fdd1dea9f035c7b1a066ee.html +++ b/dir_71f5cbd840fdd1dea9f035c7b1a066ee.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Client.Tests Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_74017a19412e2f90cc6ad11fcac82495.html b/dir_74017a19412e2f90cc6ad11fcac82495.html index 7f8fa7d13d..94b7020e03 100644 --- a/dir_74017a19412e2f90cc6ad11fcac82495.html +++ b/dir_74017a19412e2f90cc6ad11fcac82495.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Client.Tests/obj Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +

    Directories

    -directory  Release +directory  Debug  
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_78e87f8f095a8e3bb6ef1faef94cdb78.html b/dir_78e87f8f095a8e3bb6ef1faef94cdb78.html new file mode 100644 index 0000000000..91f2e780d2 --- /dev/null +++ b/dir_78e87f8f095a8e3bb6ef1faef94cdb78.html @@ -0,0 +1,88 @@ + + + + + + + +tgstation-server: tests/Tgstation.Server.Host.Service.Tests/obj/Debug Directory Reference + + + + + + + + + +
    +
    + + + + + + + +
    +
    tgstation-server +
    +
    The /tg/station 13 server suite
    +
    +
    + + + + + + + + +
    +
    + + +
    + +
    + + +
    +
    +
    +
    Debug Directory Reference
    +
    +
    + + + + +

    +Directories

    directory  net471
     
    +
    + + + + diff --git a/dir_7916dda968fadc8673161597975e4c5d.html b/dir_7916dda968fadc8673161597975e4c5d.html index 1303bcbe52..d13e086d24 100644 --- a/dir_7916dda968fadc8673161597975e4c5d.html +++ b/dir_7916dda968fadc8673161597975e4c5d.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Api.Tests/Rights Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
    diff --git a/dir_7a3fd032a1362a6005a1fc9227a8dd86.html b/dir_7a3fd032a1362a6005a1fc9227a8dd86.html index 176330d1ff..d3af05448b 100644 --- a/dir_7a3fd032a1362a6005a1fc9227a8dd86.html +++ b/dir_7a3fd032a1362a6005a1fc9227a8dd86.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_7a9487ad1984d08627fcf919e6f3d801.html b/dir_7a9487ad1984d08627fcf919e6f3d801.html index 5b573977a6..13c2a39f1f 100644 --- a/dir_7a9487ad1984d08627fcf919e6f3d801.html +++ b/dir_7a9487ad1984d08627fcf919e6f3d801.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Components/Watchdog Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_7cd79c49f3850abc2141fa4adfdd1950.html b/dir_7cd79c49f3850abc2141fa4adfdd1950.html index d29a1c61d4..a0cc013832 100644 --- a/dir_7cd79c49f3850abc2141fa4adfdd1950.html +++ b/dir_7cd79c49f3850abc2141fa4adfdd1950.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat/Commands Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_860acef72838dce8d3d54c8f98bc464b.html b/dir_860acef72838dce8d3d54c8f98bc464b.html index 085df15f52..37f6b656a4 100644 --- a/dir_860acef72838dce8d3d54c8f98bc464b.html +++ b/dir_860acef72838dce8d3d54c8f98bc464b.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Api/Rights Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_0e792d76844bf2d7c79795a56a50ebec.html b/dir_87039fa7b841d848ca75981d64237477.html similarity index 59% rename from dir_0e792d76844bf2d7c79795a56a50ebec.html rename to dir_87039fa7b841d848ca75981d64237477.html index 23a89b0749..adb323dadf 100644 --- a/dir_0e792d76844bf2d7c79795a56a50ebec.html +++ b/dir_87039fa7b841d848ca75981d64237477.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Tests/obj/Release Directory Reference + + +tgstation-server: tests/Tgstation.Server.Tests/obj/Debug Directory Reference - @@ -33,41 +31,22 @@
    - + - - + + + +
    -
    Release Directory Reference
    +
    Debug Directory Reference
    - +

    Directories

    directory  netcoreapp2.1
    directory  netcoreapp2.1
     
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_87a4f2035ed18e30422f4b60aebc4381.html b/dir_87a4f2035ed18e30422f4b60aebc4381.html index 758e9f5842..7f058037c9 100644 --- a/dir_87a4f2035ed18e30422f4b60aebc4381.html +++ b/dir_87a4f2035ed18e30422f4b60aebc4381.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Api.Tests/obj Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +

    Directories

    -directory  Release +directory  Debug  
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_6db5af7fcfa17a34c7abf23e195af4db.html b/dir_9257d56e926145e494a5aa5279887044.html similarity index 65% rename from dir_6db5af7fcfa17a34c7abf23e195af4db.html rename to dir_9257d56e926145e494a5aa5279887044.html index c6f101d612..7b3fc71854 100644 --- a/dir_6db5af7fcfa17a34c7abf23e195af4db.html +++ b/dir_9257d56e926145e494a5aa5279887044.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Tests/obj/Release/netcoreapp2.1 Directory Reference + + +tgstation-server: tests/Tgstation.Server.Tests/obj/Debug/netcoreapp2.1 Directory Reference - @@ -33,41 +31,22 @@ - + - - + + + +
    @@ -105,7 +84,7 @@ Files diff --git a/dir_9826fb2d31585a830723e6d7089b5d0e.html b/dir_9826fb2d31585a830723e6d7089b5d0e.html index 5e21d47b5d..f06042c8fa 100644 --- a/dir_9826fb2d31585a830723e6d7089b5d0e.html +++ b/dir_9826fb2d31585a830723e6d7089b5d0e.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Client Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
      file  ApiMismatchException.cs [code]   -file  AssemblyInfo.cs [code] +file  AssemblyInfo.cs [code]   file  ClientException.cs [code]   @@ -168,7 +147,7 @@ Files diff --git a/dir_9aa5991638c9344778d807333cc0bd50.html b/dir_9aa5991638c9344778d807333cc0bd50.html new file mode 100644 index 0000000000..a598538b69 --- /dev/null +++ b/dir_9aa5991638c9344778d807333cc0bd50.html @@ -0,0 +1,88 @@ + + + + + + + +tgstation-server: src/Tgstation.Server.Host.Service/obj/Debug/net471 Directory Reference + + + + + + + + + +
    +
    + + + + + + + +
    +
    tgstation-server +
    +
    The /tg/station 13 server suite
    +
    +
    + + + + + + + + +
    +
    + + +
    + +
    + + +
    +
    +
    +
    net471 Directory Reference
    +
    +
    + + + + +

    +Directories

    directory  win
     
    +
    + + + + diff --git a/dir_a01d946a2e1b048dc542232ffcdcf572.html b/dir_a01d946a2e1b048dc542232ffcdcf572.html index 3b9881a4db..890430073a 100644 --- a/dir_a01d946a2e1b048dc542232ffcdcf572.html +++ b/dir_a01d946a2e1b048dc542232ffcdcf572.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Service Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +

    Directories

    +directory  obj +  directory  Properties   @@ -112,7 +93,7 @@ Files diff --git a/dir_a24b8c5f308a77f73e7a9e43c0f243d1.html b/dir_a24b8c5f308a77f73e7a9e43c0f243d1.html index 08e11ef4a9..2d7b70f7d5 100644 --- a/dir_a24b8c5f308a77f73e7a9e43c0f243d1.html +++ b/dir_a24b8c5f308a77f73e7a9e43c0f243d1.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: tests/Tgstation.Server.Api.Tests/Models Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_13bee0ed20ecc83b9bcd4b869b726d42.html b/dir_a3714ab037275c284988fc90b4d045a5.html similarity index 63% rename from dir_13bee0ed20ecc83b9bcd4b869b726d42.html rename to dir_a3714ab037275c284988fc90b4d045a5.html index 22a0a8b491..d1b23ad2cb 100644 --- a/dir_13bee0ed20ecc83b9bcd4b869b726d42.html +++ b/dir_a3714ab037275c284988fc90b4d045a5.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Host.Watchdog/obj/Release/netstandard2.0 Directory Reference + + +tgstation-server: src/Tgstation.Server.Host.Watchdog/obj/Debug/netstandard2.0 Directory Reference - @@ -33,41 +31,22 @@
    - + - - + + + +
    @@ -103,7 +82,7 @@ Files diff --git a/dir_bb25b36c82def1362ea245058c866cdc.html b/dir_a3831f1c39821b3669f8a3808652203f.html similarity index 54% rename from dir_bb25b36c82def1362ea245058c866cdc.html rename to dir_a3831f1c39821b3669f8a3808652203f.html index 0a6e5df87f..7b7c9052f8 100644 --- a/dir_bb25b36c82def1362ea245058c866cdc.html +++ b/dir_a3831f1c39821b3669f8a3808652203f.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Service.Tests/Properties Directory Reference + + +tgstation-server: tests/Tgstation.Server.Host.Service.Tests/obj/Debug/net471 Directory Reference - @@ -33,41 +31,22 @@
    - + - - + + + +
    -
    Properties Directory Reference
    +
    net471 Directory Reference
    @@ -103,7 +82,7 @@ Files diff --git a/dir_a44a562b5a12ef1c8495ac1a63e915ea.html b/dir_a44a562b5a12ef1c8495ac1a63e915ea.html index 802764306c..64ce775e6a 100644 --- a/dir_a44a562b5a12ef1c8495ac1a63e915ea.html +++ b/dir_a44a562b5a12ef1c8495ac1a63e915ea.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Chat Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
    diff --git a/dir_a51095d0142a80f0e979ff5bf5b861be.html b/dir_a51095d0142a80f0e979ff5bf5b861be.html new file mode 100644 index 0000000000..64dc14f790 --- /dev/null +++ b/dir_a51095d0142a80f0e979ff5bf5b861be.html @@ -0,0 +1,88 @@ + + + + + + + +tgstation-server: src/Tgstation.Server.Host.Service/obj Directory Reference + + + + + + + + + +
    +
    + + + + + + + +
    +
    tgstation-server +
    +
    The /tg/station 13 server suite
    +
    +
    + + + + + + + + +
    +
    + + +
    + +
    + + +
    +
    +
    +
    obj Directory Reference
    +
    +
    + + + + +

    +Directories

    directory  Debug
     
    +
    + + + + diff --git a/dir_a536e49cdf631f66733cf2c9791144ce.html b/dir_a536e49cdf631f66733cf2c9791144ce.html index b3ed015d90..487722ebd8 100644 --- a/dir_a536e49cdf631f66733cf2c9791144ce.html +++ b/dir_a536e49cdf631f66733cf2c9791144ce.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/IO Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_fcc41a8faa41492aba200a49fc7d0aed.html b/dir_a8807eef6592489c6a360d587f5b1a66.html similarity index 62% rename from dir_fcc41a8faa41492aba200a49fc7d0aed.html rename to dir_a8807eef6592489c6a360d587f5b1a66.html index 31f97c168e..3f18e8c613 100644 --- a/dir_fcc41a8faa41492aba200a49fc7d0aed.html +++ b/dir_a8807eef6592489c6a360d587f5b1a66.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Host.Console/obj/Release/netcoreapp2.1 Directory Reference + + +tgstation-server: src/Tgstation.Server.Host.Console/obj/Debug/netcoreapp2.1 Directory Reference - @@ -33,41 +31,22 @@
    - + - - + + + +
    @@ -103,7 +82,7 @@ Files diff --git a/dir_a99ad55e4d1fa76955df2299f3783cf0.html b/dir_a99ad55e4d1fa76955df2299f3783cf0.html index 7ac4b0007f..a8d44f39d5 100644 --- a/dir_a99ad55e4d1fa76955df2299f3783cf0.html +++ b/dir_a99ad55e4d1fa76955df2299f3783cf0.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Components/Chat/Providers Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_b0d0d898ef448ca0a6a170a2896fa60e.html b/dir_b0d0d898ef448ca0a6a170a2896fa60e.html index f17774659a..e93fd6e967 100644 --- a/dir_b0d0d898ef448ca0a6a170a2896fa60e.html +++ b/dir_b0d0d898ef448ca0a6a170a2896fa60e.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Compiler Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_b524b00ec2259c3c83b44909fd47f6e3.html b/dir_b524b00ec2259c3c83b44909fd47f6e3.html index 4404253378..e363a2e25d 100644 --- a/dir_b524b00ec2259c3c83b44909fd47f6e3.html +++ b/dir_b524b00ec2259c3c83b44909fd47f6e3.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Console.Tests/obj Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +

    Directories

    -directory  Release +directory  Debug  
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_900257602d294c4a4799e88420919068.html b/dir_b551a02288ef39e099594710382363a0.html similarity index 67% rename from dir_900257602d294c4a4799e88420919068.html rename to dir_b551a02288ef39e099594710382363a0.html index bc123d8ffe..a2e7d0fe5c 100644 --- a/dir_900257602d294c4a4799e88420919068.html +++ b/dir_b551a02288ef39e099594710382363a0.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Watchdog.Tests/obj/Release/netcoreapp2.1 Directory Reference + + +tgstation-server: tests/Tgstation.Server.Host.Watchdog.Tests/obj/Debug/netcoreapp2.1 Directory Reference - @@ -33,41 +31,22 @@ - + - - + + + +
    @@ -105,7 +84,7 @@ Files diff --git a/dir_b6324197f7ac56e30d6189c3a45eec56.html b/dir_b6324197f7ac56e30d6189c3a45eec56.html index 9e1d3e72e1..0cdc6c1325 100644 --- a/dir_b6324197f7ac56e30d6189c3a45eec56.html +++ b/dir_b6324197f7ac56e30d6189c3a45eec56.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Components/Byond Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_e928c7e494884ad322b5f6005c2954e1.html b/dir_b87cbb2c60cf682b61fbfcceb9bced43.html similarity index 65% rename from dir_e928c7e494884ad322b5f6005c2954e1.html rename to dir_b87cbb2c60cf682b61fbfcceb9bced43.html index f848936f1a..4104daeb6c 100644 --- a/dir_e928c7e494884ad322b5f6005c2954e1.html +++ b/dir_b87cbb2c60cf682b61fbfcceb9bced43.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Host/obj/Release/netcoreapp2.1 Directory Reference + + +tgstation-server: src/Tgstation.Server.Host/obj/Debug/netcoreapp2.1 Directory Reference - @@ -33,41 +31,22 @@
    - + - - + + + +
    @@ -105,7 +84,7 @@ Files diff --git a/dir_40138fd4849573e743490d583f6d06d6.html b/dir_b92573f47b933d7a3661c26d1af2098b.html similarity index 60% rename from dir_40138fd4849573e743490d583f6d06d6.html rename to dir_b92573f47b933d7a3661c26d1af2098b.html index bcd2178ae4..be9864d555 100644 --- a/dir_40138fd4849573e743490d583f6d06d6.html +++ b/dir_b92573f47b933d7a3661c26d1af2098b.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Console.Tests/obj/Release Directory Reference + + +tgstation-server: tests/Tgstation.Server.Host.Console.Tests/obj/Debug Directory Reference - @@ -33,41 +31,22 @@
    - + - - + + + +
    -
    Release Directory Reference
    +
    Debug Directory Reference
    - +

    Directories

    directory  netcoreapp2.1
    directory  netcoreapp2.1
     
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_ba6c75cd9bd8b7a0d2af20e1cd5a80ab.html b/dir_ba6c75cd9bd8b7a0d2af20e1cd5a80ab.html index e03fb85211..e6ab97830b 100644 --- a/dir_ba6c75cd9bd8b7a0d2af20e1cd5a80ab.html +++ b/dir_ba6c75cd9bd8b7a0d2af20e1cd5a80ab.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Components/Byond Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
    diff --git a/dir_be6161819238d55fa660c07ade960e53.html b/dir_be6161819238d55fa660c07ade960e53.html index 6c7137dbdb..66e47a7779 100644 --- a/dir_be6161819238d55fa660c07ade960e53.html +++ b/dir_be6161819238d55fa660c07ade960e53.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Console Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    - + @@ -110,7 +89,7 @@ Files diff --git a/dir_18a5e30c14613227f95d12bd9fddc614.html b/dir_be9f3ed3485a880e3213506a311823d1.html similarity index 59% rename from dir_18a5e30c14613227f95d12bd9fddc614.html rename to dir_be9f3ed3485a880e3213506a311823d1.html index 2d245f3bd5..492f3388b0 100644 --- a/dir_18a5e30c14613227f95d12bd9fddc614.html +++ b/dir_be9f3ed3485a880e3213506a311823d1.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Api.Tests/obj/Release Directory Reference + + +tgstation-server: tests/Tgstation.Server.Api.Tests/obj/Debug Directory Reference - @@ -33,41 +31,22 @@

    Files

    file  AssemblyInfo.cs [code]
    file  AssemblyInfo.cs [code]
     
    file  Program.cs [code]
     
    - + - - + + + +
    -
    Release Directory Reference
    +
    Debug Directory Reference
    - +

    Directories

    directory  netcoreapp2.1
    directory  netcoreapp2.1
     
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_bf23e1e49f40264f2966f02ed35d8142.html b/dir_bf23e1e49f40264f2966f02ed35d8142.html index 628590894f..c05ed6bf1e 100644 --- a/dir_bf23e1e49f40264f2966f02ed35d8142.html +++ b/dir_bf23e1e49f40264f2966f02ed35d8142.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tools/ReleaseNotes/obj Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +

    Directories

    -directory  Release +directory  Debug  
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_c037ac41e54cca303e35165acb6e013d.html b/dir_c037ac41e54cca303e35165acb6e013d.html index 0f2e3d8b7a..c91f66dc83 100644 --- a/dir_c037ac41e54cca303e35165acb6e013d.html +++ b/dir_c037ac41e54cca303e35165acb6e013d.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tools/ReleaseNotes Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
    diff --git a/dir_c2c4d4ee47e55233c6ea5db8b96422c6.html b/dir_c2c4d4ee47e55233c6ea5db8b96422c6.html index 736b42129a..b618cbfddc 100644 --- a/dir_c2c4d4ee47e55233c6ea5db8b96422c6.html +++ b/dir_c2c4d4ee47e55233c6ea5db8b96422c6.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Models Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_c50f9bd139317d744e2ee08ea9a734cc.html b/dir_c50f9bd139317d744e2ee08ea9a734cc.html new file mode 100644 index 0000000000..6934619a09 --- /dev/null +++ b/dir_c50f9bd139317d744e2ee08ea9a734cc.html @@ -0,0 +1,88 @@ + + + + + + + +tgstation-server: tests/Tgstation.Server.Host.Service.Tests/obj Directory Reference + + + + + + + + + +
    +
    + + + + + + + +
    +
    tgstation-server +
    +
    The /tg/station 13 server suite
    +
    +
    + + + + + + + + +
    +
    + + +
    + +
    + + +
    +
    +
    +
    obj Directory Reference
    +
    +
    + + + + +

    +Directories

    directory  Debug
     
    +
    + + + + diff --git a/dir_c5451d9d233744a5b09a29938f0cda9a.html b/dir_c5451d9d233744a5b09a29938f0cda9a.html index dbeb37f52c..0f42e1b484 100644 --- a/dir_c5451d9d233744a5b09a29938f0cda9a.html +++ b/dir_c5451d9d233744a5b09a29938f0cda9a.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Security Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_298f2a364723f4f4cea115538f944a94.html b/dir_c5f98c05147bcbba78e71856485f5049.html similarity index 66% rename from dir_298f2a364723f4f4cea115538f944a94.html rename to dir_c5f98c05147bcbba78e71856485f5049.html index 38023d24fb..8b0b361e42 100644 --- a/dir_298f2a364723f4f4cea115538f944a94.html +++ b/dir_c5f98c05147bcbba78e71856485f5049.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Client.Tests/obj/Release/netcoreapp2.1 Directory Reference + + +tgstation-server: tests/Tgstation.Server.Client.Tests/obj/Debug/netcoreapp2.1 Directory Reference - @@ -33,41 +31,22 @@
    - + - - + + + +
    @@ -105,7 +84,7 @@ Files diff --git a/dir_c648ff9d1a57dd8752f4ab2a7c68712c.html b/dir_c648ff9d1a57dd8752f4ab2a7c68712c.html index 7e1eba29ee..76feb121fc 100644 --- a/dir_c648ff9d1a57dd8752f4ab2a7c68712c.html +++ b/dir_c648ff9d1a57dd8752f4ab2a7c68712c.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Client.Tests/Components Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_c9d0608eee53bfffcc33d03463bbe2db.html b/dir_c9d0608eee53bfffcc33d03463bbe2db.html index c5fbc2237f..62ee6c7436 100644 --- a/dir_c9d0608eee53bfffcc33d03463bbe2db.html +++ b/dir_c9d0608eee53bfffcc33d03463bbe2db.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Tests/Instance Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_d8869fc9da5c696ed284d5c470b7210f.html b/dir_d8869fc9da5c696ed284d5c470b7210f.html index c917890982..9a3029625a 100644 --- a/dir_d8869fc9da5c696ed284d5c470b7210f.html +++ b/dir_d8869fc9da5c696ed284d5c470b7210f.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Components/Chat Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_d88de13ae4b64d4d0766b0c06f1a9edf.html b/dir_d88de13ae4b64d4d0766b0c06f1a9edf.html index f97fe5fa5a..64b41696a0 100644 --- a/dir_d88de13ae4b64d4d0766b0c06f1a9edf.html +++ b/dir_d88de13ae4b64d4d0766b0c06f1a9edf.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests/Security Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_83a6f600c846cd444f33e44bb9b4f9cb.html b/dir_d8a279f7113e0073f6cd65dd050c1475.html similarity index 62% rename from dir_83a6f600c846cd444f33e44bb9b4f9cb.html rename to dir_d8a279f7113e0073f6cd65dd050c1475.html index a8019a6a86..a82f12013e 100644 --- a/dir_83a6f600c846cd444f33e44bb9b4f9cb.html +++ b/dir_d8a279f7113e0073f6cd65dd050c1475.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Api/obj/Release/netstandard2.0 Directory Reference + + +tgstation-server: src/Tgstation.Server.Api/obj/Debug/netstandard2.0 Directory Reference - @@ -33,41 +31,22 @@
    - + - - + + + +
    @@ -103,7 +82,7 @@ Files diff --git a/dir_dbb0c65ea012faeef2906502dd42dfec.html b/dir_dbb0c65ea012faeef2906502dd42dfec.html index a6b08196f4..3705c7f713 100644 --- a/dir_dbb0c65ea012faeef2906502dd42dfec.html +++ b/dir_dbb0c65ea012faeef2906502dd42dfec.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Service.Tests Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +

    Directories

    -directory  Properties +directory  obj   diff --git a/dir_df215ce6792635a450ba5a94b5a17942.html b/dir_df215ce6792635a450ba5a94b5a17942.html index 018ab5610b..0c800ec45b 100644 --- a/dir_df215ce6792635a450ba5a94b5a17942.html +++ b/dir_df215ce6792635a450ba5a94b5a17942.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: tests/Tgstation.Server.Host.Tests/IO Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@

    @@ -108,7 +87,7 @@ Files

    - + - - + + + +
    diff --git a/dir_e0c1bccb03249d93bc42ac0968ce43fd.html b/dir_e0c1bccb03249d93bc42ac0968ce43fd.html index 3c01320942..fb0ddd3187 100644 --- a/dir_e0c1bccb03249d93bc42ac0968ce43fd.html +++ b/dir_e0c1bccb03249d93bc42ac0968ce43fd.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/obj Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +

    Directories

    -directory  Release +directory  Debug  
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_e2ec88631ea78d6df8b37d27efa9bfe2.html b/dir_e2ec88631ea78d6df8b37d27efa9bfe2.html index a6da9224c0..c159a386eb 100644 --- a/dir_e2ec88631ea78d6df8b37d27efa9bfe2.html +++ b/dir_e2ec88631ea78d6df8b37d27efa9bfe2.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Api.Tests Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
    diff --git a/dir_c65d377d3c73fb4a07b3637f9c0caf4d.html b/dir_e97d380c3eebaf0856a4ec180d749620.html similarity index 60% rename from dir_c65d377d3c73fb4a07b3637f9c0caf4d.html rename to dir_e97d380c3eebaf0856a4ec180d749620.html index 8850253690..be67b52590 100644 --- a/dir_c65d377d3c73fb4a07b3637f9c0caf4d.html +++ b/dir_e97d380c3eebaf0856a4ec180d749620.html @@ -1,19 +1,17 @@ - + - -tgstation-server: tests/Tgstation.Server.Host.Watchdog.Tests/obj/Release Directory Reference + + +tgstation-server: tests/Tgstation.Server.Host.Watchdog.Tests/obj/Debug Directory Reference - @@ -33,41 +31,22 @@
    - + - - + + + +
    -
    Release Directory Reference
    +
    Debug Directory Reference
    - +

    Directories

    directory  netcoreapp2.1
    directory  netcoreapp2.1
     
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_e9975c2f0de13509bd9fb4e31ae732ab.html b/dir_e9975c2f0de13509bd9fb4e31ae732ab.html index 8e42f94bb3..a439cf68a8 100644 --- a/dir_e9975c2f0de13509bd9fb4e31ae732ab.html +++ b/dir_e9975c2f0de13509bd9fb4e31ae732ab.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Console.Tests Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
    diff --git a/dir_6c8d8f20501e8e412458f542d0998195.html b/dir_ea36b5ab01ad6e8b607438a02ae91964.html similarity index 60% rename from dir_6c8d8f20501e8e412458f542d0998195.html rename to dir_ea36b5ab01ad6e8b607438a02ae91964.html index 0a0cbe414e..9c70d2d3ff 100644 --- a/dir_6c8d8f20501e8e412458f542d0998195.html +++ b/dir_ea36b5ab01ad6e8b607438a02ae91964.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Host.Watchdog/obj/Release Directory Reference + + +tgstation-server: src/Tgstation.Server.Host.Watchdog/obj/Debug Directory Reference - @@ -33,41 +31,22 @@
    - + - - + + + +
    -
    Release Directory Reference
    +
    Debug Directory Reference
    - +

    Directories

    directory  netstandard2.0
    directory  netstandard2.0
     
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_eb7c70823ae63176c38851687b13349d.html b/dir_eb7c70823ae63176c38851687b13349d.html index 27fa3bb567..6fd1a5e0fa 100644 --- a/dir_eb7c70823ae63176c38851687b13349d.html +++ b/dir_eb7c70823ae63176c38851687b13349d.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Tests Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
    diff --git a/dir_ed78ff3b0fc4a7f5234cdb0b34617476.html b/dir_ed78ff3b0fc4a7f5234cdb0b34617476.html index f5bce8990d..448057961b 100644 --- a/dir_ed78ff3b0fc4a7f5234cdb0b34617476.html +++ b/dir_ed78ff3b0fc4a7f5234cdb0b34617476.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Host.Tests Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +
    diff --git a/dir_f0581cdd528a911f791df57d0f438bcb.html b/dir_f0581cdd528a911f791df57d0f438bcb.html index 92fb7d8e33..c042387231 100644 --- a/dir_f0581cdd528a911f791df57d0f438bcb.html +++ b/dir_f0581cdd528a911f791df57d0f438bcb.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tests/Tgstation.Server.Tests/obj Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
    - + - - + + + +

    Directories

    -directory  Release +directory  Debug  
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_f0d41009ce252337feb2b68822c4cfba.html b/dir_f0d41009ce252337feb2b68822c4cfba.html index e9fb63989b..abb4c23faa 100644 --- a/dir_f0d41009ce252337feb2b68822c4cfba.html +++ b/dir_f0d41009ce252337feb2b68822c4cfba.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Watchdog Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
    - + @@ -116,7 +95,7 @@ Files diff --git a/dir_f2a82faa4c4beef364292694cefca86d.html b/dir_f2a82faa4c4beef364292694cefca86d.html index 79081b08a0..9178cced29 100644 --- a/dir_f2a82faa4c4beef364292694cefca86d.html +++ b/dir_f2a82faa4c4beef364292694cefca86d.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: src/Tgstation.Server.Api/Models/Internal Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@

    Files

    file  AssemblyInfo.cs [code]
    file  AssemblyInfo.cs [code]
     
    file  IWatchdog.cs [code]
     
    - + - - + + + +
    diff --git a/dir_383ca23c40357ede4cca827b4a365c76.html b/dir_f88948f9bde0555374e8a59a663bdfc9.html similarity index 62% rename from dir_383ca23c40357ede4cca827b4a365c76.html rename to dir_f88948f9bde0555374e8a59a663bdfc9.html index f0da92e2cc..c0d95efec3 100644 --- a/dir_383ca23c40357ede4cca827b4a365c76.html +++ b/dir_f88948f9bde0555374e8a59a663bdfc9.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Client/obj/Release/netstandard2.0 Directory Reference + + +tgstation-server: src/Tgstation.Server.Client/obj/Debug/netstandard2.0 Directory Reference - @@ -33,41 +31,22 @@
    - + - - + + + +
    @@ -103,7 +82,7 @@ Files diff --git a/dir_7a9d035dcfcd6d9c7aa1efef4b6b58a4.html b/dir_fab1362e86740a2c573ef875dd474a67.html similarity index 59% rename from dir_7a9d035dcfcd6d9c7aa1efef4b6b58a4.html rename to dir_fab1362e86740a2c573ef875dd474a67.html index 445fc56436..df65210da7 100644 --- a/dir_7a9d035dcfcd6d9c7aa1efef4b6b58a4.html +++ b/dir_fab1362e86740a2c573ef875dd474a67.html @@ -1,19 +1,17 @@ - + - -tgstation-server: src/Tgstation.Server.Host.Console/obj/Release Directory Reference + + +tgstation-server: src/Tgstation.Server.Host.Console/obj/Debug Directory Reference - @@ -33,41 +31,22 @@
    - + - - + + + +
    -
    Release Directory Reference
    +
    Debug Directory Reference
    - +

    Directories

    directory  netcoreapp2.1
    directory  netcoreapp2.1
     
    @@ -103,7 +82,7 @@ Directories diff --git a/dir_fb12273b841438c2f2c9b5bc5398c636.html b/dir_fb12273b841438c2f2c9b5bc5398c636.html index a687d3898e..20f1d9da91 100644 --- a/dir_fb12273b841438c2f2c9b5bc5398c636.html +++ b/dir_fb12273b841438c2f2c9b5bc5398c636.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Watchdog/obj Directory Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +

    Directories

    -directory  Release +directory  Debug  
    @@ -103,7 +82,7 @@ Directories diff --git a/doxygen.css b/doxygen.css index 1425ec530d..e2515926c8 100644 --- a/doxygen.css +++ b/doxygen.css @@ -1,9 +1,13 @@ -/* The standard CSS for doxygen 1.8.11 */ +/* The standard CSS for doxygen 1.8.15 */ body, table, div, p, dl { font: 400 14px/22px Roboto,sans-serif; } +p.reference, p.definition { + font: 400 14px/22px Roboto,sans-serif; +} + /* @group Heading Levels */ h1.groupheader { @@ -76,6 +80,15 @@ p.endtd { margin-bottom: 2px; } +p.interli { +} + +p.interdd { +} + +p.intertd { +} + /* @end */ caption { @@ -130,12 +143,12 @@ a.qindex { a.qindexHL { font-weight: bold; background-color: #9CAFD4; - color: #ffffff; + color: #FFFFFF; border: 1px double #869DCA; } .contents a.qindexHL:visited { - color: #ffffff; + color: #FFFFFF; } a.el { @@ -159,6 +172,25 @@ dl.el { margin-left: -1cm; } +ul { + overflow: hidden; /*Fixed: list item bullets overlap floating elements*/ +} + +#side-nav ul { + overflow: visible; /* reset ul rule for scroll bar in GENERATE_TREEVIEW window */ +} + +#main-nav ul { + overflow: visible; /* reset ul rule for the navigation bar drop down lists */ +} + +.fragment { + text-align: left; + direction: ltr; + overflow-x: auto; /*Fixed: fragment lines overlap floating elements*/ + overflow-y: hidden; +} + pre.fragment { border: 1px solid #C4CFE5; background-color: #FBFCFD; @@ -173,8 +205,8 @@ pre.fragment { } div.fragment { - padding: 4px 6px; - margin: 4px 8px 4px 2px; + padding: 0 0 1px 0; /*Fixed: last line underline overlap border*/ + margin: 4px 8px 4px 2px; background-color: #FBFCFD; border: 1px solid #C4CFE5; } @@ -232,10 +264,19 @@ span.lineno a:hover { background-color: #C8C8C8; } +.lineno { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + div.ah, span.ah { background-color: black; font-weight: bold; - color: #ffffff; + color: #FFFFFF; margin-bottom: 3px; margin-top: 3px; padding: 0.2em; @@ -311,7 +352,7 @@ img.formulaDsp { } -img.formulaInl { +img.formulaInl, img.inline { vertical-align: middle; } @@ -389,6 +430,13 @@ blockquote { padding: 0 12px 0 16px; } +blockquote.DocNodeRTL { + border-left: 0; + border-right: 2px solid #9CAFD4; + margin: 0 4px 0 24px; + padding: 0 16px 0 12px; +} + /* @end */ /* @@ -501,6 +549,29 @@ table.memberdecls { /* Styles for detailed member documentation */ +.memtitle { + padding: 8px; + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + margin-bottom: -1px; + background-image: url('nav_f.png'); + background-repeat: repeat-x; + background-color: #E2E8F2; + line-height: 1.25; + font-weight: 300; + float:left; +} + +.permalink +{ + font-size: 65%; + display: inline-block; + vertical-align: middle; +} + .memtemplate { font-size: 80%; color: #4665A2; @@ -539,7 +610,7 @@ table.memberdecls { } .memname { - font-weight: bold; + font-weight: 400; margin-left: 6px; } @@ -555,24 +626,24 @@ table.memberdecls { color: #253555; font-weight: bold; text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); - background-image:url('nav_f.png'); - background-repeat:repeat-x; - background-color: #E2E8F2; + background-color: #DFE5F1; /* opera specific markup */ box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); border-top-right-radius: 4px; - border-top-left-radius: 4px; /* firefox specific markup */ -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; -moz-border-radius-topright: 4px; - -moz-border-radius-topleft: 4px; /* webkit specific markup */ -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); -webkit-border-top-right-radius: 4px; - -webkit-border-top-left-radius: 4px; } +.overload { + font-family: "courier new",courier,monospace; + font-size: 65%; +} + .memdoc, dl.reflist dd { border-bottom: 1px solid #A8B8D9; border-left: 1px solid #A8B8D9; @@ -630,17 +701,17 @@ dl.reflist dd { padding-left: 0px; } -.params .paramname, .retval .paramname { +.params .paramname, .retval .paramname, .tparams .paramname { font-weight: bold; vertical-align: top; } -.params .paramtype { +.params .paramtype, .tparams .paramtype { font-style: italic; vertical-align: top; } -.params .paramdir { +.params .paramdir, .tparams .paramdir { font-family: "courier new",courier,monospace; vertical-align: top; } @@ -914,6 +985,7 @@ table.fieldtable { padding-bottom: 4px; padding-top: 5px; text-align:left; + font-weight: 400; -moz-border-radius-topleft: 4px; -moz-border-radius-topright: 4px; -webkit-border-top-left-radius: 4px; @@ -1044,72 +1116,143 @@ div.headertitle padding: 5px 5px 5px 10px; } -dl -{ - padding: 0 0 0 10px; +.PageDocRTL-title div.headertitle { + text-align: right; + direction: rtl; } -/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ -dl.section -{ +dl { + padding: 0 0 0 0; +} + +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug, dl.examples */ +dl.section { margin-left: 0px; padding-left: 0px; } -dl.note -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #D0C000; +dl.section.DocNodeRTL { + margin-right: 0px; + padding-right: 0px; } -dl.warning, dl.attention -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #FF0000; +dl.note { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #D0C000; } -dl.pre, dl.post, dl.invariant -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #00D000; +dl.note.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #D0C000; } -dl.deprecated -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #505050; +dl.warning, dl.attention { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #FF0000; } -dl.todo -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #00C0E0; +dl.warning.DocNodeRTL, dl.attention.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #FF0000; } -dl.test -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #3030E0; +dl.pre, dl.post, dl.invariant { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #00D000; } -dl.bug -{ - margin-left:-7px; - padding-left: 3px; - border-left:4px solid; - border-color: #C08050; +dl.pre.DocNodeRTL, dl.post.DocNodeRTL, dl.invariant.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #00D000; +} + +dl.deprecated { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #505050; +} + +dl.deprecated.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #505050; +} + +dl.todo { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #00C0E0; +} + +dl.todo.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #00C0E0; +} + +dl.test { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #3030E0; +} + +dl.test.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #3030E0; +} + +dl.bug { + margin-left: -7px; + padding-left: 3px; + border-left: 4px solid; + border-color: #C08050; +} + +dl.bug.DocNodeRTL { + margin-left: 0; + padding-left: 0; + border-left: 0; + margin-right: -7px; + padding-right: 3px; + border-right: 4px solid; + border-color: #C08050; } dl.section dd { @@ -1178,6 +1321,11 @@ dl.section dd { text-align: center; } +.plantumlgraph +{ + text-align: center; +} + .diagraph { text-align: center; @@ -1221,6 +1369,11 @@ div.toc { width: 200px; } +.PageDocRTL-title div.toc { + float: left !important; + text-align: right; +} + div.toc li { background: url("bdwn.png") no-repeat scroll 0 5px transparent; font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; @@ -1229,6 +1382,12 @@ div.toc li { padding-top: 2px; } +.PageDocRTL-title div.toc li { + background-position-x: right !important; + padding-left: 0 !important; + padding-right: 10px; +} + div.toc h3 { font: bold 12px/1.2 Arial,FreeSans,sans-serif; color: #4665A2; @@ -1258,6 +1417,26 @@ div.toc li.level4 { margin-left: 45px; } +.PageDocRTL-title div.toc li.level1 { + margin-left: 0 !important; + margin-right: 0; +} + +.PageDocRTL-title div.toc li.level2 { + margin-left: 0 !important; + margin-right: 15px; +} + +.PageDocRTL-title div.toc li.level3 { + margin-left: 0 !important; + margin-right: 30px; +} + +.PageDocRTL-title div.toc li.level4 { + margin-left: 0 !important; + margin-right: 45px; +} + .inherit_header { font-weight: bold; color: gray; @@ -1371,7 +1550,7 @@ tr.heading h2 { } #powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { - border-top-color: #ffffff; + border-top-color: #FFFFFF; border-width: 10px; margin: 0px -10px; } @@ -1399,7 +1578,7 @@ tr.heading h2 { } #powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { - border-bottom-color: #ffffff; + border-bottom-color: #FFFFFF; border-width: 10px; margin: 0px -10px; } @@ -1426,7 +1605,7 @@ tr.heading h2 { left: 100%; } #powerTip.e:after { - border-left-color: #ffffff; + border-left-color: #FFFFFF; border-width: 10px; top: 50%; margin-top: -10px; @@ -1442,7 +1621,7 @@ tr.heading h2 { right: 100%; } #powerTip.w:after { - border-right-color: #ffffff; + border-right-color: #FFFFFF; border-width: 10px; top: 50%; margin-top: -10px; @@ -1473,3 +1652,113 @@ tr.heading h2 { } } +/* @group Markdown */ + +/* +table.markdownTable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.markdownTable td, table.markdownTable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.markdownTableHead tr { +} + +table.markdownTableBodyLeft td, table.markdownTable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +th.markdownTableHeadLeft th.markdownTableHeadRight th.markdownTableHeadCenter th.markdownTableHeadNone { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +th.markdownTableHeadLeft { + text-align: left +} + +th.markdownTableHeadRight { + text-align: right +} + +th.markdownTableHeadCenter { + text-align: center +} +*/ + +table.markdownTable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.markdownTable td, table.markdownTable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.markdownTable tr { +} + +th.markdownTableHeadLeft, th.markdownTableHeadRight, th.markdownTableHeadCenter, th.markdownTableHeadNone { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +th.markdownTableHeadLeft, td.markdownTableBodyLeft { + text-align: left +} + +th.markdownTableHeadRight, td.markdownTableBodyRight { + text-align: right +} + +th.markdownTableHeadCenter, td.markdownTableBodyCenter { + text-align: center +} + +.DocNodeRTL { + text-align: right; + direction: rtl; +} + +.DocNodeLTR { + text-align: left; + direction: ltr; +} + +table.DocNodeRTL { + width: auto; + margin-right: 0; + margin-left: auto; +} + +table.DocNodeLTR { + width: auto; + margin-right: auto; + margin-left: 0; +} + +tt, code, kbd, samp +{ + display: inline-block; + direction:ltr; +} +/* @end */ + +u { + text-decoration: underline; +} + diff --git a/dynsections.js b/dynsections.js index 1e6bf07f9f..9bff51b8b4 100644 --- a/dynsections.js +++ b/dynsections.js @@ -1,3 +1,26 @@ +/* + @licstart The following is the entire license notice for the + JavaScript code in this file. + + Copyright (C) 1997-2017 by Dimitri van Heesch + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + @licend The above is the entire license notice + for the JavaScript code in this file + */ function toggleVisibility(linkObj) { var base = $(linkObj).attr('id'); @@ -15,7 +38,7 @@ function toggleVisibility(linkObj) summary.hide(); $(linkObj).removeClass('closed').addClass('opened'); $(trigger).attr('src',src.substring(0,src.length-10)+'open.png'); - } + } return false; } @@ -94,7 +117,7 @@ function toggleInherit(id) $(img).attr('src',src.substring(0,src.length-10)+'open.png'); } } - +/* @license-end */ $(document).ready(function() { $('.code,.codeRef').each(function() { diff --git a/files.html b/files.html index f7841b9185..dcb4922da5 100644 --- a/files.html +++ b/files.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: File List @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
    Here is a list of all files with brief descriptions:
    -
    [detail level 123456]
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
    [detail level 1234567]
      src
      Tgstation.Server.Api
      Tgstation.Server.Client
      Tgstation.Server.Host
      Tgstation.Server.Host.Console
      Tgstation.Server.Host.Service
      Tgstation.Server.Host.Watchdog
      tests
      Tgstation.Server.Api.Tests
      Tgstation.Server.Client.Tests
      Tgstation.Server.Host.Console.Tests
      Tgstation.Server.Host.Service.Tests
      Tgstation.Server.Host.Tests
      Tgstation.Server.Host.Watchdog.Tests
      Tgstation.Server.Tests
      tools
      ReleaseNotes
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     docs
      src
      Tgstation.Server.Api
      Tgstation.Server.Client
      Tgstation.Server.Host
      Tgstation.Server.Host.Console
      Tgstation.Server.Host.Service
      Tgstation.Server.Host.Watchdog
      tests
      Tgstation.Server.Api.Tests
      Tgstation.Server.Client.Tests
      Tgstation.Server.Host.Console.Tests
      Tgstation.Server.Host.Service.Tests
      Tgstation.Server.Host.Tests
      Tgstation.Server.Host.Watchdog.Tests
      Tgstation.Server.Tests
      tools
      ReleaseNotes
    @@ -586,7 +574,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions.html b/functions.html index 906c665715..0485a80589 100644 --- a/functions.html +++ b/functions.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members @@ -11,9 +12,6 @@ - @@ -33,82 +31,22 @@
    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - a -

    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - b -

    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - c -

    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - d -

    - + - - - - + + + + @@ -192,7 +130,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_enum.html b/functions_enum.html index f0ca0798e5..ca31ccb536 100644 --- a/functions_enum.html +++ b/functions_enum.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Enumerations @@ -11,9 +12,6 @@ - @@ -33,53 +31,22 @@ - + - - - + + + + - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - f -

      +

      - f -

      • FetchOrigin() : Tgstation.Server.Host.Components.Repository.IRepository , Tgstation.Server.Host.Components.Repository.Repository @@ -164,7 +102,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_func.html b/functions_func.html index 02c213edc7..54180474c3 100644 --- a/functions_func.html +++ b/functions_func.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Functions @@ -11,9 +12,6 @@ - @@ -33,81 +31,22 @@
    - + - - - - + + + +
      -

    - a -

    - + - - - - + + + +
      -

    - b -

    - + - - - - + + + +
      -

    - c -

    - + - - - - + + + +
      -

    - d -

    - + - - - - + + + +
      -

    - e -

    - + - - - - + + + +
      -

    - f -

      +

      - f -

      • FetchOrigin() : Tgstation.Server.Host.Components.Repository.IRepository , Tgstation.Server.Host.Components.Repository.Repository @@ -155,7 +94,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_func_g.html b/functions_func_g.html index 64ebc23fa6..78cffff37c 100644 --- a/functions_func_g.html +++ b/functions_func_g.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Functions @@ -11,9 +12,6 @@ - @@ -33,81 +31,22 @@
    - + - - - - + + + +
      -

    - g -

    - + - - - - + + + +
      -

    - h -

      +

      - h -

      • HandleBadResponse() : Tgstation.Server.Client.ApiClient
      • @@ -180,7 +119,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_func_i.html b/functions_func_i.html index 21216af1e0..c7485cecd9 100644 --- a/functions_func_i.html +++ b/functions_func_i.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Functions @@ -11,9 +12,6 @@ - @@ -33,81 +31,22 @@
    - + - - - - + + + +
      -

    - i -

    - + - - - - + + + +
      -

    - j -

    - + - - - - + + + +
      -

    - k -

    - + - - - - + + + +
      -

    - l -

      +

      - l -

      • LatestCompileJob() : Tgstation.Server.Host.Components.IInstance , Tgstation.Server.Host.Components.Instance @@ -219,7 +158,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_func_m.html b/functions_func_m.html index ad221d378d..82f03e043b 100644 --- a/functions_func_m.html +++ b/functions_func_m.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Functions @@ -11,9 +12,6 @@ - @@ -33,81 +31,22 @@
    - + - - - - + + + +
      -

    - m -

    - + - - - - + + + +
      -

    - n -

      +

      - n -

    - + - - - - + + + +
      -

    - o -

      +

      - o -

      • OfflineInstance() : Tgstation.Server.Host.Components.IInstanceManager , Tgstation.Server.Host.Components.InstanceManager @@ -163,7 +102,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_func_p.html b/functions_func_p.html index 782678d94d..7f810ff898 100644 --- a/functions_func_p.html +++ b/functions_func_p.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Functions @@ -11,9 +12,6 @@ - @@ -33,81 +31,22 @@
    - + - - - - + + + +
      -

    - p -

      +

      - p -

      • Patch< TResult >() : Tgstation.Server.Client.ApiClient , Tgstation.Server.Client.IApiClient @@ -184,7 +123,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_func_r.html b/functions_func_r.html index 9531158966..e658ab0588 100644 --- a/functions_func_r.html +++ b/functions_func_r.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Functions @@ -11,9 +12,6 @@ - @@ -33,81 +31,22 @@
    - + - - - - + + + +
      -

    - r -

    - + - - - - + + + +
      -

    - s -

    - + - - - - + + + +
      -

    - t -

      +

      - t -

      • TemporaryDmbProvider() : Tgstation.Server.Host.Components.Compiler.TemporaryDmbProvider
      • @@ -351,7 +290,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_func_u.html b/functions_func_u.html index dca240a746..0b24b39f1b 100644 --- a/functions_func_u.html +++ b/functions_func_u.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Functions @@ -11,9 +12,6 @@ - @@ -33,81 +31,22 @@
    - + - - - - + + + +
      -

    - u -

    - + - - - - + + + +
      -

    - v -

      +

      - v -

      • ValidateConfigRelativePath() : Tgstation.Server.Host.Components.StaticFiles.Configuration
      • @@ -152,7 +91,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_func_w.html b/functions_func_w.html index e5bd529821..97d7b16c6b 100644 --- a/functions_func_w.html +++ b/functions_func_w.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Functions @@ -11,9 +12,6 @@ - @@ -33,81 +31,22 @@
    - + - - - - + + + +
      -

    - w -

    - + - - - - + + + +
      -

    - z -

      +

      - z -

      • ZipToDirectory() : Tgstation.Server.Host.IO.DefaultIOManager , Tgstation.Server.Host.IO.IIOManager @@ -137,7 +76,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_func_~.html b/functions_func_~.html new file mode 100644 index 0000000000..6fcf368135 --- /dev/null +++ b/functions_func_~.html @@ -0,0 +1,84 @@ + + + + + + + +tgstation-server: Class Members - Functions + + + + + + + + + +
        +
        + + + + + + + +
        +
        tgstation-server +
        +
        The /tg/station 13 server suite
        +
        +
        + + + + + + + +
        + +
        +
        + + +
        + +
        + +
        +  + +

        - ~ -

        +
        + + + + diff --git a/functions_g.html b/functions_g.html index 98b3679156..625ee24630 100644 --- a/functions_g.html +++ b/functions_g.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members @@ -11,9 +12,6 @@ - @@ -33,82 +31,22 @@
    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - g -

    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - h -

    diff --git a/functions_i.html b/functions_i.html index 32ec9987bc..4a6d7da8b6 100644 --- a/functions_i.html +++ b/functions_i.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members @@ -11,9 +12,6 @@ - @@ -33,82 +31,22 @@ - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - i -

    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - j -

    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - k -

    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - l -

    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - m -

    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - n -

    @@ -196,7 +134,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_o.html b/functions_o.html index a53cb057c9..00c4560938 100644 --- a/functions_o.html +++ b/functions_o.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members @@ -11,9 +12,6 @@ - @@ -33,82 +31,22 @@ - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - o -

    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - p -

    @@ -324,7 +262,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_prop.html b/functions_prop.html index 0731c75829..0a23f062bf 100644 --- a/functions_prop.html +++ b/functions_prop.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Properties @@ -11,9 +12,6 @@ - @@ -33,78 +31,22 @@ - + - - - - + + + +
      -

    - a -

    - + - - - - + + + +
      -

    - b -

    - + - - - - + + + +
      -

    - c -

    @@ -284,7 +223,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_prop_d.html b/functions_prop_d.html index ae0b280912..16116df0c2 100644 --- a/functions_prop_d.html +++ b/functions_prop_d.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Properties @@ -11,9 +12,6 @@ - @@ -33,78 +31,22 @@ - + - - - - + + + +
      -

    - d -

    - + - - - - + + + + @@ -146,7 +88,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_prop_f.html b/functions_prop_f.html index e2df914c24..87dbac364d 100644 --- a/functions_prop_f.html +++ b/functions_prop_f.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Properties @@ -11,9 +12,6 @@ - @@ -33,78 +31,22 @@ - + - - - - + + + +
      -

    - f -

      +

      - f -

      • FriendlyName : Tgstation.Server.Host.Components.Chat.Channel , Tgstation.Server.Host.Components.Chat.User @@ -134,7 +76,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_prop_g.html b/functions_prop_g.html index 073b632a07..d43243778c 100644 --- a/functions_prop_g.html +++ b/functions_prop_g.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Properties @@ -11,9 +12,6 @@ - @@ -33,78 +31,22 @@
    - + - - - - + + + +
      -

    - g -

      +

      - g -

      • GitHubAccessToken : Tgstation.Server.Host.Configuration.GeneralConfiguration
      • @@ -151,7 +93,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_prop_h.html b/functions_prop_h.html index ff854e1622..048281a16d 100644 --- a/functions_prop_h.html +++ b/functions_prop_h.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Properties @@ -11,9 +12,6 @@ - @@ -33,78 +31,22 @@
    - + - - - - + + + +
      -

    - h -

    - + - - - - + + + +
      -

    - i -

    - + - - - - + + + +
      -

    - j -

      +

      - j -

      • Job : Tgstation.Server.Api.Models.CompileJob , Tgstation.Server.Host.Models.CompileJob @@ -144,7 +86,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_prop_l.html b/functions_prop_l.html index cff26cc29f..bef0e5e071 100644 --- a/functions_prop_l.html +++ b/functions_prop_l.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Properties @@ -11,9 +12,6 @@ - @@ -33,78 +31,22 @@
    - + - - - - + + + +
      -

    - l -

    - + - - - - + + + +
      -

    - m -

    - + - - - - + + + + @@ -152,7 +94,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_prop_o.html b/functions_prop_o.html index 6939d881f9..570caac28f 100644 --- a/functions_prop_o.html +++ b/functions_prop_o.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Properties @@ -11,9 +12,6 @@ - @@ -33,78 +31,22 @@ - + - - - - + + + +
      -

    - o -

    - + - - - - + + + +
      -

    - p -

    @@ -207,7 +149,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_prop_r.html b/functions_prop_r.html index 2f98c73a8f..f2300dedd8 100644 --- a/functions_prop_r.html +++ b/functions_prop_r.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Properties @@ -11,9 +12,6 @@ - @@ -33,78 +31,22 @@ - + - - - - + + + +
      -

    - r -

    - + - - - - + + + +
      -

    - s -

    - + - - - - + + + +
      -

    - t -

    - + - - - - + + + +
      -

    - u -

    @@ -173,7 +115,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_prop_v.html b/functions_prop_v.html index 059f887b4d..4e638c0336 100644 --- a/functions_prop_v.html +++ b/functions_prop_v.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Properties @@ -11,9 +12,6 @@ - @@ -33,78 +31,22 @@ - + - - - - + + + +
      -

    - v -

      +

      - v -

      • Valid : Tgstation.Server.Api.Models.Internal.ChatConnectionStringBuilder
      • @@ -152,7 +94,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_prop_w.html b/functions_prop_w.html index a01221c2e7..8242de84c0 100644 --- a/functions_prop_w.html +++ b/functions_prop_w.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Properties @@ -11,9 +12,6 @@ - @@ -33,78 +31,22 @@
    - + - - - - + + + +
      -

    - w -

    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - q -

      +

      - q -

      • queryChannelIdMap : Tgstation.Server.Host.Components.Chat.Providers.IrcProvider
      • @@ -137,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_r.html b/functions_r.html index acc9f8fd73..dac5c8f48b 100644 --- a/functions_r.html +++ b/functions_r.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members @@ -11,9 +12,6 @@ - @@ -33,82 +31,22 @@
    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - r -

    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - s -

    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - t -

    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - u -

    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - v -

    - + - - - - + + + +
      -

    - a -

      +

      - a -

      • active : Tgstation.Server.Host.Components.Chat.JsonTrackingContext
      • @@ -249,7 +189,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_vars_b.html b/functions_vars_b.html index ed2d9ead59..06d65aaa5a 100644 --- a/functions_vars_b.html +++ b/functions_vars_b.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Variables @@ -11,9 +12,6 @@ - @@ -33,80 +31,22 @@
    - + - - - - + + + +
      -

    - b -

      +

      - b -

      • BDirectoryName : Tgstation.Server.Host.Components.Compiler.DreamMaker
      • @@ -200,7 +140,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_vars_c.html b/functions_vars_c.html index 49c8fc3409..68af2e19cb 100644 --- a/functions_vars_c.html +++ b/functions_vars_c.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Variables @@ -11,9 +12,6 @@ - @@ -33,80 +31,22 @@
    - + - - - - + + + +
      -

    - c -

      +

      - c -

      • cachedClients : Tgstation.Server.Client.InstanceManagerClient
      • @@ -274,7 +214,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_vars_d.html b/functions_vars_d.html index 11c5ace0a2..1941dc56fd 100644 --- a/functions_vars_d.html +++ b/functions_vars_d.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Variables @@ -11,9 +12,6 @@ - @@ -33,80 +31,22 @@
    - + - - - - + + + +
      -

    - d -

      +

      - d -

      • databaseContext : Tgstation.Server.Host.Security.AuthenticationContextFactory , Tgstation.Server.Host.Security.ClaimsInjector @@ -291,7 +231,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_vars_e.html b/functions_vars_e.html index a43414e8bb..2d22140a17 100644 --- a/functions_vars_e.html +++ b/functions_vars_e.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Variables @@ -11,9 +12,6 @@ - @@ -33,80 +31,22 @@
    - + - - - - + + + +
      -

    - e -

      +

      - e -

      • errorStringBuilder : Tgstation.Server.Host.Core.Process
      • @@ -149,7 +89,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_vars_f.html b/functions_vars_f.html index 96efe43074..b80b98e0d6 100644 --- a/functions_vars_f.html +++ b/functions_vars_f.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Variables @@ -11,9 +12,6 @@ - @@ -33,80 +31,22 @@
    - + - - - - + + + +
      -

    - f -

      +

      - f -

      • File : Tgstation.Server.Api.Routes
      • @@ -138,7 +78,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_vars_g.html b/functions_vars_g.html index d0b9933ae9..edc8e8b571 100644 --- a/functions_vars_g.html +++ b/functions_vars_g.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Variables @@ -11,9 +12,6 @@ - @@ -33,80 +31,22 @@
    - + - - - - + + + +
      -

    - g -

      +

      - g -

      • GameStaticFilesSubdirectory : Tgstation.Server.Host.Components.StaticFiles.Configuration
      • @@ -151,7 +91,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_vars_h.html b/functions_vars_h.html index de9fe9cdd2..31ca76a601 100644 --- a/functions_vars_h.html +++ b/functions_vars_h.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Variables @@ -11,9 +12,6 @@ - @@ -33,80 +31,22 @@
    - + - - - - + + + +
      -

    - h -

      +

      - h -

      • handle : Tgstation.Server.Host.Core.Process
      • @@ -163,7 +103,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_vars_i.html b/functions_vars_i.html index 24d8e18110..3cc91b48d3 100644 --- a/functions_vars_i.html +++ b/functions_vars_i.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Variables @@ -11,9 +12,6 @@ - @@ -33,80 +31,22 @@
    - + - - - - + + + +
      -

    - i -

      +

      - i -

      • identity : Tgstation.Server.Host.Security.WindowsSystemIdentity
      • @@ -233,7 +173,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_vars_j.html b/functions_vars_j.html index 099ed8867f..c6cbc7fd3b 100644 --- a/functions_vars_j.html +++ b/functions_vars_j.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Variables @@ -11,9 +12,6 @@ - @@ -33,80 +31,22 @@
    - + - - - - + + + +
      -

    - j -

    - + - - - - + + + +
      -

    - k -

      +

      - k -

      • Kek : Tgstation.Server.Host.Components.Chat.Commands.KekCommand
      • @@ -135,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_vars_l.html b/functions_vars_l.html index be7a7e25fa..1ed0f3d733 100644 --- a/functions_vars_l.html +++ b/functions_vars_l.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Variables @@ -11,9 +12,6 @@ - @@ -33,80 +31,22 @@
    - + - - - - + + + +
      -

    - l -

    - + - - - - + + + +
      -

    - m -

    - + - - - - + + + +
      -

    - n -

    - + - - - - + + + +
      -

    - o -

      +

      - o -

      • OctokitException : Tgstation.Server.Host.Controllers.AdministrationController
      • @@ -153,7 +93,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_vars_p.html b/functions_vars_p.html index e38cc065dc..c3005b94fe 100644 --- a/functions_vars_p.html +++ b/functions_vars_p.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Variables @@ -11,9 +12,6 @@ - @@ -33,80 +31,22 @@
    - + - - - - + + + +
      -

    - p -

    - + - - - - + + + +
      -

    - q -

      +

      - q -

      • queryChannelIdMap : Tgstation.Server.Host.Components.Chat.Providers.IrcProvider
      • @@ -135,7 +75,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_vars_r.html b/functions_vars_r.html index bbde0a2084..1db5ee25af 100644 --- a/functions_vars_r.html +++ b/functions_vars_r.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Variables @@ -11,9 +12,6 @@ - @@ -33,80 +31,22 @@
    - + - - - - + + + +
      -

    - r -

    - + - - - - + + + +
      -

    - s -

    - + - - - - + + + +
      -

    - t -

      +

      - t -

      • task : Tgstation.Server.Host.Core.JobHandler , Tgstation.Server.Host.Security.IdentityCacheObject @@ -179,7 +119,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_vars_u.html b/functions_vars_u.html index 69f342ab72..8df5161c4f 100644 --- a/functions_vars_u.html +++ b/functions_vars_u.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Variables @@ -11,9 +12,6 @@ - @@ -33,80 +31,22 @@
    - + - - - - + + + +
      -

    - u -

      +

      - u -

      • Uid : Tgstation.Server.Host.Security.WindowsSystemIdentity
      • @@ -165,7 +105,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_vars_v.html b/functions_vars_v.html index dc871eaee7..900e177079 100644 --- a/functions_vars_v.html +++ b/functions_vars_v.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Members - Variables @@ -11,9 +12,6 @@ - @@ -33,80 +31,22 @@
    - + - - - - + + + +
      -

    - v -

      +

      - v -

    - + - - - - + + + +
      -

    - w -

    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - w -

    - + - - - - + + + +
    Here is a list of all class members with links to the classes they belong to:
    -

    - z -

      +

      - z -

      • ZipToDirectory() : Tgstation.Server.Host.IO.DefaultIOManager , Tgstation.Server.Host.IO.IIOManager @@ -138,7 +76,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/functions_~.html b/functions_~.html new file mode 100644 index 0000000000..4011a3fb89 --- /dev/null +++ b/functions_~.html @@ -0,0 +1,84 @@ + + + + + + + +tgstation-server: Class Members + + + + + + + + + +
        +
        + + + + + + + +
        +
        tgstation-server +
        +
        The /tg/station 13 server suite
        +
        +
        + + + + + + + +
        + +
        +
        + + +
        + +
        + +
        +
        Here is a list of all class members with links to the classes they belong to:
        + +

        - ~ -

        +
        + + + + diff --git a/hierarchy.html b/hierarchy.html index ccf9ec0082..513f5042cd 100644 --- a/hierarchy.html +++ b/hierarchy.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Class Hierarchy @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + +
     CTgstation.Server.Host.Core.Tests.TestServiceCollectionExtensions.BadConfig3  CTgstation.Server.Api.Models.ByondRepresents a BYOND installation  CTgstation.Server.Tests.Instance.ByondTest - CTgstation.Server.Host.Components.Chat.ChannelRepresents a Providers.IProvider channel - CTgstation.Server.Host.Components.Chat.ChannelMappingRepresents a mapping of a Channel.RealId + CTgstation.Server.Host.Components.Chat.ChannelRepresents a Providers.IProvider channel + CTgstation.Server.Host.Components.Chat.ChannelMappingRepresents a mapping of a Channel.RealId  CTgstation.Server.Api.Models.Internal.ChatBotManage the server chat bots  CTgstation.Server.Api.Models.ChatBot  CTgstation.Server.Host.Models.ChatBot  CTgstation.Server.Api.Models.ChatChannelIndicates a chat channel  CTgstation.Server.Host.Models.ChatChannel  CTgstation.Server.Host.Components.Interop.ChatCommandRepresents a chat command to be handled by DD - CTgstation.Server.Api.Models.Internal.ChatConnectionStringBuilderHelper for building ChatBot.ConnectionStrings - CTgstation.Server.Api.Models.DiscordConnectionStringBuilderChatConnectionStringBuilder for ChatProvider.Discord - CTgstation.Server.Api.Models.IrcConnectionStringBuilderChatConnectionStringBuilder for ChatProvider.Irc + CTgstation.Server.Api.Models.Internal.ChatConnectionStringBuilderHelper for building ChatBot.ConnectionStrings + CTgstation.Server.Api.Models.DiscordConnectionStringBuilderChatConnectionStringBuilder for ChatProvider.Discord + CTgstation.Server.Api.Models.IrcConnectionStringBuilderChatConnectionStringBuilder for ChatProvider.Irc  CTgstation.Server.Host.Components.Interop.CommCommandRepresents a command from DD - CTgstation.Server.Api.Models.Internal.CompileJobRepresents a run of DreamMaker + CTgstation.Server.Api.Models.Internal.CompileJobRepresents a run of DreamMaker  CTgstation.Server.Api.Models.CompileJob  CTgstation.Server.Host.Models.CompileJob  CTgstation.Server.Api.Models.ConfigurationFileRepresents a game configuration file. Create and delete actions uncerimonuously overwrite/delete files  CTgstation.Server.Tests.Instance.ConfigurationTest - CTgstation.Server.Host.Components.Interop.ConstantsConstants used for communication with the DMAPI + CTgstation.Server.Host.Components.Interop.ConstantsConstants used for communication with the DMAPI  CController  CTgstation.Server.Host.Controllers.ApiControllerA Controller for API functions - CTgstation.Server.Host.Controllers.HomeControllerMain ApiController for the Application - CTgstation.Server.Host.Controllers.ModelController< TModel >An ApiController representing a TModel + CTgstation.Server.Host.Controllers.HomeControllerMain ApiController for the Application + CTgstation.Server.Host.Controllers.ModelController< TModel >An ApiController representing a TModel  CTgstation.Server.Host.Configuration.ControlPanelConfigurationConfiguration options for the web control panel  CTgstation.Server.Host.Configuration.DatabaseConfigurationConfiguration options for the Models.DatabaseContext<TParentContext>  CTgstation.Server.Host.Models.DatabaseContext< MySqlDatabaseContext > - CTgstation.Server.Host.Models.MySqlDatabaseContextDatabaseContext<TParentContext> for MySQL + CTgstation.Server.Host.Models.MySqlDatabaseContextDatabaseContext<TParentContext> for MySQL  CTgstation.Server.Host.Models.DatabaseContext< SqlServerDatabaseContext > - CTgstation.Server.Host.Models.SqlServerDatabaseContextDatabaseContext<TParentContext> for Sqlserver + CTgstation.Server.Host.Models.SqlServerDatabaseContextDatabaseContext<TParentContext> for Sqlserver  CDbContext  CTgstation.Server.Host.Models.DatabaseContext< TParentContext > - CTgstation.Server.Host.Models.Migrations.DesignTimeDbContextFactoryHelpersContains helpers for creating design time Models.DatabaseContext<TParentContext>s - CTgstation.Server.Api.Models.Internal.DreamDaemonLaunchParametersLaunch settings for DreamDaemon - CTgstation.Server.Api.Models.Internal.DreamDaemonSettingsConfigurable settings for DreamDaemon - CTgstation.Server.Api.Models.DreamDaemonRepresents an instance of BYOND's DreamDaemon game server. Create action starts the server. Delete action shuts down the server + CTgstation.Server.Host.Models.Migrations.DesignTimeDbContextFactoryHelpersContains helpers for creating design time DatabaseContext<TParentContext>s + CTgstation.Server.Api.Models.Internal.DreamDaemonLaunchParametersLaunch settings for DreamDaemon + CTgstation.Server.Api.Models.Internal.DreamDaemonSettingsConfigurable settings for DreamDaemon + CTgstation.Server.Api.Models.DreamDaemonRepresents an instance of BYOND's DreamDaemon game server. Create action starts the server. Delete action shuts down the server  CTgstation.Server.Host.Models.DreamDaemonSettings - CTgstation.Server.Api.Models.DreamMakerRepresents the state of the DreamMaker compiler. Create action starts a new compile. Delete action cancels the current compile + CTgstation.Server.Api.Models.DreamMakerRepresents the state of the DreamMaker compiler. Create action starts a new compile. Delete action cancels the current compile  CTgstation.Server.Host.Models.DreamMakerSettings  CTgstation.Server.Api.Models.ErrorMessageRepresents an error message returned by the server - CTgstation.Server.Host.Components.Interop.EventNotificationFor notifying DD of EventTypes + CTgstation.Server.Host.Components.Interop.EventNotificationFor notifying DD of EventTypes  CTgstation.Server.Host.Configuration.FileLoggingConfigurationFile logging configuration options  CTgstation.Server.Host.Configuration.GeneralConfigurationGeneral configuration options  CTgstation.Server.Host.Core.Tests.TestServiceCollectionExtensions.GoodConfig  CTgstation.Server.Client.IAdministrationClientFor managing server administration  CTgstation.Server.Client.AdministrationClient - CTgstation.Server.Client.IApiClientFactoryFor creating IApiClients + CTgstation.Server.Client.IApiClientFactoryFor creating IApiClients  CTgstation.Server.Client.ApiClientFactory  CTgstation.Server.Host.Core.IApplicationConfigures the ASP.NET Core web application  CTgstation.Server.Host.Core.Application @@ -162,24 +138,24 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CTgstation.Server.Client.Components.IByondClientFor managing the Byond installation  CTgstation.Server.Client.Components.ByondClient  CTgstation.Server.Host.Components.Byond.IByondInstallerFor downloading and installing BYOND extractions for a given system - CTgstation.Server.Host.Components.Byond.PosixByondInstallerIByondInstaller for Posix systems - CTgstation.Server.Host.Components.Byond.WindowsByondInstallerIByondInstaller for windows systems + CTgstation.Server.Host.Components.Byond.PosixByondInstallerIByondInstaller for Posix systems + CTgstation.Server.Host.Components.Byond.WindowsByondInstallerIByondInstaller for windows systems  CTgstation.Server.Client.Components.IChatBotsClientFor managing the chat bots  CTgstation.Server.Client.Components.ChatBotsClient - CTgstation.Server.Host.Components.Chat.IChatFactoryFor creating IChats + CTgstation.Server.Host.Components.Chat.IChatFactoryFor creating IChats  CTgstation.Server.Host.Components.Chat.ChatFactory - CTgstation.Server.Host.Security.IClaimsInjectorFor injecting System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look for + CTgstation.Server.Host.Security.IClaimsInjectorFor injecting System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look for  CTgstation.Server.Host.Security.ClaimsInjector  CTgstation.Server.Host.Components.Chat.Commands.ICommandRepresents a command that can be invoked by talking to chat bots  CTgstation.Server.Host.Components.Chat.Commands.ByondCommandFor displaying the installed Byond version  CTgstation.Server.Host.Components.Chat.Commands.CustomCommandRepresents a command made from DM code  CTgstation.Server.Host.Components.Chat.Commands.KekCommandkek  CTgstation.Server.Host.Components.Chat.Commands.PullRequestsCommandCommand for reading the active Api.Models.TestMerges - CTgstation.Server.Host.Components.Chat.Commands.RevisionCommandFor displaying Api.Models.Internal.RevisionInformation - CTgstation.Server.Host.Components.Chat.Commands.VersionCommandICommand to return the IApplication.VersionString - CTgstation.Server.Host.Components.Chat.Commands.ICommandFactoryFactory for built in ICommands + CTgstation.Server.Host.Components.Chat.Commands.RevisionCommandFor displaying Api.Models.Internal.RevisionInformation + CTgstation.Server.Host.Components.Chat.Commands.VersionCommandICommand to return the IApplication.VersionString + CTgstation.Server.Host.Components.Chat.Commands.ICommandFactoryFactory for built in ICommands  CTgstation.Server.Host.Components.Chat.Commands.CommandFactory - CTgstation.Server.Host.Components.Interop.ICommHandlerHandles CommCommands + CTgstation.Server.Host.Components.Interop.ICommHandlerHandles CommCommands  CTgstation.Server.Host.Components.Watchdog.SessionController  CTgstation.Server.Client.Components.IConfigurationClientFor managing ConfigurationFile files  CTgstation.Server.Client.Components.ConfigurationClient @@ -189,7 +165,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CTgstation.Server.Host.Components.Repository.CredentialsProvider  CTgstation.Server.Host.Security.ICryptographySuiteContains various cryptographic functions  CTgstation.Server.Host.Security.CryptographySuite - CTgstation.Server.Host.Components.Chat.ICustomCommandHandlerHandles Commands.ICommands that map to those defined in a IJsonTrackingContext + CTgstation.Server.Host.Components.Chat.ICustomCommandHandlerHandles Commands.ICommands that map to those defined in a IJsonTrackingContext  CTgstation.Server.Host.Components.Watchdog.Watchdog  CTgstation.Server.Host.Models.IDatabaseContextRepresents the database  CTgstation.Server.Host.Models.DatabaseContext< TParentContext > @@ -213,20 +189,20 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CTgstation.Server.Host.Components.Byond.ByondExecutableLock  CTgstation.Server.Host.Components.Byond.IByondManagerFor managing the BYOND installation  CTgstation.Server.Host.Components.Byond.ByondManager - CTgstation.Server.Host.Components.Byond.WindowsByondInstallerIByondInstaller for windows systems + CTgstation.Server.Host.Components.Byond.WindowsByondInstallerIByondInstaller for windows systems  CTgstation.Server.Host.Components.Chat.IChatFor managing connected chat services  CTgstation.Server.Host.Components.Chat.Chat  CTgstation.Server.Host.Components.Chat.IJsonTrackingContextRepresents a tracking of dynamic chat json files  CTgstation.Server.Host.Components.Chat.JsonTrackingContext  CTgstation.Server.Host.Components.Chat.Providers.IProviderFor interacting with a chat service  CTgstation.Server.Host.Components.Chat.Providers.Provider - CTgstation.Server.Host.Components.Chat.Providers.DiscordProviderIProvider for the Discord app - CTgstation.Server.Host.Components.Chat.Providers.IrcProviderIProvider for internet relay chat + CTgstation.Server.Host.Components.Chat.Providers.DiscordProviderIProvider for the Discord app + CTgstation.Server.Host.Components.Chat.Providers.IrcProviderIProvider for internet relay chat  CTgstation.Server.Host.Components.Compiler.ICompileJobConsumerSink for CompileJobs - CTgstation.Server.Host.Components.Compiler.DmbFactoryStandard IDmbFactory + CTgstation.Server.Host.Components.Compiler.DmbFactoryStandard IDmbFactory  CTgstation.Server.Host.Components.IDmbProviderProvides absolute paths to the latest compiled .dmbs  CTgstation.Server.Host.Components.Compiler.DmbProvider - CTgstation.Server.Host.Components.Compiler.TemporaryDmbProviderTemporary IDmbProvider + CTgstation.Server.Host.Components.Compiler.TemporaryDmbProviderTemporary IDmbProvider  CTgstation.Server.Host.Components.IInstanceFor interacting with the instance services  CTgstation.Server.Host.Components.Instance  CTgstation.Server.Host.Components.InstanceManager @@ -234,7 +210,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CTgstation.Server.Host.Components.Interop.CommContext  CTgstation.Server.Host.Components.Repository.IRepositoryRepresents an on-disk git repository  CTgstation.Server.Host.Components.Repository.Repository - CTgstation.Server.Host.Components.Repository.IRepositoryManagerFactory for creating and loading IRepositorys + CTgstation.Server.Host.Components.Repository.IRepositoryManagerFactory for creating and loading IRepositorys  CTgstation.Server.Host.Components.Repository.RepositoryManager  CTgstation.Server.Host.Components.StaticFiles.IConfigurationFor managing the Configuration directory  CTgstation.Server.Host.Components.StaticFiles.Configuration @@ -243,11 +219,11 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CTgstation.Server.Host.Components.Watchdog.WindowsNetworkPromptReaper  CTgstation.Server.Host.Core.IProcessBaseRepresents process lifetime  CTgstation.Server.Host.Components.Watchdog.ISessionControllerHandles communication with a DreamDaemon IProcess - CTgstation.Server.Host.Components.Watchdog.DeadSessionControllerImplements a fake "dead" ISessionController + CTgstation.Server.Host.Components.Watchdog.DeadSessionControllerImplements a fake "dead" ISessionController  CTgstation.Server.Host.Components.Watchdog.SessionController  CTgstation.Server.Host.Core.IProcessAbstraction over a System.Diagnostics.Process  CTgstation.Server.Host.Core.Process - CTgstation.Server.Host.Core.IRestartRegistrationRepresents the lifetime of a IRestartHandler registration + CTgstation.Server.Host.Core.IRestartRegistrationRepresents the lifetime of a IRestartHandler registration  CTgstation.Server.Host.Core.RestartRegistration  CTgstation.Server.Host.Core.JobHandlerClass for pairing Tasks with CancellationTokenSources  CTgstation.Server.Host.Core.JobManager @@ -256,189 +232,188 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CTgstation.Server.Host.Security.IAuthenticationContextRepresents the currently authenticated Api.Models.User  CTgstation.Server.Host.Security.AuthenticationContextManages Api.Models.Users for a scope  CTgstation.Server.Host.Security.IdentityCache - CTgstation.Server.Host.Security.IdentityCacheObjectFor keeping a specific ISystemIdentity alive for a period of time + CTgstation.Server.Host.Security.IdentityCacheObjectFor keeping a specific ISystemIdentity alive for a period of time  CTgstation.Server.Host.Security.ISystemIdentityRepresents a user on the current System.Runtime.InteropServices.OSPlatform - CTgstation.Server.Host.Security.WindowsSystemIdentityISystemIdentity for windows systems - CTgstation.Server.Host.Components.Compiler.IDmbFactoryFactory for IDmbProviders - CTgstation.Server.Host.Components.Compiler.DmbFactoryStandard IDmbFactory + CTgstation.Server.Host.Security.WindowsSystemIdentityISystemIdentity for windows systems + CTgstation.Server.Host.Components.Compiler.IDmbFactoryFactory for IDmbProviders + CTgstation.Server.Host.Components.Compiler.DmbFactoryStandard IDmbFactory  CTgstation.Server.Client.Components.IDreamDaemonClientFor managing DreamDaemon  CTgstation.Server.Client.Components.DreamDaemonClient  CTgstation.Server.Host.Components.Compiler.IDreamMakerFor managing the compiler  CTgstation.Server.Host.Components.Compiler.DreamMaker  CTgstation.Server.Client.Components.IDreamMakerClientFor managing the compiler  CTgstation.Server.Client.Components.DreamMakerClient - CTgstation.Server.Host.Components.IEventConsumerConsumes EventTypes and takes the appropriate actions + CTgstation.Server.Host.Components.IEventConsumerConsumes EventTypes and takes the appropriate actions  CTgstation.Server.Host.Components.EventConsumer  CTgstation.Server.Host.Components.StaticFiles.IConfigurationFor managing the Configuration directory  CTgstation.Server.Host.Components.Watchdog.IWatchdogRuns and monitors the twin server controllers - CIEventLog - CTgstation.Server.Host.Service.ServerServiceRepresents a IWatchdog as a ServiceBase - CTgstation.Server.Host.Core.IGitHubClientFactoryFor creating IGitHubClients - CTgstation.Server.Host.Core.GitHubClientFactory - CIHostedService - CTgstation.Server.Host.Components.Byond.IByondManagerFor managing the BYOND installation - CTgstation.Server.Host.Components.Chat.IChatFor managing connected chat services - CTgstation.Server.Host.Components.Compiler.ICompileJobConsumerSink for CompileJobs - CTgstation.Server.Host.Components.IInstanceFor interacting with the instance services - CTgstation.Server.Host.Components.IInstanceFactoryFactory for creating IInstances - CTgstation.Server.Host.Components.InstanceFactory - CTgstation.Server.Host.Components.InstanceManager - CTgstation.Server.Host.Components.StaticFiles.IConfigurationFor managing the Configuration directory - CTgstation.Server.Host.Components.Watchdog.IWatchdogRuns and monitors the twin server controllers - CTgstation.Server.Host.Components.Watchdog.WindowsNetworkPromptReaper - CTgstation.Server.Host.Core.IJobManagerManages the runtime of Jobs - CTgstation.Server.Host.Core.JobManager - CTgstation.Server.Host.Security.IIdentityCacheFor caching ISystemIdentitys - CTgstation.Server.Host.Security.IdentityCache - CTgstation.Server.Client.Components.IInstanceClientFor managing a single Instance - CTgstation.Server.Client.Components.InstanceClient - CTgstation.Server.Host.Components.IInstanceManagerFor managing IInstances - CTgstation.Server.Host.Components.InstanceManager - CTgstation.Server.Client.IInstanceManagerClientFor managing Instances - CTgstation.Server.Client.InstanceManagerClient - CTgstation.Server.Client.Components.IInstanceUserClientFor managing InstanceUsers - CTgstation.Server.Client.Components.InstanceUserClient - CTgstation.Server.Host.IO.IIOManagerInterface for using filesystems - CTgstation.Server.Host.IO.DefaultIOManagerIIOManager that resolves paths to Environment.CurrentDirectory - CTgstation.Server.Host.IO.ResolvingIOManagerAn IIOManager that resolve relative paths from another IIOManager to a subdirectory of that - CTgstation.Server.Client.Components.IJobsClientAccess to running jobs - CTgstation.Server.Client.Components.JobsClient - CTgstation.Server.Host.Components.Watchdog.INetworkPromptReaperOn Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort(). This looks out for those prompts and immediately clicks "Yes" if the owning process has registered for it - CTgstation.Server.Host.Components.Watchdog.PosixNetworkPromptReaper - CTgstation.Server.Host.Components.Watchdog.WindowsNetworkPromptReaper - CTgstation.Server.Api.Models.InstanceMetadata about a server instance - CTgstation.Server.Host.Models.InstanceRepresents an Api.Models.Instance in the database - CTgstation.Server.Tests.InstanceManagerTest - CTgstation.Server.Tests.Instance.InstanceTest - CTgstation.Server.Api.Models.InstanceUserRepresents a Users permissions in an Instance - CTgstation.Server.Host.Models.InstanceUser - CTgstation.Server.Tests.IntegrationTest - CTgstation.Server.Host.Core.IPlatformIdentifierFor identifying the current platform - CTgstation.Server.Host.Core.PlatformIdentifier - CTgstation.Server.Host.IO.IPostWriteHandlerHandles changing file modes/permissions after writing - CTgstation.Server.Host.IO.PosixPostWriteHandlerIPostWriteHandler for POSIX systems - CTgstation.Server.Host.IO.WindowsPostWriteHandlerIPostWriteHandler for Windows systems - CTgstation.Server.Host.Core.IProcessExecutorFor launching IProcess' - CTgstation.Server.Host.Core.ProcessExecutor - CTgstation.Server.Host.Components.Chat.IProviderFactoryFactory for IProviders - CTgstation.Server.Host.Components.Chat.ProviderFactory - CTgstation.Server.Host.Components.Watchdog.IReattachInfoHandlerHandles saving and loading WatchdogReattachInformation - CTgstation.Server.Host.Components.ReattachInfoHandler - CTgstation.Server.Client.Components.IRepositoryClientFor managing the Repository - CTgstation.Server.Client.Components.RepositoryClient - CTgstation.Server.Client.IRequestLoggerFor logging HTTP requests and responses - CTgstation.Server.Host.Core.IRestartHandlerHandler for server restarts - CTgstation.Server.Host.Components.Chat.Chat - CTgstation.Server.Host.Components.InstanceManager - CTgstation.Server.Host.Components.Watchdog.Watchdog - CTgstation.Server.Host.IServerRepresents the host - CTgstation.Server.Host.Server - CTgstation.Server.Tests.TestingServer - CTgstation.Server.Client.IServerClientFactoryFactory for creating IServerClients - CTgstation.Server.Client.ServerClientFactory - CTgstation.Server.Host.Core.IServerControlRepresents a service that may take an updated Host assembly and run it, stopping the current assembly in the process - CTgstation.Server.Host.Server - CTgstation.Server.Host.IServerFactoryFor creating IServers - CTgstation.Server.Host.ServerFactory - CTgstation.Server.Host.Components.Watchdog.ISessionControllerFactoryFactory for ISessionControllers - CTgstation.Server.Host.Components.Watchdog.SessionControllerFactory - CTgstation.Server.Host.Core.ISetupWizardThe command line Configuration setup wizard - CTgstation.Server.Host.Core.SetupWizard - CTgstation.Server.Host.Core.Tests.TestApplication.MockSetupWizard - CTgstation.Server.Host.IO.ISymlinkFactoryFor creating filesystem symbolic links - CTgstation.Server.Host.IO.PosixSymlinkFactoryISymlinkFactory for posix systems - CTgstation.Server.Host.IO.WindowsSymlinkFactoryISymlinkFactory for windows systems - CTgstation.Server.Host.IO.ISynchronousIOManagerFor accessing the disk in a synchronous manner - CTgstation.Server.Host.IO.SynchronousIOManager - CTgstation.Server.Host.Security.ISystemIdentityFactoryFactory for ISystemIdentitys - CTgstation.Server.Host.Security.PosixSystemIdentityFactoryISystemIdentityFactory for posix systems - CTgstation.Server.Host.Security.WindowsSystemIdentityFactoryISystemIdentityFactory for windows systems. Uses long running tasks due to potential networked domains - CTgstation.Server.Host.Security.ITokenFactoryFor creating Tokens - CTgstation.Server.Host.Security.TokenFactory - CTgstation.Server.Client.IUsersClientFor managing Users - CTgstation.Server.Client.UsersClient - CTgstation.Server.Host.Watchdog.IWatchdogThe watchdog for a Host - CTgstation.Server.Host.Watchdog.Watchdog - CTgstation.Server.Host.Watchdog.IWatchdogFactoryFactory for creating IWatchdogs - CTgstation.Server.Host.Watchdog.WatchdogFactory - CTgstation.Server.Host.Components.Watchdog.IWatchdogFactoryFor creating IWatchdogs - CTgstation.Server.Host.Components.Watchdog.WatchdogFactory - CTgstation.Server.Api.Models.Internal.JobRepresents a long running job - CTgstation.Server.Api.Models.JobRepresents a long running job on the server. Model is read-only, updates attempt to cancel the job - CTgstation.Server.Host.Models.Job - CJsonConverter - CTgstation.Server.Host.Components.Chat.Commands.BoolConverterJsonConverter for decoding bools returned by BYOND - CTgstation.Server.Host.Components.Interop.JsonFileRepresentation of the initial json passed to DreamDaemon - CTgstation.Server.Host.Components.Interop.JsonSubFileListInformation used in for reattaching and interop - CTgstation.Server.Host.Models.ReattachInformationBaseBase class for ReattachInformation - CTgstation.Server.Host.Components.Watchdog.ReattachInformationParameters necessary for duplicating a ISessionController session - CTgstation.Server.Host.Models.ReattachInformationDatabase representation of Components.Watchdog.ReattachInformation - CTgstation.Server.Host.Components.Watchdog.LaunchResultRepresents the result of trying to start a DD process - CTgstation.Server.Host.Components.Chat.Providers.MessageRepresents a message recieved by a IProvider - CMigration - CTgstation.Server.Host.Models.Migrations.MSAddMinimumSecurityAdd the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel columns for MSSQL - CTgstation.Server.Host.Models.Migrations.MSFixRevInfoIndexMake commit shas non-unique per Instance for MSSQL - CTgstation.Server.Host.Models.Migrations.MSInitialCreateThe initial database migration for MSSQL - CTgstation.Server.Host.Models.Migrations.MSNullableAndForeignKeyCleanupCleans up of nullable columns and foreign keys MSSQL - CTgstation.Server.Host.Models.Migrations.MSReattachCompileJobRequiredMarks the CompileJobs of ReattachInformations as non-nullable for MSSQL - CTgstation.Server.Host.Models.Migrations.MSToggleTestmergeCommentsAdd the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MSSQL - CTgstation.Server.Host.Models.Migrations.MYAddMinimumSecurityAdd the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel columns for MySQL/MariaDB - CTgstation.Server.Host.Models.Migrations.MYFixRevInfoIndexMake commit shas non-unique per Instance for MSSQL - CTgstation.Server.Host.Models.Migrations.MYInitialCreateThe initial database migration for MySQL/MariaDB - CTgstation.Server.Host.Models.Migrations.MYNullableAndForeignKeyCleanupCleans up of nullable columns and foreign keys MySQL/MariaDB - CTgstation.Server.Host.Models.Migrations.MYReattachCompileJobRequiredMarks the CompileJobs of ReattachInformations as non-nullable for MySQL/MariaDB - CTgstation.Server.Host.Models.Migrations.MYToggleTestmergeCommentsAdd the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MySQL/MariaDB - CTgstation.Server.Host.Controllers.ModelController< Administration > - CTgstation.Server.Host.Controllers.AdministrationControllerModelController<TModel> for Administration - CTgstation.Server.Host.Controllers.ModelController< Api.Models.Byond > - CTgstation.Server.Host.Controllers.ByondControllerController for managing Api.Models.Byond.Versions - CTgstation.Server.Host.Controllers.ModelController< Api.Models.ChatBot > - CTgstation.Server.Host.Controllers.ChatControllerModelController<TModel> for managing Api.Models.ChatBots - CTgstation.Server.Host.Controllers.ModelController< Api.Models.Instance > - CTgstation.Server.Host.Controllers.InstanceControllerController for managing Components.Instances - CTgstation.Server.Host.Controllers.ModelController< Api.Models.InstanceUser > - CTgstation.Server.Host.Controllers.InstanceUserControllerFor managing Users - CTgstation.Server.Host.Controllers.ModelController< Api.Models.Job > - CTgstation.Server.Host.Controllers.JobControllerModelController<TModel> for Api.Models.Jobs - CTgstation.Server.Host.Controllers.ModelController< ConfigurationFile > - CTgstation.Server.Host.Controllers.ConfigurationControllerThe ModelController<TModel> for ConfigurationFiles - CTgstation.Server.Host.Controllers.ModelController< DreamDaemon > - CTgstation.Server.Host.Controllers.DreamDaemonControllerModelController<TModel> for managing the DreamDaemon - CTgstation.Server.Host.Controllers.ModelController< DreamMaker > - CTgstation.Server.Host.Controllers.DreamMakerControllerController for managing the compiler - CTgstation.Server.Host.Controllers.ModelController< Repository > - CTgstation.Server.Host.Controllers.RepositoryControllerController for managing the Repositorys - CTgstation.Server.Host.Controllers.ModelController< UserUpdate > - CTgstation.Server.Host.Controllers.UserControllerFor managing Users - CModelSnapshot - CTgstation.Server.Host.Models.Migrations.MySqlDatabaseContextModelSnapshot - CTgstation.Server.Host.Models.Migrations.SqlServerDatabaseContextModelSnapshot - CTgstation.Server.Host.Components.Watchdog.MonitorStateThe (absolute) state of the Watchdog - CTgstation.Server.Host.NativeMethodsNative methods used by the code - CTgstation.Server.Host.ProgramEntrypoint for the Process - CTgstation.Server.Host.Service.ProgramContains the entrypoint for the application - CTgstation.Server.Host.Console.ProgramContains the entrypoint for the application - CReleaseNotes.ProgramContains the application entrypoint - CTgstation.Server.Api.Models.Internal.RepositorySettingsRepresents configurable settings for a Repository - CTgstation.Server.Api.Models.RepositoryRepresents a git repository - CTgstation.Server.Host.Models.RepositorySettings - CTgstation.Server.Host.Components.Chat.ResponseRepresents a chat message requested by DD - CTgstation.Server.Host.Models.RevInfoTestMergeMany to many relationship for Models.RevisionInformation and Models.TestMerge - CTgstation.Server.Api.Models.Internal.RevisionInformationRepresents information about a current git revison - CTgstation.Server.Api.Models.RevisionInformation - CTgstation.Server.Host.Models.RevisionInformation - CTgstation.Server.Api.Rights.RightsHelperHelper for RightsTypes - CTgstation.Server.Api.RoutesRoutes to a server actions - CTgstation.Server.Api.Models.ServerInformationRepresents basic server information - CTgstation.Server.Host.Components.StaticFiles.ServerSideModificationsRepresents code modifications via configuration - CServiceBase - CTgstation.Server.Host.Service.ServerServiceRepresents a IWatchdog as a ServiceBase - CTgstation.Server.Host.Core.ServiceCollectionExtensionsExtensions for IServiceCollection + CTgstation.Server.Host.Core.IGitHubClientFactoryFor creating IGitHubClients + CTgstation.Server.Host.Core.GitHubClientFactory + CIHostedService + CTgstation.Server.Host.Components.Byond.IByondManagerFor managing the BYOND installation + CTgstation.Server.Host.Components.Chat.IChatFor managing connected chat services + CTgstation.Server.Host.Components.Compiler.ICompileJobConsumerSink for CompileJobs + CTgstation.Server.Host.Components.IInstanceFor interacting with the instance services + CTgstation.Server.Host.Components.IInstanceFactoryFactory for creating IInstances + CTgstation.Server.Host.Components.InstanceFactory + CTgstation.Server.Host.Components.InstanceManager + CTgstation.Server.Host.Components.StaticFiles.IConfigurationFor managing the Configuration directory + CTgstation.Server.Host.Components.Watchdog.IWatchdogRuns and monitors the twin server controllers + CTgstation.Server.Host.Components.Watchdog.WindowsNetworkPromptReaper + CTgstation.Server.Host.Core.IJobManagerManages the runtime of Jobs + CTgstation.Server.Host.Core.JobManager + CTgstation.Server.Host.Security.IIdentityCacheFor caching ISystemIdentitys + CTgstation.Server.Host.Security.IdentityCache + CTgstation.Server.Client.Components.IInstanceClientFor managing a single Instance + CTgstation.Server.Client.Components.InstanceClient + CTgstation.Server.Host.Components.IInstanceManagerFor managing IInstances + CTgstation.Server.Host.Components.InstanceManager + CTgstation.Server.Client.IInstanceManagerClientFor managing Instances + CTgstation.Server.Client.InstanceManagerClient + CTgstation.Server.Client.Components.IInstanceUserClientFor managing InstanceUsers + CTgstation.Server.Client.Components.InstanceUserClient + CTgstation.Server.Host.IO.IIOManagerInterface for using filesystems + CTgstation.Server.Host.IO.DefaultIOManagerIIOManager that resolves paths to Environment.CurrentDirectory + CTgstation.Server.Host.IO.ResolvingIOManagerAn IIOManager that resolve relative paths from another IIOManager to a subdirectory of that + CTgstation.Server.Client.Components.IJobsClientAccess to running jobs + CTgstation.Server.Client.Components.JobsClient + CTgstation.Server.Host.Components.Watchdog.INetworkPromptReaperOn Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort(). This looks out for those prompts and immediately clicks "Yes" if the owning process has registered for it + CTgstation.Server.Host.Components.Watchdog.PosixNetworkPromptReaper + CTgstation.Server.Host.Components.Watchdog.WindowsNetworkPromptReaper + CTgstation.Server.Api.Models.InstanceMetadata about a server instance + CTgstation.Server.Host.Models.InstanceRepresents an Api.Models.Instance in the database + CTgstation.Server.Tests.InstanceManagerTest + CTgstation.Server.Tests.Instance.InstanceTest + CTgstation.Server.Api.Models.InstanceUserRepresents a Users permissions in an Instance + CTgstation.Server.Host.Models.InstanceUser + CTgstation.Server.Tests.IntegrationTest + CTgstation.Server.Host.Core.IPlatformIdentifierFor identifying the current platform + CTgstation.Server.Host.Core.PlatformIdentifier + CTgstation.Server.Host.IO.IPostWriteHandlerHandles changing file modes/permissions after writing + CTgstation.Server.Host.IO.PosixPostWriteHandlerIPostWriteHandler for POSIX systems + CTgstation.Server.Host.IO.WindowsPostWriteHandlerIPostWriteHandler for Windows systems + CTgstation.Server.Host.Core.IProcessExecutorFor launching IProcess' + CTgstation.Server.Host.Core.ProcessExecutor + CTgstation.Server.Host.Components.Chat.IProviderFactoryFactory for IProviders + CTgstation.Server.Host.Components.Chat.ProviderFactory + CTgstation.Server.Host.Components.Watchdog.IReattachInfoHandlerHandles saving and loading WatchdogReattachInformation + CTgstation.Server.Host.Components.ReattachInfoHandler + CTgstation.Server.Client.Components.IRepositoryClientFor managing the Repository + CTgstation.Server.Client.Components.RepositoryClient + CTgstation.Server.Client.IRequestLoggerFor logging HTTP requests and responses + CTgstation.Server.Host.Core.IRestartHandlerHandler for server restarts + CTgstation.Server.Host.Components.Chat.Chat + CTgstation.Server.Host.Components.InstanceManager + CTgstation.Server.Host.Components.Watchdog.Watchdog + CTgstation.Server.Host.IServerRepresents the host + CTgstation.Server.Host.Server + CTgstation.Server.Tests.TestingServer + CTgstation.Server.Client.IServerClientFactoryFactory for creating IServerClients + CTgstation.Server.Client.ServerClientFactory + CTgstation.Server.Host.Core.IServerControlRepresents a service that may take an updated Host assembly and run it, stopping the current assembly in the process + CTgstation.Server.Host.Server + CTgstation.Server.Host.IServerFactoryFor creating IServers + CTgstation.Server.Host.ServerFactory + CTgstation.Server.Host.Components.Watchdog.ISessionControllerFactoryFactory for ISessionControllers + CTgstation.Server.Host.Components.Watchdog.SessionControllerFactory + CTgstation.Server.Host.Core.ISetupWizardThe command line Configuration setup wizard + CTgstation.Server.Host.Core.SetupWizard + CTgstation.Server.Host.Core.Tests.TestApplication.MockSetupWizard + CTgstation.Server.Host.IO.ISymlinkFactoryFor creating filesystem symbolic links + CTgstation.Server.Host.IO.PosixSymlinkFactoryISymlinkFactory for posix systems + CTgstation.Server.Host.IO.WindowsSymlinkFactoryISymlinkFactory for windows systems + CTgstation.Server.Host.IO.ISynchronousIOManagerFor accessing the disk in a synchronous manner + CTgstation.Server.Host.IO.SynchronousIOManager + CTgstation.Server.Host.Security.ISystemIdentityFactoryFactory for ISystemIdentitys + CTgstation.Server.Host.Security.PosixSystemIdentityFactoryISystemIdentityFactory for posix systems + CTgstation.Server.Host.Security.WindowsSystemIdentityFactoryISystemIdentityFactory for windows systems. Uses long running tasks due to potential networked domains + CTgstation.Server.Host.Security.ITokenFactoryFor creating Tokens + CTgstation.Server.Host.Security.TokenFactory + CTgstation.Server.Client.IUsersClientFor managing Users + CTgstation.Server.Client.UsersClient + CTgstation.Server.Host.Watchdog.IWatchdogThe watchdog for a Host + CTgstation.Server.Host.Watchdog.Watchdog + CTgstation.Server.Host.Watchdog.IWatchdogFactoryFactory for creating IWatchdogs + CTgstation.Server.Host.Watchdog.WatchdogFactory + CTgstation.Server.Host.Components.Watchdog.IWatchdogFactoryFor creating IWatchdogs + CTgstation.Server.Host.Components.Watchdog.WatchdogFactory + CTgstation.Server.Api.Models.Internal.JobRepresents a long running job + CTgstation.Server.Api.Models.JobRepresents a long running job on the server. Model is read-only, updates attempt to cancel the job + CTgstation.Server.Host.Models.Job + CJsonConverter + CTgstation.Server.Host.Components.Chat.Commands.BoolConverterJsonConverter for decoding bools returned by BYOND + CTgstation.Server.Host.Components.Interop.JsonFileRepresentation of the initial json passed to DreamDaemon + CTgstation.Server.Host.Components.Interop.JsonSubFileListInformation used in for reattaching and interop + CTgstation.Server.Host.Models.ReattachInformationBaseBase class for ReattachInformation + CTgstation.Server.Host.Components.Watchdog.ReattachInformationParameters necessary for duplicating a ISessionController session + CTgstation.Server.Host.Models.ReattachInformationDatabase representation of Components.Watchdog.ReattachInformation + CTgstation.Server.Host.Components.Watchdog.LaunchResultRepresents the result of trying to start a DD process + CTgstation.Server.Host.Components.Chat.Providers.MessageRepresents a message recieved by a IProvider + CMigration + CTgstation.Server.Host.Models.Migrations.MSAddMinimumSecurityAdd the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel columns for MSSQL + CTgstation.Server.Host.Models.Migrations.MSFixRevInfoIndexMake commit shas non-unique per Instance for MSSQL + CTgstation.Server.Host.Models.Migrations.MSInitialCreateThe initial database migration for MSSQL + CTgstation.Server.Host.Models.Migrations.MSNullableAndForeignKeyCleanupCleans up of nullable columns and foreign keys MSSQL + CTgstation.Server.Host.Models.Migrations.MSReattachCompileJobRequiredMarks the CompileJobs of ReattachInformations as non-nullable for MSSQL + CTgstation.Server.Host.Models.Migrations.MSToggleTestmergeCommentsAdd the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MSSQL + CTgstation.Server.Host.Models.Migrations.MYAddMinimumSecurityAdd the Api.Models.Internal.CompileJob.MinimumSecurityLevel and DreamMaker.ApiValidationSecurityLevel columns for MySQL/MariaDB + CTgstation.Server.Host.Models.Migrations.MYFixRevInfoIndexMake commit shas non-unique per Instance for MSSQL + CTgstation.Server.Host.Models.Migrations.MYInitialCreateThe initial database migration for MySQL/MariaDB + CTgstation.Server.Host.Models.Migrations.MYNullableAndForeignKeyCleanupCleans up of nullable columns and foreign keys MySQL/MariaDB + CTgstation.Server.Host.Models.Migrations.MYReattachCompileJobRequiredMarks the CompileJobs of ReattachInformations as non-nullable for MySQL/MariaDB + CTgstation.Server.Host.Models.Migrations.MYToggleTestmergeCommentsAdd the Api.Models.Internal.RepositorySettings.PostTestMergeComment column for MySQL/MariaDB + CTgstation.Server.Host.Controllers.ModelController< Administration > + CTgstation.Server.Host.Controllers.AdministrationControllerModelController<TModel> for Administration + CTgstation.Server.Host.Controllers.ModelController< Api.Models.Byond > + CTgstation.Server.Host.Controllers.ByondControllerController for managing Api.Models.Byond.Versions + CTgstation.Server.Host.Controllers.ModelController< Api.Models.ChatBot > + CTgstation.Server.Host.Controllers.ChatControllerModelController<TModel> for managing Api.Models.ChatBots + CTgstation.Server.Host.Controllers.ModelController< Api.Models.Instance > + CTgstation.Server.Host.Controllers.InstanceControllerController for managing Components.Instances + CTgstation.Server.Host.Controllers.ModelController< Api.Models.InstanceUser > + CTgstation.Server.Host.Controllers.InstanceUserControllerFor managing Users + CTgstation.Server.Host.Controllers.ModelController< Api.Models.Job > + CTgstation.Server.Host.Controllers.JobControllerModelController<TModel> for Api.Models.Jobs + CTgstation.Server.Host.Controllers.ModelController< ConfigurationFile > + CTgstation.Server.Host.Controllers.ConfigurationControllerThe ModelController<TModel> for ConfigurationFiles + CTgstation.Server.Host.Controllers.ModelController< DreamDaemon > + CTgstation.Server.Host.Controllers.DreamDaemonControllerModelController<TModel> for managing the DreamDaemon + CTgstation.Server.Host.Controllers.ModelController< DreamMaker > + CTgstation.Server.Host.Controllers.DreamMakerControllerController for managing the compiler + CTgstation.Server.Host.Controllers.ModelController< Repository > + CTgstation.Server.Host.Controllers.RepositoryControllerController for managing the Repositorys + CTgstation.Server.Host.Controllers.ModelController< UserUpdate > + CTgstation.Server.Host.Controllers.UserControllerFor managing Users + CModelSnapshot + CTgstation.Server.Host.Models.Migrations.MySqlDatabaseContextModelSnapshot + CTgstation.Server.Host.Models.Migrations.SqlServerDatabaseContextModelSnapshot + CTgstation.Server.Host.Components.Watchdog.MonitorStateThe (absolute) state of the Watchdog + CTgstation.Server.Host.NativeMethodsNative methods used by the code + CTgstation.Server.Host.ProgramEntrypoint for the Process + CTgstation.Server.Host.Service.ProgramContains the entrypoint for the application + CTgstation.Server.Host.Console.ProgramContains the entrypoint for the application + CReleaseNotes.ProgramContains the application entrypoint + CTgstation.Server.Api.Models.Internal.RepositorySettingsRepresents configurable settings for a Repository + CTgstation.Server.Api.Models.RepositoryRepresents a git repository + CTgstation.Server.Host.Models.RepositorySettings + CTgstation.Server.Host.Components.Chat.ResponseRepresents a chat message requested by DD + CTgstation.Server.Host.Models.RevInfoTestMergeMany to many relationship for Models.RevisionInformation and Models.TestMerge + CTgstation.Server.Api.Models.Internal.RevisionInformationRepresents information about a current git revison + CTgstation.Server.Api.Models.RevisionInformation + CTgstation.Server.Host.Models.RevisionInformation + CTgstation.Server.Api.Rights.RightsHelperHelper for RightsTypes + CTgstation.Server.Api.RoutesRoutes to a server actions + CTgstation.Server.Api.Models.ServerInformationRepresents basic server information + CTgstation.Server.Host.Components.StaticFiles.ServerSideModificationsRepresents code modifications via configuration + CServiceBase + CTgstation.Server.Host.Service.ServerServiceRepresents a IWatchdog as a ServiceBase + CTgstation.Server.Host.Core.ServiceCollectionExtensionsExtensions for IServiceCollection + CTgstation.Server.Host.Core.TaskExtensionsExtensions for the Task class  CTgstation.Server.Client.Tests.TestApiClient - CTgstation.Server.Api.Tests.TestApiHeadersTests for ApiHeaders + CTgstation.Server.Api.Tests.TestApiHeadersTests for ApiHeaders  CTgstation.Server.Host.Core.Tests.TestApplicationTests for Application  CTgstation.Server.Host.Core.Tests.TestAsyncDelayer - CTgstation.Server.Host.Security.Tests.TestAuthenticationContextTests for AuthenticationContext + CTgstation.Server.Host.Security.Tests.TestAuthenticationContextTests for AuthenticationContext  CTgstation.Server.Host.IO.Tests.TestConsole  CTgstation.Server.Host.Core.Tests.TestDatabaseContextFactory  CTgstation.Server.Host.Core.Tests.TestDBConnectionFactory @@ -461,25 +436,25 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');  CTgstation.Server.Api.Rights.Tests.TestRightsTests for Rights  CTgstation.Server.Client.Tests.TestServerClientFactory  CTgstation.Server.Host.Tests.TestServerFactoryTests for ServerFactory - CTgstation.Server.Host.Service.Tests.TestServerServiceTests for ServerService + CTgstation.Server.Host.Service.Tests.TestServerServiceTests for ServerService  CTgstation.Server.Host.Core.Tests.TestServiceCollectionExtensions  CTgstation.Server.Host.Core.Tests.TestSetupWizard  CTgstation.Server.Host.IO.Tests.TestSymlinkFactory - CTgstation.Server.Host.Components.Watchdog.Tests.TestWatchdog - CTgstation.Server.Host.Watchdog.Tests.TestWatchdog + CTgstation.Server.Host.Watchdog.Tests.TestWatchdog + CTgstation.Server.Host.Components.Watchdog.Tests.TestWatchdog  CTgstation.Server.Host.Watchdog.Tests.TestWatchdogFactoryTests for WatchdogFactory  CTgstation.Server.Api.Models.TokenRepresents a JWT returned by the API  CTgstation.Server.Host.Configuration.UpdatesConfigurationConfiguration for the automatic update system - CTgstation.Server.Api.Models.Internal.UserRepresents a server User + CTgstation.Server.Api.Models.Internal.UserRepresents a server User  CTgstation.Server.Api.Models.User  CTgstation.Server.Api.Models.UserUpdateFor editing a given User. Will never be returned by the API  CTgstation.Server.Host.Models.User  CTgstation.Server.Host.Components.Chat.UserRepresents a tgs_chat_user datum - CTgstation.Server.Host.Models.WatchdogReattachInformationBaseBase class for WatchdogReattachInformation - CTgstation.Server.Host.Components.Watchdog.WatchdogReattachInformationReattach information for a IWatchdog - CTgstation.Server.Host.Models.WatchdogReattachInformationDatabase representation of Components.Watchdog.WatchdogReattachInformation + CTgstation.Server.Host.Models.WatchdogReattachInformationBaseBase class for WatchdogReattachInformation + CTgstation.Server.Host.Components.Watchdog.WatchdogReattachInformationReattach information for a IWatchdog + CTgstation.Server.Host.Models.WatchdogReattachInformationDatabase representation of Components.Watchdog.WatchdogReattachInformation  CException - CTgstation.Server.Client.ClientExceptionExceptions thrown by IServerClients + CTgstation.Server.Client.ClientExceptionExceptions thrown by IServerClients  CTgstation.Server.Client.ApiConflictExceptionOccurs when the server returns an unknown response  CTgstation.Server.Client.ApiMismatchExceptionOccurs when the API version of the client is not compatible with the server's  CTgstation.Server.Client.ConflictExceptionOccurs when the client performs an action that would result in data conflict @@ -499,7 +474,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/index.html b/index.html index a322062f6d..43ca0f744d 100644 --- a/index.html +++ b/index.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tgstation-server v4: @@ -11,9 +12,6 @@ - @@ -33,36 +31,22 @@
    - + - + + + +
    -
    +
    tgstation-server v4:
    -

    -

    -

    -

    +

    Build status + Build Status + +/> + Waffle.io - Columns and their card count +

    +

    +/> + +/> + +/> + +/> +

    +

    +/> + forinfinityandbyond +

    +

    +/> + +/> +

    This is a toolset to manage production BYOND servers. It includes the ability to update the server without having to stop or shutdown the server (the update will take effect on a "reboot" of the server) the ability start the server and restart it if it crashes, as well as systems for managing code and game files, and merging GitHub Pull Requests for test deployments.

    Legacy Servers

    Older server versions can be found in the V# branches of this repository. Note that V4 is nearly fully incompatible with existing installations. Only some static files may be copied over: https://github.com/tgstation/tgstation-server#static-files

    @@ -113,7 +117,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');

    Note that tgstation-server has only ever been tested on Linux via it's docker environment. If you are having trouble with something in a native installation, or figure out a required workaround, please contact project maintainers so this documentation may be better updated.

    Docker (Linux)

    tgstation-server supports running in a docker container and is the recommended deployment method for Linux systems. The official image repository is located at https://hub.docker.com/r/tgstation/server. It can also be built locally by running docker build . -f build/Dockerfile -t <your tag name> in the repository root.

    -

    To create a container run

    1 docker run \
    2  -ti \ #start interactive for manual configuration
    3  --restart=always \ #if you want maximum uptime
    4  --network="host" \ #if your sql server is on the same machine
    5  --name="tgs" \ #or whatever else you wanna call it
    6  --cap-add=sys_nice \ #allows tgs to schedule DreamDaemon as a higher priority process
    7  --init \ #reaps potential zombie processes
    8  -p <tgs port>:80 \
    9  -p 0.0.0.0:<public game port>:<public game port> \
    10  -v /path/to/your/configfile/directory:/config_data \ #only if you want to use manual configuration
    11  -v /path/to/store/instances:/tgs4_instances \
    12  -v /path/to/your/log/folder:/tgs_logs \
    13  tgstation/server #replace this with <your tag name> if you built the image locally

    with any additional options you desire (i.e. You'll have to expose more game ports in order to host more than one instance).

    +

    To create a container run

    docker run \
    -ti \ #start interactive for manual configuration
    --restart=always \ #if you want maximum uptime
    --network="host" \ #if your sql server is on the same machine
    --name="tgs" \ #or whatever else you wanna call it
    --cap-add=sys_nice \ #allows tgs to schedule DreamDaemon as a higher priority process
    --init \ #reaps potential zombie processes
    -p <tgs port>:80 \
    -p 0.0.0.0:<public game port>:<public game port> \
    -v /path/to/your/configfile/directory:/config_data \ #only if you want to use manual configuration
    -v /path/to/store/instances:/tgs4_instances \
    -v /path/to/your/log/folder:/tgs_logs \
    tgstation/server #replace this with <your tag name> if you built the image locally

    with any additional options you desire (i.e. You'll have to expose more game ports in order to host more than one instance).

    Note although /app/lib is specified as a volume mount point in the Dockerfile, unless you REALLY know what you're doing. Do not mount any volumes over this for fear of breaking your container.

    If using manual configuration, before starting your container make sure the aforemention appsettings.Production.json is setup properly. See below

    Configuring

    @@ -158,7 +162,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');

    The DMAPI is fully backwards compatible and should function with any tgstation-server version to date. Updates can be performed in the same manner. Using the TGS_EXTERNAL_CONFIGURATION is recommended in order to make the process as easy as replacing tgs.dm and the tgs folder with a newer version

    Example

    Here is a bare minimum example project that implements the essential code changes for integrating the DMAPI

    -

    Before tgs.dm:

    1 //Remember, every codebase is different, you probably have better methods for these defines than the ones given here
    2 #define TGS_EXTERNAL_CONFIGURATION
    3 #define TGS_DEFINE_AND_SET_GLOBAL(Name, Value) var/global/##Name = ##Value
    4 #define TGS_READ_GLOBAL(Name) global.##Name
    5 #define TGS_WRITE_GLOBAL(Name, Value) global.##Name = ##Value
    6 #define TGS_WORLD_ANNOUNCE(message) world << ##message
    7 #define TGS_INFO_LOG(message) world.log << "TGS Info: [##message]"
    8 #define TGS_ERROR_LOG(message) world.log << "TGS Error: [##message]"
    9 #define TGS_NOTIFY_ADMINS(event) world.log << "TGS Admin Message: [##event]"
    10 #define TGS_CLIENT_COUNT global.client_cout
    11 #define TGS_PROTECT_DATUM(Path) // Leave blank if your codebase doesn't give administrators code reflection capabilities

    Anywhere else:

    1 var/global/client_count = 0
    2 
    3 /world/New()
    4  ..()
    5  TgsNew()
    6  TgsInitializationsComplete()
    7 
    8 /world/Reboot()
    9  TgsReboot()
    10  ..()
    11 
    12 /world/Topic()
    13  TGS_TOPIC
    14  ..()
    15 
    16 /client/New()
    17  ..()
    18  ++global.client_count
    19 
    20 /client/Del()
    21  ..()
    22  --global.client_count

    Remote Access

    +

    Before tgs.dm:

    //Remember, every codebase is different, you probably have better methods for these defines than the ones given here
    #define TGS_EXTERNAL_CONFIGURATION
    #define TGS_DEFINE_AND_SET_GLOBAL(Name, Value) var/global/##Name = ##Value
    #define TGS_READ_GLOBAL(Name) global.##Name
    #define TGS_WRITE_GLOBAL(Name, Value) global.##Name = ##Value
    #define TGS_WORLD_ANNOUNCE(message) world << ##message
    #define TGS_INFO_LOG(message) world.log << "TGS Info: [##message]"
    #define TGS_ERROR_LOG(message) world.log << "TGS Error: [##message]"
    #define TGS_NOTIFY_ADMINS(event) world.log << "TGS Admin Message: [##event]"
    #define TGS_CLIENT_COUNT global.client_cout
    #define TGS_PROTECT_DATUM(Path) // Leave blank if your codebase doesn't give administrators code reflection capabilities

    Anywhere else:

    var/global/client_count = 0
    /world/New()
    ..()
    TgsNew()
    TgsInitializationsComplete()
    /world/Reboot()
    TgsReboot()
    ..()
    /world/Topic()
    TGS_TOPIC
    ..()
    /client/New()
    ..()
    ++global.client_count
    /client/Del()
    ..()
    --global.client_count

    Remote Access

    tgstation-server is an ASP.Net Core app based on the Kestrel web server. This section is meant to serve as a general use case overview, but the entire Kestrel configuration can be modified to your liking with the configuration JSON. See the official documentation for details.

    Exposing the builtin Kestrel server to the internet directly over HTTP is highly not reccommended due to the lack of security. The recommended way to expose tgstation-server to the internet is to host it through a reverse proxy with HTTPS support. Here are some step by step examples to achieve this for major web servers.

    System administrators will most likely have their own configuration plans, but here are some basic guides for beginners.

    @@ -181,14 +185,14 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');

    Caddy (Reccommended for Linux, or those unfamilar with configuring NGINX or Apache)

    1. Setup a basic website configuration. Instructions on how to do so are out of scope.
    2. -
    3. In your Caddyfile, under a server entry, add the following (replace 8080 with the port TGS is hosted on):
      1 proxy /tgs localhost:8080 {
      2  transparent
      3 }
    4. +
    5. In your Caddyfile, under a server entry, add the following (replace 8080 with the port TGS is hosted on):
      proxy /tgs localhost:8080 {
      transparent
      }

    See https://caddyserver.com/docs/proxy

    NGINX (Reccommended for Linux)

    1. Setup a basic website configuration. Instructions on how to do so are out of scope.
    2. Acquire an HTTPS certificate, likely via Let's Encrypt, and configure NGINX to use it.
    3. -
    4. Setup a path under a server like the following (replace 8080 with the port TGS is hosted on):
      1 location /tgs {
      2  proxy_pass http://127.0.0.1:8080;
      3  break;
      4 }
    5. +
    6. Setup a path under a server like the following (replace 8080 with the port TGS is hosted on):
      location /tgs {
      proxy_pass http://127.0.0.1:8080;
      break;
      }

    See https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/

    Apache

    @@ -196,10 +200,10 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
  • Ensure the mod_proxy extension is installed.
  • Setup a basic website configuration. Instructions on how to do so are out of scope.
  • Acquire an HTTPS certificate, likely via Let's Encrypt, and configure Apache to use it.
  • -
  • Under a VirtualHost entry, setup the following (replace 8080 with the port TGS is hosted on):
    1 ProxyPass / http://127.0.0.1:8080
    2 ProxyPassReverse / http://127.0.0.1:8080
  • +
  • Under a VirtualHost entry, setup the following (replace 8080 with the port TGS is hosted on):
    ProxyPass / http://127.0.0.1:8080
    ProxyPassReverse / http://127.0.0.1:8080
  • See https://httpd.apache.org/docs/2.4/howto/reverse_proxy.html

    -

    Example VirtualHost Entry

    1 <IfModule mod_ssl.c>
    2 <VirtualHost *:443>
    3  ServerName tgs_subdomain.example.com
    4 
    5  SSLEngine on
    6  SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
    7  SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
    8 
    9  ProxyPass / http://127.0.0.1:8080/
    10  ProxyPassReverse / http://127.0.0.1:8080/
    11 </VirtualHost>
    12 </IfModule>

    Usage

    +

    Example VirtualHost Entry

    <IfModule mod_ssl.c>
    <VirtualHost *:443>
    ServerName tgs_subdomain.example.com
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/
    </VirtualHost>
    </IfModule>

    Usage

    tgstation-server v4 is controlled via a RESTful HTTP json API. Documentation on this API can be found here. This section serves to document the concepts of the server.

    Users

    All actions apart from logging in must be taken by a user. TGS installs with one default user whose credentials can be found here. It is recommended to disable this user ASAP as it is used to create Jobs that are started by the system. If access to all users is lost, the default user can be reset using the Database:ResetAdminPassword configuration setting.

    @@ -267,7 +271,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');

    Feel free to ask for help at the coderbus discord in #tooling-questions: https://discord.gg/Vh8TJp9. Cyberboss#8246 can answer most questions.

    Contributing

    Licensing

      @@ -276,12 +280,13 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search');
    • The remainder of the project is licensed under GNU AGPL v3

    See the files in the /src/DMAPI tree for the MIT license

    -
    +
    +
    diff --git a/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_byond_client-members.html b/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_byond_client-members.html index 145a4aa925..63c952880f 100644 --- a/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_byond_client-members.html +++ b/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_byond_client-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
    Tgstation.Server.Client.Components.ByondClient - -
    + + @@ -126,9 +102,11 @@ Public Member Functions

    Detailed Description

    For managing the Byond installation

    -

    Definition at line 11 of file IByondClient.cs.

    +

    Definition at line 11 of file IByondClient.cs.

    Member Function Documentation

    - + +

    ◆ ActiveVersion()

    +

    Public Member Functions

    @@ -153,9 +131,13 @@ Public Member Functions

    Implemented in Tgstation.Server.Client.Components.ByondClient.

    +

    Referenced by Tgstation.Server.Tests.Instance.ByondTest.TestInstall511(), and Tgstation.Server.Tests.Instance.ByondTest.TestNoVersion().

    + - + +

    ◆ InstalledVersions()

    +
    @@ -180,9 +162,13 @@ Public Member Functions

    Implemented in Tgstation.Server.Client.Components.ByondClient.

    +

    Referenced by Tgstation.Server.Tests.Instance.ByondTest.TestNoVersion().

    + - + +

    ◆ SetActiveVersion()

    +
    @@ -218,6 +204,8 @@ Public Member Functions

    Implemented in Tgstation.Server.Client.Components.ByondClient.

    +

    Referenced by Tgstation.Server.Tests.Instance.ByondTest.TestInstall511().

    +
    The documentation for this interface was generated from the following file:
      @@ -228,7 +216,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_chat_bots_client-members.html b/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_chat_bots_client-members.html index caab6ebeba..7f297b51ba 100644 --- a/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_chat_bots_client-members.html +++ b/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_chat_bots_client-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + + - + - - + + + +
    Tgstation.Server.Client.Components.ChatBotsClient - -
    + + @@ -132,9 +108,11 @@ Public Member Functions

    Detailed Description

    For managing the chat bots

    -

    Definition at line 11 of file IChatBotsClient.cs.

    +

    Definition at line 11 of file IChatBotsClient.cs.

    Member Function Documentation

    - + +

    ◆ Create()

    +

    Public Member Functions

    @@ -172,7 +150,9 @@ Public Member Functions - + +

    ◆ Delete()

    +
    @@ -210,7 +190,9 @@ Public Member Functions - + +

    ◆ GetId()

    +
    @@ -248,7 +230,9 @@ Public Member Functions - + +

    ◆ List()

    +
    @@ -275,7 +259,9 @@ Public Member Functions - + +

    ◆ Update()

    +
    @@ -321,7 +307,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_configuration_client-members.html b/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_configuration_client-members.html index 998ee0d825..5ab9c1d163 100644 --- a/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_configuration_client-members.html +++ b/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_configuration_client-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + + - + - - + + + +
    Tgstation.Server.Client.Components.ConfigurationClient - -
    + + @@ -132,9 +108,11 @@ Public Member Functions

    Detailed Description

    For managing ConfigurationFile files

    -

    Definition at line 11 of file IConfigurationClient.cs.

    +

    Definition at line 11 of file IConfigurationClient.cs.

    Member Function Documentation

    - + +

    ◆ CreateDirectory()

    +

    Public Member Functions

    @@ -172,7 +150,9 @@ Public Member Functions - + +

    ◆ DeleteEmptyDirectory()

    +
    @@ -208,9 +188,13 @@ Public Member Functions

    Implemented in Tgstation.Server.Client.Components.ConfigurationClient.

    +

    Referenced by Tgstation.Server.Tests.Instance.ConfigurationTest.TestDeleteDirectory().

    + - + +

    ◆ List()

    +
    @@ -248,7 +232,9 @@ Public Member Functions - + +

    ◆ Read()

    +
    @@ -286,7 +272,9 @@ Public Member Functions - + +

    ◆ Write()

    +
    @@ -322,6 +310,8 @@ Public Member Functions

    Implemented in Tgstation.Server.Client.Components.ConfigurationClient.

    +

    Referenced by Tgstation.Server.Tests.Instance.ConfigurationTest.TestDeleteDirectory().

    +
    The documentation for this interface was generated from the following file:
      @@ -332,7 +322,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_dream_daemon_client-members.html b/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_dream_daemon_client-members.html index 235a2092b6..ca36e3c02e 100644 --- a/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_dream_daemon_client-members.html +++ b/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_dream_daemon_client-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + + - + - - + + + +
    Tgstation.Server.Client.Components.DreamDaemonClient - -
    + + - + @@ -126,15 +102,17 @@ Public Member Functions - +

    Public Member Functions

    Task< DreamDaemonRead (CancellationToken cancellationToken)
     Get the DreamDaemon represented by the IDreamDaemonClient More...
     Get the DreamDaemon represented by the IDreamDaemonClient More...
     
    Task< JobStart (CancellationToken cancellationToken)
     Start DreamDaemon More...
     Shutdown DreamDaemon More...
     
    Task< DreamDaemonUpdate (DreamDaemon dreamDaemon, CancellationToken cancellationToken)
     Update DreamDaemon. This may trigger Api.Models.Internal.DreamDaemonSettings.SoftRestart More...
     Update DreamDaemon. This may trigger Api.Models.Internal.DreamDaemonSettings.SoftRestart More...
     

    Detailed Description

    For managing DreamDaemon

    -

    Definition at line 10 of file IDreamDaemonClient.cs.

    +

    Definition at line 10 of file IDreamDaemonClient.cs.

    Member Function Documentation

    - + +

    ◆ Read()

    +
    @@ -148,7 +126,7 @@ Public Member Functions
    -

    Get the DreamDaemon represented by the IDreamDaemonClient

    +

    Get the DreamDaemon represented by the IDreamDaemonClient

    Parameters
    @@ -161,7 +139,9 @@ Public Member Functions - + +

    ◆ Restart()

    +
    cancellationTokenThe CancellationToken for the operation
    @@ -188,7 +168,9 @@ Public Member Functions - + +

    ◆ Shutdown()

    +
    @@ -215,7 +197,9 @@ Public Member Functions - + +

    ◆ Start()

    +
    @@ -242,7 +226,9 @@ Public Member Functions - + +

    ◆ Update()

    +
    @@ -266,7 +252,7 @@ Public Member Functions
    -

    Update DreamDaemon. This may trigger Api.Models.Internal.DreamDaemonSettings.SoftRestart

    +

    Update DreamDaemon. This may trigger Api.Models.Internal.DreamDaemonSettings.SoftRestart

    Parameters
    @@ -288,7 +274,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_dream_maker_client-members.html b/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_dream_maker_client-members.html index 3a6aa387da..f9f0339595 100644 --- a/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_dream_maker_client-members.html +++ b/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_dream_maker_client-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    dreamDaemonThe DreamDaemon to update
    - + - - + + + + - + - - + + + +
    Tgstation.Server.Client.Components.DreamMakerClient - -
    + + @@ -123,7 +99,7 @@ Public Member Functions - + @@ -132,9 +108,11 @@ Public Member Functions

    Detailed Description

    For managing the compiler

    -

    Definition at line 11 of file IDreamMakerClient.cs.

    +

    Definition at line 11 of file IDreamMakerClient.cs.

    Member Function Documentation

    - + +

    ◆ Compile()

    +

    Public Member Functions

     Compile the current repository revision More...
     
    Task< IReadOnlyList< CompileJob > > GetJobIds (CancellationToken cancellationToken)
     Gets the Api.Models.Internal.CompileJob.Ids of all CompileJobs for the instance More...
     Gets the Api.Models.Internal.CompileJob.Ids of all CompileJobs for the instance More...
     
    Task< CompileJobGetCompileJob (CompileJob compileJob, CancellationToken cancellationToken)
     Get a compileJob More...
    @@ -161,7 +139,9 @@ Public Member Functions - + +

    ◆ GetCompileJob()

    +
    @@ -199,7 +179,9 @@ Public Member Functions - + +

    ◆ GetJobIds()

    +
    @@ -213,20 +195,22 @@ Public Member Functions
    -

    Gets the Api.Models.Internal.CompileJob.Ids of all CompileJobs for the instance

    +

    Gets the Api.Models.Internal.CompileJob.Ids of all CompileJobs for the instance

    Parameters
    cancellationTokenThe CancellationToken for the operation
    -
    Returns
    A Task<TResult> resulting in a IReadOnlyList<T> of CompileJobs with only the Api.Models.Internal.CompileJob.Id field populated
    +
    Returns
    A Task<TResult> resulting in a IReadOnlyList<T> of CompileJobs with only the Api.Models.Internal.CompileJob.Id field populated

    Implemented in Tgstation.Server.Client.Components.DreamMakerClient.

    - + +

    ◆ Read()

    +
    @@ -253,7 +237,9 @@ Public Member Functions - + +

    ◆ Update()

    +
    @@ -299,7 +285,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_instance_client-members.html b/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_instance_client-members.html index 155b6d56ea..21bde0a11f 100644 --- a/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_instance_client-members.html +++ b/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_instance_client-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
    - + - - + + + + - + - - + + + +
    Tgstation.Server.Client.Components.InstanceClient - -
    + + - + - + - + - + - + - + - + - + - +

    Properties

    Instance Metadata [get]
     The Instance used to create the IInstanceClient More...
     The Instance used to create the IInstanceClient More...
     
    IByondClient Byond [get]
     Access the IByondClient More...
     Access the IByondClient More...
     
    IRepositoryClient Repository [get]
     Access the IRepositoryClient More...
     Access the IRepositoryClient More...
     
    IDreamDaemonClient DreamDaemon [get]
     Access the IDreamDaemonClient More...
     Access the IDreamDaemonClient More...
     
    IConfigurationClient Configuration [get]
     Access the IConfigurationClient More...
     Access the IConfigurationClient More...
     
    IInstanceUserClient Users [get]
     Access the IInstanceUserClient More...
     Access the IInstanceUserClient More...
     
    IChatBotsClient ChatBots [get]
     Access the IChatBotsClient More...
     Access the IChatBotsClient More...
     
    IDreamMakerClient DreamMaker [get]
     Access the IDreamMakerClient More...
     Access the IDreamMakerClient More...
     
    IJobsClient Jobs [get]
     Access the IJobsClient More...
     Access the IJobsClient More...
     

    Detailed Description

    For managing a single Instance

    -

    Definition at line 9 of file IInstanceClient.cs.

    +

    Definition at line 9 of file IInstanceClient.cs.

    Property Documentation

    - + +

    ◆ Byond

    +
    @@ -164,13 +142,17 @@ Properties
    -

    Access the IByondClient

    +

    Access the IByondClient

    -

    Definition at line 19 of file IInstanceClient.cs.

    +

    Definition at line 19 of file IInstanceClient.cs.

    +
    19 { get; }
    +

    Referenced by Tgstation.Server.Tests.Instance.InstanceTest.RunTests().

    - + +

    ◆ ChatBots

    +
    @@ -188,13 +170,15 @@ Properties
    -

    Access the IChatBotsClient

    - -

    Definition at line 44 of file IInstanceClient.cs.

    +

    Access the IChatBotsClient

    +

    Definition at line 44 of file IInstanceClient.cs.

    +
    44 { get; }
    - + +

    ◆ Configuration

    +
    @@ -212,13 +196,17 @@ Properties
    -

    Access the IConfigurationClient

    +

    Access the IConfigurationClient

    -

    Definition at line 34 of file IInstanceClient.cs.

    +

    Definition at line 34 of file IInstanceClient.cs.

    +
    34 { get; }
    +

    Referenced by Tgstation.Server.Tests.Instance.InstanceTest.RunTests().

    - + +

    ◆ DreamDaemon

    +
    @@ -236,13 +224,15 @@ Properties
    -

    Access the IDreamDaemonClient

    - -

    Definition at line 29 of file IInstanceClient.cs.

    +

    Access the IDreamDaemonClient

    +

    Definition at line 29 of file IInstanceClient.cs.

    +
    29 { get; }
    - + +

    ◆ DreamMaker

    +
    @@ -260,13 +250,15 @@ Properties
    -

    Access the IDreamMakerClient

    - -

    Definition at line 49 of file IInstanceClient.cs.

    +

    Access the IDreamMakerClient

    +

    Definition at line 49 of file IInstanceClient.cs.

    +
    49 { get; }
    - + +

    ◆ Jobs

    +
    @@ -284,13 +276,17 @@ Properties
    -

    Access the IJobsClient

    +

    Access the IJobsClient

    -

    Definition at line 54 of file IInstanceClient.cs.

    +

    Definition at line 54 of file IInstanceClient.cs.

    +
    54 { get; }
    +

    Referenced by Tgstation.Server.Tests.Instance.InstanceTest.RunTests().

    - + +

    ◆ Metadata

    +
    @@ -308,13 +304,17 @@ Properties
    -

    The Instance used to create the IInstanceClient

    +

    The Instance used to create the IInstanceClient

    -

    Definition at line 14 of file IInstanceClient.cs.

    +

    Definition at line 14 of file IInstanceClient.cs.

    +
    14 { get; }
    +

    Referenced by Tgstation.Server.Tests.Instance.InstanceTest.RunTests().

    - + +

    ◆ Repository

    +
    @@ -332,13 +332,15 @@ Properties
    -

    Access the IRepositoryClient

    - -

    Definition at line 24 of file IInstanceClient.cs.

    +

    Access the IRepositoryClient

    +

    Definition at line 24 of file IInstanceClient.cs.

    +
    24 { get; }
    - + +

    ◆ Users

    +
    @@ -356,10 +358,10 @@ Properties
    -

    Access the IInstanceUserClient

    - -

    Definition at line 39 of file IInstanceClient.cs.

    +

    Access the IInstanceUserClient

    +

    Definition at line 39 of file IInstanceClient.cs.

    +
    39 { get; }

    The documentation for this interface was generated from the following file:
      @@ -370,7 +372,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_instance_user_client-members.html b/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_instance_user_client-members.html index 194105ae00..6118af3271 100644 --- a/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_instance_user_client-members.html +++ b/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_instance_user_client-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
      Tgstation.Server.Client.Components.InstanceUserClient - -
      + + @@ -135,9 +111,11 @@ Public Member Functions

      Detailed Description

      For managing InstanceUsers

      -

      Definition at line 11 of file IInstanceUserClient.cs.

      +

      Definition at line 11 of file IInstanceUserClient.cs.

      Member Function Documentation

      - + +

      ◆ Create()

      +

      Public Member Functions

      @@ -175,7 +153,9 @@ Public Member Functions - + +

      ◆ Delete()

      +
      @@ -213,7 +193,9 @@ Public Member Functions - + +

      ◆ GetId()

      +
      @@ -251,7 +233,9 @@ Public Member Functions - + +

      ◆ List()

      +
      @@ -278,7 +262,9 @@ Public Member Functions - + +

      ◆ Read()

      +
      @@ -305,7 +291,9 @@ Public Member Functions - + +

      ◆ Update()

      +
      @@ -351,7 +339,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_jobs_client-members.html b/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_jobs_client-members.html index adeabd0535..b453a84a52 100644 --- a/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_jobs_client-members.html +++ b/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_jobs_client-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
      - + - - + + + + - + - - + + + +
      Tgstation.Server.Client.Components.JobsClient - -
      + + - + @@ -129,9 +105,11 @@ Public Member Functions

      Detailed Description

      Access to running jobs

      -

      Definition at line 12 of file IJobsClient.cs.

      +

      Definition at line 12 of file IJobsClient.cs.

      Member Function Documentation

      - + +

      ◆ Cancel()

      +

      Public Member Functions

      Task< IReadOnlyList< Job > > List (CancellationToken cancellationToken)
       List the Api.Models.Internal.Job.Ids in the Instance More...
       List the Api.Models.Internal.Job.Ids in the Instance More...
       
      Task< IReadOnlyList< Job > > ListActive (CancellationToken cancellationToken)
       List the active Jobs in the Instance More...
      @@ -167,9 +145,13 @@ Public Member Functions

      Implemented in Tgstation.Server.Client.Components.JobsClient.

      +

      Referenced by Tgstation.Server.Tests.Instance.ByondTest.TestInstall511().

      + - + +

      ◆ GetId()

      +
      @@ -205,9 +187,13 @@ Public Member Functions

      Implemented in Tgstation.Server.Client.Components.JobsClient.

      +

      Referenced by Tgstation.Server.Tests.Instance.ByondTest.TestInstall511().

      + - + +

      ◆ List()

      +
      @@ -221,20 +207,22 @@ Public Member Functions
      -

      List the Api.Models.Internal.Job.Ids in the Instance

      +

      List the Api.Models.Internal.Job.Ids in the Instance

      Parameters
      cancellationTokenThe CancellationToken for the operation
      -
      Returns
      A Task<TResult> resulting in a IReadOnlyList<T> of the Api.Models.Internal.Job.Ids in the Instance
      +
      Returns
      A Task<TResult> resulting in a IReadOnlyList<T> of the Api.Models.Internal.Job.Ids in the Instance

      Implemented in Tgstation.Server.Client.Components.JobsClient.

      - + +

      ◆ ListActive()

      +
      @@ -269,7 +257,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_repository_client-members.html b/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_repository_client-members.html index 7b7e6700f9..b68871e463 100644 --- a/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_repository_client-members.html +++ b/interface_tgstation_1_1_server_1_1_client_1_1_components_1_1_i_repository_client-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
      - + - - + + + + - + - - + + + +
      Tgstation.Server.Client.Components.RepositoryClient - -
      + + - + @@ -129,9 +105,11 @@ Public Member Functions

      Detailed Description

      For managing the Repository

      -

      Definition at line 10 of file IRepositoryClient.cs.

      +

      Definition at line 10 of file IRepositoryClient.cs.

      Member Function Documentation

      - + +

      ◆ Clone()

      +

      Public Member Functions

      Task< RepositoryRead (CancellationToken cancellationToken)
       Get the Repository represented by the IRepositoryClient More...
       Get the Repository represented by the IRepositoryClient More...
       
      Task< RepositoryUpdate (Repository repository, CancellationToken cancellationToken)
       Update the Repository More...
      @@ -169,7 +147,9 @@ Public Member Functions - + +

      ◆ Delete()

      +
      @@ -196,7 +176,9 @@ Public Member Functions - + +

      ◆ Read()

      +
      @@ -210,7 +192,7 @@ Public Member Functions
      -

      Get the Repository represented by the IRepositoryClient

      +

      Get the Repository represented by the IRepositoryClient

      Parameters
      @@ -223,7 +205,9 @@ Public Member Functions - + +

      ◆ Update()

      +
      cancellationTokenThe CancellationToken for the operation
      @@ -269,7 +253,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_client_1_1_i_administration_client-members.html b/interface_tgstation_1_1_server_1_1_client_1_1_i_administration_client-members.html index f5727039d9..d6389afaf9 100644 --- a/interface_tgstation_1_1_server_1_1_client_1_1_i_administration_client-members.html +++ b/interface_tgstation_1_1_server_1_1_client_1_1_i_administration_client-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
      - + - - + + + + - + - - + + + +
      Tgstation.Server.Client.AdministrationClient - -
      + + - + @@ -126,9 +102,11 @@ Public Member Functions

      Detailed Description

      For managing server administration

      -

      Definition at line 10 of file IAdministrationClient.cs.

      +

      Definition at line 10 of file IAdministrationClient.cs.

      Member Function Documentation

      - + +

      ◆ Read()

      +

      Public Member Functions

      Task< AdministrationRead (CancellationToken cancellationToken)
       Get the Administration represented by the IAdministrationClient More...
       Get the Administration represented by the IAdministrationClient More...
       
      Task Update (Administration administration, CancellationToken cancellationToken)
       Updates the Administration setttings More...
      @@ -142,20 +120,24 @@ Public Member Functions
      -

      Get the Administration represented by the IAdministrationClient

      +

      Get the Administration represented by the IAdministrationClient

      Parameters
      cancellationTokenThe CancellationToken for the operation
      -
      Returns
      A Task<TResult> resulting in the Administration represented by the IAdministrationClient
      +
      Returns
      A Task<TResult> resulting in the Administration represented by the IAdministrationClient

      Implemented in Tgstation.Server.Client.AdministrationClient.

      +

      Referenced by Tgstation.Server.Tests.AdministrationTest.TestRead().

      +
      - + +

      ◆ Restart()

      +
      @@ -182,7 +164,9 @@ Public Member Functions - + +

      ◆ Update()

      +
      @@ -218,7 +202,7 @@ Public Member Functions

      Implemented in Tgstation.Server.Client.AdministrationClient.

      -

      Referenced by Tgstation.Server.Tests.IntegrationTest.TestUpdate().

      +

      Referenced by Tgstation.Server.Tests.IntegrationTest.TestUpdate().

      @@ -230,7 +214,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_client_1_1_i_api_client-members.html b/interface_tgstation_1_1_server_1_1_client_1_1_i_api_client-members.html index 95e6743b87..0313655be9 100644 --- a/interface_tgstation_1_1_server_1_1_client_1_1_i_api_client-members.html +++ b/interface_tgstation_1_1_server_1_1_client_1_1_i_api_client-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
      - + - - + + + + - + - - + + + +
      IDisposable Tgstation.Server.Client.ApiClient - -
      + + @@ -167,7 +143,7 @@ Public Member Functions - + @@ -179,9 +155,11 @@ Properties

      Detailed Description

      Web interface for the API

      -

      Definition at line 11 of file IApiClient.cs.

      +

      Definition at line 11 of file IApiClient.cs.

      Member Function Documentation

      - + +

      ◆ AddRequestLogger()

      +

      Public Member Functions

      Properties

      ApiHeaders Headers [get, set]
       The ApiHeaders the IApiClient uses More...
       The ApiHeaders the IApiClient uses More...
       
      Uri Url [get]
       The Uri pointing the tgstation-server More...
      @@ -198,7 +176,7 @@ Properties

      Adds a requestLogger to the request pipeline

      Parameters
      - +
      requestLoggerThe IRequestLogger to add
      requestLoggerThe IRequestLogger to add
      @@ -207,7 +185,9 @@ Properties - + +

      ◆ Create< TBody, TResult >() [1/2]

      +
      @@ -259,7 +239,9 @@ Properties - + +

      ◆ Create< TBody, TResult >() [2/2]

      +
      @@ -307,7 +289,7 @@ Properties
      - +
      routeThe server route to make the request to
      bodyThe request body
      instanceIdThe Api.Models.Instance.Id to make the request to
      instanceIdThe Api.Models.Instance.Id to make the request to
      cancellationTokenThe CancellationToken for the operation
      @@ -318,7 +300,9 @@ Properties
      - + +

      ◆ Create< TResult >() [1/2]

      +
      @@ -362,7 +346,9 @@ Properties - + +

      ◆ Create< TResult >() [2/2]

      +
      @@ -402,7 +388,7 @@ Properties
      Parameters
      - +
      routeThe server route to make the request to
      instanceIdThe Api.Models.Instance.Id to make the request to
      instanceIdThe Api.Models.Instance.Id to make the request to
      cancellationTokenThe CancellationToken for the operation
      @@ -413,7 +399,9 @@ Properties
      - + +

      ◆ Delete() [1/2]

      +
      @@ -451,7 +439,9 @@ Properties - + +

      ◆ Delete() [2/2]

      +
      @@ -485,7 +475,7 @@ Properties
      Parameters
      - +
      routeThe server route to make the request to
      instanceIdThe Api.Models.Instance.Id to make the request to
      instanceIdThe Api.Models.Instance.Id to make the request to
      cancellationTokenThe CancellationToken for the operation
      @@ -496,7 +486,9 @@ Properties
      - + +

      ◆ Delete< TBody >()

      +
      @@ -543,7 +535,7 @@ Properties
      - +
      routeThe server route to make the request to
      bodyThe request body
      instanceIdThe Api.Models.Instance.Id to make the request to
      instanceIdThe Api.Models.Instance.Id to make the request to
      cancellationTokenThe CancellationToken for the operation
      @@ -554,7 +546,9 @@ Properties
      - + +

      ◆ Delete< TResult >()

      +
      @@ -594,7 +588,7 @@ Properties
      Parameters
      - +
      routeThe server route to make the request to
      instanceIdThe Api.Models.Instance.Id to make the request to
      instanceIdThe Api.Models.Instance.Id to make the request to
      cancellationTokenThe CancellationToken for the operation
      @@ -605,7 +599,9 @@ Properties
      - + +

      ◆ Patch< TResult >()

      +
      @@ -645,7 +641,7 @@ Properties
      Parameters
      - +
      routeThe server route to make the request to
      instanceIdThe Api.Models.Instance.Id to make the request to
      instanceIdThe Api.Models.Instance.Id to make the request to
      cancellationTokenThe CancellationToken for the operation
      @@ -656,7 +652,9 @@ Properties
      - + +

      ◆ Read< TResult >() [1/2]

      +
      @@ -700,7 +698,9 @@ Properties - + +

      ◆ Read< TResult >() [2/2]

      +
      @@ -740,7 +740,7 @@ Properties
      Parameters
      - +
      routeThe server route to make the request to
      instanceIdThe Api.Models.Instance.Id to make the request to
      instanceIdThe Api.Models.Instance.Id to make the request to
      cancellationTokenThe CancellationToken for the operation
      @@ -751,7 +751,9 @@ Properties
      - + +

      ◆ Update< TBody >()

      +
      @@ -802,7 +804,9 @@ Properties - + +

      ◆ Update< TBody, TResult >() [1/2]

      +
      @@ -854,7 +858,9 @@ Properties - + +

      ◆ Update< TBody, TResult >() [2/2]

      +
      @@ -902,7 +908,7 @@ Properties
      - +
      routeThe server route to make the request to
      bodyThe request body
      instanceIdThe Api.Models.Instance.Id to make the request to
      instanceIdThe Api.Models.Instance.Id to make the request to
      cancellationTokenThe CancellationToken for the operation
      @@ -913,7 +919,9 @@ Properties
      - + +

      ◆ Update< TResult >()

      +
      @@ -958,7 +966,9 @@ Properties

      Property Documentation

      - + +

      ◆ Headers

      +
      @@ -976,15 +986,17 @@ Properties
      -

      The ApiHeaders the IApiClient uses

      +

      The ApiHeaders the IApiClient uses

      -

      Definition at line 16 of file IApiClient.cs.

      - -

      Referenced by Tgstation.Server.Client.ServerClient.ServerClient().

      +

      Definition at line 16 of file IApiClient.cs.

      +
      16 { get; set; }
      +

      Referenced by Tgstation.Server.Client.ServerClient.ServerClient().

      - + +

      ◆ Timeout

      +
      @@ -1004,11 +1016,13 @@ Properties

      The request timeout

      -

      Definition at line 26 of file IApiClient.cs.

      +

      Definition at line 26 of file IApiClient.cs.

      +
      26 { get; set; }
      + + + +

      ◆ Url

      - - -
      @@ -1028,8 +1042,8 @@ Properties

      The Uri pointing the tgstation-server

      -

      Definition at line 21 of file IApiClient.cs.

      - +

      Definition at line 21 of file IApiClient.cs.

      +
      21 { get; }

      The documentation for this interface was generated from the following file:
        @@ -1040,7 +1054,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_client_1_1_i_api_client_factory-members.html b/interface_tgstation_1_1_server_1_1_client_1_1_i_api_client_factory-members.html index 0491d154ef..9f10bb4bed 100644 --- a/interface_tgstation_1_1_server_1_1_client_1_1_i_api_client_factory-members.html +++ b/interface_tgstation_1_1_server_1_1_client_1_1_i_api_client_factory-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
      - + - - + + + + - + - - + + + +
      -

      For creating IApiClients +

      For creating IApiClients More...

      Inheritance diagram for Tgstation.Server.Client.IApiClientFactory:
      @@ -108,21 +84,23 @@ Inheritance diagram for Tgstation.Server.Client.IApiClientFactory:
      Tgstation.Server.Client.ApiClientFactory - -
      + + - +

      Public Member Functions

      IApiClient CreateApiClient (Uri url, ApiHeaders apiHeaders)
       Create an IApiClient More...
       Create an IApiClient More...
       

      Detailed Description

      -

      For creating IApiClients

      +

      For creating IApiClients

      -

      Definition at line 9 of file IApiClientFactory.cs.

      +

      Definition at line 9 of file IApiClientFactory.cs.

      Member Function Documentation

      - + +

      ◆ CreateApiClient()

      +
      @@ -146,15 +124,15 @@ Public Member Functions
      -

      Create an IApiClient

      +

      Create an IApiClient

      Parameters
      - +
      urlThe base Uri
      apiHeadersThe ApiHeaders for the IApiClient
      apiHeadersThe ApiHeaders for the IApiClient
      -
      Returns
      A new IApiClient
      +
      Returns
      A new IApiClient

      Implemented in Tgstation.Server.Client.ApiClientFactory.

      @@ -168,7 +146,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_client_1_1_i_http_client-members.html b/interface_tgstation_1_1_server_1_1_client_1_1_i_http_client-members.html index 5c84e326b6..751675faef 100644 --- a/interface_tgstation_1_1_server_1_1_client_1_1_i_http_client-members.html +++ b/interface_tgstation_1_1_server_1_1_client_1_1_i_http_client-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
      - + - - + + + + - + - - + + + +
      IDisposable Tgstation.Server.Client.HttpClient - -
      + +
      @@ -128,9 +104,11 @@ Properties

      Detailed Description

      For sending HTTP requests

      -

      Definition at line 11 of file IHttpClient.cs.

      +

      Definition at line 11 of file IHttpClient.cs.

      Member Function Documentation

      - + +

      ◆ SendAsync()

      +

      Public Member Functions

      @@ -166,10 +144,14 @@ Properties

      Implemented in Tgstation.Server.Client.HttpClient.

      +

      Referenced by Tgstation.Server.Client.ApiClient.RunRequest< TResult >().

      +

      Property Documentation

      - + +

      ◆ Timeout

      +
      @@ -189,8 +171,8 @@ Properties

      The request timeout

      -

      Definition at line 16 of file IHttpClient.cs.

      - +

      Definition at line 16 of file IHttpClient.cs.

      +
      16 { get; set; }

      The documentation for this interface was generated from the following file:
        @@ -201,7 +183,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_client_1_1_i_instance_manager_client-members.html b/interface_tgstation_1_1_server_1_1_client_1_1_i_instance_manager_client-members.html index b0edf066d7..ad495b0553 100644 --- a/interface_tgstation_1_1_server_1_1_client_1_1_i_instance_manager_client-members.html +++ b/interface_tgstation_1_1_server_1_1_client_1_1_i_instance_manager_client-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
      - + - - + + + + - + - - + + + +
      Tgstation.Server.Client.InstanceManagerClient - -
      + + @@ -135,9 +111,11 @@ Public Member Functions

      Detailed Description

      For managing Instances

      -

      Definition at line 12 of file IInstanceManagerClient.cs.

      +

      Definition at line 12 of file IInstanceManagerClient.cs.

      Member Function Documentation

      - + +

      ◆ CreateClient()

      +

      Public Member Functions

      @@ -162,9 +140,13 @@ Public Member Functions

      Implemented in Tgstation.Server.Client.InstanceManagerClient.

      +

      Referenced by Tgstation.Server.Tests.InstanceManagerTest.Run().

      + - + +

      ◆ CreateOrAttach()

      +
      @@ -200,9 +182,13 @@ Public Member Functions

      Implemented in Tgstation.Server.Client.InstanceManagerClient.

      +

      Referenced by Tgstation.Server.Tests.InstanceManagerTest.Run().

      + - + +

      ◆ Detach()

      +
      @@ -238,9 +224,13 @@ Public Member Functions

      Implemented in Tgstation.Server.Client.InstanceManagerClient.

      +

      Referenced by Tgstation.Server.Tests.InstanceManagerTest.Run().

      + - + +

      ◆ GetId()

      +
      @@ -276,9 +266,13 @@ Public Member Functions

      Implemented in Tgstation.Server.Client.InstanceManagerClient.

      +

      Referenced by Tgstation.Server.Tests.InstanceManagerTest.Run().

      + - + +

      ◆ List()

      +
      @@ -305,7 +299,9 @@ Public Member Functions - + +

      ◆ Update()

      +
      @@ -341,6 +337,8 @@ Public Member Functions

      Implemented in Tgstation.Server.Client.InstanceManagerClient.

      +

      Referenced by Tgstation.Server.Tests.InstanceManagerTest.Run().

      +
      The documentation for this interface was generated from the following file:
        @@ -351,7 +349,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_client_1_1_i_request_logger-members.html b/interface_tgstation_1_1_server_1_1_client_1_1_i_request_logger-members.html index 152eb898bb..73d76f3bd8 100644 --- a/interface_tgstation_1_1_server_1_1_client_1_1_i_request_logger-members.html +++ b/interface_tgstation_1_1_server_1_1_client_1_1_i_request_logger-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
      - + - - + + + + - + - - + + + +

      Detailed Description

      For logging HTTP requests and responses

      -

      Definition at line 11 of file IRequestLogger.cs.

      +

      Definition at line 11 of file IRequestLogger.cs.

      Member Function Documentation

      - + +

      ◆ LogRequest()

      +
      @@ -152,7 +130,9 @@ Public Member Functions - + +

      ◆ LogResponse()

      +
      @@ -196,7 +176,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_client_1_1_i_server_client-members.html b/interface_tgstation_1_1_server_1_1_client_1_1_i_server_client-members.html index 724b01dd75..23df9d3b5c 100644 --- a/interface_tgstation_1_1_server_1_1_client_1_1_i_server_client-members.html +++ b/interface_tgstation_1_1_server_1_1_client_1_1_i_server_client-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
      - + - - + + + + - + - - + + + +
      IDisposable Tgstation.Server.Client.ServerClient - -
      + +
      - + @@ -128,27 +104,29 @@ Properties - + - + - + - +

      Public Member Functions

      Task< ServerInformationVersion (CancellationToken cancellationToken)
       The ServerInformation of the IServerClient More...
       The ServerInformation of the IServerClient More...
       
      void AddRequestLogger (IRequestLogger requestLogger)
       Adds a requestLogger to the request pipeline More...
       The connected server Uri More...
       
      Token Token [get, set]
       The Token used to access the server More...
       The Token used to access the server More...
       
      TimeSpan Timeout [get, set]
       The connection timeout More...
       
      IInstanceManagerClient Instances [get]
       Access the IInstanceManagerClient More...
       Access the IInstanceManagerClient More...
       
      IAdministrationClient Administration [get]
       Access the IAdministrationClient More...
       Access the IAdministrationClient More...
       
      IUsersClient Users [get]
       Access the IUsersClient More...
       Access the IUsersClient More...
       

      Detailed Description

      Main client for communicating with a server

      -

      Definition at line 11 of file IServerClient.cs.

      +

      Definition at line 11 of file IServerClient.cs.

      Member Function Documentation

      - + +

      ◆ AddRequestLogger()

      +
      @@ -165,7 +143,7 @@ Properties

      Adds a requestLogger to the request pipeline

      Parameters
      - +
      requestLoggerThe IRequestLogger to add
      requestLoggerThe IRequestLogger to add
      @@ -174,7 +152,9 @@ Properties
      - + +

      ◆ Version()

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

      The ServerInformation of the IServerClient

      +

      The ServerInformation of the IServerClient

      Parameters
      @@ -199,12 +179,14 @@ Properties

      Implemented in Tgstation.Server.Client.ServerClient.

      -

      Referenced by Tgstation.Server.Tests.IntegrationTest.TestStandardOperation().

      +

      Referenced by Tgstation.Server.Tests.IntegrationTest.TestStandardOperation().

      Property Documentation

      - + +

      ◆ Administration

      +
      cancellationTokenThe CancellationToken for the operation
      @@ -222,15 +204,17 @@ Properties
      - + +

      ◆ Instances

      +
      @@ -248,15 +232,17 @@ Properties
      -

      Access the IInstanceManagerClient

      +

      Access the IInstanceManagerClient

      -

      Definition at line 31 of file IServerClient.cs.

      - -

      Referenced by Tgstation.Server.Tests.IntegrationTest.TestStandardOperation().

      +

      Definition at line 31 of file IServerClient.cs.

      +
      31 { get; }
      +

      Referenced by Tgstation.Server.Tests.IntegrationTest.TestStandardOperation().

      - + +

      ◆ Timeout

      +
      @@ -276,11 +262,13 @@ Properties

      The connection timeout

      -

      Definition at line 26 of file IServerClient.cs.

      +

      Definition at line 26 of file IServerClient.cs.

      +
      26 { get; set; }
      + + + +

      ◆ Token

      - - -
      @@ -298,15 +286,17 @@ Properties
      -

      The Token used to access the server

      +

      The Token used to access the server

      -

      Definition at line 21 of file IServerClient.cs.

      - -

      Referenced by Tgstation.Server.Tests.IntegrationTest.TestStandardOperation().

      +

      Definition at line 21 of file IServerClient.cs.

      +
      21 { get; set; }
      +

      Referenced by Tgstation.Server.Tests.IntegrationTest.TestStandardOperation().

      - + +

      ◆ Url

      +
      @@ -326,11 +316,13 @@ Properties

      The connected server Uri

      -

      Definition at line 16 of file IServerClient.cs.

      +

      Definition at line 16 of file IServerClient.cs.

      +
      16 { get; }
      + + + +

      ◆ Users

      - - -
      @@ -348,10 +340,10 @@ Properties
      -

      Access the IUsersClient

      - -

      Definition at line 41 of file IServerClient.cs.

      +

      Access the IUsersClient

      +

      Definition at line 41 of file IServerClient.cs.

      +
      41 { get; }

      The documentation for this interface was generated from the following file:
        @@ -362,7 +354,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_client_1_1_i_server_client_factory-members.html b/interface_tgstation_1_1_server_1_1_client_1_1_i_server_client_factory-members.html index 416295135a..d9acb1fbbb 100644 --- a/interface_tgstation_1_1_server_1_1_client_1_1_i_server_client_factory-members.html +++ b/interface_tgstation_1_1_server_1_1_client_1_1_i_server_client_factory-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
        -

        Factory for creating IServerClients +

        Factory for creating IServerClients More...

        Inheritance diagram for Tgstation.Server.Client.IServerClientFactory:
        @@ -108,24 +84,26 @@ Inheritance diagram for Tgstation.Server.Client.IServerClientFactory:
        Tgstation.Server.Client.ServerClientFactory - -
        + + - + - +

        Public Member Functions

        Task< IServerClientCreateServerClient (Uri host, string username, string password, TimeSpan timeout=default, CancellationToken cancellationToken=default)
         Create a IServerClient More...
         Create a IServerClient More...
         
        IServerClient CreateServerClient (Uri host, Token token, TimeSpan timeout=default)
         Create a IServerClient More...
         Create a IServerClient More...
         

        Detailed Description

        -

        Factory for creating IServerClients

        +

        Factory for creating IServerClients

        -

        Definition at line 11 of file IServerClientFactory.cs.

        +

        Definition at line 11 of file IServerClientFactory.cs.

        Member Function Documentation

        - + +

        ◆ CreateServerClient() [1/2]

        +
        @@ -167,24 +145,28 @@ Public Member Functions
        -

        Create a IServerClient

        +

        Create a IServerClient

        Parameters
        - - + +
        hostThe URL to access TGS
        usernameThe username to for the IServerClient
        passwordThe password for the IServerClient
        usernameThe username to for the IServerClient
        passwordThe password for the IServerClient
        timeoutThe TimeSpan representing timeout for the connection
        cancellationTokenThe CancellationToken for the operation
        -
        Returns
        A Task<TResult> resulting in a new IServerClient
        +
        Returns
        A Task<TResult> resulting in a new IServerClient

        Implemented in Tgstation.Server.Client.ServerClientFactory.

        +

        Referenced by Tgstation.Server.Tests.IntegrationTest.TestStandardOperation(), and Tgstation.Server.Tests.IntegrationTest.TestUpdate().

        +
        - + +

        ◆ CreateServerClient() [2/2]

        +
        @@ -214,7 +196,7 @@ Public Member Functions
        -

        Create a IServerClient

        +

        Create a IServerClient

        Parameters
        @@ -223,7 +205,7 @@ Public Member Functions
        hostThe URL to access TGS
        -
        Returns
        A new IServerClient
        +
        Returns
        A new IServerClient

        Implemented in Tgstation.Server.Client.ServerClientFactory.

        @@ -237,7 +219,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_client_1_1_i_users_client-members.html b/interface_tgstation_1_1_server_1_1_client_1_1_i_users_client-members.html index 15e7772af9..b4603fc839 100644 --- a/interface_tgstation_1_1_server_1_1_client_1_1_i_users_client-members.html +++ b/interface_tgstation_1_1_server_1_1_client_1_1_i_users_client-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        - + - - + + + + - + - - + + + +
        Tgstation.Server.Client.UsersClient - -
        + +
        @@ -132,9 +108,11 @@ Public Member Functions

        Detailed Description

        For managing Users

        -

        Definition at line 11 of file IUsersClient.cs.

        +

        Definition at line 11 of file IUsersClient.cs.

        Member Function Documentation

        - + +

        ◆ Create()

        +

        Public Member Functions

        @@ -172,7 +150,9 @@ Public Member Functions - + +

        ◆ GetId()

        +
        @@ -210,7 +190,9 @@ Public Member Functions - + +

        ◆ List()

        +
        @@ -237,7 +219,9 @@ Public Member Functions - + +

        ◆ Read()

        +
        @@ -264,7 +248,9 @@ Public Member Functions - + +

        ◆ Update()

        +
        @@ -310,7 +296,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_i_byond_executable_lock-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_i_byond_executable_lock-members.html index 6f47d12a4a..78950b7896 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_i_byond_executable_lock-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_i_byond_executable_lock-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        - + - - + + + + - + - - + + + +
        IDisposable Tgstation.Server.Host.Components.Byond.ByondExecutableLock - -
        + + @@ -134,9 +110,11 @@ Properties

        Detailed Description

        Represents usage of the two primary BYOND server executables

        -

        Definition at line 8 of file IByondExecutableLock.cs.

        +

        Definition at line 8 of file IByondExecutableLock.cs.

        Member Function Documentation

        - + +

        ◆ DoNotDeleteThisSession()

        +

        Public Member Functions

        @@ -153,10 +131,14 @@ Properties

        Implemented in Tgstation.Server.Host.Components.Byond.ByondExecutableLock.

        +

        Referenced by Tgstation.Server.Host.Components.Watchdog.SessionController.Release().

        +

        Property Documentation

        - + +

        ◆ DreamDaemonPath

        +
        @@ -176,11 +158,13 @@ Properties

        The path to the DreamDaemon executable

        -

        Definition at line 18 of file IByondExecutableLock.cs.

        +

        Definition at line 18 of file IByondExecutableLock.cs.

        +
        18 { get; }
        + + + +

        ◆ DreamMakerPath

        - - -
        @@ -200,13 +184,15 @@ Properties

        The path to the dm/DreamMaker executable

        -

        Definition at line 23 of file IByondExecutableLock.cs.

        - -

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

        +

        Definition at line 23 of file IByondExecutableLock.cs.

        +
        23 { get; }
        +

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

        - + +

        ◆ Version

        +
        @@ -226,9 +212,9 @@ Properties

        The System.Version of the locked executables

        -

        Definition at line 13 of file IByondExecutableLock.cs.

        - -

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

        +

        Definition at line 13 of file IByondExecutableLock.cs.

        +
        13 { get; }
        +

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

        @@ -240,7 +226,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_i_byond_installer-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_i_byond_installer-members.html index 45bcbef994..56a95068a0 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_i_byond_installer-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_i_byond_installer-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        - + - - + + + + - + - - + + + +
        -Tgstation.Server.Host.Components.Byond.PosixByondInstaller -Tgstation.Server.Host.Components.Byond.WindowsByondInstaller - -
        +Tgstation.Server.Host.Components.Byond.PosixByondInstaller +Tgstation.Server.Host.Components.Byond.WindowsByondInstaller + + @@ -137,9 +113,11 @@ Properties

        Detailed Description

        For downloading and installing BYOND extractions for a given system

        -

        Definition at line 10 of file IByondInstaller.cs.

        +

        Definition at line 10 of file IByondInstaller.cs.

        Member Function Documentation

        - + +

        ◆ CleanCache()

        +

        Public Member Functions

        @@ -166,7 +144,9 @@ Properties - + +

        ◆ DownloadVersion()

        +
        @@ -202,9 +182,13 @@ Properties

        Implemented in Tgstation.Server.Host.Components.Byond.WindowsByondInstaller, and Tgstation.Server.Host.Components.Byond.PosixByondInstaller.

        +

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

        + - + +

        ◆ InstallByond()

        +
        @@ -247,10 +231,14 @@ Properties

        Implemented in Tgstation.Server.Host.Components.Byond.WindowsByondInstaller, and Tgstation.Server.Host.Components.Byond.PosixByondInstaller.

        +

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

        +

        Property Documentation

        - + +

        ◆ DreamDaemonName

        +
        @@ -270,11 +258,15 @@ Properties

        Get the file name of the DreamDaemon executable

        -

        Definition at line 15 of file IByondInstaller.cs.

        +

        Definition at line 15 of file IByondInstaller.cs.

        +
        15 { get; }
        +

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

        - + +

        ◆ DreamMakerName

        +
        @@ -294,7 +286,9 @@ Properties

        Get the file name of the DreamMaker executable

        -

        Definition at line 20 of file IByondInstaller.cs.

        +

        Definition at line 20 of file IByondInstaller.cs.

        +
        20 { get; }
        +

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

        @@ -306,7 +300,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_i_byond_manager-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_i_byond_manager-members.html index 99f52d09e9..6e613efe04 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_i_byond_manager-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_byond_1_1_i_byond_manager-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        - + - - + + + + - + - - + + + +
        IDisposable Tgstation.Server.Host.Components.Byond.ByondManager - -
        + + @@ -120,7 +96,7 @@ Public Member Functions - +

        Public Member Functions

         Change the active BYOND version More...
         
        Task< IByondExecutableLockUseExecutables (Version requiredVersion, CancellationToken cancellationToken)
         Lock the current installation's location and return a IByondExecutableLock More...
         Lock the current installation's location and return a IByondExecutableLock More...
         

        Detailed Description

        For managing the BYOND installation

        -

        Definition at line 12 of file IByondManager.cs.

        +

        Definition at line 12 of file IByondManager.cs.

        Member Function Documentation

        - + +

        ◆ ChangeVersion()

        +

        @@ -135,9 +111,11 @@ Properties

        @@ -175,7 +153,9 @@ Properties - + +

        ◆ UseExecutables()

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

        Lock the current installation's location and return a IByondExecutableLock

        +

        Lock the current installation's location and return a IByondExecutableLock

        Parameters
        @@ -207,14 +187,18 @@ Properties
        requiredVersionThe BYOND Version required
        -
        Returns
        A Task<TResult> resulting in the requested IByondExecutableLock
        +
        Returns
        A Task<TResult> resulting in the requested IByondExecutableLock

        Implemented in Tgstation.Server.Host.Components.Byond.ByondManager.

        +

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

        +

        Property Documentation

        - + +

        ◆ ActiveVersion

        +
        @@ -234,11 +218,15 @@ Properties

        The currently active BYOND version

        -

        Definition at line 17 of file IByondManager.cs.

        +

        Definition at line 17 of file IByondManager.cs.

        +
        17 { get; }
        +

        Referenced by Tgstation.Server.Host.Components.Chat.Commands.ByondCommand.Invoke().

        - + +

        ◆ InstalledVersions

        +
        @@ -258,8 +246,8 @@ Properties

        The installed BYOND versions

        -

        Definition at line 22 of file IByondManager.cs.

        - +

        Definition at line 22 of file IByondManager.cs.

        +
        22 { get; }

        The documentation for this interface was generated from the following file:
          @@ -270,7 +258,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_commands_1_1_i_command-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_commands_1_1_i_command-members.html index cd3d20cb7b..15fc51df54 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_commands_1_1_i_command-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_commands_1_1_i_command-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        - + - - + + + + - + - - + + + +
        -Tgstation.Server.Host.Components.Chat.Commands.ByondCommand -Tgstation.Server.Host.Components.Chat.Commands.CustomCommand -Tgstation.Server.Host.Components.Chat.Commands.KekCommand -Tgstation.Server.Host.Components.Chat.Commands.PullRequestsCommand -Tgstation.Server.Host.Components.Chat.Commands.RevisionCommand -Tgstation.Server.Host.Components.Chat.Commands.VersionCommand - -
        +Tgstation.Server.Host.Components.Chat.Commands.ByondCommand +Tgstation.Server.Host.Components.Chat.Commands.CustomCommand +Tgstation.Server.Host.Components.Chat.Commands.KekCommand +Tgstation.Server.Host.Components.Chat.Commands.PullRequestsCommand +Tgstation.Server.Host.Components.Chat.Commands.RevisionCommand +Tgstation.Server.Host.Components.Chat.Commands.VersionCommand + + - +

        Public Member Functions

        Task< string > Invoke (string arguments, User user, CancellationToken cancellationToken)
         Invoke the ICommand More...
         Invoke the ICommand More...
         
        - +

        @@ -132,15 +108,17 @@ Properties

         The help text to display when queires are made about the command More...
         
        bool AdminOnly [get]
         If the command should only be available to Users who's User.Channel has Channel.IsAdminChannel set More...
         If the command should only be available to Users who's User.Channel has Channel.IsAdminChannel set More...
         

        Detailed Description

        Represents a command that can be invoked by talking to chat bots

        -

        Definition at line 9 of file ICommand.cs.

        +

        Definition at line 9 of file ICommand.cs.

        Member Function Documentation

        - + +

        ◆ Invoke()

        +
        @@ -170,11 +148,11 @@ Properties
        -

        Invoke the ICommand

        +

        Invoke the ICommand

        Parameters
        - - + +
        argumentsThe text after Name with leading whitespace trimmed
        userThe User who invoked the command
        argumentsThe text after Name with leading whitespace trimmed
        userThe User who invoked the command
        cancellationTokenThe CancellationToken for the operation
        @@ -186,7 +164,9 @@ Properties

        Property Documentation

        - + +

        ◆ AdminOnly

        +
        @@ -204,13 +184,15 @@ Properties
        -

        If the command should only be available to Users who's User.Channel has Channel.IsAdminChannel set

        - -

        Definition at line 24 of file ICommand.cs.

        +

        If the command should only be available to Users who's User.Channel has Channel.IsAdminChannel set

        +

        Definition at line 24 of file ICommand.cs.

        +
        24 { get; }
        - + +

        ◆ HelpText

        +
        @@ -230,11 +212,13 @@ Properties

        The help text to display when queires are made about the command

        -

        Definition at line 19 of file ICommand.cs.

        +

        Definition at line 19 of file ICommand.cs.

        +
        19 { get; }
        + + + +

        ◆ Name

        - - -
        @@ -254,8 +238,8 @@ Properties

        The text to invoke the command. May not be "?" or "help" (case-insensitive)

        -

        Definition at line 14 of file ICommand.cs.

        - +

        Definition at line 14 of file ICommand.cs.

        +
        14 { get; }

        The documentation for this interface was generated from the following file:
          @@ -266,7 +250,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_commands_1_1_i_command_factory-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_commands_1_1_i_command_factory-members.html index 3269c3e215..c6975211d8 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_commands_1_1_i_command_factory-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_commands_1_1_i_command_factory-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        - + - - + + + + - + - - + + + +
        -

        Factory for built in ICommands +

        Factory for built in ICommands More...

        Inheritance diagram for Tgstation.Server.Host.Components.Chat.Commands.ICommandFactory:
        @@ -108,21 +84,23 @@ Inheritance diagram for Tgstation.Server.Host.Components.Chat.Commands.ICommandF Tgstation.Server.Host.Components.Chat.Commands.CommandFactory - -
        + +
        - +

        Public Member Functions

        IReadOnlyList< ICommandGenerateCommands ()
         Generate builtin ICommands More...
         Generate builtin ICommands More...
         

        Detailed Description

        -

        Factory for built in ICommands

        +

        Factory for built in ICommands

        -

        Definition at line 8 of file ICommandFactory.cs.

        +

        Definition at line 8 of file ICommandFactory.cs.

        Member Function Documentation

        - + +

        ◆ GenerateCommands()

        +
        @@ -135,11 +113,13 @@ Public Member Functions
        -

        Generate builtin ICommands

        -
        Returns
        A IReadOnlyList<T> of ICommands
        +

        Generate builtin ICommands

        +
        Returns
        A IReadOnlyList<T> of ICommands

        Implemented in Tgstation.Server.Host.Components.Chat.Commands.CommandFactory.

        +

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

        +

        The documentation for this interface was generated from the following file:
          @@ -150,7 +130,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_chat-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_chat-members.html index df64ef32bd..4acd79109a 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_chat-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_chat-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        - + - - + + + + - + - - + + + +
        IHostedService IDisposable Tgstation.Server.Host.Components.Chat.Chat - -
        + + @@ -146,9 +122,11 @@ Public Member Functions

        Detailed Description

        For managing connected chat services

        -

        Definition at line 13 of file IChat.cs.

        +

        Definition at line 13 of file IChat.cs.

        Member Function Documentation

        - + +

        ◆ ChangeChannels()

        +

        Public Member Functions

        @@ -182,7 +160,7 @@ Public Member Functions
        Parameters
        - +
        connectionIdThe ChatBot.Id of the connection
        newChannelsAn IEnumerable<T> of the new list of Api.Models.ChatChannels
        newChannelsAn IEnumerable<T> of the new list of Api.Models.ChatChannels
        cancellationTokenThe CancellationToken for the operation
        @@ -193,7 +171,9 @@ Public Member Functions - + +

        ◆ ChangeSettings()

        +
        @@ -225,13 +205,15 @@ Public Member Functions
        -
        Returns
        A Task representing the running operation. Will complete immediately if the ChatBot.Enabled property of newSettings is
        +
        Returns
        A Task representing the running operation. Will complete immediately if the ChatBot.Enabled property of newSettings is false

        Implemented in Tgstation.Server.Host.Components.Chat.Chat.

        - + +

        ◆ Connected()

        +
        @@ -252,13 +234,15 @@ Public Member Functions
        -
        Returns
        if it is connected, otherwise
        +
        Returns
        true if it is connected, false otherwise

        Implemented in Tgstation.Server.Host.Components.Chat.Chat.

        - + +

        ◆ DeleteConnection()

        +
        @@ -296,7 +280,9 @@ Public Member Functions - + +

        ◆ RegisterCommandHandler()

        +
        @@ -313,18 +299,20 @@ Public Member Functions

        Registers a customCommandHandler to use

        Parameters
        - +
        customCommandHandlerA ICustomCommandHandler
        customCommandHandlerA ICustomCommandHandler

        Implemented in Tgstation.Server.Host.Components.Chat.Chat.

        -

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

        +

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

        - + +

        ◆ SendMessage()

        +
        @@ -358,7 +346,7 @@ Public Member Functions
        Parameters
        - +
        messageThe message being sent
        channelIdsThe Models.ChatChannel.Ids of the Host.Models.ChatChannels to send to
        channelIdsThe Models.ChatChannel.Ids of the Host.Models.ChatChannels to send to
        cancellationTokenThe CancellationToken for the operation
        @@ -367,9 +355,13 @@ Public Member Functions

        Implemented in Tgstation.Server.Host.Components.Chat.Chat.

        +

        Referenced by Tgstation.Server.Host.Components.Watchdog.SessionController.HandleInterop().

        +
        - + +

        ◆ SendUpdateMessage()

        +
        @@ -405,9 +397,13 @@ Public Member Functions

        Implemented in Tgstation.Server.Host.Components.Chat.Chat.

        +

        Referenced by Tgstation.Server.Host.Components.Compiler.DreamMaker.CleanupFailedCompile(), Tgstation.Server.Host.Components.Compiler.DreamMaker.RunCompileJob(), and Tgstation.Server.Host.Components.Compiler.DreamMaker.SendDeploymentMessage().

        + - + +

        ◆ SendWatchdogMessage()

        +
        @@ -445,7 +441,9 @@ Public Member Functions - + +

        ◆ TrackJsons()

        +
        @@ -495,6 +493,8 @@ Public Member Functions

        Implemented in Tgstation.Server.Host.Components.Chat.Chat.

        +

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

        +
        The documentation for this interface was generated from the following file:
          @@ -505,7 +505,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_chat_factory-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_chat_factory-members.html index 37983d708c..f22ad6d724 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_chat_factory-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_chat_factory-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        - + - - + + + + - + - - + + + +
        -

        For creating IChats +

        For creating IChats More...

        Inheritance diagram for Tgstation.Server.Host.Components.Chat.IChatFactory:
        @@ -108,21 +84,23 @@ Inheritance diagram for Tgstation.Server.Host.Components.Chat.IChatFactory:
        Tgstation.Server.Host.Components.Chat.ChatFactory - -
        + + - +

        Public Member Functions

        IChat CreateChat (IIOManager ioManager, ICommandFactory commandFactory, IEnumerable< Models.ChatBot > initialChatBots)
         Create a IChat More...
         Create a IChat More...
         

        Detailed Description

        -

        For creating IChats

        +

        For creating IChats

        -

        Definition at line 10 of file IChatFactory.cs.

        +

        Definition at line 10 of file IChatFactory.cs.

        Member Function Documentation

        - + +

        ◆ CreateChat()

        +
        @@ -152,19 +130,21 @@ Public Member Functions
        -

        Create a IChat

        +

        Create a IChat

        Parameters
        - - - + + +
        ioManagerThe IIOManager for the IChat
        commandFactoryThe ICommandFactory for the IChat
        initialChatBotsThe initial Models.ChatBot for the IChat
        ioManagerThe IIOManager for the IChat
        commandFactoryThe ICommandFactory for the IChat
        initialChatBotsThe initial Models.ChatBot for the IChat
        -
        Returns
        A new IChat
        +
        Returns
        A new IChat

        Implemented in Tgstation.Server.Host.Components.Chat.ChatFactory.

        +

        Referenced by Tgstation.Server.Host.Components.InstanceFactory.CreateInstance().

        +

        The documentation for this interface was generated from the following file:
          @@ -175,7 +155,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_custom_command_handler-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_custom_command_handler-members.html index 4b93800679..0232167854 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_custom_command_handler-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_custom_command_handler-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        - + - - + + + + - + - - + + + +
        -

        Handles Commands.ICommands that map to those defined in a IJsonTrackingContext +

        Handles Commands.ICommands that map to those defined in a IJsonTrackingContext More...

        Inheritance diagram for Tgstation.Server.Host.Components.Chat.ICustomCommandHandler:
        @@ -108,8 +84,8 @@ Inheritance diagram for Tgstation.Server.Host.Components.Chat.ICustomCommandHand Tgstation.Server.Host.Components.Watchdog.Watchdog - -
        + + @@ -118,11 +94,13 @@ Public Member Functions

        Public Member Functions

         

        Detailed Description

        -

        Handles Commands.ICommands that map to those defined in a IJsonTrackingContext

        +

        Handles Commands.ICommands that map to those defined in a IJsonTrackingContext

        -

        Definition at line 9 of file ICustomCommandHandler.cs.

        +

        Definition at line 9 of file ICustomCommandHandler.cs.

        Member Function Documentation

        - + +

        ◆ HandleChatCommand()

        +
        @@ -163,14 +141,14 @@ Public Member Functions
        - +
        commandNameThe command name
        argumentsEverything typed after commandName minus leading spaces
        senderThe sending User
        senderThe sending User
        cancellationTokenThe CancellationToken for the operation
        Returns
        A Task<TResult> resulting in the response text to send back
        -

        Referenced by Tgstation.Server.Host.Components.Chat.Commands.CustomCommand.Invoke().

        +

        Referenced by Tgstation.Server.Host.Components.Chat.Commands.CustomCommand.Invoke().

        @@ -182,7 +160,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_json_tracking_context-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_json_tracking_context-members.html index f1a6802806..2a63a57572 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_json_tracking_context-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_json_tracking_context-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        - + - - + + + + - + - - + + + +
        IDisposable Tgstation.Server.Host.Components.Chat.JsonTrackingContext - -
        + + - + - +

        Public Member Functions

        Task< IReadOnlyList< CustomCommand > > GetCustomCommands (CancellationToken cancellationToken)
         Read CustomCommands from the IJsonTrackingContext More...
         Read CustomCommands from the IJsonTrackingContext More...
         
        Task SetChannels (IEnumerable< Channel > channels, CancellationToken cancellationToken)
         Writes information about connected channels to the IJsonTrackingContext More...
         Writes information about connected channels to the IJsonTrackingContext More...
         
        - +

        Properties

        bool Active [get, set]
         If the IJsonTrackingContext should be used for GetCustomCommands(CancellationToken) More...
         If the IJsonTrackingContext should be used for GetCustomCommands(CancellationToken) More...
         

        Detailed Description

        Represents a tracking of dynamic chat json files

        -

        Definition at line 12 of file IJsonTrackingContext.cs.

        +

        Definition at line 12 of file IJsonTrackingContext.cs.

        Member Function Documentation

        - + +

        ◆ GetCustomCommands()

        +
        @@ -147,20 +125,22 @@ Properties
        -

        Read CustomCommands from the IJsonTrackingContext

        +

        Read CustomCommands from the IJsonTrackingContext

        Parameters
        cancellationTokenThe CancellationToken for the operation
        -
        Returns
        A Task<TResult> resulting in a IReadOnlyList<T> of CustomCommands in the IJsonTrackingContext
        +
        Returns
        A Task<TResult> resulting in a IReadOnlyList<T> of CustomCommands in the IJsonTrackingContext

        Implemented in Tgstation.Server.Host.Components.Chat.JsonTrackingContext.

        - + +

        ◆ SetChannels()

        +
        @@ -184,10 +164,10 @@ Properties
        -

        Writes information about connected channels to the IJsonTrackingContext

        +

        Writes information about connected channels to the IJsonTrackingContext

        Parameters
        - +
        channelsThe Channels to write out
        channelsThe Channels to write out
        cancellationTokenThe CancellationToken for the operation
        @@ -199,7 +179,9 @@ Properties

        Property Documentation

        - + +

        ◆ Active

        + @@ -233,7 +215,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_provider_factory-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_provider_factory-members.html index e50b790a4f..ec8b15294e 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_provider_factory-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_i_provider_factory-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
        Tgstation.Server.Host.Components.Chat.ProviderFactory - -
        + + @@ -120,9 +96,11 @@ Public Member Functions

        Detailed Description

        Factory for IProviders

        -

        Definition at line 9 of file IProviderFactory.cs.

        +

        Definition at line 9 of file IProviderFactory.cs.

        Member Function Documentation

        - + +

        ◆ CreateProvider()

        +

        Public Member Functions

        @@ -145,6 +123,8 @@ Public Member Functions
        Returns
        A new IProvider
        +

        Referenced by Tgstation.Server.Host.Components.Chat.Chat.ChangeSettings().

        +
        The documentation for this interface was generated from the following file:
          @@ -155,7 +135,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_i_provider-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_i_provider-members.html index 69f3329a22..c439a6bde5 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_i_provider-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_chat_1_1_providers_1_1_i_provider-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        - + - - + + + + - + - - + + + +
        IDisposable Tgstation.Server.Host.Components.Chat.Providers.Provider -Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider -Tgstation.Server.Host.Components.Chat.Providers.IrcProvider - -
        +Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider +Tgstation.Server.Host.Components.Chat.Providers.IrcProvider + + - + - + - + - +

        Public Member Functions

        Task< MessageNextMessage (CancellationToken cancellationToken)
         Get a Task<TResult> resulting in the next Message the IProvider recieves or on a disconnect More...
         Get a Task<TResult> resulting in the next Message the IProvider recieves or null on a disconnect More...
         
        Task< bool > Connect (CancellationToken cancellationToken)
         Attempt to connect the IProvider More...
         Attempt to connect the IProvider More...
         
        Task Disconnect (CancellationToken cancellationToken)
         Gracefully disconnects the provider. Implies a call to IDisposable.Dispose More...
         
        Task< IReadOnlyList< Channel > > MapChannels (IEnumerable< Api.Models.ChatChannel > channels, CancellationToken cancellationToken)
         Get the Channels for given channels More...
         Get the Channels for given channels More...
         
        Task SendMessage (ulong channelId, string message, CancellationToken cancellationToken)
         Send a message to the IProvider More...
         Send a message to the IProvider More...
         
        - + - +

        Properties

        bool Connected [get]
         If the IProvider More...
         If the IProvider More...
         
        string BotMention [get]
         The string that indicates the IProvider was mentioned More...
         The string that indicates the IProvider was mentioned More...
         

        Detailed Description

        For interacting with a chat service

        -

        Definition at line 11 of file IProvider.cs.

        +

        Definition at line 11 of file IProvider.cs.

        Member Function Documentation

        - + +

        ◆ Connect()

        +
        @@ -161,20 +139,22 @@ Properties
        -

        Attempt to connect the IProvider

        +

        Attempt to connect the IProvider

        Parameters
        cancellationTokenThe CancellationToken for the operation
        -
        Returns
        A Task<TResult> resulting in on success, otherwise
        +
        Returns
        A Task<TResult> resulting in true on success, false otherwise

        Implemented in Tgstation.Server.Host.Components.Chat.Providers.IrcProvider, Tgstation.Server.Host.Components.Chat.Providers.DiscordProvider, and Tgstation.Server.Host.Components.Chat.Providers.Provider.

        - + +

        ◆ Disconnect()

        +
        -

        Get the Channels for given channels

        +

        Get the Channels for given channels

        Parameters
        - +
        channelsThe Api.Models.ChatChannels to map
        channelsThe Api.Models.ChatChannels to map
        cancellationTokenThe CancellationToken for the operation
        -
        Returns
        A Task<TResult> resulting in a IReadOnlyList<T> of the Channels representing channels
        +
        Returns
        A Task<TResult> resulting in a IReadOnlyList<T> of the Channels representing channels
        - + +

        ◆ NextMessage()

        +
        @@ -253,21 +237,23 @@ Properties
        -

        Get a Task<TResult> resulting in the next Message the IProvider recieves or on a disconnect

        +

        Get a Task<TResult> resulting in the next Message the IProvider recieves or null on a disconnect

        Parameters
        cancellationTokenThe CancellationToken for the operation
        -
        Returns
        A Task<TResult> resulting in the next available Message
        -

        Note that private messages will come in the form of Channels not returned in MapChannels(IEnumerable<Api.Models.ChatChannel>, CancellationToken)

        +
        Returns
        A Task<TResult> resulting in the next available Message
        +

        Note that private messages will come in the form of Channels not returned in MapChannels(IEnumerable<Api.Models.ChatChannel>, CancellationToken)

        Implemented in Tgstation.Server.Host.Components.Chat.Providers.Provider.

        - + +

        ◆ SendMessage()

        +
        @@ -297,10 +283,10 @@ Properties
        -

        Send a message to the IProvider

        +

        Send a message to the IProvider

        Parameters
        - +
        channelIdThe Channel.RealId to send to
        channelIdThe Channel.RealId to send to
        messageThe message contents
        cancellationTokenThe CancellationToken for the operation
        @@ -313,7 +299,9 @@ Properties

        Property Documentation

        - + +

        ◆ BotMention

        +
        @@ -331,15 +319,17 @@ Properties
        -

        The string that indicates the IProvider was mentioned

        +

        The string that indicates the IProvider was mentioned

        -

        Definition at line 21 of file IProvider.cs.

        - -

        Referenced by Tgstation.Server.Host.Components.Chat.Chat.ProcessMessage().

        +

        Definition at line 21 of file IProvider.cs.

        +
        21 { get; }
        +

        Referenced by Tgstation.Server.Host.Components.Chat.Chat.ProcessMessage().

        - + +

        ◆ Connected

        +
        @@ -357,11 +347,11 @@ Properties
        -

        If the IProvider

        +

        If the IProvider

        -

        Definition at line 16 of file IProvider.cs.

        - -

        Referenced by Tgstation.Server.Host.Components.Chat.Chat.ProcessMessage().

        +

        Definition at line 16 of file IProvider.cs.

        +
        16 { get; }
        +

        Referenced by Tgstation.Server.Host.Components.Chat.Chat.ProcessMessage().

        @@ -373,7 +363,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_compile_job_consumer-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_compile_job_consumer-members.html index c39338ac63..7db0dc676b 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_compile_job_consumer-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_compile_job_consumer-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
        IHostedService IDisposable -Tgstation.Server.Host.Components.Compiler.DmbFactory - -
        +Tgstation.Server.Host.Components.Compiler.DmbFactory + + - +

        Public Member Functions

        Task LoadCompileJob (CompileJob job, CancellationToken cancellationToken)
         Load a new job into the ICompileJobConsumer More...
         Load a new job into the ICompileJobConsumer More...
         

        Detailed Description

        Sink for CompileJobs

        -

        Definition at line 12 of file ICompileJobConsumer.cs.

        +

        Definition at line 12 of file ICompileJobConsumer.cs.

        Member Function Documentation

        - + +

        ◆ LoadCompileJob()

        +
        @@ -148,7 +126,7 @@ Public Member Functions
        -

        Load a new job into the ICompileJobConsumer

        +

        Load a new job into the ICompileJobConsumer

        Parameters
        @@ -160,6 +138,8 @@ Public Member Functions

        Implemented in Tgstation.Server.Host.Components.Compiler.DmbFactory.

        +

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

        +
        The documentation for this interface was generated from the following file:
          @@ -170,7 +150,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_dmb_factory-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_dmb_factory-members.html index 7886db5f40..4b2bc1c201 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_dmb_factory-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_dmb_factory-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        jobThe CompileJob to load
        - + - - + + + + - + - - + + + +
        -

        Factory for IDmbProviders +

        Factory for IDmbProviders More...

        Inheritance diagram for Tgstation.Server.Host.Components.Compiler.IDmbFactory:
        @@ -108,17 +84,17 @@ Inheritance diagram for Tgstation.Server.Host.Components.Compiler.IDmbFactory: -Tgstation.Server.Host.Components.Compiler.DmbFactory - -
        +Tgstation.Server.Host.Components.Compiler.DmbFactory + +
        - + - + @@ -127,18 +103,20 @@ Public Member Functions - + - +

        Public Member Functions

        IDmbProvider LockNextDmb (int lockCount)
         Gets the next IDmbProvider More...
         Gets the next IDmbProvider More...
         
        Task< IDmbProviderFromCompileJob (CompileJob compileJob, CancellationToken cancellationToken)
         Gets a IDmbProvider for a given CompileJob More...
         Gets a IDmbProvider for a given CompileJob More...
         
        Task CleanUnusedCompileJobs (CompileJob exceptThisOne, CancellationToken cancellationToken)
         Deletes all compile jobs that are inactive in the Game folder exceptThisOne More...

        Properties

        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...
         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...
         If LockNextDmb will succeed More...
         

        Detailed Description

        -

        Factory for IDmbProviders

        +

        Factory for IDmbProviders

        -

        Definition at line 11 of file IDmbFactory.cs.

        +

        Definition at line 11 of file IDmbFactory.cs.

        Member Function Documentation

        - + +

        ◆ CleanUnusedCompileJobs()

        +
        @@ -174,9 +152,13 @@ Properties

        Implemented in Tgstation.Server.Host.Components.Compiler.DmbFactory.

        +

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

        + - + +

        ◆ FromCompileJob()

        +
        @@ -200,21 +182,25 @@ Properties
        -

        Gets a IDmbProvider for a given CompileJob

        +

        Gets a IDmbProvider for a given CompileJob

        Parameters
        - +
        compileJobThe CompileJob to make the IDmbProvider for
        compileJobThe CompileJob to make the IDmbProvider for
        cancellationTokenThe CancellationToken for the operation
        -
        Returns
        A Task<TResult> resulting in a new IDmbProvider representing the CompileJob on success, on failure
        +
        Returns
        A Task<TResult> resulting in a new IDmbProvider representing the CompileJob on success, null on failure

        Implemented in Tgstation.Server.Host.Components.Compiler.DmbFactory.

        +

        Referenced by Tgstation.Server.Host.Components.ReattachInfoHandler.Load().

        +
        - + +

        ◆ LockNextDmb()

        +
        @@ -228,21 +214,25 @@ Properties
        -

        Gets the next IDmbProvider

        +

        Gets the next IDmbProvider

        Parameters
        - +
        lockCountThe amount of locks to give the resulting IDmbProvider. It's IDisposable.Dispose must be called this many times to properly clean the job
        lockCountThe amount of locks to give the resulting IDmbProvider. It's IDisposable.Dispose must be called this many times to properly clean the job
        -
        Returns
        A new IDmbProvider
        +
        Returns
        A new IDmbProvider

        Implemented in Tgstation.Server.Host.Components.Compiler.DmbFactory.

        +

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

        +

        Property Documentation

        - + +

        ◆ DmbAvailable

        +
        @@ -260,13 +250,17 @@ Properties
        -

        If LockNextDmb will succeed

        +

        If LockNextDmb will succeed

        -

        Definition at line 22 of file IDmbFactory.cs.

        +

        Definition at line 22 of file IDmbFactory.cs.

        +
        22 { get; }
        +

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

        - + +

        ◆ OnNewerDmb

        +
        @@ -284,11 +278,11 @@ Properties
        -

        Get a Task that completes when the result of a call to LockNextDmb will be different than the previous call if any

        +

        Get a Task that completes when the result of a call to LockNextDmb will be different than the previous call if any

        Returns
        A Task representing the running operation
        -

        Definition at line 17 of file IDmbFactory.cs.

        - +

        Definition at line 17 of file IDmbFactory.cs.

        +
        17 { get; }

        The documentation for this interface was generated from the following file:
          @@ -299,7 +293,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_dream_maker-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_dream_maker-members.html index 88f7582eed..1311ef94e6 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_dream_maker-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_dream_maker-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        - + - - + + + +
        This is the complete list of members for Tgstation.Server.Host.Components.Compiler.IDreamMaker, including all inherited members.

        - +
        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
        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
        diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_dream_maker.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_dream_maker.html index 016d11c224..82e29a729d 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_dream_maker.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_compiler_1_1_i_dream_maker.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Host.Components.Compiler.IDreamMaker Interface Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + +
        Tgstation.Server.Host.Components.Compiler.DreamMaker - -
        + + - - - + + +

        Public Member Functions

        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...
         
        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...
         

        Detailed Description

        For managing the compiler

        -

        Definition at line 11 of file IDreamMaker.cs.

        +

        Definition at line 11 of file IDreamMaker.cs.

        Member Function Documentation

        - + +

        ◆ Compile()

        +
        @@ -180,7 +158,7 @@ Public Member Functions
        Parameters
        - + @@ -189,7 +167,9 @@ Public Member Functions
        revisionInformationThe Models.RevisionInformation being compiled from the repository
        dreamMakerSettingsThe Api.Models.DreamMaker for the compile
        dreamMakerSettingsThe Api.Models.DreamMaker for the compile
        apiValidateTimeoutThe time in seconds to wait while validating the API
        repositoryThe IRepository to copy from
        progressReporterThe Action<T1> to report compilation progress
        -
        Returns
        A Task<TResult> resulting in the partially populated Models.CompileJob for the operation. In particular, note the Models.CompileJob.RevisionInformation field will only have it's Api.Models.Internal.RevisionInformation.CommitSha field populated
        +
        Returns
        A Task<TResult> resulting in the partially populated Models.CompileJob for the operation. In particular, note the Models.CompileJob.RevisionInformation field will only have it's Api.Models.Internal.RevisionInformation.CommitSha field populated
        + +

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

        @@ -201,7 +181,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_dmb_provider-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_dmb_provider-members.html index 90b7b6fc8c..c4fe8345dc 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_dmb_provider-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_dmb_provider-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
        IDisposable Tgstation.Server.Host.Components.Compiler.DmbProvider -Tgstation.Server.Host.Components.Compiler.TemporaryDmbProvider - -
        +Tgstation.Server.Host.Components.Compiler.TemporaryDmbProvider + + - +

        Public Member Functions

        void KeepAlive ()
         Disposing the IDmbProvider won't cause a cleanup of the working directory More...
         Disposing the IDmbProvider won't cause a cleanup of the working directory More...
         
        - +

        @@ -132,15 +108,17 @@ Properties

         The secondary game directory with a trailing directory separator More...
         
        CompileJob CompileJob [get]
         The CompileJob of the .dmb More...
         The CompileJob of the .dmb More...
         

        Detailed Description

        Provides absolute paths to the latest compiled .dmbs

        -

        Definition at line 9 of file IDmbProvider.cs.

        +

        Definition at line 9 of file IDmbProvider.cs.

        Member Function Documentation

        - + +

        ◆ KeepAlive()

        +
        @@ -153,14 +131,16 @@ Properties
        -

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

        +

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

        Implemented in Tgstation.Server.Host.Components.Compiler.DmbProvider, and Tgstation.Server.Host.Components.Compiler.TemporaryDmbProvider.

        Property Documentation

        - + +

        ◆ CompileJob

        + - + +

        ◆ DmbName

        +
        @@ -206,13 +188,15 @@ Properties

        The file name of the .dmb

        -

        Definition at line 14 of file IDmbProvider.cs.

        - -

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

        +

        Definition at line 14 of file IDmbProvider.cs.

        +
        14 { get; }
        +

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

        - + +

        ◆ PrimaryDirectory

        +
        @@ -232,13 +216,15 @@ Properties

        The primary game directory with a trailing directory separator

        -

        Definition at line 19 of file IDmbProvider.cs.

        - -

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

        +

        Definition at line 19 of file IDmbProvider.cs.

        +
        19 { get; }
        +

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

        - + +

        ◆ SecondaryDirectory

        +
        @@ -258,9 +244,9 @@ Properties

        The secondary game directory with a trailing directory separator

        -

        Definition at line 24 of file IDmbProvider.cs.

        - -

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

        +

        Definition at line 24 of file IDmbProvider.cs.

        +
        24 { get; }
        +

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

        @@ -272,7 +258,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_event_consumer-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_event_consumer-members.html index 0a4576dae7..1e97459608 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_event_consumer-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_event_consumer-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        - + - - + + + + - + - - + + + +
        -

        Consumes EventTypes and takes the appropriate actions +

        Consumes EventTypes and takes the appropriate actions More...

        Inheritance diagram for Tgstation.Server.Host.Components.IEventConsumer:
        @@ -108,12 +84,12 @@ Inheritance diagram for Tgstation.Server.Host.Components.IEventConsumer:
        Tgstation.Server.Host.Components.EventConsumer -Tgstation.Server.Host.Components.StaticFiles.IConfiguration -Tgstation.Server.Host.Components.Watchdog.IWatchdog +Tgstation.Server.Host.Components.StaticFiles.IConfiguration +Tgstation.Server.Host.Components.Watchdog.IWatchdog Tgstation.Server.Host.Components.StaticFiles.Configuration Tgstation.Server.Host.Components.Watchdog.Watchdog - -
        + + @@ -122,11 +98,13 @@ Public Member Functions

        Public Member Functions

         

        Detailed Description

        -

        Consumes EventTypes and takes the appropriate actions

        +

        Consumes EventTypes and takes the appropriate actions

        -

        Definition at line 10 of file IEventConsumer.cs.

        +

        Definition at line 10 of file IEventConsumer.cs.

        Member Function Documentation

        - + +

        ◆ HandleEvent()

        +
        @@ -159,17 +137,17 @@ Public Member Functions

        Handle a given eventType

        Parameters
        - +
        eventTypeThe EventType
        eventTypeThe EventType
        parametersThe parameters for eventType
        cancellationTokenThe CancellationToken for the operation
        -
        Returns
        A Task<TResult> resulting in if more IEventConsumer should run, otherwise
        +
        Returns
        A Task<TResult> resulting in true if more IEventConsumer should run, false otherwise

        Implemented in Tgstation.Server.Host.Components.Watchdog.Watchdog, Tgstation.Server.Host.Components.StaticFiles.Configuration, and Tgstation.Server.Host.Components.EventConsumer.

        -

        Referenced by Tgstation.Server.Host.Components.EventConsumer.HandleEvent().

        +

        Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ChangeVersion(), Tgstation.Server.Host.Components.Compiler.DreamMaker.Compile(), Tgstation.Server.Host.Components.EventConsumer.HandleEvent(), Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), Tgstation.Server.Host.Components.Compiler.DreamMaker.RunCompileJob(), and Tgstation.Server.Host.Components.Instance.TimerLoop().

        @@ -181,7 +159,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_instance-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_instance-members.html index 084014ece2..d1d42af5f8 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_instance-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_instance-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        - + - - + + + + - + - - + + + +
        IHostedService IDisposable Tgstation.Server.Host.Components.Instance - -
        + + @@ -120,39 +96,41 @@ Public Member Functions - + - + - +

        Public Member Functions

         The latest staged CompileJob More...
         
        void Rename (string newName)
         Rename the IInstance More...
         Rename the IInstance More...
         
        Task SetAutoUpdateInterval (uint newInterval)
         Change the Api.Models.Instance.AutoUpdateInterval for the IInstance More...
         Change the Api.Models.Instance.AutoUpdateInterval for the IInstance More...
         
        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.IJobManager More...
         Run the compile job and insert it into the database. Meant to be called by a Core.IJobManager More...
         
        - + - + - + - + - +

        Properties

        IRepositoryManager RepositoryManager [get]
         The IRepositoryManager for the IInstance More...
         The IRepositoryManager for the IInstance More...
         
        IByondManager ByondManager [get]
         The IByondManager for the IInstance More...
         The IByondManager for the IInstance More...
         
        IWatchdog Watchdog [get]
         The IWatchdog for the IInstance More...
         The IWatchdog for the IInstance More...
         
        IChat Chat [get]
         The IChat for the IInstance More...
         The IChat for the IInstance More...
         
        IConfiguration Configuration [get]
         The IConfiguration for the IInstance More...
         The IConfiguration for the IInstance More...
         

        Detailed Description

        For interacting with the instance services

        -

        Definition at line 17 of file IInstance.cs.

        +

        Definition at line 17 of file IInstance.cs.

        Member Function Documentation

        - + +

        ◆ CompileProcess()

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

        Run the compile job and insert it into the database. Meant to be called by a Core.IJobManager

        +

        Run the compile job and insert it into the database. Meant to be called by a Core.IJobManager

        Parameters
        @@ -202,9 +180,13 @@ Properties

        Implemented in Tgstation.Server.Host.Components.Instance.

        +

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

        + - + +

        ◆ LatestCompileJob()

        +
        jobThe running Job
        @@ -224,7 +206,9 @@ Properties - + +

        ◆ Rename()

        +
        @@ -238,10 +222,10 @@ Properties
        -

        Rename the IInstance

        +

        Rename the IInstance

        Parameters
        - +
        newNameThe new name for the IInstance
        newNameThe new name for the IInstance
        @@ -250,7 +234,9 @@ Properties
        - + +

        ◆ SetAutoUpdateInterval()

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

        Change the Api.Models.Instance.AutoUpdateInterval for the IInstance

        +

        Change the Api.Models.Instance.AutoUpdateInterval for the IInstance

        Parameters
        @@ -278,7 +264,9 @@ Properties

        Property Documentation

        - + +

        ◆ ByondManager

        +
        newIntervalThe new auto update inteval
        @@ -296,13 +284,17 @@ Properties
        -

        The IByondManager for the IInstance

        +

        The IByondManager for the IInstance

        -

        Definition at line 27 of file IInstance.cs.

        +

        Definition at line 27 of file IInstance.cs.

        +
        27 { get; }
        +

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

        - + +

        ◆ Chat

        +
        @@ -320,13 +312,17 @@ Properties
        -

        The IChat for the IInstance

        +

        The IChat for the IInstance

        -

        Definition at line 37 of file IInstance.cs.

        +

        Definition at line 37 of file IInstance.cs.

        +
        37 { get; }
        +

        Referenced by Tgstation.Server.Host.Controllers.ChatController.Create(), and Tgstation.Server.Host.Controllers.ChatController.Update().

        - + +

        ◆ Configuration

        + - + +

        ◆ RepositoryManager

        +
        @@ -368,13 +368,17 @@ Properties
        - + +

        ◆ Watchdog

        + @@ -406,7 +412,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_instance_factory-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_instance_factory-members.html index 4be09f9e9f..8a1f383404 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_instance_factory-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_instance_factory-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
        -

        Factory for creating IInstances +

        Factory for creating IInstances More...

        Inheritance diagram for Tgstation.Server.Host.Components.IInstanceFactory:
        @@ -109,21 +85,23 @@ Inheritance diagram for Tgstation.Server.Host.Components.IInstanceFactory:
        IHostedService Tgstation.Server.Host.Components.InstanceFactory - -
        + + - +

        Public Member Functions

        IInstance CreateInstance (Models.Instance metadata)
         Create an IInstance More...
         Create an IInstance More...
         

        Detailed Description

        -

        Factory for creating IInstances

        +

        Factory for creating IInstances

        -

        Definition at line 8 of file IInstanceFactory.cs.

        +

        Definition at line 8 of file IInstanceFactory.cs.

        Member Function Documentation

        - + +

        ◆ CreateInstance()

        +
        @@ -137,17 +115,19 @@ Public Member Functions
        -

        Create an IInstance

        +

        Create an IInstance

        Parameters
        - +
        metadataThe Models.Instance
        metadataThe Models.Instance
        -
        Returns
        A new IInstance
        +
        Returns
        A new IInstance

        Implemented in Tgstation.Server.Host.Components.InstanceFactory.

        +

        Referenced by Tgstation.Server.Host.Components.InstanceManager.OnlineInstance().

        +

        The documentation for this interface was generated from the following file:
          @@ -158,7 +138,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_instance_manager-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_instance_manager-members.html index 033572e0f2..962834234e 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_instance_manager-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_i_instance_manager-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        - + - - + + + + - + - - + + + +
        -

        For managing IInstances +

        For managing IInstances More...

        Inheritance diagram for Tgstation.Server.Host.Components.IInstanceManager:
        @@ -108,30 +84,32 @@ Inheritance diagram for Tgstation.Server.Host.Components.IInstanceManager:
        Tgstation.Server.Host.Components.InstanceManager - -
        + + - + - + - + - +

        Public Member Functions

        IInstance GetInstance (Models.Instance metadata)
         Get the IInstance associated with given metadata More...
         Get the IInstance associated with given metadata More...
         
        Task OnlineInstance (Models.Instance metadata, CancellationToken cancellationToken)
         Online an IInstance More...
         Online an IInstance More...
         
        Task OfflineInstance (Models.Instance metadata, User user, CancellationToken cancellationToken)
         Offline an IInstance More...
         Offline an IInstance More...
         
        Task MoveInstance (Models.Instance metadata, string newPath, CancellationToken cancellationToken)
         Move an IInstance More...
         Move an IInstance More...
         

        Detailed Description

        -

        For managing IInstances

        +

        For managing IInstances

        -

        Definition at line 10 of file IInstanceManager.cs.

        +

        Definition at line 10 of file IInstanceManager.cs.

        Member Function Documentation

        - + +

        ◆ GetInstance()

        +
        @@ -145,20 +123,24 @@ Public Member Functions
        -

        Get the IInstance associated with given metadata

        +

        Get the IInstance associated with given metadata

        Parameters
        - +
        metadataThe Models.Instance of the desired IInstance
        metadataThe Models.Instance of the desired IInstance
        -
        Returns
        The IInstance associated with the given metadata
        +
        Returns
        The IInstance associated with the given metadata

        Implemented in Tgstation.Server.Host.Components.InstanceManager.

        +

        Referenced by Tgstation.Server.Host.Controllers.DreamDaemonController.Create(), Tgstation.Server.Host.Controllers.ChatController.Create(), Tgstation.Server.Host.Controllers.DreamMakerController.Create(), Tgstation.Server.Host.Controllers.RepositoryController.Create(), Tgstation.Server.Host.Controllers.ConfigurationController.Create(), Tgstation.Server.Host.Controllers.ChatController.Delete(), Tgstation.Server.Host.Controllers.DreamDaemonController.Delete(), Tgstation.Server.Host.Controllers.ConfigurationController.Delete(), Tgstation.Server.Host.Controllers.RepositoryController.Delete(), Tgstation.Server.Host.Controllers.ConfigurationController.Directory(), Tgstation.Server.Host.Controllers.ConfigurationController.File(), Tgstation.Server.Host.Controllers.DreamMakerController.Read(), Tgstation.Server.Host.Controllers.RepositoryController.Read(), Tgstation.Server.Host.Controllers.DreamDaemonController.ReadImpl(), Tgstation.Server.Host.Controllers.DreamDaemonController.Restart(), Tgstation.Server.Host.Controllers.ByondController.Update(), Tgstation.Server.Host.Controllers.ConfigurationController.Update(), Tgstation.Server.Host.Controllers.DreamDaemonController.Update(), Tgstation.Server.Host.Controllers.ChatController.Update(), and Tgstation.Server.Host.Controllers.RepositoryController.Update().

        +
        - + +

        ◆ MoveInstance()

        +
        @@ -188,11 +170,11 @@ Public Member Functions
        -

        Move an IInstance

        +

        Move an IInstance

        Parameters
        - - + +
        metadataThe Models.Instance of the desired IInstance
        newPathThe new path of the IInstance. metadata will have this set on Api.Models.Instance.Path if the operation completes successfully
        metadataThe Models.Instance of the desired IInstance
        newPathThe new path of the IInstance. metadata will have this set on Api.Models.Instance.Path if the operation completes successfully
        cancellationTokenThe CancellationToken for the operation
        @@ -203,7 +185,9 @@ Public Member Functions
        - + +

        ◆ OfflineInstance()

        +
        @@ -233,10 +217,10 @@ Public Member Functions
        -

        Offline an IInstance

        +

        Offline an IInstance

        Parameters
        - +
        metadataThe Models.Instance of the desired IInstance
        metadataThe Models.Instance of the desired IInstance
        userThe User performing the operation
        cancellationTokenThe CancellationToken for the operation
        @@ -246,7 +230,9 @@ Public Member Functions
        - + +

        ◆ OnlineInstance()

        +
        @@ -270,10 +256,10 @@ Public Member Functions
        -

        Online an IInstance

        +

        Online an IInstance

        Parameters
        - +
        metadataThe Models.Instance of the desired IInstance
        metadataThe Models.Instance of the desired IInstance
        cancellationTokenThe CancellationToken for the operation
        @@ -292,7 +278,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_i_comm_context-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_i_comm_context-members.html index 2e12218902..e664ea43cb 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_i_comm_context-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_i_comm_context-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        - + - - + + + + - + - - + + + +
        IDisposable Tgstation.Server.Host.Components.Interop.CommContext - -
        + +
        - +

        Public Member Functions

        void RegisterHandler (ICommHandler handler)
         Register a handler with the ICommContext More...
         Register a handler with the ICommContext More...
         

        Detailed Description

        Represents a registration of an interop session

        -

        Definition at line 8 of file ICommContext.cs.

        +

        Definition at line 8 of file ICommContext.cs.

        Member Function Documentation

        - + +

        ◆ RegisterHandler()

        +
        @@ -137,17 +115,17 @@ Public Member Functions
        -

        Register a handler with the ICommContext

        +

        Register a handler with the ICommContext

        Parameters
        - +
        handlerThe ICommHandler to register
        handlerThe ICommHandler to register

        Implemented in Tgstation.Server.Host.Components.Interop.CommContext.

        -

        Referenced by Tgstation.Server.Host.Components.Watchdog.SessionController.SessionController().

        +

        Referenced by Tgstation.Server.Host.Components.Watchdog.SessionController.SessionController().

        @@ -159,7 +137,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_i_comm_handler-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_i_comm_handler-members.html index 34766d5795..d2d4405de4 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_i_comm_handler-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_interop_1_1_i_comm_handler-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
        -

        Handles CommCommands +

        Handles CommCommands More...

        Inheritance diagram for Tgstation.Server.Host.Components.Interop.ICommHandler:
        @@ -108,8 +84,8 @@ Inheritance diagram for Tgstation.Server.Host.Components.Interop.ICommHandler: Tgstation.Server.Host.Components.Watchdog.SessionController - -
        + + @@ -118,11 +94,13 @@ Public Member Functions

        Public Member Functions

         

        Detailed Description

        -

        Handles CommCommands

        +

        Handles CommCommands

        -

        Definition at line 9 of file ICommHandler.cs.

        +

        Definition at line 9 of file ICommHandler.cs.

        Member Function Documentation

        - + +

        ◆ HandleInterop()

        +
        @@ -149,7 +127,7 @@ Public Member Functions

        Handle a command

        Parameters
        - +
        commandThe CommCommand to handle
        commandThe CommCommand to handle
        cancellationTokenThe CancellationToken for the operation
        @@ -168,7 +146,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_repository_1_1_i_credentials_provider-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_repository_1_1_i_credentials_provider-members.html index 286a38cee3..ec5a51d36b 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_repository_1_1_i_credentials_provider-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_repository_1_1_i_credentials_provider-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        - + - - + + + + - + - - + + + +
        Tgstation.Server.Host.Components.Repository.CredentialsProvider - -
        + +
        @@ -120,9 +96,11 @@ Public Member Functions

        Detailed Description

        For generating CredentialsHandlers

        -

        Definition at line 8 of file ICredentialsProvider.cs.

        +

        Definition at line 8 of file ICredentialsProvider.cs.

        Member Function Documentation

        - + +

        ◆ GenerateHandler()

        +

        Public Member Functions

        @@ -158,6 +136,8 @@ Public Member Functions

        Implemented in Tgstation.Server.Host.Components.Repository.CredentialsProvider.

        +

        Referenced by Tgstation.Server.Host.Components.Repository.Repository.AddTestMerge(), and Tgstation.Server.Host.Components.Repository.RepositoryManager.CloneRepository().

        +
        The documentation for this interface was generated from the following file:
          @@ -168,7 +148,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_repository_1_1_i_repository-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_repository_1_1_i_repository-members.html index b9056f5ef7..dec1428aed 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_repository_1_1_i_repository-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_repository_1_1_i_repository-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
        - + - - + + + + - + - - + + + +
        IDisposable Tgstation.Server.Host.Components.Repository.Repository - -
        + + @@ -137,7 +113,7 @@ Public Member Functions - + @@ -146,33 +122,35 @@ Public Member Functions - + - + - + - + - + - + - +

        Public Member Functions

         Requires the current HEAD to be a tracked reference. Merges the reference to what it tracks on the origin repository More...
         
        Task< bool > Sychronize (string username, string password, string committerName, string committerEmail, Action< int > progressReporter, bool synchronizeTrackedBranch, CancellationToken cancellationToken)
         Runs the synchronize event script and attempts to push any changes made to the IRepository if on a tracked branch More...
         Runs the synchronize event script and attempts to push any changes made to the IRepository if on a tracked branch More...
         
        Task CopyTo (string path, CancellationToken cancellationToken)
         Copies the current working directory to a given path More...

        Properties

        bool IsGitHubRepository [get]
         If the IRepository was cloned from GitHub.com More...
         If the IRepository was cloned from GitHub.com More...
         
        string GitHubOwner [get]
         The Octokit.Repository.Owner if this IsGitHubRepository More...
         The Octokit.Repository.Owner if this IsGitHubRepository More...
         
        string GitHubRepoName [get]
         The Octokit.Repository.Name if this IsGitHubRepository More...
         The Octokit.Repository.Name if this IsGitHubRepository More...
         
        bool Tracking [get]
         If Reference tracks an upstream branch More...
         If Reference tracks an upstream branch More...
         
        string Head [get]
         The SHA of the IRepository HEAD More...
         The SHA of the IRepository HEAD More...
         
        string Reference [get]
         The current reference the IRepository HEAD is using. This can be a branch or tag More...
         The current reference the IRepository HEAD is using. This can be a branch or tag More...
         
        string Origin [get]
         The current origin remote the IRepository is using More...
         The current origin remote the IRepository is using More...
         

        Detailed Description

        Represents an on-disk git repository

        -

        Definition at line 11 of file IRepository.cs.

        +

        Definition at line 11 of file IRepository.cs.

        Member Function Documentation

        - + +

        ◆ AddTestMerge()

        +
        @@ -239,13 +217,15 @@ Properties
        -
        Returns
        A Task<TResult> resulting in a Nullable<T> bool representing the merge result that is after a fast forward or up to date, on a non-fast-forward, on a conflict
        +
        Returns
        A Task<TResult> resulting in a Nullable<T> bool representing the merge result that is true after a fast forward or up to date, false on a non-fast-forward, null on a conflict

        Implemented in Tgstation.Server.Host.Components.Repository.Repository.

        - + +

        ◆ CheckoutObject()

        +
        @@ -290,7 +270,9 @@ Properties - + +

        ◆ CopyTo()

        +
        @@ -326,11 +308,13 @@ Properties

        Implemented in Tgstation.Server.Host.Components.Repository.Repository.

        -

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

        +

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

        - + +

        ◆ FetchOrigin()

        +
        @@ -382,7 +366,9 @@ Properties - + +

        ◆ IsSha()

        +
        @@ -414,13 +400,15 @@ Properties
        -
        Returns
        A Task<TResult> resulting in if committish is a sha, otherwise
        +
        Returns
        A Task<TResult> resulting in true if committish is a sha, false otherwise

        Implemented in Tgstation.Server.Host.Components.Repository.Repository.

        - + +

        ◆ MergeOrigin()

        +
        @@ -466,13 +454,15 @@ Properties
        -
        Returns
        A Task<TResult> resulting in a Nullable<T> bool representing the merge result that is after a fast forward, on a merge or up to date, on a conflict
        +
        Returns
        A Task<TResult> resulting in a Nullable<T> bool representing the merge result that is true after a fast forward, false on a merge or up to date, null on a conflict

        Implemented in Tgstation.Server.Host.Components.Repository.Repository.

        - + +

        ◆ ResetToOrigin()

        +
        @@ -510,7 +500,9 @@ Properties - + +

        ◆ ResetToSha()

        +
        @@ -555,7 +547,9 @@ Properties - + +

        ◆ Sychronize()

        +
        @@ -609,7 +603,7 @@ Properties
        -

        Runs the synchronize event script and attempts to push any changes made to the IRepository if on a tracked branch

        +

        Runs the synchronize event script and attempts to push any changes made to the IRepository if on a tracked branch

        Parameters
        @@ -622,14 +616,16 @@ Properties
        usernameThe username to fetch from the origin repository
        -
        Returns
        A Task<TResult> resulting in if commits were pushed to the tracked origin reference, otherwise
        +
        Returns
        A Task<TResult> resulting in true if commits were pushed to the tracked origin reference, false otherwise

        Implemented in Tgstation.Server.Host.Components.Repository.Repository.

        Property Documentation

        - + +

        ◆ GitHubOwner

        +
        @@ -647,13 +643,15 @@ Properties
        -

        The Octokit.Repository.Owner if this IsGitHubRepository

        - -

        Definition at line 21 of file IRepository.cs.

        +

        The Octokit.Repository.Owner if this IsGitHubRepository

        +

        Definition at line 21 of file IRepository.cs.

        +
        21 { get; }
        - + +

        ◆ GitHubRepoName

        +
        @@ -671,13 +669,15 @@ Properties
        -

        The Octokit.Repository.Name if this IsGitHubRepository

        - -

        Definition at line 26 of file IRepository.cs.

        +

        The Octokit.Repository.Name if this IsGitHubRepository

        +

        Definition at line 26 of file IRepository.cs.

        +
        26 { get; }
        - + +

        ◆ Head

        +
        @@ -695,13 +695,17 @@ Properties
        -

        The SHA of the IRepository HEAD

        +

        The SHA of the IRepository HEAD

        -

        Definition at line 36 of file IRepository.cs.

        +

        Definition at line 36 of file IRepository.cs.

        +
        36 { get; }
        +

        Referenced by Tgstation.Server.Host.Components.Repository.Repository.AddTestMerge().

        - + +

        ◆ IsGitHubRepository

        +
        @@ -719,13 +723,15 @@ Properties
        -

        If the IRepository was cloned from GitHub.com

        - -

        Definition at line 16 of file IRepository.cs.

        +

        If the IRepository was cloned from GitHub.com

        +

        Definition at line 16 of file IRepository.cs.

        +
        16 { get; }
        - + +

        ◆ Origin

        +
        @@ -743,15 +749,17 @@ Properties
        -

        The current origin remote the IRepository is using

        +

        The current origin remote the IRepository is using

        -

        Definition at line 46 of file IRepository.cs.

        - -

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

        +

        Definition at line 46 of file IRepository.cs.

        +
        46 { get; }
        +

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

        - + +

        ◆ Reference

        +
        @@ -769,13 +777,15 @@ Properties
        -

        The current reference the IRepository HEAD is using. This can be a branch or tag

        - -

        Definition at line 41 of file IRepository.cs.

        +

        The current reference the IRepository HEAD is using. This can be a branch or tag

        +

        Definition at line 41 of file IRepository.cs.

        +
        41 { get; }
        - + +

        ◆ Tracking

        +
        @@ -793,10 +803,10 @@ Properties
        -

        If Reference tracks an upstream branch

        - -

        Definition at line 31 of file IRepository.cs.

        +

        If Reference tracks an upstream branch

        +

        Definition at line 31 of file IRepository.cs.

        +
        31 { get; }

        The documentation for this interface was generated from the following file:
          @@ -807,7 +817,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_repository_1_1_i_repository_manager-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_repository_1_1_i_repository_manager-members.html index e6590c9063..5bc2d36225 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_repository_1_1_i_repository_manager-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_repository_1_1_i_repository_manager-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
          -

          Factory for creating and loading IRepositorys +

          Factory for creating and loading IRepositorys More...

          Inheritance diagram for Tgstation.Server.Host.Components.Repository.IRepositoryManager:
          @@ -110,13 +86,13 @@ Inheritance diagram for Tgstation.Server.Host.Components.Repository.IRepositoryM IDisposable Tgstation.Server.Host.Components.Repository.RepositoryManager - -
          + + - + @@ -131,15 +107,17 @@ Properties - +

          Public Member Functions

          Task< IRepositoryLoadRepository (CancellationToken cancellationToken)
           Attempt to load the IRepository from the default location More...
           Attempt to load the IRepository from the default location More...
           
          Task< IRepositoryCloneRepository (Uri url, string initialBranch, string username, string password, Action< int > progressReporter, CancellationToken cancellationToken)
           Clone the repository at url More...
           If something is holding a lock on the repository More...
           
          bool CloneInProgress [get]
           If a CloneRepository(Uri, string, string, string, Action<int>, CancellationToken) operation is in progress More...
           If a CloneRepository(Uri, string, string, string, Action<int>, CancellationToken) operation is in progress More...
           

          Detailed Description

          -

          Factory for creating and loading IRepositorys

          +

          Factory for creating and loading IRepositorys

          -

          Definition at line 10 of file IRepositoryManager.cs.

          +

          Definition at line 10 of file IRepositoryManager.cs.

          Member Function Documentation

          - + +

          ◆ CloneRepository()

          +
          @@ -199,13 +177,15 @@ Properties
          -
          Returns
          The newly cloned IRepository, if one already exists
          +
          Returns
          The newly cloned IRepository, null if one already exists

          Implemented in Tgstation.Server.Host.Components.Repository.RepositoryManager.

          - + +

          ◆ DeleteRepository()

          +
          @@ -232,7 +212,9 @@ Properties - + +

          ◆ LoadRepository()

          +
          @@ -246,21 +228,25 @@ Properties
          -

          Attempt to load the IRepository from the default location

          +

          Attempt to load the IRepository from the default location

          Parameters
          cancellationTokenThe CancellationToken for the operation
          -
          Returns
          The loaded IRepository if it exists, otherwise
          +
          Returns
          The loaded IRepository if it exists, null otherwise

          Implemented in Tgstation.Server.Host.Components.Repository.RepositoryManager.

          +

          Referenced by Tgstation.Server.Host.Components.Chat.Commands.RevisionCommand.Invoke(), and Tgstation.Server.Host.Components.Chat.Commands.PullRequestsCommand.Invoke().

          +

          Property Documentation

          - + +

          ◆ CloneInProgress

          +
          @@ -278,13 +264,15 @@ Properties
          -

          If a CloneRepository(Uri, string, string, string, Action<int>, CancellationToken) operation is in progress

          - -

          Definition at line 20 of file IRepositoryManager.cs.

          +

          If a CloneRepository(Uri, string, string, string, Action<int>, CancellationToken) operation is in progress

          +

          Definition at line 20 of file IRepositoryManager.cs.

          +
          20 { get; }
          - + +

          ◆ InUse

          +
          @@ -304,8 +292,8 @@ Properties

          If something is holding a lock on the repository

          -

          Definition at line 15 of file IRepositoryManager.cs.

          - +

          Definition at line 15 of file IRepositoryManager.cs.

          +
          15 { get; }

          The documentation for this interface was generated from the following file:
            @@ -316,7 +304,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_static_files_1_1_i_configuration-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_static_files_1_1_i_configuration-members.html index c90e9d6d67..bf60e3a204 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_static_files_1_1_i_configuration-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_static_files_1_1_i_configuration-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + + - + - - + + + +
          IHostedService -Tgstation.Server.Host.Components.IEventConsumer +Tgstation.Server.Host.Components.IEventConsumer IDisposable Tgstation.Server.Host.Components.StaticFiles.Configuration - -
          + +
          @@ -139,15 +115,17 @@ Public Member Functions - +

          Public Member Functions

           
          - Public Member Functions inherited from Tgstation.Server.Host.Components.IEventConsumer
          Task< bool > HandleEvent (EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
           Handle a given eventType More...
           Handle a given eventType More...
           

          Detailed Description

          For managing the Configuration directory

          -

          Definition at line 14 of file IConfiguration.cs.

          +

          Definition at line 14 of file IConfiguration.cs.

          Member Function Documentation

          - + +

          ◆ CopyDMFilesTo()

          +
          @@ -186,13 +164,15 @@ Public Member Functions
          -
          Returns
          A Task<TResult> resulting in the ServerSideModifications if any
          +
          Returns
          A Task<TResult> resulting in the ServerSideModifications if any

          Implemented in Tgstation.Server.Host.Components.StaticFiles.Configuration.

          - + +

          ◆ CreateDirectory()

          +
          @@ -226,18 +206,20 @@ Public Member Functions
          Parameters
          - +
          configurationRelativePathThe relative path in the Configuration directory
          systemIdentityThe ISystemIdentity for the operation. If , the operation will be performed as the user of the Core.Application
          systemIdentityThe ISystemIdentity for the operation. If null, the operation will be performed as the user of the Core.Application
          cancellationTokenThe CancellationToken for the operation. Usage may result in partial writes
          -
          Returns
          A Task<TResult> resulting in if the directory already existed, otherwise
          +
          Returns
          A Task<TResult> resulting in true if the directory already existed, false otherwise

          Implemented in Tgstation.Server.Host.Components.StaticFiles.Configuration.

          - + +

          ◆ DeleteDirectory()

          +
          @@ -271,18 +253,20 @@ Public Member Functions
          Parameters
          - +
          configurationRelativePathThe path of the empty directory to delete
          systemIdentityThe ISystemIdentity for the operation. If , the operation will be performed as the user of the Core.Application
          systemIdentityThe ISystemIdentity for the operation. If null, the operation will be performed as the user of the Core.Application
          cancellationTokenThe CancellationToken for the operation
          -
          Returns
          if the directory was empty and deleted, otherwise
          +
          Returns
          true if the directory was empty and deleted, false otherwise

          Implemented in Tgstation.Server.Host.Components.StaticFiles.Configuration.

          - + +

          ◆ ListDirectory()

          +
          @@ -316,18 +300,20 @@ Public Member Functions
          Parameters
          - +
          configurationRelativePathThe relative path in the Configuration directory
          systemIdentityThe ISystemIdentity for the operation. If , the operation will be performed as the user of the Core.Application
          systemIdentityThe ISystemIdentity for the operation. If null, the operation will be performed as the user of the Core.Application
          cancellationTokenThe CancellationToken for the operation
          -
          Returns
          A Task<TResult> resulting in the ConfigurationFiles for the items in the directory. ConfigurationFile.Content and ConfigurationFile.LastReadHash will both be
          +
          Returns
          A Task<TResult> resulting in the ConfigurationFiles for the items in the directory. ConfigurationFile.Content and ConfigurationFile.LastReadHash will both be null

          Implemented in Tgstation.Server.Host.Components.StaticFiles.Configuration.

          - + +

          ◆ Read()

          +
          @@ -361,7 +347,7 @@ Public Member Functions
          Parameters
          - +
          configurationRelativePathThe relative path in the Configuration directory
          systemIdentityThe ISystemIdentity for the operation. If , the operation will be performed as the user of the Core.Application
          systemIdentityThe ISystemIdentity for the operation. If null, the operation will be performed as the user of the Core.Application
          cancellationTokenThe CancellationToken for the operation
          @@ -372,7 +358,9 @@ Public Member Functions
          - + +

          ◆ SymlinkStaticFilesTo()

          +
          @@ -410,7 +398,9 @@ Public Member Functions - + +

          ◆ Write()

          +
          @@ -429,7 +419,7 @@ Public Member Functions - + @@ -456,14 +446,14 @@ Public Member Functions
          Parameters
          byte[] byte []  data,
          - - + +
          configurationRelativePathThe relative path in the Configuration directory
          systemIdentityThe ISystemIdentity for the operation. If , the operation will be performed as the user of the Core.Application
          dataThe data to write. If , the file is deleted
          systemIdentityThe ISystemIdentity for the operation. If null, the operation will be performed as the user of the Core.Application
          dataThe data to write. If null, the file is deleted
          previousHashThe hash any existing file must match in order for the write to succeed
          cancellationTokenThe CancellationToken for the operation. Usage may result in partial writes
          -
          Returns
          A Task<TResult> resulting in the updated ConfigurationFile or if the write failed due to ConfigurationFile.LastReadHash conflicts
          +
          Returns
          A Task<TResult> resulting in the updated ConfigurationFile or null if the write failed due to ConfigurationFile.LastReadHash conflicts

          Implemented in Tgstation.Server.Host.Components.StaticFiles.Configuration.

          @@ -477,7 +467,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_network_prompt_reaper-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_network_prompt_reaper-members.html index 761e84605f..180bb7405e 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_network_prompt_reaper-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_network_prompt_reaper-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + + - + - - + + + +
          Tgstation.Server.Host.Components.Watchdog.PosixNetworkPromptReaper Tgstation.Server.Host.Components.Watchdog.WindowsNetworkPromptReaper - -
          + + @@ -121,9 +97,11 @@ Public Member Functions

          Detailed Description

          On Windows, DreamDaemon will show an unskippable prompt when using /world/proc/OpenPort(). This looks out for those prompts and immediately clicks "Yes" if the owning process has registered for it

          -

          Definition at line 8 of file INetworkPromptReaper.cs.

          +

          Definition at line 8 of file INetworkPromptReaper.cs.

          Member Function Documentation

          - + +

          ◆ RegisterProcess()

          +

          Public Member Functions

          @@ -147,6 +125,8 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.Components.Watchdog.WindowsNetworkPromptReaper, and Tgstation.Server.Host.Components.Watchdog.PosixNetworkPromptReaper.

          +

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

          +
          The documentation for this interface was generated from the following file:
            @@ -157,7 +137,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_reattach_info_handler-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_reattach_info_handler-members.html index dca73e26bd..62cf4d2590 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_reattach_info_handler-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_reattach_info_handler-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + + - + - - + + + +
          -

          Handles saving and loading WatchdogReattachInformation +

          Handles saving and loading WatchdogReattachInformation More...

          Inheritance diagram for Tgstation.Server.Host.Components.Watchdog.IReattachInfoHandler:
          @@ -108,8 +84,8 @@ Inheritance diagram for Tgstation.Server.Host.Components.Watchdog.IReattachInfoH Tgstation.Server.Host.Components.ReattachInfoHandler - -
          + + @@ -117,15 +93,17 @@ Public Member Functions - +

          Public Member Functions

           Save some reattachInformation More...
           
          Task< WatchdogReattachInformationLoad (CancellationToken cancellationToken)
           Load a saved WatchdogReattachInformation More...
           Load a saved WatchdogReattachInformation More...
           

          Detailed Description

          -

          Handles saving and loading WatchdogReattachInformation

          +

          Handles saving and loading WatchdogReattachInformation

          -

          Definition at line 9 of file IReattachInfoHandler.cs.

          +

          Definition at line 9 of file IReattachInfoHandler.cs.

          Member Function Documentation

          - + +

          ◆ Load()

          +
          @@ -139,20 +117,22 @@ Public Member Functions
          -

          Load a saved WatchdogReattachInformation

          +

          Load a saved WatchdogReattachInformation

          Parameters
          cancellationTokenThe CancellationToken for the operation
          -
          Returns
          A Task<TResult> resulting in the stored WatchdogReattachInformation if any
          +
          Returns
          A Task<TResult> resulting in the stored WatchdogReattachInformation if any

          Implemented in Tgstation.Server.Host.Components.ReattachInfoHandler.

          - + +

          ◆ Save()

          +
          @@ -179,7 +159,7 @@ Public Member Functions

          Save some reattachInformation

          Parameters
          - +
          reattachInformationThe WatchdogReattachInformation to save
          reattachInformationThe WatchdogReattachInformation to save
          cancellationTokenThe CancellationToken for the operation
          @@ -198,7 +178,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_session_controller-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_session_controller-members.html index 5cf48c0a30..29847455ba 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_session_controller-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_session_controller-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + +
          LaunchResultTgstation.Server.Host.Components.Watchdog.ISessionController LifetimeTgstation.Server.Host.Core.IProcessBase OnRebootTgstation.Server.Host.Components.Watchdog.ISessionController - PortTgstation.Server.Host.Components.Watchdog.ISessionController + PortTgstation.Server.Host.Components.Watchdog.ISessionController RebootStateTgstation.Server.Host.Components.Watchdog.ISessionController Release()Tgstation.Server.Host.Components.Watchdog.ISessionController ResetRebootState()Tgstation.Server.Host.Components.Watchdog.ISessionController @@ -120,7 +96,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_session_controller.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_session_controller.html index d2978df329..d976007691 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_session_controller.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_session_controller.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Host.Components.Watchdog.ISessionController Interface Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + +
          -Tgstation.Server.Host.Core.IProcessBase +Tgstation.Server.Host.Core.IProcessBase IDisposable -Tgstation.Server.Host.Components.Watchdog.DeadSessionController +Tgstation.Server.Host.Components.Watchdog.DeadSessionController Tgstation.Server.Host.Components.Watchdog.SessionController - -
          + +
          @@ -127,17 +103,17 @@ Public Member Functions - + - + - + - +

          Public Member Functions

           Causes the world to start listening on a newPort More...
           
          Task< bool > SetRebootState (RebootState newRebootState, CancellationToken cancellationToken)
           Attempts to change the current RebootState to newRebootState More...
           Attempts to change the current RebootState to newRebootState More...
           
          void ResetRebootState ()
           Changes RebootState to Components.Watchdog.RebootState.Normal without telling the DMAPI More...
           Changes RebootState to Components.Watchdog.RebootState.Normal without telling the DMAPI More...
           
          void EnableCustomChatCommands ()
           Enables the reading of custom chat commands from the ISessionController More...
           Enables the reading of custom chat commands from the ISessionController More...
           
          - Public Member Functions inherited from Tgstation.Server.Host.Core.IProcessBase
          void SetHighPriority ()
           Set's the owned System.Diagnostics.Process.PriorityClass to System.Diagnostics.ProcessPriorityClass.AboveNormal More...
           Set's the owned System.Diagnostics.Process.PriorityClass to System.Diagnostics.ProcessPriorityClass.AboveNormal More...
           
          - + - + - + - - - + + + - + - +

          @@ -146,40 +122,42 @@ Properties

           A Task that completes when DreamDaemon starts pumping the windows message queue after loading a .dmb or when it crashes More...
           
          bool IsPrimary [get]
           If the IDmbProvider.PrimaryDirectory of Dmb is being used More...
           If the IDmbProvider.PrimaryDirectory of Dmb is being used More...
           
          bool TerminationWasRequested [get]
           If the DreamDaemon instance sent a More...
           
          ApiValidationStatus ApiValidationStatus [get]
           The DMAPI Components.Watchdog.ApiValidationStatus More...
           The DMAPI Components.Watchdog.ApiValidationStatus More...
           
          IDmbProvider Dmb [get]
           The IDmbProvider being used More...
           The IDmbProvider being used More...
           
          ushort Port [get]
           The current port DreamDaemon is listening on More...
           
          ushort? Port [get]
           The current port DreamDaemon is listening on More...
           
          bool ClosePortOnReboot [get, set]
           If the port should be rotated off when the world reboots More...
           
          RebootState RebootState [get]
           The current RebootState More...
           The current RebootState More...
           
          Task OnReboot [get]
           A Task that completes when the server calls /world/Reboot() More...
           
          - Properties inherited from Tgstation.Server.Host.Core.IProcessBase
          Task< int > Lifetime [get]
           The Task<TResult> resulting in the exit code of the process More...
           The Task<TResult> resulting in the exit code of the process More...
           

          Detailed Description

          Handles communication with a DreamDaemon IProcess

          -

          Definition at line 10 of file ISessionController.cs.

          +

          Definition at line 10 of file ISessionController.cs.

          Member Function Documentation

          - + +

          ◆ EnableCustomChatCommands()

          + - + +

          ◆ Release()

          + - + +

          ◆ SendCommand()

          + - + +

          ◆ SetRebootState()

          +
          @@ -347,24 +335,26 @@ Properties
          -

          Attempts to change the current RebootState to newRebootState

          +

          Attempts to change the current RebootState to newRebootState

          Parameters
          - +
          newRebootStateThe new RebootState
          newRebootStateThe new RebootState
          cancellationTokenThe CancellationToken for the operation
          -
          Returns
          A Task<TResult> resulting in if the operation succeeded, otherwise
          +
          Returns
          A Task<TResult> resulting in true if the operation succeeded, false otherwise

          Implemented in Tgstation.Server.Host.Components.Watchdog.SessionController, and Tgstation.Server.Host.Components.Watchdog.DeadSessionController.

          -

          Referenced by Tgstation.Server.Host.Components.Watchdog.Watchdog.TerminateNoLock().

          +

          Referenced by Tgstation.Server.Host.Components.Watchdog.Watchdog.TerminateNoLock().

          Property Documentation

          - + +

          ◆ ApiValidationStatus

          +
          @@ -382,13 +372,15 @@ Properties
          -

          The DMAPI Components.Watchdog.ApiValidationStatus

          - -

          Definition at line 30 of file ISessionController.cs.

          +

          The DMAPI Components.Watchdog.ApiValidationStatus

          +

          Definition at line 30 of file ISessionController.cs.

          +
          30 { get; }
          - + +

          ◆ ClosePortOnReboot

          +
          @@ -408,13 +400,15 @@ Properties

          If the port should be rotated off when the world reboots

          -

          Definition at line 45 of file ISessionController.cs.

          - -

          Referenced by Tgstation.Server.Host.Components.Watchdog.Watchdog.HandlerMonitorWakeup().

          +

          Definition at line 45 of file ISessionController.cs.

          +
          45 { get; set; }
          +

          Referenced by Tgstation.Server.Host.Components.Watchdog.Watchdog.HandlerMonitorWakeup().

          - + +

          ◆ Dmb

          +
          @@ -432,15 +426,17 @@ Properties
          -

          The IDmbProvider being used

          +

          The IDmbProvider being used

          -

          Definition at line 35 of file ISessionController.cs.

          - -

          Referenced by Tgstation.Server.Host.Components.Watchdog.Watchdog.HandlerMonitorWakeup().

          +

          Definition at line 35 of file ISessionController.cs.

          +
          35 { get; }
          +

          Referenced by Tgstation.Server.Host.Components.Watchdog.Watchdog.HandlerMonitorWakeup().

          - + +

          ◆ IsPrimary

          +
          @@ -458,15 +454,17 @@ Properties
          - + +

          ◆ LaunchResult

          +
          @@ -486,13 +484,15 @@ Properties

          A Task that completes when DreamDaemon starts pumping the windows message queue after loading a .dmb or when it crashes

          -

          Definition at line 15 of file ISessionController.cs.

          - -

          Referenced by Tgstation.Server.Host.Components.Watchdog.Watchdog.LaunchImplNoLock().

          +

          Definition at line 15 of file ISessionController.cs.

          +
          15 { get; }
          +

          Referenced by Tgstation.Server.Host.Components.Watchdog.Watchdog.LaunchImplNoLock().

          - + +

          ◆ OnReboot

          +
          @@ -512,11 +512,13 @@ Properties

          A Task that completes when the server calls /world/Reboot()

          -

          Definition at line 55 of file ISessionController.cs.

          +

          Definition at line 55 of file ISessionController.cs.

          +
          55 { get; }
          + + + +

          ◆ Port

          - - -
          @@ -524,7 +526,7 @@ Properties @@ -536,11 +538,13 @@ Properties

          The current port DreamDaemon is listening on

          -

          Definition at line 40 of file ISessionController.cs.

          +

          Definition at line 40 of file ISessionController.cs.

          +
          40 { get; }
          + + + +

          ◆ RebootState

          - - -
          - +
          ushort Tgstation.Server.Host.Components.Watchdog.ISessionController.Portushort? Tgstation.Server.Host.Components.Watchdog.ISessionController.Port
          @@ -558,15 +562,17 @@ Properties
          - + +

          ◆ TerminationWasRequested

          +
          @@ -586,9 +592,9 @@ Properties

          If the DreamDaemon instance sent a

          -

          Definition at line 25 of file ISessionController.cs.

          - -

          Referenced by Tgstation.Server.Host.Components.Watchdog.Watchdog.HandlerMonitorWakeup().

          +

          Definition at line 25 of file ISessionController.cs.

          +
          25 { get; }
          +

          Referenced by Tgstation.Server.Host.Components.Watchdog.Watchdog.HandlerMonitorWakeup().

          @@ -600,7 +606,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_session_controller_factory-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_session_controller_factory-members.html index 4d22048f8c..6b8e88cdff 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_session_controller_factory-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_session_controller_factory-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + + - + - - + + + +
          -

          Factory for ISessionControllers +

          Factory for ISessionControllers More...

          Inheritance diagram for Tgstation.Server.Host.Components.Watchdog.ISessionControllerFactory:
          @@ -108,27 +84,29 @@ Inheritance diagram for Tgstation.Server.Host.Components.Watchdog.ISessionContro Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory - -
          + +
          - + - + - +

          Public Member Functions

          Task< ISessionControllerLaunchNew (DreamDaemonLaunchParameters launchParameters, IDmbProvider dmbProvider, IByondExecutableLock currentByondLock, bool primaryPort, bool primaryDirectory, bool apiValidate, CancellationToken cancellationToken)
           Create a ISessionController from a freshly launch DreamDaemon instance More...
           Create a ISessionController from a freshly launch DreamDaemon instance More...
           
          Task< ISessionControllerReattach (ReattachInformation reattachInformation, CancellationToken cancellationToken)
           Create a ISessionController from an existing DreamDaemon instance More...
           Create a ISessionController from an existing DreamDaemon instance More...
           
          ISessionController CreateDeadSession (IDmbProvider dmbProvider)
           Creates a ISessionController that appears to have started and died with exit code -1 More...
           Creates a ISessionController that appears to have started and died with exit code -1 More...
           

          Detailed Description

          -

          Factory for ISessionControllers

          +

          Factory for ISessionControllers

          -

          Definition at line 11 of file ISessionControllerFactory.cs.

          +

          Definition at line 11 of file ISessionControllerFactory.cs.

          Member Function Documentation

          - + +

          ◆ CreateDeadSession()

          +
          @@ -142,20 +120,22 @@ Public Member Functions
          -

          Creates a ISessionController that appears to have started and died with exit code -1

          +

          Creates a ISessionController that appears to have started and died with exit code -1

          Parameters
          - +
          dmbProviderThe IDmbProvider for the ISessionController
          dmbProviderThe IDmbProvider for the ISessionController
          -
          Returns
          A dead ISessionController
          +
          Returns
          A dead ISessionController

          Implemented in Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.

          - + +

          ◆ LaunchNew()

          +
          @@ -209,26 +189,30 @@ Public Member Functions
          -

          Create a ISessionController from a freshly launch DreamDaemon instance

          +

          Create a ISessionController from a freshly launch DreamDaemon instance

          Parameters
          - + - - + +
          launchParametersThe DreamDaemonLaunchParameters to use. DreamDaemonLaunchParameters.SecurityLevel will be updated with the minumum required security level for the launch
          dmbProviderThe IDmbProvider to use
          dmbProviderThe IDmbProvider to use
          currentByondLockThe current IByondExecutableLock if any
          primaryPortIf the DreamDaemonLaunchParameters.PrimaryPort of launchParameters should be used
          primaryDirectoryIf the IDmbProvider.PrimaryDirectory of dmbProvider should be used
          apiValidateIf the ISessionController should only validate the DMAPI then exit
          primaryDirectoryIf the IDmbProvider.PrimaryDirectory of dmbProvider should be used
          apiValidateIf the ISessionController should only validate the DMAPI then exit
          cancellationTokenThe CancellationToken for the operation
          -
          Returns
          A Task<TResult> resulting in a new ISessionController
          +
          Returns
          A Task<TResult> resulting in a new ISessionController

          Implemented in Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.

          +

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

          +
          - + +

          ◆ Reattach()

          +
          @@ -252,15 +236,15 @@ Public Member Functions
          -

          Create a ISessionController from an existing DreamDaemon instance

          +

          Create a ISessionController from an existing DreamDaemon instance

          Parameters
          - +
          reattachInformationThe ReattachInformation to use
          reattachInformationThe ReattachInformation to use
          cancellationTokenThe CancellationToken for the operation
          -
          Returns
          A Task<TResult> resulting in a new ISessionController on success or on failure to reattach
          +
          Returns
          A Task<TResult> resulting in a new ISessionController on success or null on failure to reattach

          Implemented in Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.

          @@ -274,7 +258,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_watchdog-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_watchdog-members.html index be51f651cb..1fc701c511 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_watchdog-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_watchdog-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + +
          HandleEvent(EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)Tgstation.Server.Host.Components.IEventConsumer LastLaunchParametersTgstation.Server.Host.Components.Watchdog.IWatchdog Launch(CancellationToken cancellationToken)Tgstation.Server.Host.Components.Watchdog.IWatchdog - RebootStateTgstation.Server.Host.Components.Watchdog.IWatchdog + RebootStateTgstation.Server.Host.Components.Watchdog.IWatchdog ResetRebootState(CancellationToken cancellationToken)Tgstation.Server.Host.Components.Watchdog.IWatchdog Restart(bool graceful, CancellationToken cancellationToken)Tgstation.Server.Host.Components.Watchdog.IWatchdog RunningTgstation.Server.Host.Components.Watchdog.IWatchdog @@ -115,7 +91,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_watchdog.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_watchdog.html index ad07bd1ff1..cf2f93c34c 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_watchdog.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_watchdog.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Host.Components.Watchdog.IWatchdog Interface Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + +
          IHostedService IDisposable -Tgstation.Server.Host.Components.IEventConsumer +Tgstation.Server.Host.Components.IEventConsumer Tgstation.Server.Host.Components.Watchdog.Watchdog - -
          + +
          - + - + @@ -134,7 +110,7 @@ Public Member Functions - +

          Public Member Functions

          Task Launch (CancellationToken cancellationToken)
           Start the IWatchdog More...
           Start the IWatchdog More...
           
          Task ChangeSettings (DreamDaemonLaunchParameters launchParameters, CancellationToken cancellationToken)
           Changes the ActiveLaunchParameters. If currently Running triggers a graceful restart More...
           Changes the ActiveLaunchParameters. If currently Running triggers a graceful restart More...
           
          Task Restart (bool graceful, CancellationToken cancellationToken)
           Restarts the watchdog More...
           
          - Public Member Functions inherited from Tgstation.Server.Host.Components.IEventConsumer
          Task< bool > HandleEvent (EventType eventType, IEnumerable< string > parameters, CancellationToken cancellationToken)
           Handle a given eventType More...
           Handle a given eventType More...
           
          - - - + + +

          @@ -154,16 +130,18 @@ Properties

          DreamDaemonLaunchParameters LastLaunchParameters [get]
           The DreamDaemonLaunchParameters to be applied More...
           
          RebootState RebootState [get]
           The Components.Watchdog.RebootState of the active server More...
           
          RebootStateRebootState [get]
           The Components.Watchdog.RebootState of the active server More...
           

          Detailed Description

          Runs and monitors the twin server controllers

          -

          Definition at line 12 of file IWatchdog.cs.

          +

          Definition at line 12 of file IWatchdog.cs.

          Member Function Documentation

          - + +

          ◆ ChangeSettings()

          +
          @@ -187,7 +165,7 @@ Properties
          -

          Changes the ActiveLaunchParameters. If currently Running triggers a graceful restart

          +

          Changes the ActiveLaunchParameters. If currently Running triggers a graceful restart

          Parameters
          @@ -201,7 +179,9 @@ Properties - + +

          ◆ Launch()

          +
          launchParametersThe new DreamDaemonLaunchParameters. May be modified
          @@ -215,7 +195,7 @@ Properties
          -

          Start the IWatchdog

          +

          Start the IWatchdog

          Parameters
          @@ -228,7 +208,9 @@ Properties - + +

          ◆ ResetRebootState()

          +
          cancellationTokenThe CancellationToken for the operation
          @@ -255,7 +237,9 @@ Properties - + +

          ◆ Restart()

          +
          @@ -282,7 +266,7 @@ Properties

          Restarts the watchdog

          Parameters
          - +
          gracefulIf the restart will be delayed until a reboot is detected in the active server's DMAPI and this function will retrun immediately
          gracefulIf true the restart will be delayed until a reboot is detected in the active server's DMAPI and this function will retrun immediately
          cancellationTokenThe CancellationToken for the operation
          @@ -293,7 +277,9 @@ Properties
          - + +

          ◆ Terminate()

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

          Stops the watchdog

          Parameters
          - +
          gracefulIf the termination will be delayed until a reboot is detected in the active server's DMAPI and this function will return immediately
          gracefulIf true the termination will be delayed until a reboot is detected in the active server's DMAPI and this function will return immediately
          cancellationTokenThe CancellationToken for the operation
          @@ -329,10 +315,14 @@ Properties

          Implemented in Tgstation.Server.Host.Components.Watchdog.Watchdog.

          +

          Referenced by Tgstation.Server.Host.Controllers.DreamDaemonController.Delete().

          +

          Property Documentation

          - + +

          ◆ ActiveCompileJob

          +
          @@ -352,11 +342,15 @@ Properties

          The CompileJob currently running on the server

          -

          Definition at line 27 of file IWatchdog.cs.

          +

          Definition at line 27 of file IWatchdog.cs.

          +
          27 { get; }
          +

          Referenced by Tgstation.Server.Host.Components.Chat.Commands.ByondCommand.Invoke(), Tgstation.Server.Host.Components.Chat.Commands.RevisionCommand.Invoke(), and Tgstation.Server.Host.Components.Chat.Commands.PullRequestsCommand.Invoke().

          - + +

          ◆ ActiveLaunchParameters

          +
          @@ -376,11 +370,13 @@ Properties

          The DreamDaemonLaunchParameters the active server is using

          -

          Definition at line 32 of file IWatchdog.cs.

          +

          Definition at line 32 of file IWatchdog.cs.

          +
          32 { get; }
          + + + +

          ◆ AlphaIsActive

          - - -
          @@ -400,11 +396,13 @@ Properties

          If the alpha server is the active server

          -

          Definition at line 22 of file IWatchdog.cs.

          +

          Definition at line 22 of file IWatchdog.cs.

          +
          22 { get; }
          + + + +

          ◆ LastLaunchParameters

          - - -
          @@ -424,11 +422,13 @@ Properties

          The DreamDaemonLaunchParameters to be applied

          -

          Definition at line 37 of file IWatchdog.cs.

          +

          Definition at line 37 of file IWatchdog.cs.

          +
          37 { get; }
          + + + +

          ◆ RebootState

          - - -
          @@ -436,7 +436,7 @@ Properties @@ -446,13 +446,15 @@ Properties
          - +
          RebootState Tgstation.Server.Host.Components.Watchdog.IWatchdog.RebootStateRebootState? Tgstation.Server.Host.Components.Watchdog.IWatchdog.RebootState
          -

          The Components.Watchdog.RebootState of the active server

          - -

          Definition at line 42 of file IWatchdog.cs.

          +

          The Components.Watchdog.RebootState of the active server

          +

          Definition at line 42 of file IWatchdog.cs.

          +
          42 { get; }
          - + +

          ◆ Running

          +
          @@ -472,7 +474,9 @@ Properties

          If the watchdog is running

          -

          Definition at line 17 of file IWatchdog.cs.

          +

          Definition at line 17 of file IWatchdog.cs.

          +
          17 { get; }
          +

          Referenced by Tgstation.Server.Host.Components.Chat.Commands.ByondCommand.Invoke(), Tgstation.Server.Host.Components.Chat.Commands.RevisionCommand.Invoke(), Tgstation.Server.Host.Components.Chat.Commands.PullRequestsCommand.Invoke(), and Tgstation.Server.Host.Components.Compiler.DreamMaker.RunCompileJob().

          @@ -484,7 +488,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_watchdog_factory-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_watchdog_factory-members.html index 476814695d..543b28070d 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_watchdog_factory-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_components_1_1_watchdog_1_1_i_watchdog_factory-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + + - + - - + + + +
          -

          For creating IWatchdogs +

          For creating IWatchdogs More...

          Inheritance diagram for Tgstation.Server.Host.Components.Watchdog.IWatchdogFactory:
          @@ -108,21 +84,23 @@ Inheritance diagram for Tgstation.Server.Host.Components.Watchdog.IWatchdogFacto Tgstation.Server.Host.Components.Watchdog.WatchdogFactory - -
          + +
          - +

          Public Member Functions

          IWatchdog CreateWatchdog (IChat chat, IDmbFactory dmbFactory, IReattachInfoHandler reattachInfoHandler, IEventConsumer eventConsumer, ISessionControllerFactory sessionControllerFactory, Api.Models.Instance instance, DreamDaemonSettings settings)
           Creates a IWatchdog More...
           Creates a IWatchdog More...
           

          Detailed Description

          -

          For creating IWatchdogs

          +

          For creating IWatchdogs

          -

          Definition at line 10 of file IWatchdogFactory.cs.

          +

          Definition at line 10 of file IWatchdogFactory.cs.

          Member Function Documentation

          - + +

          ◆ CreateWatchdog()

          +
          @@ -176,23 +154,25 @@ Public Member Functions
          -

          Creates a IWatchdog

          +

          Creates a IWatchdog

          Parameters
          - - - - - - - + + + + + + +
          chatThe IChat for the IWatchdog
          dmbFactoryThe IDmbFactory for the IWatchdog with
          reattachInfoHandlerThe IReattachInfoHandler for the IWatchdog
          eventConsumerThe IEventConsumer for the IWatchdog
          sessionControllerFactoryThe ISessionControllerFactory for the IWatchdog
          instanceThe Instance for the IWatchdog
          settingsThe initial DreamDaemonSettings for the IWatchdog
          chatThe IChat for the IWatchdog
          dmbFactoryThe IDmbFactory for the IWatchdog with
          reattachInfoHandlerThe IReattachInfoHandler for the IWatchdog
          eventConsumerThe IEventConsumer for the IWatchdog
          sessionControllerFactoryThe ISessionControllerFactory for the IWatchdog
          instanceThe Instance for the IWatchdog
          settingsThe initial DreamDaemonSettings for the IWatchdog
          -
          Returns
          A new IWatchdog
          +
          Returns
          A new IWatchdog

          Implemented in Tgstation.Server.Host.Components.Watchdog.WatchdogFactory.

          +

          Referenced by Tgstation.Server.Host.Components.InstanceFactory.CreateInstance().

          +

          The documentation for this interface was generated from the following file:
            @@ -203,7 +183,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_application-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_application-members.html index cd0b5ae52d..3f5625a122 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_application-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_application-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + + - + - - + + + +
          Tgstation.Server.Host.Core.Application - -
          + + - +

          Public Member Functions

          void Ready (Exception initializationError)
           Mark the IApplication as ready to run More...
           Mark the IApplication as ready to run More...
           
          - + - + @@ -133,9 +109,11 @@ Properties

          Detailed Description

          Configures the ASP.NET Core web application

          -

          Definition at line 8 of file IApplication.cs.

          +

          Definition at line 8 of file IApplication.cs.

          Member Function Documentation

          - + +

          ◆ Ready()

          +

          Properties

          string VersionPrefix [get]
           Prefix to VersionString More...
           Prefix to VersionString More...
           
          string VersionString [get]
           A more verbose version of Version More...
           A more verbose version of Version More...
           
          Version Version [get]
           The version of the Application More...
          @@ -149,7 +127,7 @@ Properties
          -

          Mark the IApplication as ready to run

          +

          Mark the IApplication as ready to run

          Parameters
          @@ -162,7 +140,9 @@ Properties

          Property Documentation

          - + +

          ◆ Version

          +
          initializationErrorThe Exception that put the application in a corrupted state if any
          @@ -182,11 +162,15 @@ Properties

          The version of the Application

          -

          Definition at line 23 of file IApplication.cs.

          +

          Definition at line 23 of file IApplication.cs.

          +
          23 { get; }
          +

          Referenced by Tgstation.Server.Host.Components.InstanceManager.HandleRestart(), Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), Tgstation.Server.Host.Controllers.AdministrationController.Read(), and Tgstation.Server.Host.Controllers.AdministrationController.Update().

          - + +

          ◆ VersionPrefix

          +
          @@ -204,13 +188,17 @@ Properties
          -

          Prefix to VersionString

          +

          Prefix to VersionString

          -

          Definition at line 13 of file IApplication.cs.

          +

          Definition at line 13 of file IApplication.cs.

          +
          13 { get; }
          +

          Referenced by Tgstation.Server.Host.Core.SetupWizard.ConfigureDatabase(), and Tgstation.Server.Host.Controllers.InstanceController.Create().

          - + +

          ◆ VersionString

          +
          @@ -228,11 +216,11 @@ Properties
          -

          A more verbose version of Version

          +

          A more verbose version of Version

          -

          Definition at line 18 of file IApplication.cs.

          - -

          Referenced by Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.IrcProvider().

          +

          Definition at line 18 of file IApplication.cs.

          +
          18 { get; }
          +

          Referenced by Tgstation.Server.Host.Components.Chat.Providers.IrcProvider.IrcProvider().

          @@ -244,7 +232,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_async_delayer-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_async_delayer-members.html index 3bc38b7e9f..b1528e267b 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_async_delayer-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_async_delayer-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
          Tgstation.Server.Host.Core.AsyncDelayer - -
          + + @@ -120,9 +96,11 @@ Public Member Functions

          Detailed Description

          For waiting asynchronously

          -

          Definition at line 10 of file IAsyncDelayer.cs.

          +

          Definition at line 10 of file IAsyncDelayer.cs.

          Member Function Documentation

          - + +

          ◆ Delay()

          +

          Public Member Functions

          @@ -158,7 +136,7 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.Core.AsyncDelayer.

          -

          Referenced by Tgstation.Server.Host.Security.IdentityCacheObject.IdentityCacheObject().

          +

          Referenced by Tgstation.Server.Host.Core.SetupWizard.CheckRunWizard(), Tgstation.Server.Host.Security.TokenFactory.CreateToken(), Tgstation.Server.Host.Security.IdentityCacheObject.IdentityCacheObject(), Tgstation.Server.Host.Components.Chat.Chat.MonitorMessages(), Tgstation.Server.Host.Components.Watchdog.WindowsNetworkPromptReaper.Run(), and Tgstation.Server.Host.Core.SetupWizard.SaveConfiguration().

          @@ -170,7 +148,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_d_b_connection_factory-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_d_b_connection_factory-members.html index 17e5876ba9..4711eb651e 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_d_b_connection_factory-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_d_b_connection_factory-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + + - + - - + + + +
          Tgstation.Server.Host.Core.DBConnectionFactory - -
          + + @@ -120,9 +96,11 @@ Public Member Functions

          Detailed Description

          For creating DbConnection

          -

          Definition at line 9 of file IDBConnectionFactory.cs.

          +

          Definition at line 9 of file IDBConnectionFactory.cs.

          Member Function Documentation

          - + +

          ◆ CreateConnection()

          +

          Public Member Functions

          @@ -158,6 +136,8 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.Core.DBConnectionFactory.

          +

          Referenced by Tgstation.Server.Host.Core.SetupWizard.ConfigureDatabase().

          +
          The documentation for this interface was generated from the following file:
            @@ -168,7 +148,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_database_context_factory-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_database_context_factory-members.html index b08e32afec..9585d9da76 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_database_context_factory-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_database_context_factory-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + + - + - - + + + +
          Tgstation.Server.Host.Core.DatabaseContextFactory - -
          + + @@ -120,9 +96,11 @@ Public Member Functions

          Detailed Description

          Factory for scoping usage of IDatabaseContexts. Meant for use by Components

          -

          Definition at line 10 of file IDatabaseContextFactory.cs.

          +

          Definition at line 10 of file IDatabaseContextFactory.cs.

          Member Function Documentation

          - + +

          ◆ UseContext()

          +

          Public Member Functions

          @@ -147,6 +125,8 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.Core.DatabaseContextFactory.

          +

          Referenced by Tgstation.Server.Host.Core.JobManager.CancelJob(), Tgstation.Server.Host.Components.Compiler.DmbFactory.CleanUnusedCompileJobs(), Tgstation.Server.Host.Components.Compiler.DmbFactory.FromCompileJob(), Tgstation.Server.Host.Components.Chat.Commands.PullRequestsCommand.Invoke(), Tgstation.Server.Host.Components.ReattachInfoHandler.Load(), Tgstation.Server.Host.Components.InstanceManager.MoveInstance(), Tgstation.Server.Host.Components.InstanceManager.OfflineInstance(), Tgstation.Server.Host.Core.JobManager.RunJob(), Tgstation.Server.Host.Core.JobManager.StartAsync(), Tgstation.Server.Host.Components.Instance.StartAsync(), Tgstation.Server.Host.Components.InstanceManager.StopAsync(), and Tgstation.Server.Host.Components.Instance.TimerLoop().

          +
          The documentation for this interface was generated from the following file:
            @@ -157,7 +137,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_git_hub_client_factory-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_git_hub_client_factory-members.html index 850d7247be..c540db1c25 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_git_hub_client_factory-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_git_hub_client_factory-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + + - + - - + + + +
          Tgstation.Server.Host.Core.GitHubClientFactory - -
          + + @@ -123,9 +99,11 @@ Public Member Functions

          Detailed Description

          For creating IGitHubClients

          -

          Definition at line 8 of file IGitHubClientFactory.cs.

          +

          Definition at line 8 of file IGitHubClientFactory.cs.

          Member Function Documentation

          - + +

          ◆ CreateClient() [1/2]

          +

          Public Member Functions

          @@ -143,9 +121,13 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.Core.GitHubClientFactory.

          +

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

          + - + +

          ◆ CreateClient() [2/2]

          +
          @@ -180,7 +162,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_job_manager-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_job_manager-members.html index 1234fb2ead..6ac5a4b0d8 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_job_manager-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_job_manager-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + +
          This is the complete list of members for Tgstation.Server.Host.Core.IJobManager, including all inherited members.

          - +
          CancelJob(Job job, User user, bool blocking, CancellationToken cancellationToken)Tgstation.Server.Host.Core.IJobManager
          JobProgress(Job job)Tgstation.Server.Host.Core.IJobManager
          JobProgress(Job job)Tgstation.Server.Host.Core.IJobManager
          RegisterOperation(Job job, Func< Job, IDatabaseContext, Action< int >, CancellationToken, Task > operation, CancellationToken cancellationToken)Tgstation.Server.Host.Core.IJobManager
          WaitForJobCompletion(Job job, User canceller, CancellationToken jobCancellationToken, CancellationToken cancellationToken)Tgstation.Server.Host.Core.IJobManager
          @@ -107,7 +83,7 @@ var searchBox = new SearchBox("searchBox", "search",false,'Search'); diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_job_manager.html b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_job_manager.html index 05ab9c95e8..ef2bd56476 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_job_manager.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_job_manager.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Host.Core.IJobManager Interface Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + +
          IHostedService Tgstation.Server.Host.Core.JobManager - -
          + + - - - + + + @@ -130,9 +106,11 @@ Public Member Functions

          Detailed Description

          Manages the runtime of Jobs

          -

          Definition at line 12 of file IJobManager.cs.

          +

          Definition at line 12 of file IJobManager.cs.

          Member Function Documentation

          - + +

          ◆ CancelJob()

          +

          Public Member Functions

          int JobProgress (Job job)
           Get the Api.Models.Job.Progress for a job More...
           
          int? JobProgress (Job job)
           Get the Api.Models.Job.Progress for a job More...
           
          Task RegisterOperation (Job job, Func< Job, IDatabaseContext, Action< int >, CancellationToken, Task > operation, CancellationToken cancellationToken)
           Registers a given Job and begins running it More...
           
          @@ -178,18 +156,22 @@ Public Member Functions
          -
          Returns
          A Task<TResult> resulting in if the job was cancelled, if it couldn't be found
          +
          Returns
          A Task<TResult> resulting in true if the job was cancelled, false if it couldn't be found

          Implemented in Tgstation.Server.Host.Core.JobManager.

          +

          Referenced by Tgstation.Server.Host.Controllers.JobController.Delete(), and Tgstation.Server.Host.Components.InstanceManager.OfflineInstance().

          + - + +

          ◆ JobProgress()

          +
          - + @@ -198,20 +180,24 @@ Public Member Functions
          int Tgstation.Server.Host.Core.IJobManager.JobProgress int? Tgstation.Server.Host.Core.IJobManager.JobProgress ( Job  job)
          -

          Get the Api.Models.Job.Progress for a job

          +

          Get the Api.Models.Job.Progress for a job

          Parameters
          - +
          jobThe Job to get Api.Models.Job.Progress for
          jobThe Job to get Api.Models.Job.Progress for
          -
          Returns
          The Api.Models.Job.Progress of job
          +
          Returns
          The Api.Models.Job.Progress of job
          -

          Implemented in Tgstation.Server.Host.Core.JobManager.

          +

          Implemented in Tgstation.Server.Host.Core.JobManager.

          + +

          Referenced by Tgstation.Server.Host.Controllers.JobController.GetId().

          - + +

          ◆ RegisterOperation()

          +
          @@ -254,9 +240,13 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.Core.JobManager.

          +

          Referenced by Tgstation.Server.Host.Controllers.DreamDaemonController.Create(), Tgstation.Server.Host.Controllers.DreamMakerController.Create(), Tgstation.Server.Host.Controllers.RepositoryController.Create(), Tgstation.Server.Host.Controllers.RepositoryController.Delete(), Tgstation.Server.Host.Controllers.DreamDaemonController.Restart(), Tgstation.Server.Host.Components.Instance.TimerLoop(), Tgstation.Server.Host.Controllers.ByondController.Update(), and Tgstation.Server.Host.Controllers.RepositoryController.Update().

          + - + +

          ◆ WaitForJobCompletion()

          +
          @@ -306,6 +296,8 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.Core.JobManager.

          +

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

          +
          The documentation for this interface was generated from the following file:
            @@ -316,7 +308,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_platform_identifier-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_platform_identifier-members.html index 4ca466beb7..3683a2d981 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_platform_identifier-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_platform_identifier-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + + - + - - + + + +
          Tgstation.Server.Host.Core.PlatformIdentifier - -
          + + @@ -123,9 +99,11 @@ Properties

          Detailed Description

          For identifying the current platform

          -

          Definition at line 6 of file IPlatformIdentifier.cs.

          +

          Definition at line 6 of file IPlatformIdentifier.cs.

          Property Documentation

          - + +

          ◆ IsWindows

          +

          Properties

          @@ -145,13 +123,15 @@ Properties

          If the current platform is a Windows platform

          -

          Definition at line 11 of file IPlatformIdentifier.cs.

          - -

          Referenced by Tgstation.Server.Host.Core.Application.ConfigureServices().

          +

          Definition at line 11 of file IPlatformIdentifier.cs.

          +
          11 { get; }
          +

          Referenced by Tgstation.Server.Host.Core.SetupWizard.ConfigureDatabase(), Tgstation.Server.Host.Core.Application.ConfigureServices(), Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), Tgstation.Server.Host.Controllers.InstanceController.NormalizeModelPath(), and Tgstation.Server.Host.Controllers.AdministrationController.Read().

          - + +

          ◆ ScriptFileExtension

          +
          @@ -171,8 +151,8 @@ Properties

          The extension of executable script files for the system

          -

          Definition at line 16 of file IPlatformIdentifier.cs.

          - +

          Definition at line 16 of file IPlatformIdentifier.cs.

          +
          16 { get; }

          The documentation for this interface was generated from the following file:
            @@ -183,7 +163,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process-members.html index 9009f06097..cd1c733705 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + + - + - - + + + +
          -Tgstation.Server.Host.Core.IProcessBase +Tgstation.Server.Host.Core.IProcessBase IDisposable Tgstation.Server.Host.Core.Process - -
          + + - + - + - + - +

          Public Member Functions

          string GetErrorOutput ()
           Get the stderr output of the IProcess More...
           Get the stderr output of the IProcess More...
           
          string GetStandardOutput ()
           Get the stdout output of the IProcess More...
           Get the stdout output of the IProcess More...
           
          string GetCombinedOutput ()
           Get the stderr and stdout output of the IProcess More...
           Get the stderr and stdout output of the IProcess More...
           
          void Terminate ()
           Terminates the process More...
           
          - Public Member Functions inherited from Tgstation.Server.Host.Core.IProcessBase
          void SetHighPriority ()
           Set's the owned System.Diagnostics.Process.PriorityClass to System.Diagnostics.ProcessPriorityClass.AboveNormal More...
           Set's the owned System.Diagnostics.Process.PriorityClass to System.Diagnostics.ProcessPriorityClass.AboveNormal More...
           
          - + - + - +

          Properties

          int Id [get]
           The IProcess' ID More...
           The IProcess' ID More...
           
          Task Startup [get]
           The Task representing the time until the IProcess becomes "idle" More...
           The Task representing the time until the IProcess becomes "idle" More...
           
          - Properties inherited from Tgstation.Server.Host.Core.IProcessBase
          Task< int > Lifetime [get]
           The Task<TResult> resulting in the exit code of the process More...
           The Task<TResult> resulting in the exit code of the process More...
           

          Detailed Description

          Abstraction over a System.Diagnostics.Process

          -

          Definition at line 9 of file IProcess.cs.

          +

          Definition at line 9 of file IProcess.cs.

          Member Function Documentation

          - + +

          ◆ GetCombinedOutput()

          +
          @@ -164,14 +142,16 @@ Properties
          -

          Get the stderr and stdout output of the IProcess

          -
          Returns
          The stderr and stdout output of the IProcess
          +

          Get the stderr and stdout output of the IProcess

          +
          Returns
          The stderr and stdout output of the IProcess

          Implemented in Tgstation.Server.Host.Core.Process.

          - + +

          ◆ GetErrorOutput()

          +
          @@ -184,14 +164,16 @@ Properties
          -

          Get the stderr output of the IProcess

          -
          Returns
          The stderr output of the IProcess
          +

          Get the stderr output of the IProcess

          +
          Returns
          The stderr output of the IProcess

          Implemented in Tgstation.Server.Host.Core.Process.

          - + +

          ◆ GetStandardOutput()

          +
          @@ -204,14 +186,16 @@ Properties
          -

          Get the stdout output of the IProcess

          -
          Returns
          The stdout output of the IProcess
          +

          Get the stdout output of the IProcess

          +
          Returns
          The stdout output of the IProcess

          Implemented in Tgstation.Server.Host.Core.Process.

          - + +

          ◆ Terminate()

          + - + +

          ◆ Startup

          +
          @@ -277,11 +265,11 @@ Properties
          -

          The Task representing the time until the IProcess becomes "idle"

          +

          The Task representing the time until the IProcess becomes "idle"

          -

          Definition at line 19 of file IProcess.cs.

          - -

          Referenced by Tgstation.Server.Host.Components.Watchdog.SessionController.SessionController().

          +

          Definition at line 19 of file IProcess.cs.

          +
          19 { get; }
          +

          Referenced by Tgstation.Server.Host.Components.Watchdog.SessionController.SessionController().

          @@ -293,7 +281,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process_base-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process_base-members.html index 1ff491e254..95a25f7d94 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process_base-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process_base-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
          IDisposable -Tgstation.Server.Host.Components.Watchdog.ISessionController -Tgstation.Server.Host.Core.IProcess -Tgstation.Server.Host.Components.Watchdog.DeadSessionController +Tgstation.Server.Host.Components.Watchdog.ISessionController +Tgstation.Server.Host.Core.IProcess +Tgstation.Server.Host.Components.Watchdog.DeadSessionController Tgstation.Server.Host.Components.Watchdog.SessionController Tgstation.Server.Host.Core.Process - -
          + + @@ -132,9 +108,11 @@ Properties

          Detailed Description

          Represents process lifetime

          -

          Definition at line 9 of file IProcessBase.cs.

          +

          Definition at line 9 of file IProcessBase.cs.

          Member Function Documentation

          - + +

          ◆ SetHighPriority()

          +

          Public Member Functions

          @@ -151,12 +129,14 @@ Properties

          Implemented in Tgstation.Server.Host.Components.Watchdog.SessionController, Tgstation.Server.Host.Core.Process, and Tgstation.Server.Host.Components.Watchdog.DeadSessionController.

          -

          Referenced by Tgstation.Server.Host.Components.Watchdog.Watchdog.HandlerMonitorWakeup(), and Tgstation.Server.Host.Components.Watchdog.Watchdog.LaunchImplNoLock().

          +

          Referenced by Tgstation.Server.Host.Components.Watchdog.Watchdog.HandlerMonitorWakeup(), and Tgstation.Server.Host.Components.Watchdog.Watchdog.LaunchImplNoLock().

          Property Documentation

          - + +

          ◆ Lifetime

          +
          @@ -176,9 +156,9 @@ Properties

          The Task<TResult> resulting in the exit code of the process

          -

          Definition at line 14 of file IProcessBase.cs.

          - -

          Referenced by Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond(), Tgstation.Server.Host.Components.Watchdog.Watchdog.MonitorLifetimes(), Tgstation.Server.Host.Components.Watchdog.WindowsNetworkPromptReaper.RegisterProcess(), and Tgstation.Server.Host.Components.Watchdog.SessionController.SessionController().

          +

          Definition at line 14 of file IProcessBase.cs.

          +
          14 { get; }
          +

          Referenced by Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond(), Tgstation.Server.Host.Components.Watchdog.Watchdog.MonitorLifetimes(), Tgstation.Server.Host.Components.Watchdog.WindowsNetworkPromptReaper.RegisterProcess(), and Tgstation.Server.Host.Components.Watchdog.SessionController.SessionController().

          @@ -190,7 +170,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process_executor-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process_executor-members.html index afce5449e3..9225681dcf 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process_executor-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_process_executor-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + + - + - - + + + +
          -

          For launching IProcess' +

          For launching IProcess' More...

          Inheritance diagram for Tgstation.Server.Host.Core.IProcessExecutor:
          @@ -108,24 +84,26 @@ Inheritance diagram for Tgstation.Server.Host.Core.IProcessExecutor:
          Tgstation.Server.Host.Core.ProcessExecutor - -
          + + - + - +

          Public Member Functions

          IProcess LaunchProcess (string fileName, string workingDirectory, string arguments=null, bool readOutput=false, bool readError=false, bool noShellExecute=false)
           Launch a IProcess More...
           Launch a IProcess More...
           
          IProcess GetProcess (int id)
           Get a IProcess by id More...
           Get a IProcess by id More...
           

          Detailed Description

          -

          For launching IProcess'

          +

          For launching IProcess'

          -

          Definition at line 6 of file IProcessExecutor.cs.

          +

          Definition at line 6 of file IProcessExecutor.cs.

          Member Function Documentation

          - + +

          ◆ GetProcess()

          +
          @@ -139,20 +117,24 @@ Public Member Functions
          -

          Get a IProcess by id

          +

          Get a IProcess by id

          Parameters
          - +
          idThe IProcess.Id
          idThe IProcess.Id
          -
          Returns
          The IProcess represented by id on success, on failure
          +
          Returns
          The IProcess represented by id on success, null on failure

          Implemented in Tgstation.Server.Host.Core.ProcessExecutor.

          +

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

          +
          - + +

          ◆ LaunchProcess()

          +
          @@ -200,22 +182,24 @@ Public Member Functions
          -

          Launch a IProcess

          +

          Launch a IProcess

          Parameters
          - - + +
          fileNameThe full path to the executable file
          workingDirectoryThe working directory for the IProcess
          argumentsThe arguments for the IProcess
          workingDirectoryThe working directory for the IProcess
          argumentsThe arguments for the IProcess
          readOutputIf standard output should be read
          readErrorIf standard error should be read
          noShellExecuteIf shell execute should not be used. Ignored if readError or readOutput are set
          -
          Returns
          A new IProcess
          +
          Returns
          A new IProcess

          Implemented in Tgstation.Server.Host.Core.ProcessExecutor.

          +

          Referenced by Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond(), Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), and Tgstation.Server.Host.Components.Compiler.DreamMaker.RunDreamMaker().

          +

          The documentation for this interface was generated from the following file:
            @@ -226,7 +210,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_restart_handler-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_restart_handler-members.html index 1f1ba4dfb6..690697720c 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_restart_handler-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_restart_handler-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + + - + - - + + + +
          Tgstation.Server.Host.Components.Chat.Chat Tgstation.Server.Host.Components.InstanceManager Tgstation.Server.Host.Components.Watchdog.Watchdog - -
          + + @@ -122,9 +98,11 @@ Public Member Functions

          Detailed Description

          Handler for server restarts

          -

          Definition at line 10 of file IRestartHandler.cs.

          +

          Definition at line 10 of file IRestartHandler.cs.

          Member Function Documentation

          - + +

          ◆ HandleRestart()

          +

          Public Member Functions

          @@ -151,7 +129,7 @@ Public Member Functions

          Handle a restart of the server

          Parameters
          - +
          updateVersionThe Version being updated to, if not being changed
          updateVersionThe Version being updated to, null if not being changed
          cancellationTokenThe CancellationToken for the operation
          @@ -170,7 +148,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_restart_registration.html b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_restart_registration.html index 9e8e27d0ff..b54f25bbb1 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_restart_registration.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_restart_registration.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Host.Core.IRestartRegistration Interface Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + +
          -

          Represents the lifetime of a IRestartHandler registration +

          Represents the lifetime of a IRestartHandler registration More...

          Inheritance diagram for Tgstation.Server.Host.Core.IRestartRegistration:
          @@ -106,12 +82,12 @@ Inheritance diagram for Tgstation.Server.Host.Core.IRestartRegistration:
          IDisposable Tgstation.Server.Host.Core.RestartRegistration - -
          + +

          Detailed Description

          -

          Represents the lifetime of a IRestartHandler registration

          +

          Represents the lifetime of a IRestartHandler registration

          -

          Definition at line 8 of file IRestartRegistration.cs.

          +

          Definition at line 8 of file IRestartRegistration.cs.


          The documentation for this interface was generated from the following file: @@ -120,7 +96,7 @@ Inheritance diagram for Tgstation.Server.Host.Core.IRestartRegistration:
          diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_server_control-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_server_control-members.html index a65db40834..869e54eb8f 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_server_control-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_server_control-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
          Tgstation.Server.Host.Server - -
          + + @@ -130,15 +106,17 @@ Public Member Functions - +

          Public Member Functions

          Properties

          bool WatchdogPresent [get]
           if live updates are supported, . ApplyUpdate(Version, Uri, IIOManager) and Restart will fail if this is More...
           true if live updates are supported, false. ApplyUpdate(Version, Uri, IIOManager) and Restart will fail if this is false More...
           

          Detailed Description

          Represents a service that may take an updated Host assembly and run it, stopping the current assembly in the process

          -

          Definition at line 11 of file IServerControl.cs.

          +

          Definition at line 11 of file IServerControl.cs.

          Member Function Documentation

          - + +

          ◆ ApplyUpdate()

          +
          @@ -177,13 +155,17 @@ Properties
          -
          Returns
          if the update started successfully, if there was another update in progress
          +
          Returns
          true if the update started successfully, false if there was another update in progress

          Implemented in Tgstation.Server.Host.Server.

          +

          Referenced by Tgstation.Server.Host.Controllers.AdministrationController.CheckReleasesAndApplyUpdate().

          +
          - + +

          ◆ Die()

          +
          @@ -210,7 +192,9 @@ Properties - + +

          ◆ RegisterForRestart()

          +
          @@ -227,19 +211,21 @@ Properties

          Register a given handler to run before stopping the server for a restart

          Parameters
          - +
          handlerThe IRestartHandler to register
          handlerThe IRestartHandler to register
          -
          Returns
          A new IRestartRegistration representing the scope of the registration
          +
          Returns
          A new IRestartRegistration representing the scope of the registration

          Implemented in Tgstation.Server.Host.Server.

          -

          Referenced by Tgstation.Server.Host.Components.Chat.Chat.Chat(), Tgstation.Server.Host.Components.InstanceManager.InstanceManager(), and Tgstation.Server.Host.Components.Watchdog.Watchdog.Watchdog().

          +

          Referenced by Tgstation.Server.Host.Components.Chat.Chat.Chat(), Tgstation.Server.Host.Components.InstanceManager.InstanceManager(), and Tgstation.Server.Host.Components.Watchdog.Watchdog.Watchdog().

          - + +

          ◆ Restart()

          +
          @@ -257,12 +243,14 @@ Properties

          Implemented in Tgstation.Server.Host.Server.

          -

          Referenced by Tgstation.Server.Host.Core.Application.Configure().

          +

          Referenced by Tgstation.Server.Host.Core.Application.Configure(), and Tgstation.Server.Host.Controllers.AdministrationController.Delete().

          Property Documentation

          - + +

          ◆ WatchdogPresent

          +
          @@ -280,11 +268,11 @@ Properties
          -

          if live updates are supported, . ApplyUpdate(Version, Uri, IIOManager) and Restart will fail if this is

          +

          true if live updates are supported, false. ApplyUpdate(Version, Uri, IIOManager) and Restart will fail if this is false

          -

          Definition at line 16 of file IServerControl.cs.

          - -

          Referenced by Tgstation.Server.Host.Core.Application.Configure().

          +

          Definition at line 16 of file IServerControl.cs.

          +
          16 { get; }
          +

          Referenced by Tgstation.Server.Host.Core.Application.Configure(), Tgstation.Server.Host.Controllers.AdministrationController.Delete(), and Tgstation.Server.Host.Controllers.AdministrationController.Update().

          @@ -296,7 +284,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_setup_wizard-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_setup_wizard-members.html index 116f573933..f705f89f2c 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_setup_wizard-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_core_1_1_i_setup_wizard-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
          Tgstation.Server.Host.Core.SetupWizard Tgstation.Server.Host.Core.Tests.TestApplication.MockSetupWizard - -
          + + @@ -121,9 +97,11 @@ Public Member Functions

          Detailed Description

          The command line Configuration setup wizard

          -

          Definition at line 9 of file ISetupWizard.cs.

          +

          Definition at line 9 of file ISetupWizard.cs.

          Member Function Documentation

          - + +

          ◆ CheckRunWizard()

          +

          Public Member Functions

          @@ -144,11 +122,11 @@ Public Member Functions
          -
          Returns
          A Task<TResult> resulting in if the wizard ran, otherwise
          +
          Returns
          A Task<TResult> resulting in true if the wizard ran, false otherwise

          Implemented in Tgstation.Server.Host.Core.SetupWizard, and Tgstation.Server.Host.Core.Tests.TestApplication.MockSetupWizard.

          -

          Referenced by Tgstation.Server.Host.Core.Application.ConfigureServices().

          +

          Referenced by Tgstation.Server.Host.Core.Application.ConfigureServices().

          @@ -160,7 +138,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_console-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_console-members.html index 0fedf07dfb..c549127b5c 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_console-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_console-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
          Tgstation.Server.Host.IO.Console - -
          + + - + - + - +

          Public Member Functions

          Task WriteAsync (string text, bool newLine, CancellationToken cancellationToken)
           Write some text to the IConsole More...
           Write some text to the IConsole More...
           
          Task PressAnyKeyAsync (CancellationToken cancellationToken)
           Wait for a key press on the IConsole More...
           Wait for a key press on the IConsole More...
           
          Task< string > ReadLineAsync (bool usePasswordChar, CancellationToken cancellationToken)
           Read a line from the IConsole More...
           Read a line from the IConsole More...
           
          - +

          Properties

          bool Available [get]
           If the IConsole is visible to the user More...
           If the IConsole is visible to the user More...
           

          Detailed Description

          Abstraction for System.Console

          -

          Definition at line 9 of file IConsole.cs.

          +

          Definition at line 9 of file IConsole.cs.

          Member Function Documentation

          - + +

          ◆ PressAnyKeyAsync()

          +
          @@ -149,7 +127,7 @@ Properties
          -

          Wait for a key press on the IConsole

          +

          Wait for a key press on the IConsole

          Parameters
          @@ -160,9 +138,13 @@ Properties

          Implemented in Tgstation.Server.Host.IO.Console.

          +

          Referenced by Tgstation.Server.Host.Core.SetupWizard.ConfigureDatabase(), and Tgstation.Server.Host.Core.SetupWizard.SaveConfiguration().

          + - + +

          ◆ ReadLineAsync()

          +
          cancellationTokenThe CancellationToken for the operations
          @@ -186,7 +168,7 @@ Properties
          -

          Read a line from the IConsole

          +

          Read a line from the IConsole

          Parameters
          @@ -194,13 +176,17 @@ Properties
          usePasswordCharIf the input should be retrieved using the '*' character
          -
          Returns
          A Task<TResult> resulting in the string read by the IConsole
          +
          Returns
          A Task<TResult> resulting in the string read by the IConsole

          Implemented in Tgstation.Server.Host.IO.Console.

          +

          Referenced by Tgstation.Server.Host.Core.SetupWizard.ConfigureControlPanel(), Tgstation.Server.Host.Core.SetupWizard.ConfigureDatabase(), Tgstation.Server.Host.Core.SetupWizard.ConfigureGeneral(), Tgstation.Server.Host.Core.SetupWizard.ConfigureLogging(), Tgstation.Server.Host.Core.SetupWizard.PromptForHostingPort(), and Tgstation.Server.Host.Core.SetupWizard.PromptYesNo().

          +
          - + +

          ◆ WriteAsync()

          + @@ -278,7 +270,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_i_o_manager-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_i_o_manager-members.html index 64fd53e621..77d347c503 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_i_o_manager-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_i_o_manager-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
          -Tgstation.Server.Host.IO.DefaultIOManager -Tgstation.Server.Host.IO.ResolvingIOManager - -
          +Tgstation.Server.Host.IO.DefaultIOManager +Tgstation.Server.Host.IO.ResolvingIOManager + + - + @@ -184,16 +160,18 @@ Public Member Functions

          Detailed Description

          Interface for using filesystems

          -

          Definition at line 11 of file IIOManager.cs.

          +

          Definition at line 11 of file IIOManager.cs.

          Member Function Documentation

          - + +

          ◆ ConcatPath()

          +

          Public Member Functions

          string ResolvePath (string path)
           Retrieve the full path of some path given a relative path. Must be used before passing relative paths to other APIs. All other operations in this call this internally on given paths More...
           Retrieve the full path of some path given a relative path. Must be used before passing relative paths to other APIs. All other operations in this interface call this internally on given paths More...
           
          string GetFileName (string path)
           Gets the file name portion of a path More...
          - + @@ -211,11 +189,13 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.IO.DefaultIOManager.

          -

          Referenced by Tgstation.Server.Host.Core.Application.ConfigureServices().

          +

          Referenced by Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.CleanCache(), Tgstation.Server.Host.Core.SetupWizard.ConfigureLogging(), Tgstation.Server.Host.Core.Application.ConfigureServices(), Tgstation.Server.Host.Components.StaticFiles.Configuration.CopyDMFilesTo(), Tgstation.Server.Host.Controllers.InstanceController.Create(), Tgstation.Server.Host.Controllers.InstanceController.Delete(), Tgstation.Server.Host.Components.Compiler.DmbFactory.FromCompileJob(), Tgstation.Server.Host.Components.Byond.PosixByondInstaller.InstallByond(), Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond(), Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), Tgstation.Server.Host.Components.Compiler.DreamMaker.ModifyDme(), Tgstation.Server.Host.Components.Compiler.DreamMaker.RunCompileJob(), Tgstation.Server.Host.Components.Compiler.DreamMaker.RunDreamMaker(), Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync(), Tgstation.Server.Host.Components.StaticFiles.Configuration.SymlinkStaticFilesTo(), Tgstation.Server.Host.Components.Chat.Chat.TrackJsons(), Tgstation.Server.Host.Components.Byond.ByondManager.UseExecutables(), and Tgstation.Server.Host.Components.Compiler.DreamMaker.VerifyApi().

          - + +

          ◆ CopyDirectory()

          +
          string Tgstation.Server.Host.IO.IIOManager.ConcatPath (params string[] params string []  paths)
          @@ -265,9 +245,13 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.IO.DefaultIOManager.

          +

          Referenced by Tgstation.Server.Host.Components.StaticFiles.Configuration.CopyDMFilesTo(), Tgstation.Server.Host.Components.InstanceManager.MoveInstance(), and Tgstation.Server.Host.Components.Compiler.DreamMaker.RunCompileJob().

          + - + +

          ◆ CopyFile()

          +
          @@ -312,7 +296,9 @@ Public Member Functions - + +

          ◆ CreateDirectory()

          +
          @@ -348,9 +334,13 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.IO.DefaultIOManager.

          +

          Referenced by Tgstation.Server.Host.Components.Compiler.DmbFactory.CleanUnusedCompileJobs(), Tgstation.Server.Host.Core.SetupWizard.ConfigureLogging(), Tgstation.Server.Host.Controllers.InstanceController.Create(), Tgstation.Server.Host.Components.StaticFiles.Configuration.EnsureDirectories(), Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond(), Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), and Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync().

          + - + +

          ◆ DeleteDirectory()

          +
          @@ -386,11 +376,13 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.IO.DefaultIOManager.

          -

          Referenced by Tgstation.Server.Host.Server.ApplyUpdate().

          +

          Referenced by Tgstation.Server.Host.Server.ApplyUpdate(), Tgstation.Server.Host.Components.Byond.PosixByondInstaller.CleanCache(), Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.CleanCache(), Tgstation.Server.Host.Components.Compiler.DmbFactory.CleanJob(), Tgstation.Server.Host.Components.Compiler.DmbFactory.CleanUnusedCompileJobs(), Tgstation.Server.Host.Components.Compiler.DreamMaker.CleanupFailedCompile(), Tgstation.Server.Host.Components.Repository.RepositoryManager.CloneRepository(), Tgstation.Server.Host.Components.Repository.RepositoryManager.DeleteRepository(), Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), Tgstation.Server.Host.Components.InstanceManager.MoveInstance(), Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync(), and Tgstation.Server.Host.Components.StaticFiles.Configuration.SymlinkStaticFilesTo().

          - + +

          ◆ DeleteFile()

          +
          @@ -426,9 +418,13 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.IO.DefaultIOManager.

          +

          Referenced by Tgstation.Server.Host.Core.SetupWizard.ConfigureLogging(), Tgstation.Server.Host.Controllers.InstanceController.Create(), Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync(), and Tgstation.Server.Host.Components.StaticFiles.Configuration.SymlinkStaticFilesTo().

          + - + +

          ◆ DirectoryExists()

          +
          @@ -460,13 +456,17 @@ Public Member Functions
          -
          Returns
          A Task resulting in if the directory at path exists, otherwise
          +
          Returns
          A Task resulting in true if the directory at path exists, false otherwise

          Implemented in Tgstation.Server.Host.IO.DefaultIOManager.

          +

          Referenced by Tgstation.Server.Host.Components.Repository.RepositoryManager.CloneRepository(), Tgstation.Server.Host.Controllers.InstanceController.Create(), and Tgstation.Server.Host.Components.StaticFiles.Configuration.SymlinkStaticFilesTo().

          + - + +

          ◆ DownloadFile()

          + - + +

          ◆ GetDirectories()

          +
          @@ -580,9 +586,13 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.IO.DefaultIOManager.

          +

          Referenced by Tgstation.Server.Host.Components.Compiler.DmbFactory.CleanUnusedCompileJobs(), Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync(), and Tgstation.Server.Host.Components.StaticFiles.Configuration.SymlinkStaticFilesTo().

          + - + +

          ◆ GetDirectoryName()

          +
          @@ -609,7 +619,9 @@ Public Member Functions - + +

          ◆ GetFileName()

          +
          @@ -634,9 +646,13 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.IO.DefaultIOManager.

          +

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

          + - + +

          ◆ GetFileNameWithoutExtension()

          +
          @@ -663,7 +679,9 @@ Public Member Functions - + +

          ◆ GetFiles()

          +
          @@ -699,9 +717,13 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.IO.DefaultIOManager.

          +

          Referenced by Tgstation.Server.Host.Components.StaticFiles.Configuration.SymlinkStaticFilesTo().

          + - + +

          ◆ GetFilesWithExtension()

          +
          @@ -744,9 +766,13 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.IO.DefaultIOManager.

          +

          Referenced by Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), and Tgstation.Server.Host.Components.Compiler.DreamMaker.RunCompileJob().

          + - + +

          ◆ MoveDirectory()

          +
          @@ -791,7 +817,9 @@ Public Member Functions - + +

          ◆ MoveFile()

          +
          @@ -836,7 +864,9 @@ Public Member Functions - + +

          ◆ PathContainsParentAccess()

          +
          @@ -857,13 +887,17 @@ Public Member Functions
          -
          Returns
          if path contains a '..' accessor, otherwise
          +
          Returns
          true if path contains a '..' accessor, false otherwise

          Implemented in Tgstation.Server.Host.IO.DefaultIOManager.

          +

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

          +
          - + +

          ◆ ReadAllBytes()

          +
          -

          Retrieve the full path of some path given a relative path. Must be used before passing relative paths to other APIs. All other operations in this call this internally on given paths

          +

          Retrieve the full path of some path given a relative path. Must be used before passing relative paths to other APIs. All other operations in this interface call this internally on given paths

          Parameters
          @@ -926,11 +964,13 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.IO.DefaultIOManager, and Tgstation.Server.Host.IO.ResolvingIOManager.

          -

          Referenced by Tgstation.Server.Host.Components.Interop.CommContext.CommContext(), and Tgstation.Server.Host.IO.ResolvingIOManager.ResolvingIOManager().

          +

          Referenced by Tgstation.Server.Host.Components.Compiler.DreamMaker.CleanupFailedCompile(), Tgstation.Server.Host.Components.Repository.RepositoryManager.CloneRepository(), Tgstation.Server.Host.Components.Interop.CommContext.CommContext(), Tgstation.Server.Host.Controllers.InstanceController.Create(), Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), Tgstation.Server.Host.Components.Repository.RepositoryManager.LoadRepository(), Tgstation.Server.Host.Components.Compiler.DreamMaker.ModifyDme(), Tgstation.Server.Host.Controllers.InstanceController.NormalizeModelPath(), Tgstation.Server.Host.IO.ResolvingIOManager.ResolvingIOManager(), Tgstation.Server.Host.Components.Compiler.DreamMaker.RunCompileJob(), Tgstation.Server.Host.Components.Compiler.DreamMaker.RunDreamMaker(), Tgstation.Server.Host.Components.Byond.ByondManager.StartAsync(), Tgstation.Server.Host.Components.StaticFiles.Configuration.SymlinkStaticFilesTo(), Tgstation.Server.Host.Components.Byond.ByondManager.UseExecutables(), Tgstation.Server.Host.Components.StaticFiles.Configuration.ValidateConfigRelativePath(), and Tgstation.Server.Host.Components.Compiler.DreamMaker.VerifyApi().

          - + +

          ◆ WriteAllBytes()

          +
          pathSome path to retrieve the full path of
          @@ -943,7 +983,7 @@ Public Member Functions - + @@ -973,9 +1013,13 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.IO.DefaultIOManager.

          +

          Referenced by Tgstation.Server.Host.Components.Byond.ByondManager.ChangeVersion(), Tgstation.Server.Host.Core.SetupWizard.ConfigureLogging(), Tgstation.Server.Host.Controllers.InstanceController.Delete(), Tgstation.Server.Host.Components.StaticFiles.Configuration.EnsureDirectories(), Tgstation.Server.Host.Components.Byond.PosixByondInstaller.InstallByond(), Tgstation.Server.Host.Components.Byond.WindowsByondInstaller.InstallByond(), Tgstation.Server.Host.Components.Byond.ByondManager.InstallVersion(), Tgstation.Server.Host.Components.Watchdog.SessionControllerFactory.LaunchNew(), Tgstation.Server.Host.Components.Compiler.DreamMaker.ModifyDme(), Tgstation.Server.Host.Core.SetupWizard.SaveConfiguration(), and Tgstation.Server.Host.Components.Chat.JsonTrackingContext.SetChannels().

          + - + +

          ◆ ZipToDirectory()

          +
          byte[] byte []  contents,
          @@ -988,7 +1032,7 @@ Public Member Functions - + @@ -1018,7 +1062,7 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.IO.DefaultIOManager.

          -

          Referenced by Tgstation.Server.Host.Server.ApplyUpdate().

          +

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

          @@ -1030,7 +1074,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_post_write_handler-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_post_write_handler-members.html index 13ecf3697d..01774a4bbc 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_post_write_handler-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_post_write_handler-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          byte[] byte []  zipFileBytes,
          - + - - + + + + - + - - + + + +
          -Tgstation.Server.Host.IO.PosixPostWriteHandler -Tgstation.Server.Host.IO.WindowsPostWriteHandler - -
          +Tgstation.Server.Host.IO.PosixPostWriteHandler +Tgstation.Server.Host.IO.WindowsPostWriteHandler + +
          @@ -121,9 +97,11 @@ Public Member Functions

          Detailed Description

          Handles changing file modes/permissions after writing

          -

          Definition at line 6 of file IPostWriteHandler.cs.

          +

          Definition at line 6 of file IPostWriteHandler.cs.

          Member Function Documentation

          - + +

          ◆ HandleWrite()

          +

          Public Member Functions

          @@ -147,7 +125,7 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.IO.PosixPostWriteHandler, and Tgstation.Server.Host.IO.WindowsPostWriteHandler.

          -

          Referenced by Tgstation.Server.Host.IO.Tests.TestPostWriteHandler.TestPostWrite(), and Tgstation.Server.Host.IO.Tests.TestPostWriteHandler.TestThrowsWithNullArg().

          +

          Referenced by Tgstation.Server.Host.Components.Byond.PosixByondInstaller.InstallByond(), Tgstation.Server.Host.IO.Tests.TestPostWriteHandler.TestPostWrite(), and Tgstation.Server.Host.IO.Tests.TestPostWriteHandler.TestThrowsWithNullArg().

          @@ -159,7 +137,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_symlink_factory-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_symlink_factory-members.html index 5e54a81b5e..e107d934be 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_symlink_factory-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_symlink_factory-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + + - + - - + + + +
          -Tgstation.Server.Host.IO.PosixSymlinkFactory -Tgstation.Server.Host.IO.WindowsSymlinkFactory - -
          +Tgstation.Server.Host.IO.PosixSymlinkFactory +Tgstation.Server.Host.IO.WindowsSymlinkFactory + + @@ -121,9 +97,11 @@ Public Member Functions

          Detailed Description

          For creating filesystem symbolic links

          -

          Definition at line 9 of file ISymlinkFactory.cs.

          +

          Definition at line 9 of file ISymlinkFactory.cs.

          Member Function Documentation

          - + +

          ◆ CreateSymbolicLink()

          +

          Public Member Functions

          @@ -166,7 +144,7 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.IO.PosixSymlinkFactory, and Tgstation.Server.Host.IO.WindowsSymlinkFactory.

          -

          Referenced by Tgstation.Server.Host.IO.Tests.TestSymlinkFactory.TestDirectoryWorks(), Tgstation.Server.Host.IO.Tests.TestSymlinkFactory.TestFailsProperly(), and Tgstation.Server.Host.IO.Tests.TestSymlinkFactory.TestFileWorks().

          +

          Referenced by Tgstation.Server.Host.Components.StaticFiles.Configuration.SymlinkStaticFilesTo(), Tgstation.Server.Host.IO.Tests.TestSymlinkFactory.TestDirectoryWorks(), Tgstation.Server.Host.IO.Tests.TestSymlinkFactory.TestFailsProperly(), and Tgstation.Server.Host.IO.Tests.TestSymlinkFactory.TestFileWorks().

          @@ -178,7 +156,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_synchronous_i_o_manager-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_synchronous_i_o_manager-members.html index cfd461ceec..a2a24f1fb8 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_synchronous_i_o_manager-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_i_o_1_1_i_synchronous_i_o_manager-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + + - + - - + + + +
          Tgstation.Server.Host.IO.SynchronousIOManager - -
          + + @@ -122,7 +98,7 @@ Public Member Functions - + @@ -138,9 +114,11 @@ Public Member Functions

          Detailed Description

          For accessing the disk in a synchronous manner

          -

          Definition at line 9 of file ISynchronousIOManager.cs.

          +

          Definition at line 9 of file ISynchronousIOManager.cs.

          Member Function Documentation

          - + +

          ◆ CreateDirectory()

          +

          Public Member Functions

          bool CreateDirectory (string path, CancellationToken cancellationToken)
           Create an empty directory at path More...
           
          byte[] ReadFile (string path)
          byte [] ReadFile (string path)
           Read the bytes of a file at a given path More...
           
          bool DeleteDirectory (string path)
          @@ -172,13 +150,15 @@ Public Member Functions
          -
          Returns
          if the directory already existed, otherwise
          +
          Returns
          true if the directory already existed, false otherwise

          Implemented in Tgstation.Server.Host.IO.SynchronousIOManager.

          - + +

          ◆ DeleteDirectory()

          +
          @@ -199,13 +179,15 @@ Public Member Functions
          -
          Returns
          if the directory does not exist or is empty and was deleted. otherwise
          +
          Returns
          true if the directory does not exist or is empty and was deleted. false otherwise

          Implemented in Tgstation.Server.Host.IO.SynchronousIOManager.

          - + +

          ◆ GetDirectories()

          +
          @@ -241,9 +223,13 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.IO.SynchronousIOManager.

          +

          Referenced by Tgstation.Server.Host.Components.StaticFiles.Configuration.ListDirectory().

          + - + +

          ◆ GetFiles()

          +
          @@ -279,9 +265,13 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.IO.SynchronousIOManager.

          +

          Referenced by Tgstation.Server.Host.Components.StaticFiles.Configuration.ListDirectory().

          + - + +

          ◆ IsDirectory()

          +
          @@ -302,13 +292,17 @@ Public Member Functions
          -
          Returns
          if path is a directory, otherwise
          +
          Returns
          true if path is a directory, false otherwise

          Implemented in Tgstation.Server.Host.IO.SynchronousIOManager.

          +

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

          +
          - + +

          ◆ ReadFile()

          +
          @@ -333,9 +327,13 @@ Public Member Functions

          Implemented in Tgstation.Server.Host.IO.SynchronousIOManager.

          +

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

          + - + +

          ◆ WriteFileChecked()

          +
          @@ -348,7 +346,7 @@ Public Member Functions - + @@ -381,7 +379,7 @@ Public Member Functions
          byte[] byte []  data,
          -
          Returns
          on success, if the operation failed due to sha1InOut not matching the file's contents
          +
          Returns
          true on success, false if the operation failed due to sha1InOut not matching the file's contents

          Implemented in Tgstation.Server.Host.IO.SynchronousIOManager.

          @@ -395,7 +393,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_i_server-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_i_server-members.html index ebb2c245ff..e23d6c0287 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_i_server-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_i_server-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
          - + - - + + + + - + - - + + + +
          Tgstation.Server.Host.Server Tgstation.Server.Tests.TestingServer - -
          + + - +

          Public Member Functions

          Task RunAsync (CancellationToken cancellationToken)
           Runs the IServer More...
           Runs the IServer More...
           
          - +

          Properties

          bool RestartRequested [get]
           If the IServer should restart More...
           If the IServer should restart More...
           

          Detailed Description

          Represents the host

          -

          Definition at line 9 of file IServer.cs.

          +

          Definition at line 9 of file IServer.cs.

          Member Function Documentation

          - + +

          ◆ RunAsync()

          +
          @@ -144,7 +122,7 @@ Properties
          -

          Runs the IServer

          +

          Runs the IServer

          Parameters
          @@ -155,12 +133,14 @@ Properties

          Implemented in Tgstation.Server.Host.Server, and Tgstation.Server.Tests.TestingServer.

          -

          Referenced by Tgstation.Server.Host.Program.Main().

          +

          Referenced by Tgstation.Server.Host.Program.Main().

          Property Documentation

          - + +

          ◆ RestartRequested

          +
          cancellationTokenThe CancellationToken for the operation
          @@ -178,10 +158,10 @@ Properties
          -

          If the IServer should restart

          - -

          Definition at line 14 of file IServer.cs.

          +

          If the IServer should restart

          +

          Definition at line 14 of file IServer.cs.

          +
          14 { get; }

          The documentation for this interface was generated from the following file:
            @@ -192,7 +172,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_i_server_factory-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_i_server_factory-members.html index 5bab397cec..2df9ab7f60 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_i_server_factory-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_i_server_factory-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
            -

            For creating IServers +

            For creating IServers More...

            Inheritance diagram for Tgstation.Server.Host.IServerFactory:
            @@ -108,28 +84,30 @@ Inheritance diagram for Tgstation.Server.Host.IServerFactory:
            Tgstation.Server.Host.ServerFactory - -
            + + - +

            Public Member Functions

            IServer CreateServer (string[] args, string updatePath)
             Create a IServer More...
             Create a IServer More...
             

            Detailed Description

            -

            For creating IServers

            +

            For creating IServers

            -

            Definition at line 6 of file IServerFactory.cs.

            +

            Definition at line 6 of file IServerFactory.cs.

            Member Function Documentation

            - + +

            ◆ CreateServer()

            +
            - + @@ -146,20 +124,18 @@ Public Member Functions
            IServer Tgstation.Server.Host.IServerFactory.CreateServer (string[] string []  args,
            -

            Create a IServer

            +

            Create a IServer

            Parameters
            - +
            argsThe arguments for the IServer
            argsThe arguments for the IServer
            updatePathThe directory in which to install server updates
            -
            Returns
            A new IServer
            +
            Returns
            A new IServer

            Implemented in Tgstation.Server.Host.ServerFactory.

            -

            Referenced by Tgstation.Server.Host.Program.Main().

            -

            The documentation for this interface was generated from the following file:
              @@ -170,7 +146,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_models_1_1_i_database_context-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_models_1_1_i_database_context-members.html index e70fad968e..c03d7d5472 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_models_1_1_i_database_context-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_models_1_1_i_database_context-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
            - + - - + + + + - + - - + + + +
            Tgstation.Server.Host.Models.DatabaseContext< TParentContext > - -
            + + - + - + @@ -127,51 +103,53 @@ Public Member Functions - + - + - + - + - + - + - + - + - + - + - + - + - +

            Public Member Functions

            Task Save (CancellationToken cancellationToken)
             Saves changes made to the IDatabaseContext More...
             Saves changes made to the IDatabaseContext More...
             
            Task Initialize (CancellationToken cancellationToken)
             Creates and migrates the IDatabaseContext More...
             Creates and migrates the IDatabaseContext More...
             
            Task SchemaDowngradeForServerVersion (Version version, CancellationToken cancellationToken)
             Attempt to downgrade the schema to the migration used for a given server version More...

            Properties

            DbSet< UserUsers [get]
             The Users in the IDatabaseContext More...
             The Users in the IDatabaseContext More...
             
            DbSet< InstanceInstances [get]
             The Instances in the IDatabaseContext More...
             The Instances in the IDatabaseContext More...
             
            DbSet< InstanceUserInstanceUsers [get]
             The InstanceUsers in the IDatabaseContext More...
             The InstanceUsers in the IDatabaseContext More...
             
            DbSet< JobJobs [get]
             The Jobs in the IDatabaseContext More...
             The Jobs in the IDatabaseContext More...
             
            DbSet< CompileJobCompileJobs [get]
             The CompileJobs in the IDatabaseContext More...
             The CompileJobs in the IDatabaseContext More...
             
            DbSet< RevisionInformationRevisionInformations [get]
             The RevisionInformations in the IDatabaseContext More...
             The RevisionInformations in the IDatabaseContext More...
             
            DbSet< DreamMakerSettingsDreamMakerSettings [get, set]
             The Models.DreamMakerSettings in the IDatabaseContext More...
             The Models.DreamMakerSettings in the IDatabaseContext More...
             
            DbSet< DreamDaemonSettingsDreamDaemonSettings [get, set]
             The Models.DreamDaemonSettings in the IDatabaseContext More...
             The Models.DreamDaemonSettings in the IDatabaseContext More...
             
            DbSet< ChatBotChatBots [get, set]
             The Models.ChatBot in the IDatabaseContext More...
             The Models.ChatBot in the IDatabaseContext More...
             
            DbSet< ChatChannelChatChannels [get, set]
             The ChatChannel in the IDatabaseContext More...
             The ChatChannel in the IDatabaseContext More...
             
            DbSet< RepositorySettingsRepositorySettings [get, set]
             The Models.RepositorySettings in the IDatabaseContext More...
             The Models.RepositorySettings in the IDatabaseContext More...
             
            DbSet< ReattachInformationReattachInformations [get, set]
             The DbSet<TEntity> for Models.ReattachInformations More...
             The DbSet<TEntity> for Models.ReattachInformations More...
             
            DbSet< WatchdogReattachInformationWatchdogReattachInformations [get, set]
             The DbSet<TEntity> for Models.WatchdogReattachInformations More...
             The DbSet<TEntity> for Models.WatchdogReattachInformations More...
             

            Detailed Description

            Represents the database

            -

            Definition at line 11 of file IDatabaseContext.cs.

            +

            Definition at line 11 of file IDatabaseContext.cs.

            Member Function Documentation

            - + +

            ◆ Initialize()

            +
            @@ -185,7 +163,7 @@ Properties
            -

            Creates and migrates the IDatabaseContext

            +

            Creates and migrates the IDatabaseContext

            Parameters
            @@ -198,7 +176,9 @@ Properties - + +

            ◆ Save()

            +
            cancellationTokenThe CancellationToken for the operation
            @@ -212,7 +192,7 @@ Properties
            -

            Saves changes made to the IDatabaseContext

            +

            Saves changes made to the IDatabaseContext

            Parameters
            @@ -223,11 +203,13 @@ Properties

            Implemented in Tgstation.Server.Host.Models.DatabaseContext< TParentContext >.

            -

            Referenced by Tgstation.Server.Host.Models.DatabaseSeeder.ResetAdminPassword(), and Tgstation.Server.Host.Models.DatabaseSeeder.SeedDatabase().

            +

            Referenced by Tgstation.Server.Host.Models.DatabaseSeeder.ResetAdminPassword(), and Tgstation.Server.Host.Models.DatabaseSeeder.SeedDatabase().

            - + +

            ◆ SchemaDowngradeForServerVersion()

            +
            cancellationTokenThe CancellationToken for the operation
            @@ -266,7 +248,9 @@ Properties

            Property Documentation

            - + +

            ◆ ChatBots

            +
            @@ -284,13 +268,15 @@ Properties
            -

            The Models.ChatBot in the IDatabaseContext

            - -

            Definition at line 56 of file IDatabaseContext.cs.

            +

            The Models.ChatBot in the IDatabaseContext

            +

            Definition at line 56 of file IDatabaseContext.cs.

            +
            56 { get; set; }
            - + +

            ◆ ChatChannels

            +
            @@ -308,13 +294,15 @@ Properties
            -

            The ChatChannel in the IDatabaseContext

            - -

            Definition at line 61 of file IDatabaseContext.cs.

            +

            The ChatChannel in the IDatabaseContext

            +

            Definition at line 61 of file IDatabaseContext.cs.

            +
            61 { get; set; }
            - + +

            ◆ CompileJobs

            +
            @@ -332,15 +320,17 @@ Properties
            -

            The CompileJobs in the IDatabaseContext

            +

            The CompileJobs in the IDatabaseContext

            -

            Definition at line 36 of file IDatabaseContext.cs.

            - -

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

            +

            Definition at line 36 of file IDatabaseContext.cs.

            +
            36 { get; }
            +

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

            - + +

            ◆ DreamDaemonSettings

            +
            @@ -358,15 +348,17 @@ Properties
            - + +

            ◆ DreamMakerSettings

            +
            @@ -384,15 +376,17 @@ Properties
            - + +

            ◆ Instances

            +
            @@ -410,15 +404,17 @@ Properties
            -

            The Instances in the IDatabaseContext

            +

            The Instances in the IDatabaseContext

            -

            Definition at line 21 of file IDatabaseContext.cs.

            - -

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

            +

            Definition at line 21 of file IDatabaseContext.cs.

            +
            21 { get; }
            +

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

            - + +

            ◆ InstanceUsers

            +
            @@ -436,13 +432,17 @@ Properties
            -

            The InstanceUsers in the IDatabaseContext

            +

            The InstanceUsers in the IDatabaseContext

            -

            Definition at line 26 of file IDatabaseContext.cs.

            +

            Definition at line 26 of file IDatabaseContext.cs.

            +
            26 { get; }
            +

            Referenced by Tgstation.Server.Host.Security.AuthenticationContextFactory.CreateAuthenticationContext().

            - + +

            ◆ Jobs

            +
            @@ -460,13 +460,15 @@ Properties
            -

            The Jobs in the IDatabaseContext

            - -

            Definition at line 31 of file IDatabaseContext.cs.

            +

            The Jobs in the IDatabaseContext

            +

            Definition at line 31 of file IDatabaseContext.cs.

            +
            31 { get; }
            - + +

            ◆ ReattachInformations

            +
            @@ -484,13 +486,15 @@ Properties
            -

            The DbSet<TEntity> for Models.ReattachInformations

            - -

            Definition at line 71 of file IDatabaseContext.cs.

            +

            The DbSet<TEntity> for Models.ReattachInformations

            +

            Definition at line 71 of file IDatabaseContext.cs.

            +
            71 { get; set; }
            - + +

            ◆ RepositorySettings

            +
            @@ -508,15 +512,17 @@ Properties
            - + +

            ◆ RevisionInformations

            + - + +

            ◆ Users

            + - + +

            ◆ WatchdogReattachInformations

            +
            @@ -586,10 +596,10 @@ Properties
            -

            The DbSet<TEntity> for Models.WatchdogReattachInformations

            - -

            Definition at line 76 of file IDatabaseContext.cs.

            +

            The DbSet<TEntity> for Models.WatchdogReattachInformations

            +

            Definition at line 76 of file IDatabaseContext.cs.

            +
            76 { get; set; }

            The documentation for this interface was generated from the following file:
              @@ -600,7 +610,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_models_1_1_i_database_seeder-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_models_1_1_i_database_seeder-members.html index 3293b2a0c8..a77b515848 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_models_1_1_i_database_seeder-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_models_1_1_i_database_seeder-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
              Tgstation.Server.Host.Models.DatabaseSeeder - -
              + + @@ -117,15 +93,17 @@ Public Member Functions - +

              Public Member Functions

               Initially seed a given databaseContext More...
               
              Task ResetAdminPassword (IDatabaseContext databaseContext, CancellationToken cancellationToken)
               Changes the admin password in IDatabaseContext back to it's default and enables the account More...
               Changes the admin password in IDatabaseContext back to it's default and enables the account More...
               

              Detailed Description

              For initially seeding a database

              -

              Definition at line 9 of file IDatabaseSeeder.cs.

              +

              Definition at line 9 of file IDatabaseSeeder.cs.

              Member Function Documentation

              - + +

              ◆ ResetAdminPassword()

              +
              @@ -149,10 +127,10 @@ Public Member Functions
              -

              Changes the admin password in IDatabaseContext back to it's default and enables the account

              +

              Changes the admin password in IDatabaseContext back to it's default and enables the account

              Parameters
              - +
              databaseContextThe IDatabaseContext to reset the admin password for
              databaseContextThe IDatabaseContext to reset the admin password for
              cancellationTokenThe CancellationToken for the operation
              @@ -161,9 +139,13 @@ Public Member Functions

              Implemented in Tgstation.Server.Host.Models.DatabaseSeeder.

              +

              Referenced by Tgstation.Server.Host.Models.DatabaseContext< SqlServerDatabaseContext >.Initialize().

              +
              - + +

              ◆ SeedDatabase()

              +
              @@ -190,7 +172,7 @@ Public Member Functions

              Initially seed a given databaseContext

              Parameters
              - +
              databaseContextThe IDatabaseContext to seed
              databaseContextThe IDatabaseContext to seed
              cancellationTokenThe CancellationToken for the operation
              @@ -199,6 +181,8 @@ Public Member Functions

              Implemented in Tgstation.Server.Host.Models.DatabaseSeeder.

              +

              Referenced by Tgstation.Server.Host.Models.DatabaseContext< SqlServerDatabaseContext >.Initialize().

              +

              The documentation for this interface was generated from the following file:
                @@ -209,7 +193,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_authentication_context-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_authentication_context-members.html index 443d82eb38..c378c6864b 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_authentication_context-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_authentication_context-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
                IDisposable -Tgstation.Server.Host.Security.AuthenticationContext - -
                +Tgstation.Server.Host.Security.AuthenticationContext + + @@ -125,18 +101,20 @@ Properties - + - +

                Public Member Functions

                 The authenticated user More...
                 
                InstanceUser InstanceUser [get]
                 The InstanceUser of User if applicable More...
                 The InstanceUser of User if applicable More...
                 
                ISystemIdentity SystemIdentity [get]
                 The ISystemIdentity of User if applicable More...
                 The ISystemIdentity of User if applicable More...
                 

                Detailed Description

                Represents the currently authenticated Api.Models.User

                -

                Definition at line 10 of file IAuthenticationContext.cs.

                +

                Definition at line 10 of file IAuthenticationContext.cs.

                Member Function Documentation

                - + +

                ◆ GetRight()

                +
                @@ -157,14 +135,16 @@ Properties
                -
                Returns
                The value of rightsType . Note that if InstanceUser is all Instance based rights will return 0
                +
                Returns
                The value of rightsType . Note that if InstanceUser is null all Instance based rights will return 0

                Implemented in Tgstation.Server.Host.Security.AuthenticationContext.

                Property Documentation

                - + +

                ◆ InstanceUser

                +
                @@ -182,13 +162,15 @@ Properties
                -

                The InstanceUser of User if applicable

                - -

                Definition at line 20 of file IAuthenticationContext.cs.

                +

                The InstanceUser of User if applicable

                +

                Definition at line 20 of file IAuthenticationContext.cs.

                +
                20 { get; }
                - + +

                ◆ SystemIdentity

                +
                @@ -206,13 +188,15 @@ Properties
                -

                The ISystemIdentity of User if applicable

                - -

                Definition at line 32 of file IAuthenticationContext.cs.

                +

                The ISystemIdentity of User if applicable

                +

                Definition at line 32 of file IAuthenticationContext.cs.

                +
                32 { get; }
                - + +

                ◆ User

                +
                @@ -232,8 +216,8 @@ Properties

                The authenticated user

                -

                Definition at line 15 of file IAuthenticationContext.cs.

                - +

                Definition at line 15 of file IAuthenticationContext.cs.

                +
                15 { get; }

                The documentation for this interface was generated from the following file:
                  @@ -244,7 +228,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_authentication_context_factory-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_authentication_context_factory-members.html index 54e40f6b91..1ce97fefd8 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_authentication_context_factory-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_authentication_context_factory-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
                - + - - + + + +
                This is the complete list of members for Tgstation.Server.Host.Security.IAuthenticationContextFactory, including all inherited members.

                - +
                CreateAuthenticationContext(long userId, long?instanceId, DateTimeOffset validAfter, CancellationToken cancellationToken)Tgstation.Server.Host.Security.IAuthenticationContextFactory
                CreateAuthenticationContext(long userId, long? instanceId, DateTimeOffset validAfter, CancellationToken cancellationToken)Tgstation.Server.Host.Security.IAuthenticationContextFactory
                CurrentAuthenticationContextTgstation.Server.Host.Security.IAuthenticationContextFactory
                diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_authentication_context_factory.html b/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_authentication_context_factory.html index 2623a3a42a..bebd46df5e 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_authentication_context_factory.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_authentication_context_factory.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Tgstation.Server.Host.Security.IAuthenticationContextFactory Interface Reference @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
                - + - - + + + +
                Tgstation.Server.Host.Security.AuthenticationContextFactory - -
                + + - - - + + +

                Public Member Functions

                Task CreateAuthenticationContext (long userId, long?instanceId, DateTimeOffset validAfter, CancellationToken cancellationToken)
                 Create an IAuthenticationContext to populate CurrentAuthenticationContext More...
                 
                Task CreateAuthenticationContext (long userId, long? instanceId, DateTimeOffset validAfter, CancellationToken cancellationToken)
                 Create an IAuthenticationContext to populate CurrentAuthenticationContext More...
                 
                - +

                Properties

                IAuthenticationContext CurrentAuthenticationContext [get]
                 The IAuthenticationContext the IAuthenticationContextFactory created More...
                 The IAuthenticationContext the IAuthenticationContextFactory created More...
                 

                Detailed Description

                For creating and accessing authentication contexts

                -

                Definition at line 10 of file IAuthenticationContextFactory.cs.

                +

                Definition at line 10 of file IAuthenticationContextFactory.cs.

                Member Function Documentation

                - + +

                ◆ CreateAuthenticationContext()

                +
                @@ -165,24 +143,28 @@ Properties
                -

                Create an IAuthenticationContext to populate CurrentAuthenticationContext

                +

                Create an IAuthenticationContext to populate CurrentAuthenticationContext

                Parameters
                - - - + + +
                userIdThe Api.Models.Internal.User.Id of the IAuthenticationContext.User
                instanceIdThe Api.Models.Instance.Id of the operation
                validAfterThe DateTimeOffset the resulting IAuthenticationContext.User's password must be valid after
                userIdThe Api.Models.Internal.User.Id of the IAuthenticationContext.User
                instanceIdThe Api.Models.Instance.Id of the operation
                validAfterThe DateTimeOffset the resulting IAuthenticationContext.User's password must be valid after
                cancellationTokenThe CancellationToken for the operation
                Returns
                A Task representing the running operation
                -

                Implemented in Tgstation.Server.Host.Security.AuthenticationContextFactory.

                +

                Implemented in Tgstation.Server.Host.Security.AuthenticationContextFactory.

                + +

                Referenced by Tgstation.Server.Host.Security.ClaimsInjector.InjectClaimsIntoContext().

                Property Documentation

                - + +

                ◆ CurrentAuthenticationContext

                + @@ -216,7 +198,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_claims_injector-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_claims_injector-members.html index d832717d32..9e1c2d6d77 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_claims_injector-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_claims_injector-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
                -

                For injecting System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look for +

                For injecting System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look for More...

                Inheritance diagram for Tgstation.Server.Host.Security.IClaimsInjector:
                @@ -108,8 +84,8 @@ Inheritance diagram for Tgstation.Server.Host.Security.IClaimsInjector:
                Tgstation.Server.Host.Security.ClaimsInjector - -
                + + @@ -118,11 +94,13 @@ Public Member Functions

                Public Member Functions

                 

                Detailed Description

                -

                For injecting System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look for

                +

                For injecting System.Security.Claims.Claims that Controllers.TgsAuthorizeAttribute can look for

                -

                Definition at line 10 of file IClaimsInjector.cs.

                +

                Definition at line 10 of file IClaimsInjector.cs.

                Member Function Documentation

                - + +

                ◆ InjectClaimsIntoContext()

                +
                @@ -168,7 +146,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_cryptography_suite-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_cryptography_suite-members.html index 0875acc86e..e50e4b1e2f 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_cryptography_suite-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_cryptography_suite-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
                - + - - + + + + - + - - + + + +
                Tgstation.Server.Host.Security.CryptographySuite - -
                + +
                - + @@ -129,9 +105,11 @@ Public Member Functions

                Detailed Description

                Contains various cryptographic functions

                -

                Definition at line 8 of file ICryptographySuite.cs.

                +

                Definition at line 8 of file ICryptographySuite.cs.

                Member Function Documentation

                - + +

                ◆ CheckUserPassword()

                +

                Public Member Functions

                byte[] GetSecureBytes (uint amount)
                byte [] GetSecureBytes (uint amount)
                 Generates a secure set of bytes More...
                 
                void SetUserPassword (User user, string newPassword, bool newUser)
                @@ -163,13 +141,17 @@ Public Member Functions
                -
                Returns
                if password matches the hash, otherwise
                +
                Returns
                true if password matches the hash, false otherwise

                Implemented in Tgstation.Server.Host.Security.CryptographySuite.

                +

                Referenced by Tgstation.Server.Host.Controllers.HomeController.CreateToken().

                + - + +

                ◆ GetSecureBytes()

                +
                @@ -194,11 +176,13 @@ Public Member Functions

                Implemented in Tgstation.Server.Host.Security.CryptographySuite.

                -

                Referenced by Tgstation.Server.Host.Security.TokenFactory.TokenFactory().

                +

                Referenced by Tgstation.Server.Host.Security.TokenFactory.TokenFactory().

                - + +

                ◆ GetSecureString()

                +
                @@ -216,9 +200,13 @@ Public Member Functions

                Implemented in Tgstation.Server.Host.Security.CryptographySuite.

                +

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

                + - + +

                ◆ SetUserPassword()

                +
                @@ -260,6 +248,8 @@ Public Member Functions

                Implemented in Tgstation.Server.Host.Security.CryptographySuite.

                +

                Referenced by Tgstation.Server.Host.Controllers.UserController.Create(), Tgstation.Server.Host.Models.DatabaseSeeder.ResetAdminPassword(), Tgstation.Server.Host.Models.DatabaseSeeder.SeedAdminUser(), and Tgstation.Server.Host.Controllers.UserController.Update().

                +
                The documentation for this interface was generated from the following file:
                  @@ -270,7 +260,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_identity_cache-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_identity_cache-members.html index 30e1bc2614..0c1ac570a4 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_identity_cache-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_identity_cache-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
                - + - - + + + + - + - - + + + +
                -

                For caching ISystemIdentitys +

                For caching ISystemIdentitys More...

                Inheritance diagram for Tgstation.Server.Host.Security.IIdentityCache:
                @@ -108,8 +84,8 @@ Inheritance diagram for Tgstation.Server.Host.Security.IIdentityCache:
                Tgstation.Server.Host.Security.IdentityCache - -
                + + @@ -117,15 +93,17 @@ Public Member Functions - +

                Public Member Functions

                 Keep a user 's systemIdentity alive until an expiry time More...
                 
                ISystemIdentity LoadCachedIdentity (User user)
                 Attempt to load a cached ISystemIdentity More...
                 Attempt to load a cached ISystemIdentity More...
                 

                Detailed Description

                -

                For caching ISystemIdentitys

                +

                For caching ISystemIdentitys

                -

                Definition at line 9 of file IIdentityCache.cs.

                +

                Definition at line 9 of file IIdentityCache.cs.

                Member Function Documentation

                - + +

                ◆ CacheSystemIdentity()

                +
                @@ -159,7 +137,7 @@ Public Member Functions
                Parameters
                - +
                userThe User the systemIdentity belongs to
                systemIdentityThe ISystemIdentity to cache
                systemIdentityThe ISystemIdentity to cache
                expiryWhen the systemIdentity should expire
                @@ -167,9 +145,13 @@ Public Member Functions

                Implemented in Tgstation.Server.Host.Security.IdentityCache.

                +

                Referenced by Tgstation.Server.Host.Controllers.HomeController.CreateToken().

                +
                - + +

                ◆ LoadCachedIdentity()

                +
                @@ -183,17 +165,19 @@ Public Member Functions
                -

                Attempt to load a cached ISystemIdentity

                +

                Attempt to load a cached ISystemIdentity

                Parameters
                - +
                userThe User the ISystemIdentity belongs to
                userThe User the ISystemIdentity belongs to
                -
                Returns
                The cached ISystemIdentity or if it doesn't exist or expired
                +
                Returns
                The cached ISystemIdentity or null if it doesn't exist or expired

                Implemented in Tgstation.Server.Host.Security.IdentityCache.

                +

                Referenced by Tgstation.Server.Host.Security.AuthenticationContextFactory.CreateAuthenticationContext().

                +

                The documentation for this interface was generated from the following file:
                  @@ -204,7 +188,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_system_identity-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_system_identity-members.html index ebfc216694..fdc2d845e8 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_system_identity-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_system_identity-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
                - + - - + + + + - + - - + + + +
                IDisposable -Tgstation.Server.Host.Security.WindowsSystemIdentity - -
                +Tgstation.Server.Host.Security.WindowsSystemIdentity + + - + - +

                Public Member Functions

                ISystemIdentity Clone ()
                 Clone the ISystemIdentity creating another copy that must have IDisposable.Dispose called on it More...
                 Clone the ISystemIdentity creating another copy that must have IDisposable.Dispose called on it More...
                 
                Task RunImpersonated (Action action, CancellationToken cancellationToken)
                 Runs a given action in the context of the ISystemIdentity More...
                 Runs a given action in the context of the ISystemIdentity More...
                 

                Detailed Description

                Represents a user on the current System.Runtime.InteropServices.OSPlatform

                -

                Definition at line 11 of file ISystemIdentity.cs.

                +

                Definition at line 11 of file ISystemIdentity.cs.

                Member Function Documentation

                - + +

                ◆ Clone()

                +

                @@ -134,9 +110,11 @@ Properties

                @@ -149,16 +127,18 @@ Properties
                -

                Clone the ISystemIdentity creating another copy that must have IDisposable.Dispose called on it

                -
                Returns
                A new ISystemIdentity mirroring the current one
                +

                Clone the ISystemIdentity creating another copy that must have IDisposable.Dispose called on it

                +
                Returns
                A new ISystemIdentity mirroring the current one

                Implemented in Tgstation.Server.Host.Security.WindowsSystemIdentity.

                -

                Referenced by Tgstation.Server.Host.Security.IdentityCache.CacheSystemIdentity().

                +

                Referenced by Tgstation.Server.Host.Security.IdentityCache.CacheSystemIdentity().

                - + +

                ◆ RunImpersonated()

                +
                @@ -182,7 +162,7 @@ Properties
                -

                Runs a given action in the context of the ISystemIdentity

                +

                Runs a given action in the context of the ISystemIdentity

                Parameters
                @@ -194,12 +174,14 @@ Properties

                Implemented in Tgstation.Server.Host.Security.WindowsSystemIdentity.

                -

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

                +

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

                Property Documentation

                - + +

                ◆ Uid

                +
                actionThe Action to perform, should be simple and not use any Tasks or threading
                @@ -219,13 +201,15 @@ Properties

                A unique identifier for the user

                -

                Definition at line 16 of file ISystemIdentity.cs.

                - -

                Referenced by Tgstation.Server.Host.Security.IdentityCache.CacheSystemIdentity(), and Tgstation.Server.Host.Controllers.HomeController.CreateToken().

                +

                Definition at line 16 of file ISystemIdentity.cs.

                +
                16 { get; }
                +

                Referenced by Tgstation.Server.Host.Security.IdentityCache.CacheSystemIdentity(), and Tgstation.Server.Host.Controllers.HomeController.CreateToken().

                - + +

                ◆ Username

                +
                @@ -245,9 +229,9 @@ Properties

                The user's name

                -

                Definition at line 21 of file ISystemIdentity.cs.

                - -

                Referenced by Tgstation.Server.Host.Controllers.HomeController.CreateToken().

                +

                Definition at line 21 of file ISystemIdentity.cs.

                +
                21 { get; }
                +

                Referenced by Tgstation.Server.Host.Controllers.HomeController.CreateToken().

                @@ -259,7 +243,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_system_identity_factory-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_system_identity_factory-members.html index b4bdda2a23..02b0fc78c8 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_system_identity_factory-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_system_identity_factory-members.html @@ -1,9 +1,10 @@ - + - + +tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
                - + - - + + + + - + - - + + + +
                -

                Factory for ISystemIdentitys +

                Factory for ISystemIdentitys More...

                Inheritance diagram for Tgstation.Server.Host.Security.ISystemIdentityFactory:
                @@ -107,26 +83,28 @@ Inheritance diagram for Tgstation.Server.Host.Security.ISystemIdentityFactory: -Tgstation.Server.Host.Security.PosixSystemIdentityFactory +Tgstation.Server.Host.Security.PosixSystemIdentityFactory Tgstation.Server.Host.Security.WindowsSystemIdentityFactory - -
                + +
                - + - +

                Public Member Functions

                Task< ISystemIdentityCreateSystemIdentity (User user, CancellationToken cancellationToken)
                 Create a ISystemIdentity for a given user More...
                 Create a ISystemIdentity for a given user More...
                 
                Task< ISystemIdentityCreateSystemIdentity (string username, string password, CancellationToken cancellationToken)
                 Create a ISystemIdentity for a given username and password More...
                 Create a ISystemIdentity for a given username and password More...
                 

                Detailed Description

                -

                Factory for ISystemIdentitys

                +

                Factory for ISystemIdentitys

                -

                Definition at line 10 of file ISystemIdentityFactory.cs.

                +

                Definition at line 10 of file ISystemIdentityFactory.cs.

                Member Function Documentation

                - + +

                ◆ CreateSystemIdentity() [1/2]

                +
                @@ -150,21 +128,25 @@ Public Member Functions
                -

                Create a ISystemIdentity for a given user

                +

                Create a ISystemIdentity for a given user

                Parameters
                - +
                userThe user to create a ISystemIdentity for
                userThe user to create a ISystemIdentity for
                cancellationTokenThe CancellationToken for the operation
                -
                Returns
                A new ISystemIdentity or if the user has no ISystemIdentity
                +
                Returns
                A new ISystemIdentity or null if the user has no ISystemIdentity

                Implemented in Tgstation.Server.Host.Security.WindowsSystemIdentityFactory, and Tgstation.Server.Host.Security.PosixSystemIdentityFactory.

                +

                Referenced by Tgstation.Server.Host.Controllers.UserController.Create(), and Tgstation.Server.Host.Controllers.HomeController.CreateToken().

                +
                - + +

                ◆ CreateSystemIdentity() [2/2]

                +
                @@ -194,7 +176,7 @@ Public Member Functions
                -

                Create a ISystemIdentity for a given username and password

                +

                Create a ISystemIdentity for a given username and password

                Parameters
                @@ -203,7 +185,7 @@ Public Member Functions
                usernameThe username of the user
                -
                Returns
                A new ISystemIdentity
                +
                Returns
                A new ISystemIdentity

                Implemented in Tgstation.Server.Host.Security.WindowsSystemIdentityFactory, and Tgstation.Server.Host.Security.PosixSystemIdentityFactory.

                @@ -217,7 +199,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_token_factory-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_token_factory-members.html index 97518c45fe..832f7697bb 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_token_factory-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_security_1_1_i_token_factory-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@
                - + - - + + + + - + - - + + + +
                Tgstation.Server.Host.Security.TokenFactory - -
                + +
                @@ -121,15 +97,17 @@ Public Member Functions - +

                Public Member Functions

                Properties

                TokenValidationParameters ValidationParameters [get]
                 The TokenValidationParameters for the ITokenFactory More...
                 The TokenValidationParameters for the ITokenFactory More...
                 

                Detailed Description

                For creating Tokens

                -

                Definition at line 11 of file ITokenFactory.cs.

                +

                Definition at line 11 of file ITokenFactory.cs.

                Member Function Documentation

                - + +

                ◆ CreateToken()

                +
                @@ -156,7 +134,7 @@ Properties

                Create a Token for a given user

                Parameters
                - +
                userThe Models.User to create the token for. Must have the Api.Models.Internal.User.Id field available
                userThe Models.User to create the token for. Must have the Api.Models.Internal.User.Id field available
                cancellationTokenThe CancellationToken for the operation
                @@ -165,10 +143,14 @@ Properties

                Implemented in Tgstation.Server.Host.Security.TokenFactory.

                +

                Referenced by Tgstation.Server.Host.Controllers.HomeController.CreateToken().

                +

                Property Documentation

                - + +

                ◆ ValidationParameters

                +
                @@ -186,11 +168,11 @@ Properties
                -

                The TokenValidationParameters for the ITokenFactory

                +

                The TokenValidationParameters for the ITokenFactory

                -

                Definition at line 16 of file ITokenFactory.cs.

                - -

                Referenced by Tgstation.Server.Host.Core.Application.ConfigureServices().

                +

                Definition at line 16 of file ITokenFactory.cs.

                +
                16 { get; }
                +

                Referenced by Tgstation.Server.Host.Core.Application.ConfigureServices(), and Tgstation.Server.Host.Controllers.HomeController.CreateToken().

                @@ -202,7 +184,7 @@ Properties diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_watchdog_1_1_i_watchdog-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_watchdog_1_1_i_watchdog-members.html index b320ae99e6..6bf546d361 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_watchdog_1_1_i_watchdog-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_watchdog_1_1_i_watchdog-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
                Tgstation.Server.Host.Watchdog.Watchdog - -
                + + - +

                Public Member Functions

                Task RunAsync (bool runConfigure, string[] args, CancellationToken cancellationToken)
                 Run the IWatchdog More...
                 Run the IWatchdog More...
                 

                Detailed Description

                The watchdog for a Host

                -

                Definition at line 9 of file IWatchdog.cs.

                +

                Definition at line 9 of file IWatchdog.cs.

                Member Function Documentation

                - + +

                ◆ RunAsync()

                +
                @@ -135,7 +113,7 @@ Public Member Functions - + @@ -152,11 +130,11 @@ Public Member Functions
                string[] string []  args,
                -

                Run the IWatchdog

                +

                Run the IWatchdog

                Parameters
                - - + +
                runConfigureIf the IWatchdog should just run the host configuration wizard and exit
                argsThe arguments for the IWatchdog
                runConfigureIf the IWatchdog should just run the host configuration wizard and exit
                argsThe arguments for the IWatchdog
                cancellationTokenThe CancellationToken for the operation
                @@ -165,6 +143,8 @@ Public Member Functions

                Implemented in Tgstation.Server.Host.Watchdog.Watchdog.

                +

                Referenced by Tgstation.Server.Host.Console.Program.Main(), Tgstation.Server.Host.Service.Program.OnExecuteAsync(), and Tgstation.Server.Host.Service.ServerService.RunWatchdog().

                +

                The documentation for this interface was generated from the following file:
                  @@ -175,7 +155,7 @@ Public Member Functions diff --git a/interface_tgstation_1_1_server_1_1_host_1_1_watchdog_1_1_i_watchdog_factory-members.html b/interface_tgstation_1_1_server_1_1_host_1_1_watchdog_1_1_i_watchdog_factory-members.html index 72abf938d8..0578db6f5f 100644 --- a/interface_tgstation_1_1_server_1_1_host_1_1_watchdog_1_1_i_watchdog_factory-members.html +++ b/interface_tgstation_1_1_server_1_1_host_1_1_watchdog_1_1_i_watchdog_factory-members.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: Member List @@ -11,9 +12,6 @@ - @@ -33,44 +31,22 @@ - + - - + + + + - + - - + + + +
                  -

                  Factory for creating IWatchdogs +

                  Factory for creating IWatchdogs More...

                  Inheritance diagram for Tgstation.Server.Host.Watchdog.IWatchdogFactory:
                  @@ -108,21 +84,23 @@ Inheritance diagram for Tgstation.Server.Host.Watchdog.IWatchdogFactory:
                  Tgstation.Server.Host.Watchdog.WatchdogFactory - -
                  + + - +

                  Public Member Functions

                  IWatchdog CreateWatchdog (ILoggerFactory loggerFactory)
                   Create a IWatchdog More...
                   Create a IWatchdog More...
                   

                  Detailed Description

                  -

                  Factory for creating IWatchdogs

                  +

                  Factory for creating IWatchdogs

                  -

                  Definition at line 8 of file IWatchdogFactory.cs.

                  +

                  Definition at line 8 of file IWatchdogFactory.cs.

                  Member Function Documentation

                  - + +

                  ◆ CreateWatchdog()

                  +
                  @@ -136,18 +114,18 @@ Public Member Functions
                  -

                  Create a IWatchdog

                  +

                  Create a IWatchdog

                  Parameters
                  loggerFactoryThe ILoggerFactory to use for error reporting
                  -
                  Returns
                  A new IWatchdog
                  +
                  Returns
                  A new IWatchdog

                  Implemented in Tgstation.Server.Host.Watchdog.WatchdogFactory.

                  -

                  Referenced by Tgstation.Server.Host.Service.ServerService.ServerService().

                  +

                  Referenced by Tgstation.Server.Host.Service.ServerService.ServerService().

                  @@ -159,7 +137,7 @@ Public Member Functions diff --git a/jquery.js b/jquery.js index 1f4d0b47ce..1ee895ca32 100644 --- a/jquery.js +++ b/jquery.js @@ -1,5 +1,5 @@ /*! - * jQuery JavaScript Library v1.7.1 + * jQuery JavaScript Library v1.7.2 * http://jquery.com/ * * Copyright 2011, John Resig @@ -11,16 +11,16 @@ * Copyright 2011, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * - * Date: Mon Nov 21 21:11:03 2011 -0500 + * Date: Wed Mar 21 12:46:34 2012 -0700 */ -(function(bb,L){var av=bb.document,bu=bb.navigator,bl=bb.location;var b=(function(){var bF=function(b0,b1){return new bF.fn.init(b0,b1,bD)},bU=bb.jQuery,bH=bb.$,bD,bY=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,bM=/\S/,bI=/^\s+/,bE=/\s+$/,bA=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,bN=/^[\],:{}\s]*$/,bW=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,bP=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,bJ=/(?:^|:|,)(?:\s*\[)+/g,by=/(webkit)[ \/]([\w.]+)/,bR=/(opera)(?:.*version)?[ \/]([\w.]+)/,bQ=/(msie) ([\w.]+)/,bS=/(mozilla)(?:.*? rv:([\w.]+))?/,bB=/-([a-z]|[0-9])/ig,bZ=/^-ms-/,bT=function(b0,b1){return(b1+"").toUpperCase()},bX=bu.userAgent,bV,bC,e,bL=Object.prototype.toString,bG=Object.prototype.hasOwnProperty,bz=Array.prototype.push,bK=Array.prototype.slice,bO=String.prototype.trim,bv=Array.prototype.indexOf,bx={};bF.fn=bF.prototype={constructor:bF,init:function(b0,b4,b3){var b2,b5,b1,b6;if(!b0){return this}if(b0.nodeType){this.context=this[0]=b0;this.length=1;return this}if(b0==="body"&&!b4&&av.body){this.context=av;this[0]=av.body;this.selector=b0;this.length=1;return this}if(typeof b0==="string"){if(b0.charAt(0)==="<"&&b0.charAt(b0.length-1)===">"&&b0.length>=3){b2=[null,b0,null]}else{b2=bY.exec(b0)}if(b2&&(b2[1]||!b4)){if(b2[1]){b4=b4 instanceof bF?b4[0]:b4;b6=(b4?b4.ownerDocument||b4:av);b1=bA.exec(b0);if(b1){if(bF.isPlainObject(b4)){b0=[av.createElement(b1[1])];bF.fn.attr.call(b0,b4,true)}else{b0=[b6.createElement(b1[1])]}}else{b1=bF.buildFragment([b2[1]],[b6]);b0=(b1.cacheable?bF.clone(b1.fragment):b1.fragment).childNodes}return bF.merge(this,b0)}else{b5=av.getElementById(b2[2]);if(b5&&b5.parentNode){if(b5.id!==b2[2]){return b3.find(b0)}this.length=1;this[0]=b5}this.context=av;this.selector=b0;return this}}else{if(!b4||b4.jquery){return(b4||b3).find(b0)}else{return this.constructor(b4).find(b0)}}}else{if(bF.isFunction(b0)){return b3.ready(b0)}}if(b0.selector!==L){this.selector=b0.selector;this.context=b0.context}return bF.makeArray(b0,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return bK.call(this,0)},get:function(b0){return b0==null?this.toArray():(b0<0?this[this.length+b0]:this[b0])},pushStack:function(b1,b3,b0){var b2=this.constructor();if(bF.isArray(b1)){bz.apply(b2,b1)}else{bF.merge(b2,b1)}b2.prevObject=this;b2.context=this.context;if(b3==="find"){b2.selector=this.selector+(this.selector?" ":"")+b0}else{if(b3){b2.selector=this.selector+"."+b3+"("+b0+")"}}return b2},each:function(b1,b0){return bF.each(this,b1,b0)},ready:function(b0){bF.bindReady();bC.add(b0);return this},eq:function(b0){b0=+b0;return b0===-1?this.slice(b0):this.slice(b0,b0+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(bK.apply(this,arguments),"slice",bK.call(arguments).join(","))},map:function(b0){return this.pushStack(bF.map(this,function(b2,b1){return b0.call(b2,b1,b2)}))},end:function(){return this.prevObject||this.constructor(null)},push:bz,sort:[].sort,splice:[].splice};bF.fn.init.prototype=bF.fn;bF.extend=bF.fn.extend=function(){var b9,b2,b0,b1,b6,b7,b5=arguments[0]||{},b4=1,b3=arguments.length,b8=false;if(typeof b5==="boolean"){b8=b5;b5=arguments[1]||{};b4=2}if(typeof b5!=="object"&&!bF.isFunction(b5)){b5={}}if(b3===b4){b5=this;--b4}for(;b40){return}bC.fireWith(av,[bF]);if(bF.fn.trigger){bF(av).trigger("ready").off("ready")}}},bindReady:function(){if(bC){return}bC=bF.Callbacks("once memory");if(av.readyState==="complete"){return setTimeout(bF.ready,1)}if(av.addEventListener){av.addEventListener("DOMContentLoaded",e,false);bb.addEventListener("load",bF.ready,false)}else{if(av.attachEvent){av.attachEvent("onreadystatechange",e);bb.attachEvent("onload",bF.ready);var b0=false;try{b0=bb.frameElement==null}catch(b1){}if(av.documentElement.doScroll&&b0){bw()}}}},isFunction:function(b0){return bF.type(b0)==="function"},isArray:Array.isArray||function(b0){return bF.type(b0)==="array"},isWindow:function(b0){return b0&&typeof b0==="object"&&"setInterval" in b0},isNumeric:function(b0){return !isNaN(parseFloat(b0))&&isFinite(b0)},type:function(b0){return b0==null?String(b0):bx[bL.call(b0)]||"object"},isPlainObject:function(b2){if(!b2||bF.type(b2)!=="object"||b2.nodeType||bF.isWindow(b2)){return false}try{if(b2.constructor&&!bG.call(b2,"constructor")&&!bG.call(b2.constructor.prototype,"isPrototypeOf")){return false}}catch(b1){return false}var b0;for(b0 in b2){}return b0===L||bG.call(b2,b0)},isEmptyObject:function(b1){for(var b0 in b1){return false}return true},error:function(b0){throw new Error(b0)},parseJSON:function(b0){if(typeof b0!=="string"||!b0){return null}b0=bF.trim(b0);if(bb.JSON&&bb.JSON.parse){return bb.JSON.parse(b0)}if(bN.test(b0.replace(bW,"@").replace(bP,"]").replace(bJ,""))){return(new Function("return "+b0))()}bF.error("Invalid JSON: "+b0)},parseXML:function(b2){var b0,b1;try{if(bb.DOMParser){b1=new DOMParser();b0=b1.parseFromString(b2,"text/xml")}else{b0=new ActiveXObject("Microsoft.XMLDOM");b0.async="false";b0.loadXML(b2)}}catch(b3){b0=L}if(!b0||!b0.documentElement||b0.getElementsByTagName("parsererror").length){bF.error("Invalid XML: "+b2)}return b0},noop:function(){},globalEval:function(b0){if(b0&&bM.test(b0)){(bb.execScript||function(b1){bb["eval"].call(bb,b1)})(b0)}},camelCase:function(b0){return b0.replace(bZ,"ms-").replace(bB,bT)},nodeName:function(b1,b0){return b1.nodeName&&b1.nodeName.toUpperCase()===b0.toUpperCase()},each:function(b3,b6,b2){var b1,b4=0,b5=b3.length,b0=b5===L||bF.isFunction(b3);if(b2){if(b0){for(b1 in b3){if(b6.apply(b3[b1],b2)===false){break}}}else{for(;b40&&b0[0]&&b0[b1-1])||b1===0||bF.isArray(b0));if(b3){for(;b21?aJ.call(arguments,0):bG;if(!(--bw)){bC.resolveWith(bC,bx)}}}function bz(bF){return function(bG){bB[bF]=arguments.length>1?aJ.call(arguments,0):bG;bC.notifyWith(bE,bB)}}if(e>1){for(;bv
                  a";bI=bv.getElementsByTagName("*");bF=bv.getElementsByTagName("a")[0];if(!bI||!bI.length||!bF){return{}}bG=av.createElement("select");bx=bG.appendChild(av.createElement("option"));bE=bv.getElementsByTagName("input")[0];bJ={leadingWhitespace:(bv.firstChild.nodeType===3),tbody:!bv.getElementsByTagName("tbody").length,htmlSerialize:!!bv.getElementsByTagName("link").length,style:/top/.test(bF.getAttribute("style")),hrefNormalized:(bF.getAttribute("href")==="/a"),opacity:/^0.55/.test(bF.style.opacity),cssFloat:!!bF.style.cssFloat,checkOn:(bE.value==="on"),optSelected:bx.selected,getSetAttribute:bv.className!=="t",enctype:!!av.createElement("form").enctype,html5Clone:av.createElement("nav").cloneNode(true).outerHTML!=="<:nav>",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true};bE.checked=true;bJ.noCloneChecked=bE.cloneNode(true).checked;bG.disabled=true;bJ.optDisabled=!bx.disabled;try{delete bv.test}catch(bC){bJ.deleteExpando=false}if(!bv.addEventListener&&bv.attachEvent&&bv.fireEvent){bv.attachEvent("onclick",function(){bJ.noCloneEvent=false});bv.cloneNode(true).fireEvent("onclick")}bE=av.createElement("input");bE.value="t";bE.setAttribute("type","radio");bJ.radioValue=bE.value==="t";bE.setAttribute("checked","checked");bv.appendChild(bE);bD=av.createDocumentFragment();bD.appendChild(bv.lastChild);bJ.checkClone=bD.cloneNode(true).cloneNode(true).lastChild.checked;bJ.appendChecked=bE.checked;bD.removeChild(bE);bD.appendChild(bv);bv.innerHTML="";if(bb.getComputedStyle){bA=av.createElement("div");bA.style.width="0";bA.style.marginRight="0";bv.style.width="2px";bv.appendChild(bA);bJ.reliableMarginRight=(parseInt((bb.getComputedStyle(bA,null)||{marginRight:0}).marginRight,10)||0)===0}if(bv.attachEvent){for(by in {submit:1,change:1,focusin:1}){bB="on"+by;bw=(bB in bv);if(!bw){bv.setAttribute(bB,"return;");bw=(typeof bv[bB]==="function")}bJ[by+"Bubbles"]=bw}}bD.removeChild(bv);bD=bG=bx=bA=bv=bE=null;b(function(){var bM,bU,bV,bT,bN,bO,bL,bS,bR,e,bP,bQ=av.getElementsByTagName("body")[0];if(!bQ){return}bL=1;bS="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";bR="visibility:hidden;border:0;";e="style='"+bS+"border:5px solid #000;padding:0;'";bP="
                  ";bM=av.createElement("div");bM.style.cssText=bR+"width:0;height:0;position:static;top:0;margin-top:"+bL+"px";bQ.insertBefore(bM,bQ.firstChild);bv=av.createElement("div");bM.appendChild(bv);bv.innerHTML="
                  t
                  ";bz=bv.getElementsByTagName("td");bw=(bz[0].offsetHeight===0);bz[0].style.display="";bz[1].style.display="none";bJ.reliableHiddenOffsets=bw&&(bz[0].offsetHeight===0);bv.innerHTML="";bv.style.width=bv.style.paddingLeft="1px";b.boxModel=bJ.boxModel=bv.offsetWidth===2;if(typeof bv.style.zoom!=="undefined"){bv.style.display="inline";bv.style.zoom=1;bJ.inlineBlockNeedsLayout=(bv.offsetWidth===2);bv.style.display="";bv.innerHTML="
                  ";bJ.shrinkWrapBlocks=(bv.offsetWidth!==2)}bv.style.cssText=bS+bR;bv.innerHTML=bP;bU=bv.firstChild;bV=bU.firstChild;bN=bU.nextSibling.firstChild.firstChild;bO={doesNotAddBorder:(bV.offsetTop!==5),doesAddBorderForTableAndCells:(bN.offsetTop===5)};bV.style.position="fixed";bV.style.top="20px";bO.fixedPosition=(bV.offsetTop===20||bV.offsetTop===15);bV.style.position=bV.style.top="";bU.style.overflow="hidden";bU.style.position="relative";bO.subtractsBorderForOverflowNotVisible=(bV.offsetTop===-5);bO.doesNotIncludeMarginInBodyOffset=(bQ.offsetTop!==bL);bQ.removeChild(bM);bv=bM=null;b.extend(bJ,bO)});return bJ})();var aS=/^(?:\{.*\}|\[.*\])$/,aA=/([A-Z])/g;b.extend({cache:{},uuid:0,expando:"jQuery"+(b.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?b.cache[e[b.expando]]:e[b.expando];return !!e&&!S(e)},data:function(bx,bv,bz,by){if(!b.acceptData(bx)){return}var bG,bA,bD,bE=b.expando,bC=typeof bv==="string",bF=bx.nodeType,e=bF?b.cache:bx,bw=bF?bx[bE]:bx[bE]&&bE,bB=bv==="events";if((!bw||!e[bw]||(!bB&&!by&&!e[bw].data))&&bC&&bz===L){return}if(!bw){if(bF){bx[bE]=bw=++b.uuid}else{bw=bE}}if(!e[bw]){e[bw]={};if(!bF){e[bw].toJSON=b.noop}}if(typeof bv==="object"||typeof bv==="function"){if(by){e[bw]=b.extend(e[bw],bv)}else{e[bw].data=b.extend(e[bw].data,bv)}}bG=bA=e[bw];if(!by){if(!bA.data){bA.data={}}bA=bA.data}if(bz!==L){bA[b.camelCase(bv)]=bz}if(bB&&!bA[bv]){return bG.events}if(bC){bD=bA[bv];if(bD==null){bD=bA[b.camelCase(bv)]}}else{bD=bA}return bD},removeData:function(bx,bv,by){if(!b.acceptData(bx)){return}var bB,bA,bz,bC=b.expando,bD=bx.nodeType,e=bD?b.cache:bx,bw=bD?bx[bC]:bC;if(!e[bw]){return}if(bv){bB=by?e[bw]:e[bw].data;if(bB){if(!b.isArray(bv)){if(bv in bB){bv=[bv]}else{bv=b.camelCase(bv);if(bv in bB){bv=[bv]}else{bv=bv.split(" ")}}}for(bA=0,bz=bv.length;bA-1){return true}}return false},val:function(bx){var e,bv,by,bw=this[0];if(!arguments.length){if(bw){e=b.valHooks[bw.nodeName.toLowerCase()]||b.valHooks[bw.type];if(e&&"get" in e&&(bv=e.get(bw,"value"))!==L){return bv}bv=bw.value;return typeof bv==="string"?bv.replace(aU,""):bv==null?"":bv}return}by=b.isFunction(bx);return this.each(function(bA){var bz=b(this),bB;if(this.nodeType!==1){return}if(by){bB=bx.call(this,bA,bz.val())}else{bB=bx}if(bB==null){bB=""}else{if(typeof bB==="number"){bB+=""}else{if(b.isArray(bB)){bB=b.map(bB,function(bC){return bC==null?"":bC+""})}}}e=b.valHooks[this.nodeName.toLowerCase()]||b.valHooks[this.type];if(!e||!("set" in e)||e.set(this,bB,"value")===L){this.value=bB}})}});b.extend({valHooks:{option:{get:function(e){var bv=e.attributes.value;return !bv||bv.specified?e.value:e.text}},select:{get:function(e){var bA,bv,bz,bx,by=e.selectedIndex,bB=[],bC=e.options,bw=e.type==="select-one";if(by<0){return null}bv=bw?by:0;bz=bw?by+1:bC.length;for(;bv=0});if(!e.length){bv.selectedIndex=-1}return e}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(bA,bx,bB,bz){var bw,e,by,bv=bA.nodeType;if(!bA||bv===3||bv===8||bv===2){return}if(bz&&bx in b.attrFn){return b(bA)[bx](bB)}if(typeof bA.getAttribute==="undefined"){return b.prop(bA,bx,bB)}by=bv!==1||!b.isXMLDoc(bA);if(by){bx=bx.toLowerCase();e=b.attrHooks[bx]||(ao.test(bx)?aY:be)}if(bB!==L){if(bB===null){b.removeAttr(bA,bx);return}else{if(e&&"set" in e&&by&&(bw=e.set(bA,bB,bx))!==L){return bw}else{bA.setAttribute(bx,""+bB);return bB}}}else{if(e&&"get" in e&&by&&(bw=e.get(bA,bx))!==null){return bw}else{bw=bA.getAttribute(bx);return bw===null?L:bw}}},removeAttr:function(bx,bz){var by,bA,bv,e,bw=0;if(bz&&bx.nodeType===1){bA=bz.toLowerCase().split(af);e=bA.length;for(;bw=0)}}})});var bd=/^(?:textarea|input|select)$/i,n=/^([^\.]*)?(?:\.(.+))?$/,J=/\bhover(\.\S+)?\b/,aO=/^key/,bf=/^(?:mouse|contextmenu)|click/,T=/^(?:focusinfocus|focusoutblur)$/,U=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,Y=function(e){var bv=U.exec(e);if(bv){bv[1]=(bv[1]||"").toLowerCase();bv[3]=bv[3]&&new RegExp("(?:^|\\s)"+bv[3]+"(?:\\s|$)")}return bv},j=function(bw,e){var bv=bw.attributes||{};return((!e[1]||bw.nodeName.toLowerCase()===e[1])&&(!e[2]||(bv.id||{}).value===e[2])&&(!e[3]||e[3].test((bv["class"]||{}).value)))},bt=function(e){return b.event.special.hover?e:e.replace(J,"mouseenter$1 mouseleave$1")};b.event={add:function(bx,bC,bJ,bA,by){var bD,bB,bK,bI,bH,bF,e,bG,bv,bz,bw,bE;if(bx.nodeType===3||bx.nodeType===8||!bC||!bJ||!(bD=b._data(bx))){return}if(bJ.handler){bv=bJ;bJ=bv.handler}if(!bJ.guid){bJ.guid=b.guid++}bK=bD.events;if(!bK){bD.events=bK={}}bB=bD.handle;if(!bB){bD.handle=bB=function(bL){return typeof b!=="undefined"&&(!bL||b.event.triggered!==bL.type)?b.event.dispatch.apply(bB.elem,arguments):L};bB.elem=bx}bC=b.trim(bt(bC)).split(" ");for(bI=0;bI=0){bG=bG.slice(0,-1);bw=true}if(bG.indexOf(".")>=0){bx=bG.split(".");bG=bx.shift();bx.sort()}if((!bA||b.event.customEvent[bG])&&!b.event.global[bG]){return}bv=typeof bv==="object"?bv[b.expando]?bv:new b.Event(bG,bv):new b.Event(bG);bv.type=bG;bv.isTrigger=true;bv.exclusive=bw;bv.namespace=bx.join(".");bv.namespace_re=bv.namespace?new RegExp("(^|\\.)"+bx.join("\\.(?:.*\\.)?")+"(\\.|$)"):null;by=bG.indexOf(":")<0?"on"+bG:"";if(!bA){e=b.cache;for(bC in e){if(e[bC].events&&e[bC].events[bG]){b.event.trigger(bv,bD,e[bC].handle.elem,true)}}return}bv.result=L;if(!bv.target){bv.target=bA}bD=bD!=null?b.makeArray(bD):[];bD.unshift(bv);bF=b.event.special[bG]||{};if(bF.trigger&&bF.trigger.apply(bA,bD)===false){return}bB=[[bA,bF.bindType||bG]];if(!bJ&&!bF.noBubble&&!b.isWindow(bA)){bI=bF.delegateType||bG;bH=T.test(bI+bG)?bA:bA.parentNode;bz=null;for(;bH;bH=bH.parentNode){bB.push([bH,bI]);bz=bH}if(bz&&bz===bA.ownerDocument){bB.push([bz.defaultView||bz.parentWindow||bb,bI])}}for(bC=0;bCbA){bH.push({elem:this,matches:bz.slice(bA)})}for(bC=0;bC0?this.on(e,null,bx,bw):this.trigger(e)};if(b.attrFn){b.attrFn[e]=true}if(aO.test(e)){b.event.fixHooks[e]=b.event.keyHooks}if(bf.test(e)){b.event.fixHooks[e]=b.event.mouseHooks}}); +(function(bd,L){var av=bd.document,bu=bd.navigator,bm=bd.location;var b=(function(){var bF=function(b0,b1){return new bF.fn.init(b0,b1,bD)},bU=bd.jQuery,bH=bd.$,bD,bY=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,bM=/\S/,bI=/^\s+/,bE=/\s+$/,bA=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,bN=/^[\],:{}\s]*$/,bW=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,bP=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,bJ=/(?:^|:|,)(?:\s*\[)+/g,by=/(webkit)[ \/]([\w.]+)/,bR=/(opera)(?:.*version)?[ \/]([\w.]+)/,bQ=/(msie) ([\w.]+)/,bS=/(mozilla)(?:.*? rv:([\w.]+))?/,bB=/-([a-z]|[0-9])/ig,bZ=/^-ms-/,bT=function(b0,b1){return(b1+"").toUpperCase()},bX=bu.userAgent,bV,bC,e,bL=Object.prototype.toString,bG=Object.prototype.hasOwnProperty,bz=Array.prototype.push,bK=Array.prototype.slice,bO=String.prototype.trim,bv=Array.prototype.indexOf,bx={};bF.fn=bF.prototype={constructor:bF,init:function(b0,b4,b3){var b2,b5,b1,b6;if(!b0){return this}if(b0.nodeType){this.context=this[0]=b0;this.length=1;return this}if(b0==="body"&&!b4&&av.body){this.context=av;this[0]=av.body;this.selector=b0;this.length=1;return this}if(typeof b0==="string"){if(b0.charAt(0)==="<"&&b0.charAt(b0.length-1)===">"&&b0.length>=3){b2=[null,b0,null]}else{b2=bY.exec(b0)}if(b2&&(b2[1]||!b4)){if(b2[1]){b4=b4 instanceof bF?b4[0]:b4;b6=(b4?b4.ownerDocument||b4:av);b1=bA.exec(b0);if(b1){if(bF.isPlainObject(b4)){b0=[av.createElement(b1[1])];bF.fn.attr.call(b0,b4,true)}else{b0=[b6.createElement(b1[1])]}}else{b1=bF.buildFragment([b2[1]],[b6]);b0=(b1.cacheable?bF.clone(b1.fragment):b1.fragment).childNodes}return bF.merge(this,b0)}else{b5=av.getElementById(b2[2]);if(b5&&b5.parentNode){if(b5.id!==b2[2]){return b3.find(b0)}this.length=1;this[0]=b5}this.context=av;this.selector=b0;return this}}else{if(!b4||b4.jquery){return(b4||b3).find(b0)}else{return this.constructor(b4).find(b0)}}}else{if(bF.isFunction(b0)){return b3.ready(b0)}}if(b0.selector!==L){this.selector=b0.selector;this.context=b0.context}return bF.makeArray(b0,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return bK.call(this,0)},get:function(b0){return b0==null?this.toArray():(b0<0?this[this.length+b0]:this[b0])},pushStack:function(b1,b3,b0){var b2=this.constructor();if(bF.isArray(b1)){bz.apply(b2,b1)}else{bF.merge(b2,b1)}b2.prevObject=this;b2.context=this.context;if(b3==="find"){b2.selector=this.selector+(this.selector?" ":"")+b0}else{if(b3){b2.selector=this.selector+"."+b3+"("+b0+")"}}return b2},each:function(b1,b0){return bF.each(this,b1,b0)},ready:function(b0){bF.bindReady();bC.add(b0);return this},eq:function(b0){b0=+b0;return b0===-1?this.slice(b0):this.slice(b0,b0+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(bK.apply(this,arguments),"slice",bK.call(arguments).join(","))},map:function(b0){return this.pushStack(bF.map(this,function(b2,b1){return b0.call(b2,b1,b2)}))},end:function(){return this.prevObject||this.constructor(null)},push:bz,sort:[].sort,splice:[].splice};bF.fn.init.prototype=bF.fn;bF.extend=bF.fn.extend=function(){var b9,b2,b0,b1,b6,b7,b5=arguments[0]||{},b4=1,b3=arguments.length,b8=false;if(typeof b5==="boolean"){b8=b5;b5=arguments[1]||{};b4=2}if(typeof b5!=="object"&&!bF.isFunction(b5)){b5={}}if(b3===b4){b5=this;--b4}for(;b40){return}bC.fireWith(av,[bF]);if(bF.fn.trigger){bF(av).trigger("ready").off("ready")}}},bindReady:function(){if(bC){return}bC=bF.Callbacks("once memory");if(av.readyState==="complete"){return setTimeout(bF.ready,1)}if(av.addEventListener){av.addEventListener("DOMContentLoaded",e,false);bd.addEventListener("load",bF.ready,false)}else{if(av.attachEvent){av.attachEvent("onreadystatechange",e);bd.attachEvent("onload",bF.ready);var b0=false;try{b0=bd.frameElement==null}catch(b1){}if(av.documentElement.doScroll&&b0){bw()}}}},isFunction:function(b0){return bF.type(b0)==="function"},isArray:Array.isArray||function(b0){return bF.type(b0)==="array"},isWindow:function(b0){return b0!=null&&b0==b0.window},isNumeric:function(b0){return !isNaN(parseFloat(b0))&&isFinite(b0)},type:function(b0){return b0==null?String(b0):bx[bL.call(b0)]||"object"},isPlainObject:function(b2){if(!b2||bF.type(b2)!=="object"||b2.nodeType||bF.isWindow(b2)){return false}try{if(b2.constructor&&!bG.call(b2,"constructor")&&!bG.call(b2.constructor.prototype,"isPrototypeOf")){return false}}catch(b1){return false}var b0;for(b0 in b2){}return b0===L||bG.call(b2,b0)},isEmptyObject:function(b1){for(var b0 in b1){return false}return true},error:function(b0){throw new Error(b0)},parseJSON:function(b0){if(typeof b0!=="string"||!b0){return null}b0=bF.trim(b0);if(bd.JSON&&bd.JSON.parse){return bd.JSON.parse(b0)}if(bN.test(b0.replace(bW,"@").replace(bP,"]").replace(bJ,""))){return(new Function("return "+b0))()}bF.error("Invalid JSON: "+b0)},parseXML:function(b2){if(typeof b2!=="string"||!b2){return null}var b0,b1;try{if(bd.DOMParser){b1=new DOMParser();b0=b1.parseFromString(b2,"text/xml")}else{b0=new ActiveXObject("Microsoft.XMLDOM");b0.async="false";b0.loadXML(b2)}}catch(b3){b0=L}if(!b0||!b0.documentElement||b0.getElementsByTagName("parsererror").length){bF.error("Invalid XML: "+b2)}return b0},noop:function(){},globalEval:function(b0){if(b0&&bM.test(b0)){(bd.execScript||function(b1){bd["eval"].call(bd,b1)})(b0)}},camelCase:function(b0){return b0.replace(bZ,"ms-").replace(bB,bT)},nodeName:function(b1,b0){return b1.nodeName&&b1.nodeName.toUpperCase()===b0.toUpperCase()},each:function(b3,b6,b2){var b1,b4=0,b5=b3.length,b0=b5===L||bF.isFunction(b3);if(b2){if(b0){for(b1 in b3){if(b6.apply(b3[b1],b2)===false){break}}}else{for(;b40&&b0[0]&&b0[b1-1])||b1===0||bF.isArray(b0));if(b3){for(;b21?aK.call(arguments,0):bG;if(!(--bw)){bC.resolveWith(bC,bx)}}}function bz(bF){return function(bG){bB[bF]=arguments.length>1?aK.call(arguments,0):bG;bC.notifyWith(bE,bB)}}if(e>1){for(;bv
                  a";bH=bv.getElementsByTagName("*");bE=bv.getElementsByTagName("a")[0];if(!bH||!bH.length||!bE){return{}}bF=av.createElement("select");bx=bF.appendChild(av.createElement("option"));bD=bv.getElementsByTagName("input")[0];bI={leadingWhitespace:(bv.firstChild.nodeType===3),tbody:!bv.getElementsByTagName("tbody").length,htmlSerialize:!!bv.getElementsByTagName("link").length,style:/top/.test(bE.getAttribute("style")),hrefNormalized:(bE.getAttribute("href")==="/a"),opacity:/^0.55/.test(bE.style.opacity),cssFloat:!!bE.style.cssFloat,checkOn:(bD.value==="on"),optSelected:bx.selected,getSetAttribute:bv.className!=="t",enctype:!!av.createElement("form").enctype,html5Clone:av.createElement("nav").cloneNode(true).outerHTML!=="<:nav>",submitBubbles:true,changeBubbles:true,focusinBubbles:false,deleteExpando:true,noCloneEvent:true,inlineBlockNeedsLayout:false,shrinkWrapBlocks:false,reliableMarginRight:true,pixelMargin:true};b.boxModel=bI.boxModel=(av.compatMode==="CSS1Compat");bD.checked=true;bI.noCloneChecked=bD.cloneNode(true).checked;bF.disabled=true;bI.optDisabled=!bx.disabled;try{delete bv.test}catch(bB){bI.deleteExpando=false}if(!bv.addEventListener&&bv.attachEvent&&bv.fireEvent){bv.attachEvent("onclick",function(){bI.noCloneEvent=false});bv.cloneNode(true).fireEvent("onclick")}bD=av.createElement("input");bD.value="t";bD.setAttribute("type","radio");bI.radioValue=bD.value==="t";bD.setAttribute("checked","checked");bD.setAttribute("name","t");bv.appendChild(bD);bC=av.createDocumentFragment();bC.appendChild(bv.lastChild);bI.checkClone=bC.cloneNode(true).cloneNode(true).lastChild.checked;bI.appendChecked=bD.checked;bC.removeChild(bD);bC.appendChild(bv);if(bv.attachEvent){for(by in {submit:1,change:1,focusin:1}){bA="on"+by;bw=(bA in bv);if(!bw){bv.setAttribute(bA,"return;");bw=(typeof bv[bA]==="function")}bI[by+"Bubbles"]=bw}}bC.removeChild(bv);bC=bF=bx=bv=bD=null;b(function(){var bM,bV,bW,bU,bO,bP,bR,bL,bK,bQ,bN,e,bT,bS=av.getElementsByTagName("body")[0];if(!bS){return}bL=1;bT="padding:0;margin:0;border:";bN="position:absolute;top:0;left:0;width:1px;height:1px;";e=bT+"0;visibility:hidden;";bK="style='"+bN+bT+"5px solid #000;";bQ="
                  ";bM=av.createElement("div");bM.style.cssText=e+"width:0;height:0;position:static;top:0;margin-top:"+bL+"px";bS.insertBefore(bM,bS.firstChild);bv=av.createElement("div");bM.appendChild(bv);bv.innerHTML="
                  t
                  ";bz=bv.getElementsByTagName("td");bw=(bz[0].offsetHeight===0);bz[0].style.display="";bz[1].style.display="none";bI.reliableHiddenOffsets=bw&&(bz[0].offsetHeight===0);if(bd.getComputedStyle){bv.innerHTML="";bR=av.createElement("div");bR.style.width="0";bR.style.marginRight="0";bv.style.width="2px";bv.appendChild(bR);bI.reliableMarginRight=(parseInt((bd.getComputedStyle(bR,null)||{marginRight:0}).marginRight,10)||0)===0}if(typeof bv.style.zoom!=="undefined"){bv.innerHTML="";bv.style.width=bv.style.padding="1px";bv.style.border=0;bv.style.overflow="hidden";bv.style.display="inline";bv.style.zoom=1;bI.inlineBlockNeedsLayout=(bv.offsetWidth===3);bv.style.display="block";bv.style.overflow="visible";bv.innerHTML="
                  ";bI.shrinkWrapBlocks=(bv.offsetWidth!==3)}bv.style.cssText=bN+e;bv.innerHTML=bQ;bV=bv.firstChild;bW=bV.firstChild;bO=bV.nextSibling.firstChild.firstChild;bP={doesNotAddBorder:(bW.offsetTop!==5),doesAddBorderForTableAndCells:(bO.offsetTop===5)};bW.style.position="fixed";bW.style.top="20px";bP.fixedPosition=(bW.offsetTop===20||bW.offsetTop===15);bW.style.position=bW.style.top="";bV.style.overflow="hidden";bV.style.position="relative";bP.subtractsBorderForOverflowNotVisible=(bW.offsetTop===-5);bP.doesNotIncludeMarginInBodyOffset=(bS.offsetTop!==bL);if(bd.getComputedStyle){bv.style.marginTop="1%";bI.pixelMargin=(bd.getComputedStyle(bv,null)||{marginTop:0}).marginTop!=="1%"}if(typeof bM.style.zoom!=="undefined"){bM.style.zoom=1}bS.removeChild(bM);bR=bv=bM=null;b.extend(bI,bP)});return bI})();var aT=/^(?:\{.*\}|\[.*\])$/,aA=/([A-Z])/g;b.extend({cache:{},uuid:0,expando:"jQuery"+(b.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:true,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:true},hasData:function(e){e=e.nodeType?b.cache[e[b.expando]]:e[b.expando];return !!e&&!S(e)},data:function(bx,bv,bz,by){if(!b.acceptData(bx)){return}var bG,bA,bD,bE=b.expando,bC=typeof bv==="string",bF=bx.nodeType,e=bF?b.cache:bx,bw=bF?bx[bE]:bx[bE]&&bE,bB=bv==="events";if((!bw||!e[bw]||(!bB&&!by&&!e[bw].data))&&bC&&bz===L){return}if(!bw){if(bF){bx[bE]=bw=++b.uuid}else{bw=bE}}if(!e[bw]){e[bw]={};if(!bF){e[bw].toJSON=b.noop}}if(typeof bv==="object"||typeof bv==="function"){if(by){e[bw]=b.extend(e[bw],bv)}else{e[bw].data=b.extend(e[bw].data,bv)}}bG=bA=e[bw];if(!by){if(!bA.data){bA.data={}}bA=bA.data}if(bz!==L){bA[b.camelCase(bv)]=bz}if(bB&&!bA[bv]){return bG.events}if(bC){bD=bA[bv];if(bD==null){bD=bA[b.camelCase(bv)]}}else{bD=bA}return bD},removeData:function(bx,bv,by){if(!b.acceptData(bx)){return}var bB,bA,bz,bC=b.expando,bD=bx.nodeType,e=bD?b.cache:bx,bw=bD?bx[bC]:bC;if(!e[bw]){return}if(bv){bB=by?e[bw]:e[bw].data;if(bB){if(!b.isArray(bv)){if(bv in bB){bv=[bv]}else{bv=b.camelCase(bv);if(bv in bB){bv=[bv]}else{bv=bv.split(" ")}}}for(bA=0,bz=bv.length;bA1,null,false)},removeData:function(e){return this.each(function(){b.removeData(this,e)})}});function a6(bx,bw,by){if(by===L&&bx.nodeType===1){var bv="data-"+bw.replace(aA,"-$1").toLowerCase();by=bx.getAttribute(bv);if(typeof by==="string"){try{by=by==="true"?true:by==="false"?false:by==="null"?null:b.isNumeric(by)?+by:aT.test(by)?b.parseJSON(by):by}catch(bz){}b.data(bx,bw,by)}else{by=L}}return by}function S(bv){for(var e in bv){if(e==="data"&&b.isEmptyObject(bv[e])){continue}if(e!=="toJSON"){return false}}return true}function bj(by,bx,bA){var bw=bx+"defer",bv=bx+"queue",e=bx+"mark",bz=b._data(by,bw);if(bz&&(bA==="queue"||!b._data(by,bv))&&(bA==="mark"||!b._data(by,e))){setTimeout(function(){if(!b._data(by,bv)&&!b._data(by,e)){b.removeData(by,bw,true);bz.fire()}},0)}}b.extend({_mark:function(bv,e){if(bv){e=(e||"fx")+"mark";b._data(bv,e,(b._data(bv,e)||0)+1)}},_unmark:function(by,bx,bv){if(by!==true){bv=bx;bx=by;by=false}if(bx){bv=bv||"fx";var e=bv+"mark",bw=by?0:((b._data(bx,e)||1)-1);if(bw){b._data(bx,e,bw)}else{b.removeData(bx,e,true);bj(bx,bv,"mark")}}},queue:function(bv,e,bx){var bw;if(bv){e=(e||"fx")+"queue";bw=b._data(bv,e);if(bx){if(!bw||b.isArray(bx)){bw=b._data(bv,e,b.makeArray(bx))}else{bw.push(bx)}}return bw||[]}},dequeue:function(by,bx){bx=bx||"fx";var bv=b.queue(by,bx),bw=bv.shift(),e={};if(bw==="inprogress"){bw=bv.shift()}if(bw){if(bx==="fx"){bv.unshift("inprogress")}b._data(by,bx+".run",e);bw.call(by,function(){b.dequeue(by,bx)},e)}if(!bv.length){b.removeData(by,bx+"queue "+bx+".run",true);bj(by,bx,"queue")}}});b.fn.extend({queue:function(e,bv){var bw=2;if(typeof e!=="string"){bv=e;e="fx";bw--}if(arguments.length1)},removeAttr:function(e){return this.each(function(){b.removeAttr(this,e)})},prop:function(e,bv){return b.access(this,b.prop,e,bv,arguments.length>1)},removeProp:function(e){e=b.propFix[e]||e;return this.each(function(){try{this[e]=L;delete this[e]}catch(bv){}})},addClass:function(by){var bA,bw,bv,bx,bz,bB,e;if(b.isFunction(by)){return this.each(function(bC){b(this).addClass(by.call(this,bC,this.className))})}if(by&&typeof by==="string"){bA=by.split(ag);for(bw=0,bv=this.length;bw-1){return true}}return false},val:function(bx){var e,bv,by,bw=this[0];if(!arguments.length){if(bw){e=b.valHooks[bw.type]||b.valHooks[bw.nodeName.toLowerCase()];if(e&&"get" in e&&(bv=e.get(bw,"value"))!==L){return bv}bv=bw.value;return typeof bv==="string"?bv.replace(aV,""):bv==null?"":bv}return}by=b.isFunction(bx);return this.each(function(bA){var bz=b(this),bB;if(this.nodeType!==1){return}if(by){bB=bx.call(this,bA,bz.val())}else{bB=bx}if(bB==null){bB=""}else{if(typeof bB==="number"){bB+=""}else{if(b.isArray(bB)){bB=b.map(bB,function(bC){return bC==null?"":bC+""})}}}e=b.valHooks[this.type]||b.valHooks[this.nodeName.toLowerCase()];if(!e||!("set" in e)||e.set(this,bB,"value")===L){this.value=bB}})}});b.extend({valHooks:{option:{get:function(e){var bv=e.attributes.value;return !bv||bv.specified?e.value:e.text}},select:{get:function(e){var bA,bv,bz,bx,by=e.selectedIndex,bB=[],bC=e.options,bw=e.type==="select-one";if(by<0){return null}bv=bw?by:0;bz=bw?by+1:bC.length;for(;bv=0});if(!e.length){bv.selectedIndex=-1}return e}}},attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(bA,bx,bB,bz){var bw,e,by,bv=bA.nodeType;if(!bA||bv===3||bv===8||bv===2){return}if(bz&&bx in b.attrFn){return b(bA)[bx](bB)}if(typeof bA.getAttribute==="undefined"){return b.prop(bA,bx,bB)}by=bv!==1||!b.isXMLDoc(bA);if(by){bx=bx.toLowerCase();e=b.attrHooks[bx]||(ao.test(bx)?aZ:bf)}if(bB!==L){if(bB===null){b.removeAttr(bA,bx);return}else{if(e&&"set" in e&&by&&(bw=e.set(bA,bB,bx))!==L){return bw}else{bA.setAttribute(bx,""+bB);return bB}}}else{if(e&&"get" in e&&by&&(bw=e.get(bA,bx))!==null){return bw}else{bw=bA.getAttribute(bx);return bw===null?L:bw}}},removeAttr:function(by,bA){var bz,bB,bw,e,bv,bx=0;if(bA&&by.nodeType===1){bB=bA.toLowerCase().split(ag);e=bB.length;for(;bx=0)}}})});var be=/^(?:textarea|input|select)$/i,n=/^([^\.]*)?(?:\.(.+))?$/,J=/(?:^|\s)hover(\.\S+)?\b/,aP=/^key/,bg=/^(?:mouse|contextmenu)|click/,T=/^(?:focusinfocus|focusoutblur)$/,U=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,Y=function(e){var bv=U.exec(e);if(bv){bv[1]=(bv[1]||"").toLowerCase();bv[3]=bv[3]&&new RegExp("(?:^|\\s)"+bv[3]+"(?:\\s|$)")}return bv},j=function(bw,e){var bv=bw.attributes||{};return((!e[1]||bw.nodeName.toLowerCase()===e[1])&&(!e[2]||(bv.id||{}).value===e[2])&&(!e[3]||e[3].test((bv["class"]||{}).value)))},bt=function(e){return b.event.special.hover?e:e.replace(J,"mouseenter$1 mouseleave$1")};b.event={add:function(bx,bC,bJ,bA,by){var bD,bB,bK,bI,bH,bF,e,bG,bv,bz,bw,bE;if(bx.nodeType===3||bx.nodeType===8||!bC||!bJ||!(bD=b._data(bx))){return}if(bJ.handler){bv=bJ;bJ=bv.handler;by=bv.selector}if(!bJ.guid){bJ.guid=b.guid++}bK=bD.events;if(!bK){bD.events=bK={}}bB=bD.handle;if(!bB){bD.handle=bB=function(bL){return typeof b!=="undefined"&&(!bL||b.event.triggered!==bL.type)?b.event.dispatch.apply(bB.elem,arguments):L};bB.elem=bx}bC=b.trim(bt(bC)).split(" ");for(bI=0;bI=0){bG=bG.slice(0,-1);bw=true}if(bG.indexOf(".")>=0){bx=bG.split(".");bG=bx.shift();bx.sort()}if((!bA||b.event.customEvent[bG])&&!b.event.global[bG]){return}bv=typeof bv==="object"?bv[b.expando]?bv:new b.Event(bG,bv):new b.Event(bG);bv.type=bG;bv.isTrigger=true;bv.exclusive=bw;bv.namespace=bx.join(".");bv.namespace_re=bv.namespace?new RegExp("(^|\\.)"+bx.join("\\.(?:.*\\.)?")+"(\\.|$)"):null;by=bG.indexOf(":")<0?"on"+bG:"";if(!bA){e=b.cache;for(bC in e){if(e[bC].events&&e[bC].events[bG]){b.event.trigger(bv,bD,e[bC].handle.elem,true)}}return}bv.result=L;if(!bv.target){bv.target=bA}bD=bD!=null?b.makeArray(bD):[];bD.unshift(bv);bF=b.event.special[bG]||{};if(bF.trigger&&bF.trigger.apply(bA,bD)===false){return}bB=[[bA,bF.bindType||bG]];if(!bJ&&!bF.noBubble&&!b.isWindow(bA)){bI=bF.delegateType||bG;bH=T.test(bI+bG)?bA:bA.parentNode;bz=null;for(;bH;bH=bH.parentNode){bB.push([bH,bI]);bz=bH}if(bz&&bz===bA.ownerDocument){bB.push([bz.defaultView||bz.parentWindow||bd,bI])}}for(bC=0;bCbC){bv.push({elem:this,matches:bD.slice(bC)})}for(bJ=0;bJ0?this.on(e,null,bx,bw):this.trigger(e)};if(b.attrFn){b.attrFn[e]=true}if(aP.test(e)){b.event.fixHooks[e]=b.event.keyHooks}if(bg.test(e)){b.event.fixHooks[e]=b.event.mouseHooks}}); /*! * Sizzle CSS Selector Engine * Copyright 2011, The Dojo Foundation * Released under the MIT, BSD, and GPL Licenses. * More information: http://sizzlejs.com/ */ -(function(){var bH=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,bC="sizcache"+(Math.random()+"").replace(".",""),bI=0,bL=Object.prototype.toString,bB=false,bA=true,bK=/\\/g,bO=/\r\n/g,bQ=/\W/;[0,0].sort(function(){bA=false;return 0});var by=function(bV,e,bY,bZ){bY=bY||[];e=e||av;var b1=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!bV||typeof bV!=="string"){return bY}var bS,b3,b6,bR,b2,b5,b4,bX,bU=true,bT=by.isXML(e),bW=[],b0=bV;do{bH.exec("");bS=bH.exec(b0);if(bS){b0=bS[3];bW.push(bS[1]);if(bS[2]){bR=bS[3];break}}}while(bS);if(bW.length>1&&bD.exec(bV)){if(bW.length===2&&bE.relative[bW[0]]){b3=bM(bW[0]+bW[1],e,bZ)}else{b3=bE.relative[bW[0]]?[e]:by(bW.shift(),e);while(bW.length){bV=bW.shift();if(bE.relative[bV]){bV+=bW.shift()}b3=bM(bV,b3,bZ)}}}else{if(!bZ&&bW.length>1&&e.nodeType===9&&!bT&&bE.match.ID.test(bW[0])&&!bE.match.ID.test(bW[bW.length-1])){b2=by.find(bW.shift(),e,bT);e=b2.expr?by.filter(b2.expr,b2.set)[0]:b2.set[0]}if(e){b2=bZ?{expr:bW.pop(),set:bF(bZ)}:by.find(bW.pop(),bW.length===1&&(bW[0]==="~"||bW[0]==="+")&&e.parentNode?e.parentNode:e,bT);b3=b2.expr?by.filter(b2.expr,b2.set):b2.set;if(bW.length>0){b6=bF(b3)}else{bU=false}while(bW.length){b5=bW.pop();b4=b5;if(!bE.relative[b5]){b5=""}else{b4=bW.pop()}if(b4==null){b4=e}bE.relative[b5](b6,b4,bT)}}else{b6=bW=[]}}if(!b6){b6=b3}if(!b6){by.error(b5||bV)}if(bL.call(b6)==="[object Array]"){if(!bU){bY.push.apply(bY,b6)}else{if(e&&e.nodeType===1){for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&(b6[bX]===true||b6[bX].nodeType===1&&by.contains(e,b6[bX]))){bY.push(b3[bX])}}}else{for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&b6[bX].nodeType===1){bY.push(b3[bX])}}}}}else{bF(b6,bY)}if(bR){by(bR,b1,bY,bZ);by.uniqueSort(bY)}return bY};by.uniqueSort=function(bR){if(bJ){bB=bA;bR.sort(bJ);if(bB){for(var e=1;e0};by.find=function(bX,e,bY){var bW,bS,bU,bT,bV,bR;if(!bX){return[]}for(bS=0,bU=bE.order.length;bS":function(bW,bR){var bV,bU=typeof bR==="string",bS=0,e=bW.length;if(bU&&!bQ.test(bR)){bR=bR.toLowerCase();for(;bS=0)){if(!bS){e.push(bV)}}else{if(bS){bR[bU]=false}}}}return false},ID:function(e){return e[1].replace(bK,"")},TAG:function(bR,e){return bR[1].replace(bK,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){by.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var bR=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(bR[1]+(bR[2]||1))-0;e[3]=bR[3]-0}else{if(e[2]){by.error(e[0])}}e[0]=bI++;return e},ATTR:function(bU,bR,bS,e,bV,bW){var bT=bU[1]=bU[1].replace(bK,"");if(!bW&&bE.attrMap[bT]){bU[1]=bE.attrMap[bT]}bU[4]=(bU[4]||bU[5]||"").replace(bK,"");if(bU[2]==="~="){bU[4]=" "+bU[4]+" "}return bU},PSEUDO:function(bU,bR,bS,e,bV){if(bU[1]==="not"){if((bH.exec(bU[3])||"").length>1||/^\w/.test(bU[3])){bU[3]=by(bU[3],null,null,bR)}else{var bT=by.filter(bU[3],bR,bS,true^bV);if(!bS){e.push.apply(e,bT)}return false}}else{if(bE.match.POS.test(bU[0])||bE.match.CHILD.test(bU[0])){return true}}return bU},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(bS,bR,e){return !!by(e[3],bS).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(bS){var e=bS.getAttribute("type"),bR=bS.type;return bS.nodeName.toLowerCase()==="input"&&"text"===bR&&(e===bR||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===bR.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===bR.type},button:function(bR){var e=bR.nodeName.toLowerCase();return e==="input"&&"button"===bR.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(bR,e){return e===0},last:function(bS,bR,e,bT){return bR===bT.length-1},even:function(bR,e){return e%2===0},odd:function(bR,e){return e%2===1},lt:function(bS,bR,e){return bRe[3]-0},nth:function(bS,bR,e){return e[3]-0===bR},eq:function(bS,bR,e){return e[3]-0===bR}},filter:{PSEUDO:function(bS,bX,bW,bY){var e=bX[1],bR=bE.filters[e];if(bR){return bR(bS,bW,bX,bY)}else{if(e==="contains"){return(bS.textContent||bS.innerText||bw([bS])||"").indexOf(bX[3])>=0}else{if(e==="not"){var bT=bX[3];for(var bV=0,bU=bT.length;bV=0)}}},ID:function(bR,e){return bR.nodeType===1&&bR.getAttribute("id")===e},TAG:function(bR,e){return(e==="*"&&bR.nodeType===1)||!!bR.nodeName&&bR.nodeName.toLowerCase()===e},CLASS:function(bR,e){return(" "+(bR.className||bR.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(bV,bT){var bS=bT[1],e=by.attr?by.attr(bV,bS):bE.attrHandle[bS]?bE.attrHandle[bS](bV):bV[bS]!=null?bV[bS]:bV.getAttribute(bS),bW=e+"",bU=bT[2],bR=bT[4];return e==null?bU==="!=":!bU&&by.attr?e!=null:bU==="="?bW===bR:bU==="*="?bW.indexOf(bR)>=0:bU==="~="?(" "+bW+" ").indexOf(bR)>=0:!bR?bW&&e!==false:bU==="!="?bW!==bR:bU==="^="?bW.indexOf(bR)===0:bU==="$="?bW.substr(bW.length-bR.length)===bR:bU==="|="?bW===bR||bW.substr(0,bR.length+1)===bR+"-":false},POS:function(bU,bR,bS,bV){var e=bR[2],bT=bE.setFilters[e];if(bT){return bT(bU,bS,bR,bV)}}}};var bD=bE.match.POS,bx=function(bR,e){return"\\"+(e-0+1)};for(var bz in bE.match){bE.match[bz]=new RegExp(bE.match[bz].source+(/(?![^\[]*\])(?![^\(]*\))/.source));bE.leftMatch[bz]=new RegExp(/(^(?:.|\r|\n)*?)/.source+bE.match[bz].source.replace(/\\(\d+)/g,bx))}var bF=function(bR,e){bR=Array.prototype.slice.call(bR,0);if(e){e.push.apply(e,bR);return e}return bR};try{Array.prototype.slice.call(av.documentElement.childNodes,0)[0].nodeType}catch(bP){bF=function(bU,bT){var bS=0,bR=bT||[];if(bL.call(bU)==="[object Array]"){Array.prototype.push.apply(bR,bU)}else{if(typeof bU.length==="number"){for(var e=bU.length;bS";e.insertBefore(bR,e.firstChild);if(av.getElementById(bS)){bE.find.ID=function(bU,bV,bW){if(typeof bV.getElementById!=="undefined"&&!bW){var bT=bV.getElementById(bU[1]);return bT?bT.id===bU[1]||typeof bT.getAttributeNode!=="undefined"&&bT.getAttributeNode("id").nodeValue===bU[1]?[bT]:L:[]}};bE.filter.ID=function(bV,bT){var bU=typeof bV.getAttributeNode!=="undefined"&&bV.getAttributeNode("id");return bV.nodeType===1&&bU&&bU.nodeValue===bT}}e.removeChild(bR);e=bR=null})();(function(){var e=av.createElement("div");e.appendChild(av.createComment(""));if(e.getElementsByTagName("*").length>0){bE.find.TAG=function(bR,bV){var bU=bV.getElementsByTagName(bR[1]);if(bR[1]==="*"){var bT=[];for(var bS=0;bU[bS];bS++){if(bU[bS].nodeType===1){bT.push(bU[bS])}}bU=bT}return bU}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){bE.attrHandle.href=function(bR){return bR.getAttribute("href",2)}}e=null})();if(av.querySelectorAll){(function(){var e=by,bT=av.createElement("div"),bS="__sizzle__";bT.innerHTML="

                  ";if(bT.querySelectorAll&&bT.querySelectorAll(".TEST").length===0){return}by=function(b4,bV,bZ,b3){bV=bV||av;if(!b3&&!by.isXML(bV)){var b2=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b4);if(b2&&(bV.nodeType===1||bV.nodeType===9)){if(b2[1]){return bF(bV.getElementsByTagName(b4),bZ)}else{if(b2[2]&&bE.find.CLASS&&bV.getElementsByClassName){return bF(bV.getElementsByClassName(b2[2]),bZ)}}}if(bV.nodeType===9){if(b4==="body"&&bV.body){return bF([bV.body],bZ)}else{if(b2&&b2[3]){var bY=bV.getElementById(b2[3]);if(bY&&bY.parentNode){if(bY.id===b2[3]){return bF([bY],bZ)}}else{return bF([],bZ)}}}try{return bF(bV.querySelectorAll(b4),bZ)}catch(b0){}}else{if(bV.nodeType===1&&bV.nodeName.toLowerCase()!=="object"){var bW=bV,bX=bV.getAttribute("id"),bU=bX||bS,b6=bV.parentNode,b5=/^\s*[+~]/.test(b4);if(!bX){bV.setAttribute("id",bU)}else{bU=bU.replace(/'/g,"\\$&")}if(b5&&b6){bV=bV.parentNode}try{if(!b5||b6){return bF(bV.querySelectorAll("[id='"+bU+"'] "+b4),bZ)}}catch(b1){}finally{if(!bX){bW.removeAttribute("id")}}}}}return e(b4,bV,bZ,b3)};for(var bR in e){by[bR]=e[bR]}bT=null})()}(function(){var e=av.documentElement,bS=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(bS){var bU=!bS.call(av.createElement("div"),"div"),bR=false;try{bS.call(av.documentElement,"[test!='']:sizzle")}catch(bT){bR=true}by.matchesSelector=function(bW,bY){bY=bY.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!by.isXML(bW)){try{if(bR||!bE.match.PSEUDO.test(bY)&&!/!=/.test(bY)){var bV=bS.call(bW,bY);if(bV||!bU||bW.document&&bW.document.nodeType!==11){return bV}}}catch(bX){}}return by(bY,null,null,[bW]).length>0}}})();(function(){var e=av.createElement("div");e.innerHTML="
                  ";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}bE.order.splice(1,0,"CLASS");bE.find.CLASS=function(bR,bS,bT){if(typeof bS.getElementsByClassName!=="undefined"&&!bT){return bS.getElementsByClassName(bR[1])}};e=null})();function bv(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT0){bU=e;break}}}e=e[bR]}bZ[bT]=bU}}}if(av.documentElement.contains){by.contains=function(bR,e){return bR!==e&&(bR.contains?bR.contains(e):true)}}else{if(av.documentElement.compareDocumentPosition){by.contains=function(bR,e){return !!(bR.compareDocumentPosition(e)&16)}}else{by.contains=function(){return false}}}by.isXML=function(e){var bR=(e?e.ownerDocument||e:0).documentElement;return bR?bR.nodeName!=="HTML":false};var bM=function(bS,e,bW){var bV,bX=[],bU="",bY=e.nodeType?[e]:e;while((bV=bE.match.PSEUDO.exec(bS))){bU+=bV[0];bS=bS.replace(bE.match.PSEUDO,"")}bS=bE.relative[bS]?bS+"*":bS;for(var bT=0,bR=bY.length;bT0){for(bB=bA;bB=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(by,bx){var bv=[],bw,e,bz=this[0];if(b.isArray(by)){var bB=1;while(bz&&bz.ownerDocument&&bz!==bx){for(bw=0;bw-1:b.find.matchesSelector(bz,by)){bv.push(bz);break}else{bz=bz.parentNode;if(!bz||!bz.ownerDocument||bz===bx||bz.nodeType===11){break}}}}bv=bv.length>1?b.unique(bv):bv;return this.pushStack(bv,"closest",by)},index:function(e){if(!e){return(this[0]&&this[0].parentNode)?this.prevAll().length:-1}if(typeof e==="string"){return b.inArray(this[0],b(e))}return b.inArray(e.jquery?e[0]:e,this)},add:function(e,bv){var bx=typeof e==="string"?b(e,bv):b.makeArray(e&&e.nodeType?[e]:e),bw=b.merge(this.get(),bx);return this.pushStack(C(bx[0])||C(bw[0])?bw:b.unique(bw))},andSelf:function(){return this.add(this.prevObject)}});function C(e){return !e||!e.parentNode||e.parentNode.nodeType===11}b.each({parent:function(bv){var e=bv.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(bv,e,bw){return b.dir(bv,"parentNode",bw)},next:function(e){return b.nth(e,2,"nextSibling")},prev:function(e){return b.nth(e,2,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(bv,e,bw){return b.dir(bv,"nextSibling",bw)},prevUntil:function(bv,e,bw){return b.dir(bv,"previousSibling",bw)},siblings:function(e){return b.sibling(e.parentNode.firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.makeArray(e.childNodes)}},function(e,bv){b.fn[e]=function(by,bw){var bx=b.map(this,bv,by);if(!ab.test(e)){bw=by}if(bw&&typeof bw==="string"){bx=b.filter(bw,bx)}bx=this.length>1&&!ay[e]?b.unique(bx):bx;if((this.length>1||a9.test(bw))&&aq.test(e)){bx=bx.reverse()}return this.pushStack(bx,e,P.call(arguments).join(","))}});b.extend({filter:function(bw,e,bv){if(bv){bw=":not("+bw+")"}return e.length===1?b.find.matchesSelector(e[0],bw)?[e[0]]:[]:b.find.matches(bw,e)},dir:function(bw,bv,by){var e=[],bx=bw[bv];while(bx&&bx.nodeType!==9&&(by===L||bx.nodeType!==1||!b(bx).is(by))){if(bx.nodeType===1){e.push(bx)}bx=bx[bv]}return e},nth:function(by,e,bw,bx){e=e||1;var bv=0;for(;by;by=by[bw]){if(by.nodeType===1&&++bv===e){break}}return by},sibling:function(bw,bv){var e=[];for(;bw;bw=bw.nextSibling){if(bw.nodeType===1&&bw!==bv){e.push(bw)}}return e}});function aG(bx,bw,e){bw=bw||0;if(b.isFunction(bw)){return b.grep(bx,function(bz,by){var bA=!!bw.call(bz,by,bz);return bA===e})}else{if(bw.nodeType){return b.grep(bx,function(bz,by){return(bz===bw)===e})}else{if(typeof bw==="string"){var bv=b.grep(bx,function(by){return by.nodeType===1});if(bp.test(bw)){return b.filter(bw,bv,!e)}else{bw=b.filter(bw,bv)}}}}return b.grep(bx,function(bz,by){return(b.inArray(bz,bw)>=0)===e})}function a(e){var bw=aR.split("|"),bv=e.createDocumentFragment();if(bv.createElement){while(bw.length){bv.createElement(bw.pop())}}return bv}var aR="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ag=/ jQuery\d+="(?:\d+|null)"/g,ar=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/<([\w:]+)/,w=/",""],legend:[1,"
                  ","
                  "],thead:[1,"","
                  "],tr:[2,"","
                  "],td:[3,"","
                  "],col:[2,"","
                  "],area:[1,"",""],_default:[0,"",""]},ac=a(av);ax.optgroup=ax.option;ax.tbody=ax.tfoot=ax.colgroup=ax.caption=ax.thead;ax.th=ax.td;if(!b.support.htmlSerialize){ax._default=[1,"div
                  ","
                  "]}b.fn.extend({text:function(e){if(b.isFunction(e)){return this.each(function(bw){var bv=b(this);bv.text(e.call(this,bw,bv.text()))})}if(typeof e!=="object"&&e!==L){return this.empty().append((this[0]&&this[0].ownerDocument||av).createTextNode(e))}return b.text(this)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(bw){b(this).wrapAll(e.call(this,bw))})}if(this[0]){var bv=b(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){bv.insertBefore(this[0])}bv.map(function(){var bw=this;while(bw.firstChild&&bw.firstChild.nodeType===1){bw=bw.firstChild}return bw}).append(this)}return this},wrapInner:function(e){if(b.isFunction(e)){return this.each(function(bv){b(this).wrapInner(e.call(this,bv))})}return this.each(function(){var bv=b(this),bw=bv.contents();if(bw.length){bw.wrapAll(e)}else{bv.append(e)}})},wrap:function(e){var bv=b.isFunction(e);return this.each(function(bw){b(this).wrapAll(bv?e.call(this,bw):e)})},unwrap:function(){return this.parent().each(function(){if(!b.nodeName(this,"body")){b(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.insertBefore(e,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this)})}else{if(arguments.length){var e=b.clean(arguments);e.push.apply(e,this.toArray());return this.pushStack(e,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this.nextSibling)})}else{if(arguments.length){var e=this.pushStack(this,"after",arguments);e.push.apply(e,b.clean(arguments));return e}}},remove:function(e,bx){for(var bv=0,bw;(bw=this[bv])!=null;bv++){if(!e||b.filter(e,[bw]).length){if(!bx&&bw.nodeType===1){b.cleanData(bw.getElementsByTagName("*"));b.cleanData([bw])}if(bw.parentNode){bw.parentNode.removeChild(bw)}}}return this},empty:function(){for(var e=0,bv;(bv=this[e])!=null;e++){if(bv.nodeType===1){b.cleanData(bv.getElementsByTagName("*"))}while(bv.firstChild){bv.removeChild(bv.firstChild)}}return this},clone:function(bv,e){bv=bv==null?false:bv;e=e==null?bv:e;return this.map(function(){return b.clone(this,bv,e)})},html:function(bx){if(bx===L){return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(ag,""):null}else{if(typeof bx==="string"&&!ae.test(bx)&&(b.support.leadingWhitespace||!ar.test(bx))&&!ax[(d.exec(bx)||["",""])[1].toLowerCase()]){bx=bx.replace(R,"<$1>");try{for(var bw=0,bv=this.length;bw1&&bw0?this.clone(true):this).get();b(bC[bA])[bv](by);bz=bz.concat(by)}return this.pushStack(bz,e,bC.selector)}}});function bg(e){if(typeof e.getElementsByTagName!=="undefined"){return e.getElementsByTagName("*")}else{if(typeof e.querySelectorAll!=="undefined"){return e.querySelectorAll("*")}else{return[]}}}function az(e){if(e.type==="checkbox"||e.type==="radio"){e.defaultChecked=e.checked}}function E(e){var bv=(e.nodeName||"").toLowerCase();if(bv==="input"){az(e)}else{if(bv!=="script"&&typeof e.getElementsByTagName!=="undefined"){b.grep(e.getElementsByTagName("input"),az)}}}function al(e){var bv=av.createElement("div");ac.appendChild(bv);bv.innerHTML=e.outerHTML;return bv.firstChild}b.extend({clone:function(by,bA,bw){var e,bv,bx,bz=b.support.html5Clone||!ah.test("<"+by.nodeName)?by.cloneNode(true):al(by);if((!b.support.noCloneEvent||!b.support.noCloneChecked)&&(by.nodeType===1||by.nodeType===11)&&!b.isXMLDoc(by)){ai(by,bz);e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){if(bv[bx]){ai(e[bx],bv[bx])}}}if(bA){t(by,bz);if(bw){e=bg(by);bv=bg(bz);for(bx=0;e[bx];++bx){t(e[bx],bv[bx])}}}e=bv=null;return bz},clean:function(bw,by,bH,bA){var bF;by=by||av;if(typeof by.createElement==="undefined"){by=by.ownerDocument||by[0]&&by[0].ownerDocument||av}var bI=[],bB;for(var bE=0,bz;(bz=bw[bE])!=null;bE++){if(typeof bz==="number"){bz+=""}if(!bz){continue}if(typeof bz==="string"){if(!W.test(bz)){bz=by.createTextNode(bz)}else{bz=bz.replace(R,"<$1>");var bK=(d.exec(bz)||["",""])[1].toLowerCase(),bx=ax[bK]||ax._default,bD=bx[0],bv=by.createElement("div");if(by===av){ac.appendChild(bv)}else{a(by).appendChild(bv)}bv.innerHTML=bx[1]+bz+bx[2];while(bD--){bv=bv.lastChild}if(!b.support.tbody){var e=w.test(bz),bC=bK==="table"&&!e?bv.firstChild&&bv.firstChild.childNodes:bx[1]===""&&!e?bv.childNodes:[];for(bB=bC.length-1;bB>=0;--bB){if(b.nodeName(bC[bB],"tbody")&&!bC[bB].childNodes.length){bC[bB].parentNode.removeChild(bC[bB])}}}if(!b.support.leadingWhitespace&&ar.test(bz)){bv.insertBefore(by.createTextNode(ar.exec(bz)[0]),bv.firstChild)}bz=bv.childNodes}}var bG;if(!b.support.appendChecked){if(bz[0]&&typeof(bG=bz.length)==="number"){for(bB=0;bB=0){return bx+"px"}}else{return bx}}}});if(!b.support.opacity){b.cssHooks.opacity={get:function(bv,e){return au.test((e&&bv.currentStyle?bv.currentStyle.filter:bv.style.filter)||"")?(parseFloat(RegExp.$1)/100)+"":e?"1":""},set:function(by,bz){var bx=by.style,bv=by.currentStyle,e=b.isNumeric(bz)?"alpha(opacity="+bz*100+")":"",bw=bv&&bv.filter||bx.filter||"";bx.zoom=1;if(bz>=1&&b.trim(bw.replace(ak,""))===""){bx.removeAttribute("filter");if(bv&&!bv.filter){return}}bx.filter=ak.test(bw)?bw.replace(ak,e):bw+" "+e}}}b(function(){if(!b.support.reliableMarginRight){b.cssHooks.marginRight={get:function(bw,bv){var e;b.swap(bw,{display:"inline-block"},function(){if(bv){e=Z(bw,"margin-right","marginRight")}else{e=bw.style.marginRight}});return e}}}});if(av.defaultView&&av.defaultView.getComputedStyle){aI=function(by,bw){var bv,bx,e;bw=bw.replace(z,"-$1").toLowerCase();if((bx=by.ownerDocument.defaultView)&&(e=bx.getComputedStyle(by,null))){bv=e.getPropertyValue(bw);if(bv===""&&!b.contains(by.ownerDocument.documentElement,by)){bv=b.style(by,bw)}}return bv}}if(av.documentElement.currentStyle){aX=function(bz,bw){var bA,e,by,bv=bz.currentStyle&&bz.currentStyle[bw],bx=bz.style;if(bv===null&&bx&&(by=bx[bw])){bv=by}if(!bc.test(bv)&&bn.test(bv)){bA=bx.left;e=bz.runtimeStyle&&bz.runtimeStyle.left;if(e){bz.runtimeStyle.left=bz.currentStyle.left}bx.left=bw==="fontSize"?"1em":(bv||0);bv=bx.pixelLeft+"px";bx.left=bA;if(e){bz.runtimeStyle.left=e}}return bv===""?"auto":bv}}Z=aI||aX;function p(by,bw,bv){var bA=bw==="width"?by.offsetWidth:by.offsetHeight,bz=bw==="width"?an:a1,bx=0,e=bz.length;if(bA>0){if(bv!=="border"){for(;bx)<[^<]*)*<\/script>/gi,q=/^(?:select|textarea)/i,h=/\s+/,br=/([?&])_=[^&]*/,K=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,A=b.fn.load,aa={},r={},aE,s,aV=["*/"]+["*"];try{aE=bl.href}catch(aw){aE=av.createElement("a");aE.href="";aE=aE.href}s=K.exec(aE.toLowerCase())||[];function f(e){return function(by,bA){if(typeof by!=="string"){bA=by;by="*"}if(b.isFunction(bA)){var bx=by.toLowerCase().split(h),bw=0,bz=bx.length,bv,bB,bC;for(;bw=0){var e=bw.slice(by,bw.length);bw=bw.slice(0,by)}var bx="GET";if(bz){if(b.isFunction(bz)){bA=bz;bz=L}else{if(typeof bz==="object"){bz=b.param(bz,b.ajaxSettings.traditional);bx="POST"}}}var bv=this;b.ajax({url:bw,type:bx,dataType:"html",data:bz,complete:function(bC,bB,bD){bD=bC.responseText;if(bC.isResolved()){bC.done(function(bE){bD=bE});bv.html(e?b("
                  ").append(bD.replace(a6,"")).find(e):bD)}if(bA){bv.each(bA,[bD,bB,bC])}}});return this},serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?b.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||q.test(this.nodeName)||aZ.test(this.type))}).map(function(e,bv){var bw=b(this).val();return bw==null?null:b.isArray(bw)?b.map(bw,function(by,bx){return{name:bv.name,value:by.replace(bs,"\r\n")}}):{name:bv.name,value:bw.replace(bs,"\r\n")}}).get()}});b.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,bv){b.fn[bv]=function(bw){return this.on(bv,bw)}});b.each(["get","post"],function(e,bv){b[bv]=function(bw,by,bz,bx){if(b.isFunction(by)){bx=bx||bz;bz=by;by=L}return b.ajax({type:bv,url:bw,data:by,success:bz,dataType:bx})}});b.extend({getScript:function(e,bv){return b.get(e,L,bv,"script")},getJSON:function(e,bv,bw){return b.get(e,bv,bw,"json")},ajaxSetup:function(bv,e){if(e){am(bv,b.ajaxSettings)}else{e=bv;bv=b.ajaxSettings}am(bv,e);return bv},ajaxSettings:{url:aE,isLocal:aM.test(s[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":aV},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":bb.String,"text html":true,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:f(aa),ajaxTransport:f(r),ajax:function(bz,bx){if(typeof bz==="object"){bx=bz;bz=L}bx=bx||{};var bD=b.ajaxSetup({},bx),bS=bD.context||bD,bG=bS!==bD&&(bS.nodeType||bS instanceof b)?b(bS):b.event,bR=b.Deferred(),bN=b.Callbacks("once memory"),bB=bD.statusCode||{},bC,bH={},bO={},bQ,by,bL,bE,bI,bA=0,bw,bK,bJ={readyState:0,setRequestHeader:function(bT,bU){if(!bA){var e=bT.toLowerCase();bT=bO[e]=bO[e]||bT;bH[bT]=bU}return this},getAllResponseHeaders:function(){return bA===2?bQ:null},getResponseHeader:function(bT){var e;if(bA===2){if(!by){by={};while((e=aD.exec(bQ))){by[e[1].toLowerCase()]=e[2]}}e=by[bT.toLowerCase()]}return e===L?null:e},overrideMimeType:function(e){if(!bA){bD.mimeType=e}return this},abort:function(e){e=e||"abort";if(bL){bL.abort(e)}bF(0,e);return this}};function bF(bZ,bU,b0,bW){if(bA===2){return}bA=2;if(bE){clearTimeout(bE)}bL=L;bQ=bW||"";bJ.readyState=bZ>0?4:0;var bT,b4,b3,bX=bU,bY=b0?bj(bD,bJ,b0):L,bV,b2;if(bZ>=200&&bZ<300||bZ===304){if(bD.ifModified){if((bV=bJ.getResponseHeader("Last-Modified"))){b.lastModified[bC]=bV}if((b2=bJ.getResponseHeader("Etag"))){b.etag[bC]=b2}}if(bZ===304){bX="notmodified";bT=true}else{try{b4=G(bD,bY);bX="success";bT=true}catch(b1){bX="parsererror";b3=b1}}}else{b3=bX;if(!bX||bZ){bX="error";if(bZ<0){bZ=0}}}bJ.status=bZ;bJ.statusText=""+(bU||bX);if(bT){bR.resolveWith(bS,[b4,bX,bJ])}else{bR.rejectWith(bS,[bJ,bX,b3])}bJ.statusCode(bB);bB=L;if(bw){bG.trigger("ajax"+(bT?"Success":"Error"),[bJ,bD,bT?b4:b3])}bN.fireWith(bS,[bJ,bX]);if(bw){bG.trigger("ajaxComplete",[bJ,bD]);if(!(--b.active)){b.event.trigger("ajaxStop")}}}bR.promise(bJ);bJ.success=bJ.done;bJ.error=bJ.fail;bJ.complete=bN.add;bJ.statusCode=function(bT){if(bT){var e;if(bA<2){for(e in bT){bB[e]=[bB[e],bT[e]]}}else{e=bT[bJ.status];bJ.then(e,e)}}return this};bD.url=((bz||bD.url)+"").replace(bq,"").replace(c,s[1]+"//");bD.dataTypes=b.trim(bD.dataType||"*").toLowerCase().split(h);if(bD.crossDomain==null){bI=K.exec(bD.url.toLowerCase());bD.crossDomain=!!(bI&&(bI[1]!=s[1]||bI[2]!=s[2]||(bI[3]||(bI[1]==="http:"?80:443))!=(s[3]||(s[1]==="http:"?80:443))))}if(bD.data&&bD.processData&&typeof bD.data!=="string"){bD.data=b.param(bD.data,bD.traditional)}aW(aa,bD,bx,bJ);if(bA===2){return false}bw=bD.global;bD.type=bD.type.toUpperCase();bD.hasContent=!aQ.test(bD.type);if(bw&&b.active++===0){b.event.trigger("ajaxStart")}if(!bD.hasContent){if(bD.data){bD.url+=(M.test(bD.url)?"&":"?")+bD.data;delete bD.data}bC=bD.url;if(bD.cache===false){var bv=b.now(),bP=bD.url.replace(br,"$1_="+bv);bD.url=bP+((bP===bD.url)?(M.test(bD.url)?"&":"?")+"_="+bv:"")}}if(bD.data&&bD.hasContent&&bD.contentType!==false||bx.contentType){bJ.setRequestHeader("Content-Type",bD.contentType)}if(bD.ifModified){bC=bC||bD.url;if(b.lastModified[bC]){bJ.setRequestHeader("If-Modified-Since",b.lastModified[bC])}if(b.etag[bC]){bJ.setRequestHeader("If-None-Match",b.etag[bC])}}bJ.setRequestHeader("Accept",bD.dataTypes[0]&&bD.accepts[bD.dataTypes[0]]?bD.accepts[bD.dataTypes[0]]+(bD.dataTypes[0]!=="*"?", "+aV+"; q=0.01":""):bD.accepts["*"]);for(bK in bD.headers){bJ.setRequestHeader(bK,bD.headers[bK])}if(bD.beforeSend&&(bD.beforeSend.call(bS,bJ,bD)===false||bA===2)){bJ.abort();return false}for(bK in {success:1,error:1,complete:1}){bJ[bK](bD[bK])}bL=aW(r,bD,bx,bJ);if(!bL){bF(-1,"No Transport")}else{bJ.readyState=1;if(bw){bG.trigger("ajaxSend",[bJ,bD])}if(bD.async&&bD.timeout>0){bE=setTimeout(function(){bJ.abort("timeout")},bD.timeout)}try{bA=1;bL.send(bH,bF)}catch(bM){if(bA<2){bF(-1,bM)}else{throw bM}}}return bJ},param:function(e,bw){var bv=[],by=function(bz,bA){bA=b.isFunction(bA)?bA():bA;bv[bv.length]=encodeURIComponent(bz)+"="+encodeURIComponent(bA)};if(bw===L){bw=b.ajaxSettings.traditional}if(b.isArray(e)||(e.jquery&&!b.isPlainObject(e))){b.each(e,function(){by(this.name,this.value)})}else{for(var bx in e){v(bx,e[bx],bw,by)}}return bv.join("&").replace(k,"+")}});function v(bw,by,bv,bx){if(b.isArray(by)){b.each(by,function(bA,bz){if(bv||ap.test(bw)){bx(bw,bz)}else{v(bw+"["+(typeof bz==="object"||b.isArray(bz)?bA:"")+"]",bz,bv,bx)}})}else{if(!bv&&by!=null&&typeof by==="object"){for(var e in by){v(bw+"["+e+"]",by[e],bv,bx)}}else{bx(bw,by)}}}b.extend({active:0,lastModified:{},etag:{}});function bj(bD,bC,bz){var bv=bD.contents,bB=bD.dataTypes,bw=bD.responseFields,by,bA,bx,e;for(bA in bw){if(bA in bz){bC[bw[bA]]=bz[bA]}}while(bB[0]==="*"){bB.shift();if(by===L){by=bD.mimeType||bC.getResponseHeader("content-type")}}if(by){for(bA in bv){if(bv[bA]&&bv[bA].test(by)){bB.unshift(bA);break}}}if(bB[0] in bz){bx=bB[0]}else{for(bA in bz){if(!bB[0]||bD.converters[bA+" "+bB[0]]){bx=bA;break}if(!e){e=bA}}bx=bx||e}if(bx){if(bx!==bB[0]){bB.unshift(bx)}return bz[bx]}}function G(bH,bz){if(bH.dataFilter){bz=bH.dataFilter(bz,bH.dataType)}var bD=bH.dataTypes,bG={},bA,bE,bw=bD.length,bB,bC=bD[0],bx,by,bF,bv,e;for(bA=1;bA=bw.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();bw.animatedProperties[this.prop]=true;for(bA in bw.animatedProperties){if(bw.animatedProperties[bA]!==true){e=false}}if(e){if(bw.overflow!=null&&!b.support.shrinkWrapBlocks){b.each(["","X","Y"],function(bC,bD){bz.style["overflow"+bD]=bw.overflow[bC]})}if(bw.hide){b(bz).hide()}if(bw.hide||bw.show){for(bA in bw.animatedProperties){b.style(bz,bA,bw.orig[bA]);b.removeData(bz,"fxshow"+bA,true);b.removeData(bz,"toggle"+bA,true)}}bv=bw.complete;if(bv){bw.complete=false;bv.call(bz)}}return false}else{if(bw.duration==Infinity){this.now=bx}else{bB=bx-this.startTime;this.state=bB/bw.duration;this.pos=b.easing[bw.animatedProperties[this.prop]](this.state,bB,0,1,bw.duration);this.now=this.start+((this.end-this.start)*this.pos)}this.update()}return true}};b.extend(b.fx,{tick:function(){var bw,bv=b.timers,e=0;for(;e").appendTo(e),bw=bv.css("display");bv.remove();if(bw==="none"||bw===""){if(!a8){a8=av.createElement("iframe");a8.frameBorder=a8.width=a8.height=0}e.appendChild(a8);if(!m||!a8.createElement){m=(a8.contentWindow||a8.contentDocument).document;m.write((av.compatMode==="CSS1Compat"?"":"")+"");m.close()}bv=m.createElement(bx);m.body.appendChild(bv);bw=b.css(bv,"display");e.removeChild(a8)}Q[bx]=bw}return Q[bx]}var V=/^t(?:able|d|h)$/i,ad=/^(?:body|html)$/i;if("getBoundingClientRect" in av.documentElement){b.fn.offset=function(bI){var by=this[0],bB;if(bI){return this.each(function(e){b.offset.setOffset(this,bI,e)})}if(!by||!by.ownerDocument){return null}if(by===by.ownerDocument.body){return b.offset.bodyOffset(by)}try{bB=by.getBoundingClientRect()}catch(bF){}var bH=by.ownerDocument,bw=bH.documentElement;if(!bB||!b.contains(bw,by)){return bB?{top:bB.top,left:bB.left}:{top:0,left:0}}var bC=bH.body,bD=aK(bH),bA=bw.clientTop||bC.clientTop||0,bE=bw.clientLeft||bC.clientLeft||0,bv=bD.pageYOffset||b.support.boxModel&&bw.scrollTop||bC.scrollTop,bz=bD.pageXOffset||b.support.boxModel&&bw.scrollLeft||bC.scrollLeft,bG=bB.top+bv-bA,bx=bB.left+bz-bE;return{top:bG,left:bx}}}else{b.fn.offset=function(bF){var bz=this[0];if(bF){return this.each(function(bG){b.offset.setOffset(this,bF,bG)})}if(!bz||!bz.ownerDocument){return null}if(bz===bz.ownerDocument.body){return b.offset.bodyOffset(bz)}var bC,bw=bz.offsetParent,bv=bz,bE=bz.ownerDocument,bx=bE.documentElement,bA=bE.body,bB=bE.defaultView,e=bB?bB.getComputedStyle(bz,null):bz.currentStyle,bD=bz.offsetTop,by=bz.offsetLeft;while((bz=bz.parentNode)&&bz!==bA&&bz!==bx){if(b.support.fixedPosition&&e.position==="fixed"){break}bC=bB?bB.getComputedStyle(bz,null):bz.currentStyle;bD-=bz.scrollTop;by-=bz.scrollLeft;if(bz===bw){bD+=bz.offsetTop;by+=bz.offsetLeft;if(b.support.doesNotAddBorder&&!(b.support.doesAddBorderForTableAndCells&&V.test(bz.nodeName))){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}bv=bw;bw=bz.offsetParent}if(b.support.subtractsBorderForOverflowNotVisible&&bC.overflow!=="visible"){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}e=bC}if(e.position==="relative"||e.position==="static"){bD+=bA.offsetTop;by+=bA.offsetLeft}if(b.support.fixedPosition&&e.position==="fixed"){bD+=Math.max(bx.scrollTop,bA.scrollTop);by+=Math.max(bx.scrollLeft,bA.scrollLeft)}return{top:bD,left:by}}}b.offset={bodyOffset:function(e){var bw=e.offsetTop,bv=e.offsetLeft;if(b.support.doesNotIncludeMarginInBodyOffset){bw+=parseFloat(b.css(e,"marginTop"))||0;bv+=parseFloat(b.css(e,"marginLeft"))||0}return{top:bw,left:bv}},setOffset:function(bx,bG,bA){var bB=b.css(bx,"position");if(bB==="static"){bx.style.position="relative"}var bz=b(bx),bv=bz.offset(),e=b.css(bx,"top"),bE=b.css(bx,"left"),bF=(bB==="absolute"||bB==="fixed")&&b.inArray("auto",[e,bE])>-1,bD={},bC={},bw,by;if(bF){bC=bz.position();bw=bC.top;by=bC.left}else{bw=parseFloat(e)||0;by=parseFloat(bE)||0}if(b.isFunction(bG)){bG=bG.call(bx,bA,bv)}if(bG.top!=null){bD.top=(bG.top-bv.top)+bw}if(bG.left!=null){bD.left=(bG.left-bv.left)+by}if("using" in bG){bG.using.call(bx,bD)}else{bz.css(bD)}}};b.fn.extend({position:function(){if(!this[0]){return null}var bw=this[0],bv=this.offsetParent(),bx=this.offset(),e=ad.test(bv[0].nodeName)?{top:0,left:0}:bv.offset();bx.top-=parseFloat(b.css(bw,"marginTop"))||0;bx.left-=parseFloat(b.css(bw,"marginLeft"))||0;e.top+=parseFloat(b.css(bv[0],"borderTopWidth"))||0;e.left+=parseFloat(b.css(bv[0],"borderLeftWidth"))||0;return{top:bx.top-e.top,left:bx.left-e.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||av.body;while(e&&(!ad.test(e.nodeName)&&b.css(e,"position")==="static")){e=e.offsetParent}return e})}});b.each(["Left","Top"],function(bv,e){var bw="scroll"+e;b.fn[bw]=function(bz){var bx,by;if(bz===L){bx=this[0];if(!bx){return null}by=aK(bx);return by?("pageXOffset" in by)?by[bv?"pageYOffset":"pageXOffset"]:b.support.boxModel&&by.document.documentElement[bw]||by.document.body[bw]:bx[bw]}return this.each(function(){by=aK(this);if(by){by.scrollTo(!bv?bz:b(by).scrollLeft(),bv?bz:b(by).scrollTop())}else{this[bw]=bz}})}});function aK(e){return b.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}b.each(["Height","Width"],function(bv,e){var bw=e.toLowerCase();b.fn["inner"+e]=function(){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,"padding")):this[bw]():null};b.fn["outer"+e]=function(by){var bx=this[0];return bx?bx.style?parseFloat(b.css(bx,bw,by?"margin":"border")):this[bw]():null};b.fn[bw]=function(bz){var bA=this[0];if(!bA){return bz==null?null:this}if(b.isFunction(bz)){return this.each(function(bE){var bD=b(this);bD[bw](bz.call(this,bE,bD[bw]()))})}if(b.isWindow(bA)){var bB=bA.document.documentElement["client"+e],bx=bA.document.body;return bA.document.compatMode==="CSS1Compat"&&bB||bx&&bx["client"+e]||bB}else{if(bA.nodeType===9){return Math.max(bA.documentElement["client"+e],bA.body["scroll"+e],bA.documentElement["scroll"+e],bA.body["offset"+e],bA.documentElement["offset"+e])}else{if(bz===L){var bC=b.css(bA,bw),by=parseFloat(bC);return b.isNumeric(by)?by:bC}else{return this.css(bw,typeof bz==="string"?bz:bz+"px")}}}}});bb.jQuery=bb.$=b;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return b})}})(window);/*! +(function(){var bH=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,bC="sizcache"+(Math.random()+"").replace(".",""),bI=0,bL=Object.prototype.toString,bB=false,bA=true,bK=/\\/g,bO=/\r\n/g,bQ=/\W/;[0,0].sort(function(){bA=false;return 0});var by=function(bV,e,bY,bZ){bY=bY||[];e=e||av;var b1=e;if(e.nodeType!==1&&e.nodeType!==9){return[]}if(!bV||typeof bV!=="string"){return bY}var bS,b3,b6,bR,b2,b5,b4,bX,bU=true,bT=by.isXML(e),bW=[],b0=bV;do{bH.exec("");bS=bH.exec(b0);if(bS){b0=bS[3];bW.push(bS[1]);if(bS[2]){bR=bS[3];break}}}while(bS);if(bW.length>1&&bD.exec(bV)){if(bW.length===2&&bE.relative[bW[0]]){b3=bM(bW[0]+bW[1],e,bZ)}else{b3=bE.relative[bW[0]]?[e]:by(bW.shift(),e);while(bW.length){bV=bW.shift();if(bE.relative[bV]){bV+=bW.shift()}b3=bM(bV,b3,bZ)}}}else{if(!bZ&&bW.length>1&&e.nodeType===9&&!bT&&bE.match.ID.test(bW[0])&&!bE.match.ID.test(bW[bW.length-1])){b2=by.find(bW.shift(),e,bT);e=b2.expr?by.filter(b2.expr,b2.set)[0]:b2.set[0]}if(e){b2=bZ?{expr:bW.pop(),set:bF(bZ)}:by.find(bW.pop(),bW.length===1&&(bW[0]==="~"||bW[0]==="+")&&e.parentNode?e.parentNode:e,bT);b3=b2.expr?by.filter(b2.expr,b2.set):b2.set;if(bW.length>0){b6=bF(b3)}else{bU=false}while(bW.length){b5=bW.pop();b4=b5;if(!bE.relative[b5]){b5=""}else{b4=bW.pop()}if(b4==null){b4=e}bE.relative[b5](b6,b4,bT)}}else{b6=bW=[]}}if(!b6){b6=b3}if(!b6){by.error(b5||bV)}if(bL.call(b6)==="[object Array]"){if(!bU){bY.push.apply(bY,b6)}else{if(e&&e.nodeType===1){for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&(b6[bX]===true||b6[bX].nodeType===1&&by.contains(e,b6[bX]))){bY.push(b3[bX])}}}else{for(bX=0;b6[bX]!=null;bX++){if(b6[bX]&&b6[bX].nodeType===1){bY.push(b3[bX])}}}}}else{bF(b6,bY)}if(bR){by(bR,b1,bY,bZ);by.uniqueSort(bY)}return bY};by.uniqueSort=function(bR){if(bJ){bB=bA;bR.sort(bJ);if(bB){for(var e=1;e0};by.find=function(bX,e,bY){var bW,bS,bU,bT,bV,bR;if(!bX){return[]}for(bS=0,bU=bE.order.length;bS":function(bW,bR){var bV,bU=typeof bR==="string",bS=0,e=bW.length;if(bU&&!bQ.test(bR)){bR=bR.toLowerCase();for(;bS=0)){if(!bS){e.push(bV)}}else{if(bS){bR[bU]=false}}}}return false},ID:function(e){return e[1].replace(bK,"")},TAG:function(bR,e){return bR[1].replace(bK,"").toLowerCase()},CHILD:function(e){if(e[1]==="nth"){if(!e[2]){by.error(e[0])}e[2]=e[2].replace(/^\+|\s*/g,"");var bR=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(e[2]==="even"&&"2n"||e[2]==="odd"&&"2n+1"||!/\D/.test(e[2])&&"0n+"+e[2]||e[2]);e[2]=(bR[1]+(bR[2]||1))-0;e[3]=bR[3]-0}else{if(e[2]){by.error(e[0])}}e[0]=bI++;return e},ATTR:function(bU,bR,bS,e,bV,bW){var bT=bU[1]=bU[1].replace(bK,"");if(!bW&&bE.attrMap[bT]){bU[1]=bE.attrMap[bT]}bU[4]=(bU[4]||bU[5]||"").replace(bK,"");if(bU[2]==="~="){bU[4]=" "+bU[4]+" "}return bU},PSEUDO:function(bU,bR,bS,e,bV){if(bU[1]==="not"){if((bH.exec(bU[3])||"").length>1||/^\w/.test(bU[3])){bU[3]=by(bU[3],null,null,bR)}else{var bT=by.filter(bU[3],bR,bS,true^bV);if(!bS){e.push.apply(e,bT)}return false}}else{if(bE.match.POS.test(bU[0])||bE.match.CHILD.test(bU[0])){return true}}return bU},POS:function(e){e.unshift(true);return e}},filters:{enabled:function(e){return e.disabled===false&&e.type!=="hidden"},disabled:function(e){return e.disabled===true},checked:function(e){return e.checked===true},selected:function(e){if(e.parentNode){e.parentNode.selectedIndex}return e.selected===true},parent:function(e){return !!e.firstChild},empty:function(e){return !e.firstChild},has:function(bS,bR,e){return !!by(e[3],bS).length},header:function(e){return(/h\d/i).test(e.nodeName)},text:function(bS){var e=bS.getAttribute("type"),bR=bS.type;return bS.nodeName.toLowerCase()==="input"&&"text"===bR&&(e===bR||e===null)},radio:function(e){return e.nodeName.toLowerCase()==="input"&&"radio"===e.type},checkbox:function(e){return e.nodeName.toLowerCase()==="input"&&"checkbox"===e.type},file:function(e){return e.nodeName.toLowerCase()==="input"&&"file"===e.type},password:function(e){return e.nodeName.toLowerCase()==="input"&&"password"===e.type},submit:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"submit"===bR.type},image:function(e){return e.nodeName.toLowerCase()==="input"&&"image"===e.type},reset:function(bR){var e=bR.nodeName.toLowerCase();return(e==="input"||e==="button")&&"reset"===bR.type},button:function(bR){var e=bR.nodeName.toLowerCase();return e==="input"&&"button"===bR.type||e==="button"},input:function(e){return(/input|select|textarea|button/i).test(e.nodeName)},focus:function(e){return e===e.ownerDocument.activeElement}},setFilters:{first:function(bR,e){return e===0},last:function(bS,bR,e,bT){return bR===bT.length-1},even:function(bR,e){return e%2===0},odd:function(bR,e){return e%2===1},lt:function(bS,bR,e){return bRe[3]-0},nth:function(bS,bR,e){return e[3]-0===bR},eq:function(bS,bR,e){return e[3]-0===bR}},filter:{PSEUDO:function(bS,bX,bW,bY){var e=bX[1],bR=bE.filters[e];if(bR){return bR(bS,bW,bX,bY)}else{if(e==="contains"){return(bS.textContent||bS.innerText||bw([bS])||"").indexOf(bX[3])>=0}else{if(e==="not"){var bT=bX[3];for(var bV=0,bU=bT.length;bV=0)}}},ID:function(bR,e){return bR.nodeType===1&&bR.getAttribute("id")===e},TAG:function(bR,e){return(e==="*"&&bR.nodeType===1)||!!bR.nodeName&&bR.nodeName.toLowerCase()===e},CLASS:function(bR,e){return(" "+(bR.className||bR.getAttribute("class"))+" ").indexOf(e)>-1},ATTR:function(bV,bT){var bS=bT[1],e=by.attr?by.attr(bV,bS):bE.attrHandle[bS]?bE.attrHandle[bS](bV):bV[bS]!=null?bV[bS]:bV.getAttribute(bS),bW=e+"",bU=bT[2],bR=bT[4];return e==null?bU==="!=":!bU&&by.attr?e!=null:bU==="="?bW===bR:bU==="*="?bW.indexOf(bR)>=0:bU==="~="?(" "+bW+" ").indexOf(bR)>=0:!bR?bW&&e!==false:bU==="!="?bW!==bR:bU==="^="?bW.indexOf(bR)===0:bU==="$="?bW.substr(bW.length-bR.length)===bR:bU==="|="?bW===bR||bW.substr(0,bR.length+1)===bR+"-":false},POS:function(bU,bR,bS,bV){var e=bR[2],bT=bE.setFilters[e];if(bT){return bT(bU,bS,bR,bV)}}}};var bD=bE.match.POS,bx=function(bR,e){return"\\"+(e-0+1)};for(var bz in bE.match){bE.match[bz]=new RegExp(bE.match[bz].source+(/(?![^\[]*\])(?![^\(]*\))/.source));bE.leftMatch[bz]=new RegExp(/(^(?:.|\r|\n)*?)/.source+bE.match[bz].source.replace(/\\(\d+)/g,bx))}bE.match.globalPOS=bD;var bF=function(bR,e){bR=Array.prototype.slice.call(bR,0);if(e){e.push.apply(e,bR);return e}return bR};try{Array.prototype.slice.call(av.documentElement.childNodes,0)[0].nodeType}catch(bP){bF=function(bU,bT){var bS=0,bR=bT||[];if(bL.call(bU)==="[object Array]"){Array.prototype.push.apply(bR,bU)}else{if(typeof bU.length==="number"){for(var e=bU.length;bS";e.insertBefore(bR,e.firstChild);if(av.getElementById(bS)){bE.find.ID=function(bU,bV,bW){if(typeof bV.getElementById!=="undefined"&&!bW){var bT=bV.getElementById(bU[1]);return bT?bT.id===bU[1]||typeof bT.getAttributeNode!=="undefined"&&bT.getAttributeNode("id").nodeValue===bU[1]?[bT]:L:[]}};bE.filter.ID=function(bV,bT){var bU=typeof bV.getAttributeNode!=="undefined"&&bV.getAttributeNode("id");return bV.nodeType===1&&bU&&bU.nodeValue===bT}}e.removeChild(bR);e=bR=null})();(function(){var e=av.createElement("div");e.appendChild(av.createComment(""));if(e.getElementsByTagName("*").length>0){bE.find.TAG=function(bR,bV){var bU=bV.getElementsByTagName(bR[1]);if(bR[1]==="*"){var bT=[];for(var bS=0;bU[bS];bS++){if(bU[bS].nodeType===1){bT.push(bU[bS])}}bU=bT}return bU}}e.innerHTML="";if(e.firstChild&&typeof e.firstChild.getAttribute!=="undefined"&&e.firstChild.getAttribute("href")!=="#"){bE.attrHandle.href=function(bR){return bR.getAttribute("href",2)}}e=null})();if(av.querySelectorAll){(function(){var e=by,bT=av.createElement("div"),bS="__sizzle__";bT.innerHTML="

                  ";if(bT.querySelectorAll&&bT.querySelectorAll(".TEST").length===0){return}by=function(b4,bV,bZ,b3){bV=bV||av;if(!b3&&!by.isXML(bV)){var b2=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b4);if(b2&&(bV.nodeType===1||bV.nodeType===9)){if(b2[1]){return bF(bV.getElementsByTagName(b4),bZ)}else{if(b2[2]&&bE.find.CLASS&&bV.getElementsByClassName){return bF(bV.getElementsByClassName(b2[2]),bZ)}}}if(bV.nodeType===9){if(b4==="body"&&bV.body){return bF([bV.body],bZ)}else{if(b2&&b2[3]){var bY=bV.getElementById(b2[3]);if(bY&&bY.parentNode){if(bY.id===b2[3]){return bF([bY],bZ)}}else{return bF([],bZ)}}}try{return bF(bV.querySelectorAll(b4),bZ)}catch(b0){}}else{if(bV.nodeType===1&&bV.nodeName.toLowerCase()!=="object"){var bW=bV,bX=bV.getAttribute("id"),bU=bX||bS,b6=bV.parentNode,b5=/^\s*[+~]/.test(b4);if(!bX){bV.setAttribute("id",bU)}else{bU=bU.replace(/'/g,"\\$&")}if(b5&&b6){bV=bV.parentNode}try{if(!b5||b6){return bF(bV.querySelectorAll("[id='"+bU+"'] "+b4),bZ)}}catch(b1){}finally{if(!bX){bW.removeAttribute("id")}}}}}return e(b4,bV,bZ,b3)};for(var bR in e){by[bR]=e[bR]}bT=null})()}(function(){var e=av.documentElement,bS=e.matchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.msMatchesSelector;if(bS){var bU=!bS.call(av.createElement("div"),"div"),bR=false;try{bS.call(av.documentElement,"[test!='']:sizzle")}catch(bT){bR=true}by.matchesSelector=function(bW,bY){bY=bY.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!by.isXML(bW)){try{if(bR||!bE.match.PSEUDO.test(bY)&&!/!=/.test(bY)){var bV=bS.call(bW,bY);if(bV||!bU||bW.document&&bW.document.nodeType!==11){return bV}}}catch(bX){}}return by(bY,null,null,[bW]).length>0}}})();(function(){var e=av.createElement("div");e.innerHTML="
                  ";if(!e.getElementsByClassName||e.getElementsByClassName("e").length===0){return}e.lastChild.className="e";if(e.getElementsByClassName("e").length===1){return}bE.order.splice(1,0,"CLASS");bE.find.CLASS=function(bR,bS,bT){if(typeof bS.getElementsByClassName!=="undefined"&&!bT){return bS.getElementsByClassName(bR[1])}};e=null})();function bv(bR,bW,bV,bZ,bX,bY){for(var bT=0,bS=bZ.length;bT0){bU=e;break}}}e=e[bR]}bZ[bT]=bU}}}if(av.documentElement.contains){by.contains=function(bR,e){return bR!==e&&(bR.contains?bR.contains(e):true)}}else{if(av.documentElement.compareDocumentPosition){by.contains=function(bR,e){return !!(bR.compareDocumentPosition(e)&16)}}else{by.contains=function(){return false}}}by.isXML=function(e){var bR=(e?e.ownerDocument||e:0).documentElement;return bR?bR.nodeName!=="HTML":false};var bM=function(bS,e,bW){var bV,bX=[],bU="",bY=e.nodeType?[e]:e;while((bV=bE.match.PSEUDO.exec(bS))){bU+=bV[0];bS=bS.replace(bE.match.PSEUDO,"")}bS=bE.relative[bS]?bS+"*":bS;for(var bT=0,bR=bY.length;bT0){for(bB=bA;bB=0:b.filter(e,this).length>0:this.filter(e).length>0)},closest:function(by,bx){var bv=[],bw,e,bz=this[0];if(b.isArray(by)){var bB=1;while(bz&&bz.ownerDocument&&bz!==bx){for(bw=0;bw-1:b.find.matchesSelector(bz,by)){bv.push(bz);break}else{bz=bz.parentNode;if(!bz||!bz.ownerDocument||bz===bx||bz.nodeType===11){break}}}}bv=bv.length>1?b.unique(bv):bv;return this.pushStack(bv,"closest",by)},index:function(e){if(!e){return(this[0]&&this[0].parentNode)?this.prevAll().length:-1}if(typeof e==="string"){return b.inArray(this[0],b(e))}return b.inArray(e.jquery?e[0]:e,this)},add:function(e,bv){var bx=typeof e==="string"?b(e,bv):b.makeArray(e&&e.nodeType?[e]:e),bw=b.merge(this.get(),bx);return this.pushStack(B(bx[0])||B(bw[0])?bw:b.unique(bw))},andSelf:function(){return this.add(this.prevObject)}});function B(e){return !e||!e.parentNode||e.parentNode.nodeType===11}b.each({parent:function(bv){var e=bv.parentNode;return e&&e.nodeType!==11?e:null},parents:function(e){return b.dir(e,"parentNode")},parentsUntil:function(bv,e,bw){return b.dir(bv,"parentNode",bw)},next:function(e){return b.nth(e,2,"nextSibling")},prev:function(e){return b.nth(e,2,"previousSibling")},nextAll:function(e){return b.dir(e,"nextSibling")},prevAll:function(e){return b.dir(e,"previousSibling")},nextUntil:function(bv,e,bw){return b.dir(bv,"nextSibling",bw)},prevUntil:function(bv,e,bw){return b.dir(bv,"previousSibling",bw)},siblings:function(e){return b.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return b.sibling(e.firstChild)},contents:function(e){return b.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:b.makeArray(e.childNodes)}},function(e,bv){b.fn[e]=function(by,bw){var bx=b.map(this,bv,by);if(!ab.test(e)){bw=by}if(bw&&typeof bw==="string"){bx=b.filter(bw,bx)}bx=this.length>1&&!ay[e]?b.unique(bx):bx;if((this.length>1||bb.test(bw))&&aq.test(e)){bx=bx.reverse()}return this.pushStack(bx,e,P.call(arguments).join(","))}});b.extend({filter:function(bw,e,bv){if(bv){bw=":not("+bw+")"}return e.length===1?b.find.matchesSelector(e[0],bw)?[e[0]]:[]:b.find.matches(bw,e)},dir:function(bw,bv,by){var e=[],bx=bw[bv];while(bx&&bx.nodeType!==9&&(by===L||bx.nodeType!==1||!b(bx).is(by))){if(bx.nodeType===1){e.push(bx)}bx=bx[bv]}return e},nth:function(by,e,bw,bx){e=e||1;var bv=0;for(;by;by=by[bw]){if(by.nodeType===1&&++bv===e){break}}return by},sibling:function(bw,bv){var e=[];for(;bw;bw=bw.nextSibling){if(bw.nodeType===1&&bw!==bv){e.push(bw)}}return e}});function aH(bx,bw,e){bw=bw||0;if(b.isFunction(bw)){return b.grep(bx,function(bz,by){var bA=!!bw.call(bz,by,bz);return bA===e})}else{if(bw.nodeType){return b.grep(bx,function(bz,by){return(bz===bw)===e})}else{if(typeof bw==="string"){var bv=b.grep(bx,function(by){return by.nodeType===1});if(bp.test(bw)){return b.filter(bw,bv,!e)}else{bw=b.filter(bw,bv)}}}}return b.grep(bx,function(bz,by){return(b.inArray(bz,bw)>=0)===e})}function a(e){var bw=aS.split("|"),bv=e.createDocumentFragment();if(bv.createElement){while(bw.length){bv.createElement(bw.pop())}}return bv}var aS="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ah=/ jQuery\d+="(?:\d+|null)"/g,ar=/^\s+/,R=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,d=/<([\w:]+)/,v=/
                  ]","i"),o=/checked\s*(?:[^=]|=\s*.checked.)/i,bn=/\/(java|ecma)script/i,aO=/^\s*",""],legend:[1,"
                  ","
                  "],thead:[1,"
                  ","
                  "],tr:[2,"","
                  "],td:[3,"","
                  "],col:[2,"","
                  "],area:[1,"",""],_default:[0,"",""]},ac=a(av);ax.optgroup=ax.option;ax.tbody=ax.tfoot=ax.colgroup=ax.caption=ax.thead;ax.th=ax.td;if(!b.support.htmlSerialize){ax._default=[1,"div
                  ","
                  "]}b.fn.extend({text:function(e){return b.access(this,function(bv){return bv===L?b.text(this):this.empty().append((this[0]&&this[0].ownerDocument||av).createTextNode(bv))},null,e,arguments.length)},wrapAll:function(e){if(b.isFunction(e)){return this.each(function(bw){b(this).wrapAll(e.call(this,bw))})}if(this[0]){var bv=b(e,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){bv.insertBefore(this[0])}bv.map(function(){var bw=this;while(bw.firstChild&&bw.firstChild.nodeType===1){bw=bw.firstChild}return bw}).append(this)}return this},wrapInner:function(e){if(b.isFunction(e)){return this.each(function(bv){b(this).wrapInner(e.call(this,bv))})}return this.each(function(){var bv=b(this),bw=bv.contents();if(bw.length){bw.wrapAll(e)}else{bv.append(e)}})},wrap:function(e){var bv=b.isFunction(e);return this.each(function(bw){b(this).wrapAll(bv?e.call(this,bw):e)})},unwrap:function(){return this.parent().each(function(){if(!b.nodeName(this,"body")){b(this).replaceWith(this.childNodes)}}).end()},append:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.appendChild(e)}})},prepend:function(){return this.domManip(arguments,true,function(e){if(this.nodeType===1){this.insertBefore(e,this.firstChild)}})},before:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this)})}else{if(arguments.length){var e=b.clean(arguments);e.push.apply(e,this.toArray());return this.pushStack(e,"before",arguments)}}},after:function(){if(this[0]&&this[0].parentNode){return this.domManip(arguments,false,function(bv){this.parentNode.insertBefore(bv,this.nextSibling)})}else{if(arguments.length){var e=this.pushStack(this,"after",arguments);e.push.apply(e,b.clean(arguments));return e}}},remove:function(e,bx){for(var bv=0,bw;(bw=this[bv])!=null;bv++){if(!e||b.filter(e,[bw]).length){if(!bx&&bw.nodeType===1){b.cleanData(bw.getElementsByTagName("*"));b.cleanData([bw])}if(bw.parentNode){bw.parentNode.removeChild(bw)}}}return this},empty:function(){for(var e=0,bv;(bv=this[e])!=null;e++){if(bv.nodeType===1){b.cleanData(bv.getElementsByTagName("*"))}while(bv.firstChild){bv.removeChild(bv.firstChild)}}return this},clone:function(bv,e){bv=bv==null?false:bv;e=e==null?bv:e;return this.map(function(){return b.clone(this,bv,e)})},html:function(e){return b.access(this,function(by){var bx=this[0]||{},bw=0,bv=this.length;if(by===L){return bx.nodeType===1?bx.innerHTML.replace(ah,""):null}if(typeof by==="string"&&!ae.test(by)&&(b.support.leadingWhitespace||!ar.test(by))&&!ax[(d.exec(by)||["",""])[1].toLowerCase()]){by=by.replace(R,"<$1>");try{for(;bw1&&bw0?this.clone(true):this).get();b(bC[bA])[bv](by);bz=bz.concat(by)}return this.pushStack(bz,e,bC.selector)}}});function bh(e){if(typeof e.getElementsByTagName!=="undefined"){return e.getElementsByTagName("*")}else{if(typeof e.querySelectorAll!=="undefined"){return e.querySelectorAll("*")}else{return[]}}}function az(e){if(e.type==="checkbox"||e.type==="radio"){e.defaultChecked=e.checked}}function D(e){var bv=(e.nodeName||"").toLowerCase();if(bv==="input"){az(e)}else{if(bv!=="script"&&typeof e.getElementsByTagName!=="undefined"){b.grep(e.getElementsByTagName("input"),az)}}}function am(e){var bv=av.createElement("div");ac.appendChild(bv);bv.innerHTML=e.outerHTML;return bv.firstChild}b.extend({clone:function(by,bA,bw){var e,bv,bx,bz=b.support.html5Clone||b.isXMLDoc(by)||!ai.test("<"+by.nodeName+">")?by.cloneNode(true):am(by);if((!b.support.noCloneEvent||!b.support.noCloneChecked)&&(by.nodeType===1||by.nodeType===11)&&!b.isXMLDoc(by)){aj(by,bz);e=bh(by);bv=bh(bz);for(bx=0;e[bx];++bx){if(bv[bx]){aj(e[bx],bv[bx])}}}if(bA){s(by,bz);if(bw){e=bh(by);bv=bh(bz);for(bx=0;e[bx];++bx){s(e[bx],bv[bx])}}}e=bv=null;return bz},clean:function(bI,bw,bv,bx){var bA,bH,bD,bJ=[];bw=bw||av;if(typeof bw.createElement==="undefined"){bw=bw.ownerDocument||bw[0]&&bw[0].ownerDocument||av}for(var bE=0,bG;(bG=bI[bE])!=null;bE++){if(typeof bG==="number"){bG+=""}if(!bG){continue}if(typeof bG==="string"){if(!W.test(bG)){bG=bw.createTextNode(bG)}else{bG=bG.replace(R,"<$1>");var bN=(d.exec(bG)||["",""])[1].toLowerCase(),bz=ax[bN]||ax._default,bK=bz[0],bB=bw.createElement("div"),bL=ac.childNodes,bM;if(bw===av){ac.appendChild(bB)}else{a(bw).appendChild(bB)}bB.innerHTML=bz[1]+bG+bz[2];while(bK--){bB=bB.lastChild}if(!b.support.tbody){var by=v.test(bG),e=bN==="table"&&!by?bB.firstChild&&bB.firstChild.childNodes:bz[1]===""&&!by?bB.childNodes:[];for(bD=e.length-1;bD>=0;--bD){if(b.nodeName(e[bD],"tbody")&&!e[bD].childNodes.length){e[bD].parentNode.removeChild(e[bD])}}}if(!b.support.leadingWhitespace&&ar.test(bG)){bB.insertBefore(bw.createTextNode(ar.exec(bG)[0]),bB.firstChild)}bG=bB.childNodes;if(bB){bB.parentNode.removeChild(bB);if(bL.length>0){bM=bL[bL.length-1];if(bM&&bM.parentNode){bM.parentNode.removeChild(bM)}}}}}var bF;if(!b.support.appendChecked){if(bG[0]&&typeof(bF=bG.length)==="number"){for(bD=0;bD1)};b.extend({cssHooks:{opacity:{get:function(bw,bv){if(bv){var e=Z(bw,"opacity");return e===""?"1":e}else{return bw.style.opacity}}}},cssNumber:{fillOpacity:true,fontWeight:true,lineHeight:true,opacity:true,orphans:true,widows:true,zIndex:true,zoom:true},cssProps:{"float":b.support.cssFloat?"cssFloat":"styleFloat"},style:function(bx,bw,bD,by){if(!bx||bx.nodeType===3||bx.nodeType===8||!bx.style){return}var bB,bC,bz=b.camelCase(bw),bv=bx.style,bE=b.cssHooks[bz];bw=b.cssProps[bz]||bz;if(bD!==L){bC=typeof bD;if(bC==="string"&&(bB=I.exec(bD))){bD=(+(bB[1]+1)*+bB[2])+parseFloat(b.css(bx,bw));bC="number"}if(bD==null||bC==="number"&&isNaN(bD)){return}if(bC==="number"&&!b.cssNumber[bz]){bD+="px"}if(!bE||!("set" in bE)||(bD=bE.set(bx,bD))!==L){try{bv[bw]=bD}catch(bA){}}}else{if(bE&&"get" in bE&&(bB=bE.get(bx,false,by))!==L){return bB}return bv[bw]}},css:function(by,bx,bv){var bw,e;bx=b.camelCase(bx);e=b.cssHooks[bx];bx=b.cssProps[bx]||bx;if(bx==="cssFloat"){bx="float"}if(e&&"get" in e&&(bw=e.get(by,true,bv))!==L){return bw}else{if(Z){return Z(by,bx)}}},swap:function(by,bx,bz){var e={},bw,bv;for(bv in bx){e[bv]=by.style[bv];by.style[bv]=bx[bv]}bw=bz.call(by);for(bv in bx){by.style[bv]=e[bv]}return bw}});b.curCSS=b.css;if(av.defaultView&&av.defaultView.getComputedStyle){aJ=function(bA,bw){var bv,bz,e,by,bx=bA.style;bw=bw.replace(y,"-$1").toLowerCase();if((bz=bA.ownerDocument.defaultView)&&(e=bz.getComputedStyle(bA,null))){bv=e.getPropertyValue(bw);if(bv===""&&!b.contains(bA.ownerDocument.documentElement,bA)){bv=b.style(bA,bw)}}if(!b.support.pixelMargin&&e&&aE.test(bw)&&a1.test(bv)){by=bx.width;bx.width=bv;bv=e.width;bx.width=by}return bv}}if(av.documentElement.currentStyle){aY=function(bz,bw){var bA,e,by,bv=bz.currentStyle&&bz.currentStyle[bw],bx=bz.style;if(bv==null&&bx&&(by=bx[bw])){bv=by}if(a1.test(bv)){bA=bx.left;e=bz.runtimeStyle&&bz.runtimeStyle.left;if(e){bz.runtimeStyle.left=bz.currentStyle.left}bx.left=bw==="fontSize"?"1em":bv;bv=bx.pixelLeft+"px";bx.left=bA;if(e){bz.runtimeStyle.left=e}}return bv===""?"auto":bv}}Z=aJ||aY;function af(by,bw,bv){var bz=bw==="width"?by.offsetWidth:by.offsetHeight,bx=bw==="width"?1:0,e=4;if(bz>0){if(bv!=="border"){for(;bx=1&&b.trim(bw.replace(al,""))===""){bx.removeAttribute("filter");if(bv&&!bv.filter){return}}bx.filter=al.test(bw)?bw.replace(al,e):bw+" "+e}}}b(function(){if(!b.support.reliableMarginRight){b.cssHooks.marginRight={get:function(bv,e){return b.swap(bv,{display:"inline-block"},function(){if(e){return Z(bv,"margin-right")}else{return bv.style.marginRight}})}}}});if(b.expr&&b.expr.filters){b.expr.filters.hidden=function(bw){var bv=bw.offsetWidth,e=bw.offsetHeight;return(bv===0&&e===0)||(!b.support.reliableHiddenOffsets&&((bw.style&&bw.style.display)||b.css(bw,"display"))==="none")};b.expr.filters.visible=function(e){return !b.expr.filters.hidden(e)}}b.each({margin:"",padding:"",border:"Width"},function(e,bv){b.cssHooks[e+bv]={expand:function(by){var bx,bz=typeof by==="string"?by.split(" "):[by],bw={};for(bx=0;bx<4;bx++){bw[e+G[bx]+bv]=bz[bx]||bz[bx-2]||bz[0]}return bw}}});var k=/%20/g,ap=/\[\]$/,bs=/\r?\n/g,bq=/#.*$/,aD=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,a0=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,aN=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,aR=/^(?:GET|HEAD)$/,c=/^\/\//,M=/\?/,a7=/)<[^<]*)*<\/script>/gi,p=/^(?:select|textarea)/i,h=/\s+/,br=/([?&])_=[^&]*/,K=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,z=b.fn.load,aa={},q={},aF,r,aW=["*/"]+["*"];try{aF=bm.href}catch(aw){aF=av.createElement("a");aF.href="";aF=aF.href}r=K.exec(aF.toLowerCase())||[];function f(e){return function(by,bA){if(typeof by!=="string"){bA=by;by="*"}if(b.isFunction(bA)){var bx=by.toLowerCase().split(h),bw=0,bz=bx.length,bv,bB,bC;for(;bw=0){var e=bw.slice(by,bw.length);bw=bw.slice(0,by)}var bx="GET";if(bz){if(b.isFunction(bz)){bA=bz;bz=L}else{if(typeof bz==="object"){bz=b.param(bz,b.ajaxSettings.traditional);bx="POST"}}}var bv=this;b.ajax({url:bw,type:bx,dataType:"html",data:bz,complete:function(bC,bB,bD){bD=bC.responseText;if(bC.isResolved()){bC.done(function(bE){bD=bE});bv.html(e?b("
                  ").append(bD.replace(a7,"")).find(e):bD)}if(bA){bv.each(bA,[bD,bB,bC])}}});return this},serialize:function(){return b.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?b.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||p.test(this.nodeName)||a0.test(this.type))}).map(function(e,bv){var bw=b(this).val();return bw==null?null:b.isArray(bw)?b.map(bw,function(by,bx){return{name:bv.name,value:by.replace(bs,"\r\n")}}):{name:bv.name,value:bw.replace(bs,"\r\n")}}).get()}});b.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,bv){b.fn[bv]=function(bw){return this.on(bv,bw)}});b.each(["get","post"],function(e,bv){b[bv]=function(bw,by,bz,bx){if(b.isFunction(by)){bx=bx||bz;bz=by;by=L}return b.ajax({type:bv,url:bw,data:by,success:bz,dataType:bx})}});b.extend({getScript:function(e,bv){return b.get(e,L,bv,"script")},getJSON:function(e,bv,bw){return b.get(e,bv,bw,"json")},ajaxSetup:function(bv,e){if(e){an(bv,b.ajaxSettings)}else{e=bv;bv=b.ajaxSettings}an(bv,e);return bv},ajaxSettings:{url:aF,isLocal:aN.test(r[1]),global:true,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:true,async:true,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":aW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":bd.String,"text html":true,"text json":b.parseJSON,"text xml":b.parseXML},flatOptions:{context:true,url:true}},ajaxPrefilter:f(aa),ajaxTransport:f(q),ajax:function(bz,bx){if(typeof bz==="object"){bx=bz;bz=L}bx=bx||{};var bD=b.ajaxSetup({},bx),bS=bD.context||bD,bG=bS!==bD&&(bS.nodeType||bS instanceof b)?b(bS):b.event,bR=b.Deferred(),bN=b.Callbacks("once memory"),bB=bD.statusCode||{},bC,bH={},bO={},bQ,by,bL,bE,bI,bA=0,bw,bK,bJ={readyState:0,setRequestHeader:function(bT,bU){if(!bA){var e=bT.toLowerCase();bT=bO[e]=bO[e]||bT;bH[bT]=bU}return this},getAllResponseHeaders:function(){return bA===2?bQ:null},getResponseHeader:function(bT){var e;if(bA===2){if(!by){by={};while((e=aD.exec(bQ))){by[e[1].toLowerCase()]=e[2]}}e=by[bT.toLowerCase()]}return e===L?null:e},overrideMimeType:function(e){if(!bA){bD.mimeType=e}return this},abort:function(e){e=e||"abort";if(bL){bL.abort(e)}bF(0,e);return this}};function bF(bZ,bU,b0,bW){if(bA===2){return}bA=2;if(bE){clearTimeout(bE)}bL=L;bQ=bW||"";bJ.readyState=bZ>0?4:0;var bT,b4,b3,bX=bU,bY=b0?bk(bD,bJ,b0):L,bV,b2;if(bZ>=200&&bZ<300||bZ===304){if(bD.ifModified){if((bV=bJ.getResponseHeader("Last-Modified"))){b.lastModified[bC]=bV}if((b2=bJ.getResponseHeader("Etag"))){b.etag[bC]=b2}}if(bZ===304){bX="notmodified";bT=true}else{try{b4=F(bD,bY);bX="success";bT=true}catch(b1){bX="parsererror";b3=b1}}}else{b3=bX;if(!bX||bZ){bX="error";if(bZ<0){bZ=0}}}bJ.status=bZ;bJ.statusText=""+(bU||bX);if(bT){bR.resolveWith(bS,[b4,bX,bJ])}else{bR.rejectWith(bS,[bJ,bX,b3])}bJ.statusCode(bB);bB=L;if(bw){bG.trigger("ajax"+(bT?"Success":"Error"),[bJ,bD,bT?b4:b3])}bN.fireWith(bS,[bJ,bX]);if(bw){bG.trigger("ajaxComplete",[bJ,bD]);if(!(--b.active)){b.event.trigger("ajaxStop")}}}bR.promise(bJ);bJ.success=bJ.done;bJ.error=bJ.fail;bJ.complete=bN.add;bJ.statusCode=function(bT){if(bT){var e;if(bA<2){for(e in bT){bB[e]=[bB[e],bT[e]]}}else{e=bT[bJ.status];bJ.then(e,e)}}return this};bD.url=((bz||bD.url)+"").replace(bq,"").replace(c,r[1]+"//");bD.dataTypes=b.trim(bD.dataType||"*").toLowerCase().split(h);if(bD.crossDomain==null){bI=K.exec(bD.url.toLowerCase());bD.crossDomain=!!(bI&&(bI[1]!=r[1]||bI[2]!=r[2]||(bI[3]||(bI[1]==="http:"?80:443))!=(r[3]||(r[1]==="http:"?80:443))))}if(bD.data&&bD.processData&&typeof bD.data!=="string"){bD.data=b.param(bD.data,bD.traditional)}aX(aa,bD,bx,bJ);if(bA===2){return false}bw=bD.global;bD.type=bD.type.toUpperCase();bD.hasContent=!aR.test(bD.type);if(bw&&b.active++===0){b.event.trigger("ajaxStart")}if(!bD.hasContent){if(bD.data){bD.url+=(M.test(bD.url)?"&":"?")+bD.data;delete bD.data}bC=bD.url;if(bD.cache===false){var bv=b.now(),bP=bD.url.replace(br,"$1_="+bv);bD.url=bP+((bP===bD.url)?(M.test(bD.url)?"&":"?")+"_="+bv:"")}}if(bD.data&&bD.hasContent&&bD.contentType!==false||bx.contentType){bJ.setRequestHeader("Content-Type",bD.contentType)}if(bD.ifModified){bC=bC||bD.url;if(b.lastModified[bC]){bJ.setRequestHeader("If-Modified-Since",b.lastModified[bC])}if(b.etag[bC]){bJ.setRequestHeader("If-None-Match",b.etag[bC])}}bJ.setRequestHeader("Accept",bD.dataTypes[0]&&bD.accepts[bD.dataTypes[0]]?bD.accepts[bD.dataTypes[0]]+(bD.dataTypes[0]!=="*"?", "+aW+"; q=0.01":""):bD.accepts["*"]);for(bK in bD.headers){bJ.setRequestHeader(bK,bD.headers[bK])}if(bD.beforeSend&&(bD.beforeSend.call(bS,bJ,bD)===false||bA===2)){bJ.abort();return false}for(bK in {success:1,error:1,complete:1}){bJ[bK](bD[bK])}bL=aX(q,bD,bx,bJ);if(!bL){bF(-1,"No Transport")}else{bJ.readyState=1;if(bw){bG.trigger("ajaxSend",[bJ,bD])}if(bD.async&&bD.timeout>0){bE=setTimeout(function(){bJ.abort("timeout")},bD.timeout)}try{bA=1;bL.send(bH,bF)}catch(bM){if(bA<2){bF(-1,bM)}else{throw bM}}}return bJ},param:function(e,bw){var bv=[],by=function(bz,bA){bA=b.isFunction(bA)?bA():bA;bv[bv.length]=encodeURIComponent(bz)+"="+encodeURIComponent(bA)};if(bw===L){bw=b.ajaxSettings.traditional}if(b.isArray(e)||(e.jquery&&!b.isPlainObject(e))){b.each(e,function(){by(this.name,this.value)})}else{for(var bx in e){u(bx,e[bx],bw,by)}}return bv.join("&").replace(k,"+")}});function u(bw,by,bv,bx){if(b.isArray(by)){b.each(by,function(bA,bz){if(bv||ap.test(bw)){bx(bw,bz)}else{u(bw+"["+(typeof bz==="object"?bA:"")+"]",bz,bv,bx)}})}else{if(!bv&&b.type(by)==="object"){for(var e in by){u(bw+"["+e+"]",by[e],bv,bx)}}else{bx(bw,by)}}}b.extend({active:0,lastModified:{},etag:{}});function bk(bD,bC,bz){var bv=bD.contents,bB=bD.dataTypes,bw=bD.responseFields,by,bA,bx,e;for(bA in bw){if(bA in bz){bC[bw[bA]]=bz[bA]}}while(bB[0]==="*"){bB.shift();if(by===L){by=bD.mimeType||bC.getResponseHeader("content-type")}}if(by){for(bA in bv){if(bv[bA]&&bv[bA].test(by)){bB.unshift(bA);break}}}if(bB[0] in bz){bx=bB[0]}else{for(bA in bz){if(!bB[0]||bD.converters[bA+" "+bB[0]]){bx=bA;break}if(!e){e=bA}}bx=bx||e}if(bx){if(bx!==bB[0]){bB.unshift(bx)}return bz[bx]}}function F(bH,bz){if(bH.dataFilter){bz=bH.dataFilter(bz,bH.dataType)}var bD=bH.dataTypes,bG={},bA,bE,bw=bD.length,bB,bC=bD[0],bx,by,bF,bv,e;for(bA=1;bA=bw.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();bw.animatedProperties[this.prop]=true;for(bA in bw.animatedProperties){if(bw.animatedProperties[bA]!==true){e=false}}if(e){if(bw.overflow!=null&&!b.support.shrinkWrapBlocks){b.each(["","X","Y"],function(bC,bD){bz.style["overflow"+bD]=bw.overflow[bC]})}if(bw.hide){b(bz).hide()}if(bw.hide||bw.show){for(bA in bw.animatedProperties){b.style(bz,bA,bw.orig[bA]);b.removeData(bz,"fxshow"+bA,true);b.removeData(bz,"toggle"+bA,true)}}bv=bw.complete;if(bv){bw.complete=false;bv.call(bz)}}return false}else{if(bw.duration==Infinity){this.now=bx}else{bB=bx-this.startTime;this.state=bB/bw.duration;this.pos=b.easing[bw.animatedProperties[this.prop]](this.state,bB,0,1,bw.duration);this.now=this.start+((this.end-this.start)*this.pos)}this.update()}return true}};b.extend(b.fx,{tick:function(){var bw,bv=b.timers,e=0;for(;e").appendTo(e),bw=bv.css("display");bv.remove();if(bw==="none"||bw===""){if(!ba){ba=av.createElement("iframe");ba.frameBorder=ba.width=ba.height=0}e.appendChild(ba);if(!m||!ba.createElement){m=(ba.contentWindow||ba.contentDocument).document;m.write((b.support.boxModel?"":"")+"");m.close()}bv=m.createElement(bx);m.body.appendChild(bv);bw=b.css(bv,"display");e.removeChild(ba)}Q[bx]=bw}return Q[bx]}var a8,V=/^t(?:able|d|h)$/i,ad=/^(?:body|html)$/i;if("getBoundingClientRect" in av.documentElement){a8=function(by,bH,bw,bB){try{bB=by.getBoundingClientRect()}catch(bF){}if(!bB||!b.contains(bw,by)){return bB?{top:bB.top,left:bB.left}:{top:0,left:0}}var bC=bH.body,bD=aL(bH),bA=bw.clientTop||bC.clientTop||0,bE=bw.clientLeft||bC.clientLeft||0,bv=bD.pageYOffset||b.support.boxModel&&bw.scrollTop||bC.scrollTop,bz=bD.pageXOffset||b.support.boxModel&&bw.scrollLeft||bC.scrollLeft,bG=bB.top+bv-bA,bx=bB.left+bz-bE;return{top:bG,left:bx}}}else{a8=function(bz,bE,bx){var bC,bw=bz.offsetParent,bv=bz,bA=bE.body,bB=bE.defaultView,e=bB?bB.getComputedStyle(bz,null):bz.currentStyle,bD=bz.offsetTop,by=bz.offsetLeft;while((bz=bz.parentNode)&&bz!==bA&&bz!==bx){if(b.support.fixedPosition&&e.position==="fixed"){break}bC=bB?bB.getComputedStyle(bz,null):bz.currentStyle;bD-=bz.scrollTop;by-=bz.scrollLeft;if(bz===bw){bD+=bz.offsetTop;by+=bz.offsetLeft;if(b.support.doesNotAddBorder&&!(b.support.doesAddBorderForTableAndCells&&V.test(bz.nodeName))){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}bv=bw;bw=bz.offsetParent}if(b.support.subtractsBorderForOverflowNotVisible&&bC.overflow!=="visible"){bD+=parseFloat(bC.borderTopWidth)||0;by+=parseFloat(bC.borderLeftWidth)||0}e=bC}if(e.position==="relative"||e.position==="static"){bD+=bA.offsetTop;by+=bA.offsetLeft}if(b.support.fixedPosition&&e.position==="fixed"){bD+=Math.max(bx.scrollTop,bA.scrollTop);by+=Math.max(bx.scrollLeft,bA.scrollLeft)}return{top:bD,left:by}}}b.fn.offset=function(e){if(arguments.length){return e===L?this:this.each(function(bx){b.offset.setOffset(this,e,bx)})}var bv=this[0],bw=bv&&bv.ownerDocument;if(!bw){return null}if(bv===bw.body){return b.offset.bodyOffset(bv)}return a8(bv,bw,bw.documentElement)};b.offset={bodyOffset:function(e){var bw=e.offsetTop,bv=e.offsetLeft;if(b.support.doesNotIncludeMarginInBodyOffset){bw+=parseFloat(b.css(e,"marginTop"))||0;bv+=parseFloat(b.css(e,"marginLeft"))||0}return{top:bw,left:bv}},setOffset:function(bx,bG,bA){var bB=b.css(bx,"position");if(bB==="static"){bx.style.position="relative"}var bz=b(bx),bv=bz.offset(),e=b.css(bx,"top"),bE=b.css(bx,"left"),bF=(bB==="absolute"||bB==="fixed")&&b.inArray("auto",[e,bE])>-1,bD={},bC={},bw,by;if(bF){bC=bz.position();bw=bC.top;by=bC.left}else{bw=parseFloat(e)||0;by=parseFloat(bE)||0}if(b.isFunction(bG)){bG=bG.call(bx,bA,bv)}if(bG.top!=null){bD.top=(bG.top-bv.top)+bw}if(bG.left!=null){bD.left=(bG.left-bv.left)+by}if("using" in bG){bG.using.call(bx,bD)}else{bz.css(bD)}}};b.fn.extend({position:function(){if(!this[0]){return null}var bw=this[0],bv=this.offsetParent(),bx=this.offset(),e=ad.test(bv[0].nodeName)?{top:0,left:0}:bv.offset();bx.top-=parseFloat(b.css(bw,"marginTop"))||0;bx.left-=parseFloat(b.css(bw,"marginLeft"))||0;e.top+=parseFloat(b.css(bv[0],"borderTopWidth"))||0;e.left+=parseFloat(b.css(bv[0],"borderLeftWidth"))||0;return{top:bx.top-e.top,left:bx.left-e.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||av.body;while(e&&(!ad.test(e.nodeName)&&b.css(e,"position")==="static")){e=e.offsetParent}return e})}});b.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(bw,bv){var e=/Y/.test(bv);b.fn[bw]=function(bx){return b.access(this,function(by,bB,bA){var bz=aL(by);if(bA===L){return bz?(bv in bz)?bz[bv]:b.support.boxModel&&bz.document.documentElement[bB]||bz.document.body[bB]:by[bB]}if(bz){bz.scrollTo(!e?bA:b(bz).scrollLeft(),e?bA:b(bz).scrollTop())}else{by[bB]=bA}},bw,bx,arguments.length,null)}});function aL(e){return b.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:false}b.each({Height:"height",Width:"width"},function(bw,bx){var bv="client"+bw,e="scroll"+bw,by="offset"+bw;b.fn["inner"+bw]=function(){var bz=this[0];return bz?bz.style?parseFloat(b.css(bz,bx,"padding")):this[bx]():null};b.fn["outer"+bw]=function(bA){var bz=this[0];return bz?bz.style?parseFloat(b.css(bz,bx,bA?"margin":"border")):this[bx]():null};b.fn[bx]=function(bz){return b.access(this,function(bC,bB,bD){var bF,bE,bG,bA;if(b.isWindow(bC)){bF=bC.document;bE=bF.documentElement[bv];return b.support.boxModel&&bE||bF.body&&bF.body[bv]||bE}if(bC.nodeType===9){bF=bC.documentElement;if(bF[bv]>=bF[e]){return bF[bv]}return Math.max(bC.body[e],bF[e],bC.body[by],bF[by])}if(bD===L){bG=b.css(bC,bB);bA=parseFloat(bG);return b.isNumeric(bA)?bA:bG}b(bC).css(bB,bD)},bx,bz,arguments.length,null)}});bd.jQuery=bd.$=b;if(typeof define==="function"&&define.amd&&define.amd.jQuery){define("jquery",[],function(){return b})}})(window);/*! * jQuery UI 1.8.18 * * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about) @@ -65,4 +65,23 @@ Released under MIT license. https://raw.github.com/stevenbenner/jquery-powertip/master/LICENSE.txt */ -(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{a(jQuery)}}(function(k){var A=k(document),s=k(window),w=k("body");var n="displayController",e="hasActiveHover",d="forcedOpen",u="hasMouseMove",f="mouseOnToPopup",g="originalTitle",y="powertip",o="powertipjq",l="powertiptarget",E=180/Math.PI;var c={isTipOpen:false,isFixedTipOpen:false,isClosing:false,tipOpenImminent:false,activeHover:null,currentX:0,currentY:0,previousX:0,previousY:0,desyncTimeout:null,mouseTrackingActive:false,delayInProgress:false,windowWidth:0,windowHeight:0,scrollTop:0,scrollLeft:0};var p={none:0,top:1,bottom:2,left:4,right:8};k.fn.powerTip=function(F,N){if(!this.length){return this}if(k.type(F)==="string"&&k.powerTip[F]){return k.powerTip[F].call(this,this,N)}var O=k.extend({},k.fn.powerTip.defaults,F),G=new x(O);h();this.each(function M(){var R=k(this),Q=R.data(y),P=R.data(o),T=R.data(l),S;if(R.data(n)){k.powerTip.destroy(R)}S=R.attr("title");if(!Q&&!T&&!P&&S){R.data(y,S);R.data(g,S);R.removeAttr("title")}R.data(n,new t(R,O,G))});if(!O.manual){this.on({"mouseenter.powertip":function J(P){k.powerTip.show(this,P)},"mouseleave.powertip":function L(){k.powerTip.hide(this)},"focus.powertip":function K(){k.powerTip.show(this)},"blur.powertip":function H(){k.powerTip.hide(this,true)},"keydown.powertip":function I(P){if(P.keyCode===27){k.powerTip.hide(this,true)}}})}return this};k.fn.powerTip.defaults={fadeInTime:200,fadeOutTime:100,followMouse:false,popupId:"powerTip",intentSensitivity:7,intentPollInterval:100,closeDelay:100,placement:"n",smartPlacement:false,offset:10,mouseOnToPopup:false,manual:false};k.fn.powerTip.smartPlacementLists={n:["n","ne","nw","s"],e:["e","ne","se","w","nw","sw","n","s","e"],s:["s","se","sw","n"],w:["w","nw","sw","e","ne","se","n","s","w"],nw:["nw","w","sw","n","s","se","nw"],ne:["ne","e","se","n","s","sw","ne"],sw:["sw","w","nw","s","n","ne","sw"],se:["se","e","ne","s","n","nw","se"],"nw-alt":["nw-alt","n","ne-alt","sw-alt","s","se-alt","w","e"],"ne-alt":["ne-alt","n","nw-alt","se-alt","s","sw-alt","e","w"],"sw-alt":["sw-alt","s","se-alt","nw-alt","n","ne-alt","w","e"],"se-alt":["se-alt","s","sw-alt","ne-alt","n","nw-alt","e","w"]};k.powerTip={show:function z(F,G){if(G){i(G);c.previousX=G.pageX;c.previousY=G.pageY;k(F).data(n).show()}else{k(F).first().data(n).show(true,true)}return F},reposition:function r(F){k(F).first().data(n).resetPosition();return F},hide:function D(G,F){if(G){k(G).first().data(n).hide(F)}else{if(c.activeHover){c.activeHover.data(n).hide(true)}}return G},destroy:function C(G){k(G).off(".powertip").each(function F(){var I=k(this),H=[g,n,e,d];if(I.data(g)){I.attr("title",I.data(g));H.push(y)}I.removeData(H)});return G}};k.powerTip.showTip=k.powerTip.show;k.powerTip.closeTip=k.powerTip.hide;function b(){var F=this;F.top="auto";F.left="auto";F.right="auto";F.bottom="auto";F.set=function(H,G){if(k.isNumeric(G)){F[H]=Math.round(G)}}}function t(K,N,F){var J=null;function L(P,Q){M();if(!K.data(e)){if(!P){c.tipOpenImminent=true;J=setTimeout(function O(){J=null;I()},N.intentPollInterval)}else{if(Q){K.data(d,true)}F.showTip(K)}}}function G(P){M();c.tipOpenImminent=false;if(K.data(e)){K.data(d,false);if(!P){c.delayInProgress=true;J=setTimeout(function O(){J=null;F.hideTip(K);c.delayInProgress=false},N.closeDelay)}else{F.hideTip(K)}}}function I(){var Q=Math.abs(c.previousX-c.currentX),O=Math.abs(c.previousY-c.currentY),P=Q+O;if(P",{id:Q.popupId});if(w.length===0){w=k("body")}w.append(O)}if(Q.followMouse){if(!O.data(u)){A.on("mousemove",M);s.on("scroll",M);O.data(u,true)}}if(Q.mouseOnToPopup){O.on({mouseenter:function L(){if(O.data(f)){if(c.activeHover){c.activeHover.data(n).cancel()}}},mouseleave:function N(){if(c.activeHover){c.activeHover.data(n).hide()}}})}function I(S){S.data(e,true);O.queue(function R(T){H(S);T()})}function H(S){var U;if(!S.data(e)){return}if(c.isTipOpen){if(!c.isClosing){K(c.activeHover)}O.delay(100).queue(function R(V){H(S);V()});return}S.trigger("powerTipPreRender");U=B(S);if(U){O.empty().append(U)}else{return}S.trigger("powerTipRender");c.activeHover=S;c.isTipOpen=true;O.data(f,Q.mouseOnToPopup);if(!Q.followMouse){G(S);c.isFixedTipOpen=true}else{M()}O.fadeIn(Q.fadeInTime,function T(){if(!c.desyncTimeout){c.desyncTimeout=setInterval(J,500)}S.trigger("powerTipOpen")})}function K(R){c.isClosing=true;c.activeHover=null;c.isTipOpen=false;c.desyncTimeout=clearInterval(c.desyncTimeout);R.data(e,false);R.data(d,false);O.fadeOut(Q.fadeOutTime,function S(){var T=new b();c.isClosing=false;c.isFixedTipOpen=false;O.removeClass();T.set("top",c.currentY+Q.offset);T.set("left",c.currentX+Q.offset);O.css(T);R.trigger("powerTipClose")})}function M(){if(!c.isFixedTipOpen&&(c.isTipOpen||(c.tipOpenImminent&&O.data(u)))){var R=O.outerWidth(),V=O.outerHeight(),U=new b(),S,T;U.set("top",c.currentY+Q.offset);U.set("left",c.currentX+Q.offset);S=m(U,R,V);if(S!==p.none){T=a(S);if(T===1){if(S===p.right){U.set("left",c.windowWidth-R)}else{if(S===p.bottom){U.set("top",c.scrollTop+c.windowHeight-V)}}}else{U.set("left",c.currentX-R-Q.offset);U.set("top",c.currentY-V-Q.offset)}}O.css(U)}}function G(S){var R,T;if(Q.smartPlacement){R=k.fn.powerTip.smartPlacementLists[Q.placement];k.each(R,function(U,W){var V=m(F(S,W),O.outerWidth(),O.outerHeight());T=W;if(V===p.none){return false}})}else{F(S,Q.placement);T=Q.placement}O.addClass(T)}function F(U,T){var R=0,S,W,V=new b();V.set("top",0);V.set("left",0);O.css(V);do{S=O.outerWidth();W=O.outerHeight();V=P.compute(U,T,S,W,Q.offset);O.css(V)}while(++R<=5&&(S!==O.outerWidth()||W!==O.outerHeight()));return V}function J(){var R=false;if(c.isTipOpen&&!c.isClosing&&!c.delayInProgress){if(c.activeHover.data(e)===false||c.activeHover.is(":disabled")){R=true}else{if(!v(c.activeHover)&&!c.activeHover.is(":focus")&&!c.activeHover.data(d)){if(O.data(f)){if(!v(O)){R=true}}else{R=true}}}if(R){K(c.activeHover)}}}this.showTip=I;this.hideTip=K;this.resetPosition=G}function q(F){return window.SVGElement&&F[0] instanceof SVGElement}function h(){if(!c.mouseTrackingActive){c.mouseTrackingActive=true;k(function H(){c.scrollLeft=s.scrollLeft();c.scrollTop=s.scrollTop();c.windowWidth=s.width();c.windowHeight=s.height()});A.on("mousemove",i);s.on({resize:function G(){c.windowWidth=s.width();c.windowHeight=s.height()},scroll:function F(){var I=s.scrollLeft(),J=s.scrollTop();if(I!==c.scrollLeft){c.currentX+=I-c.scrollLeft;c.scrollLeft=I}if(J!==c.scrollTop){c.currentY+=J-c.scrollTop;c.scrollTop=J}}})}}function i(F){c.currentX=F.pageX;c.currentY=F.pageY}function v(F){var H=F.offset(),J=F[0].getBoundingClientRect(),I=J.right-J.left,G=J.bottom-J.top;return c.currentX>=H.left&&c.currentX<=H.left+I&&c.currentY>=H.top&&c.currentY<=H.top+G}function B(I){var G=I.data(y),F=I.data(o),K=I.data(l),H,J;if(G){if(k.isFunction(G)){G=G.call(I[0])}J=G}else{if(F){if(k.isFunction(F)){F=F.call(I[0])}if(F.length>0){J=F.clone(true,true)}}else{if(K){H=k("#"+K);if(H.length>0){J=H.html()}}}}return J}function m(M,L,K){var G=c.scrollTop,J=c.scrollLeft,I=G+c.windowHeight,F=J+c.windowWidth,H=p.none;if(M.topI||Math.abs(M.bottom-c.windowHeight)>I){H|=p.bottom}if(M.leftF){H|=p.left}if(M.left+L>F||M.right",{id:Q.popupId});if(w.length===0){w=k("body")}w.append(O)}if(Q.followMouse){if(!O.data(u)){A.on("mousemove",M);s.on("scroll",M);O.data(u,true)}}if(Q.mouseOnToPopup){O.on({mouseenter:function L(){if(O.data(f)){if(c.activeHover){c.activeHover.data(n).cancel()}}},mouseleave:function N(){if(c.activeHover){c.activeHover.data(n).hide()}}})}function I(S){S.data(e,true);O.queue(function R(T){H(S);T()})}function H(S){var U;if(!S.data(e)){return}if(c.isTipOpen){if(!c.isClosing){K(c.activeHover)}O.delay(100).queue(function R(V){H(S);V()});return}S.trigger("powerTipPreRender");U=B(S);if(U){O.empty().append(U)}else{return}S.trigger("powerTipRender");c.activeHover=S;c.isTipOpen=true;O.data(f,Q.mouseOnToPopup);if(!Q.followMouse){G(S);c.isFixedTipOpen=true}else{M()}O.fadeIn(Q.fadeInTime,function T(){if(!c.desyncTimeout){c.desyncTimeout=setInterval(J,500)}S.trigger("powerTipOpen")})}function K(R){c.isClosing=true;c.activeHover=null;c.isTipOpen=false;c.desyncTimeout=clearInterval(c.desyncTimeout);R.data(e,false);R.data(d,false);O.fadeOut(Q.fadeOutTime,function S(){var T=new b();c.isClosing=false;c.isFixedTipOpen=false;O.removeClass();T.set("top",c.currentY+Q.offset);T.set("left",c.currentX+Q.offset);O.css(T);R.trigger("powerTipClose")})}function M(){if(!c.isFixedTipOpen&&(c.isTipOpen||(c.tipOpenImminent&&O.data(u)))){var R=O.outerWidth(),V=O.outerHeight(),U=new b(),S,T;U.set("top",c.currentY+Q.offset);U.set("left",c.currentX+Q.offset);S=m(U,R,V);if(S!==p.none){T=a(S);if(T===1){if(S===p.right){U.set("left",c.windowWidth-R)}else{if(S===p.bottom){U.set("top",c.scrollTop+c.windowHeight-V)}}}else{U.set("left",c.currentX-R-Q.offset);U.set("top",c.currentY-V-Q.offset)}}O.css(U)}}function G(S){var R,T;if(Q.smartPlacement){R=k.fn.powerTip.smartPlacementLists[Q.placement];k.each(R,function(U,W){var V=m(F(S,W),O.outerWidth(),O.outerHeight());T=W;if(V===p.none){return false}})}else{F(S,Q.placement);T=Q.placement}O.addClass(T)}function F(U,T){var R=0,S,W,V=new b();V.set("top",0);V.set("left",0);O.css(V);do{S=O.outerWidth();W=O.outerHeight();V=P.compute(U,T,S,W,Q.offset);O.css(V)}while(++R<=5&&(S!==O.outerWidth()||W!==O.outerHeight()));return V}function J(){var R=false;if(c.isTipOpen&&!c.isClosing&&!c.delayInProgress){if(c.activeHover.data(e)===false||c.activeHover.is(":disabled")){R=true}else{if(!v(c.activeHover)&&!c.activeHover.is(":focus")&&!c.activeHover.data(d)){if(O.data(f)){if(!v(O)){R=true}}else{R=true}}}if(R){K(c.activeHover)}}}this.showTip=I;this.hideTip=K;this.resetPosition=G}function q(F){return window.SVGElement&&F[0] instanceof SVGElement}function h(){if(!c.mouseTrackingActive){c.mouseTrackingActive=true;k(function H(){c.scrollLeft=s.scrollLeft();c.scrollTop=s.scrollTop();c.windowWidth=s.width();c.windowHeight=s.height()});A.on("mousemove",i);s.on({resize:function G(){c.windowWidth=s.width();c.windowHeight=s.height()},scroll:function F(){var I=s.scrollLeft(),J=s.scrollTop();if(I!==c.scrollLeft){c.currentX+=I-c.scrollLeft;c.scrollLeft=I}if(J!==c.scrollTop){c.currentY+=J-c.scrollTop;c.scrollTop=J}}})}}function i(F){c.currentX=F.pageX;c.currentY=F.pageY}function v(F){var H=F.offset(),J=F[0].getBoundingClientRect(),I=J.right-J.left,G=J.bottom-J.top;return c.currentX>=H.left&&c.currentX<=H.left+I&&c.currentY>=H.top&&c.currentY<=H.top+G}function B(I){var G=I.data(y),F=I.data(o),K=I.data(l),H,J;if(G){if(k.isFunction(G)){G=G.call(I[0])}J=G}else{if(F){if(k.isFunction(F)){F=F.call(I[0])}if(F.length>0){J=F.clone(true,true)}}else{if(K){H=k("#"+K);if(H.length>0){J=H.html()}}}}return J}function m(M,L,K){var G=c.scrollTop,J=c.scrollLeft,I=G+c.windowHeight,F=J+c.windowWidth,H=p.none;if(M.topI||Math.abs(M.bottom-c.windowHeight)>I){H|=p.bottom}if(M.leftF){H|=p.left}if(M.left+L>F||M.right1){return}h.preventDefault();var j=h.originalEvent.changedTouches[0],g=document.createEvent("MouseEvents");g.initMouseEvent(i,true,true,window,1,j.screenX,j.screenY,j.clientX,j.clientY,false,false,false,false,0,null);h.target.dispatchEvent(g)}d._touchStart=function(h){var g=this;if(a||!g._mouseCapture(h.originalEvent.changedTouches[0])){return}a=true;g._touchMoved=false;e(h,"mouseover");e(h,"mousemove");e(h,"mousedown")};d._touchMove=function(g){if(!a){return}this._touchMoved=true;e(g,"mousemove")};d._touchEnd=function(g){if(!a){return}e(g,"mouseup");e(g,"mouseout");if(!this._touchMoved){e(g,"click")}a=false};d._mouseInit=function(){var g=this;g.element.bind({touchstart:b.proxy(g,"_touchStart"),touchmove:b.proxy(g,"_touchMove"),touchend:b.proxy(g,"_touchEnd")});f.call(g)};d._mouseDestroy=function(){var g=this;g.element.unbind({touchstart:b.proxy(g,"_touchStart"),touchmove:b.proxy(g,"_touchMove"),touchend:b.proxy(g,"_touchEnd")});c.call(g)}})(jQuery);/*! + * SmartMenus jQuery Plugin - v1.0.0 - January 27, 2016 + * http://www.smartmenus.org/ + * + * Copyright Vasil Dinkov, Vadikom Web Ltd. + * http://vadikom.com + * + * Licensed MIT + */ +(function(a){if(typeof define==="function"&&define.amd){define(["jquery"],a)}else{if(typeof module==="object"&&typeof module.exports==="object"){module.exports=a(require("jquery"))}else{a(jQuery)}}}(function(a){var b=[],e=!!window.createPopup,f=false,d="ontouchstart" in window,h=false,g=window.requestAnimationFrame||function(l){return setTimeout(l,1000/60)},c=window.cancelAnimationFrame||function(l){clearTimeout(l)};function k(m){var n=".smartmenus_mouse";if(!h&&!m){var o=true,l=null;a(document).bind(i([["mousemove",function(s){var t={x:s.pageX,y:s.pageY,timeStamp:new Date().getTime()};if(l){var q=Math.abs(l.x-t.x),p=Math.abs(l.y-t.y);if((q>0||p>0)&&q<=2&&p<=2&&t.timeStamp-l.timeStamp<=300){f=true;if(o){var r=a(s.target).closest("a");if(r.is("a")){a.each(b,function(){if(a.contains(this.$root[0],r[0])){this.itemEnter({currentTarget:r[0]});return false}})}o=false}}}l=t}],[d?"touchstart":"pointerover pointermove pointerout MSPointerOver MSPointerMove MSPointerOut",function(p){if(j(p.originalEvent)){f=false}}]],n));h=true}else{if(h&&m){a(document).unbind(n);h=false}}}function j(l){return !/^(4|mouse)$/.test(l.pointerType)}function i(l,n){if(!n){n=""}var m={};a.each(l,function(o,p){m[p[0].split(" ").join(n+" ")+n]=p[1]});return m}a.SmartMenus=function(m,l){this.$root=a(m);this.opts=l;this.rootId="";this.accessIdPrefix="";this.$subArrow=null;this.activatedItems=[];this.visibleSubMenus=[];this.showTimeout=0;this.hideTimeout=0;this.scrollTimeout=0;this.clickActivated=false;this.focusActivated=false;this.zIndexInc=0;this.idInc=0;this.$firstLink=null;this.$firstSub=null;this.disabled=false;this.$disableOverlay=null;this.$touchScrollingSub=null;this.cssTransforms3d="perspective" in m.style||"webkitPerspective" in m.style;this.wasCollapsible=false;this.init()};a.extend(a.SmartMenus,{hideAll:function(){a.each(b,function(){this.menuHideAll()})},destroy:function(){while(b.length){b[0].destroy()}k(true)},prototype:{init:function(n){var l=this;if(!n){b.push(this);this.rootId=(new Date().getTime()+Math.random()+"").replace(/\D/g,"");this.accessIdPrefix="sm-"+this.rootId+"-";if(this.$root.hasClass("sm-rtl")){this.opts.rightToLeftSubMenus=true}var r=".smartmenus";this.$root.data("smartmenus",this).attr("data-smartmenus-id",this.rootId).dataSM("level",1).bind(i([["mouseover focusin",a.proxy(this.rootOver,this)],["mouseout focusout",a.proxy(this.rootOut,this)],["keydown",a.proxy(this.rootKeyDown,this)]],r)).delegate("a",i([["mouseenter",a.proxy(this.itemEnter,this)],["mouseleave",a.proxy(this.itemLeave,this)],["mousedown",a.proxy(this.itemDown,this)],["focus",a.proxy(this.itemFocus,this)],["blur",a.proxy(this.itemBlur,this)],["click",a.proxy(this.itemClick,this)]],r));r+=this.rootId;if(this.opts.hideOnClick){a(document).bind(i([["touchstart",a.proxy(this.docTouchStart,this)],["touchmove",a.proxy(this.docTouchMove,this)],["touchend",a.proxy(this.docTouchEnd,this)],["click",a.proxy(this.docClick,this)]],r))}a(window).bind(i([["resize orientationchange",a.proxy(this.winResize,this)]],r));if(this.opts.subIndicators){this.$subArrow=a("").addClass("sub-arrow");if(this.opts.subIndicatorsText){this.$subArrow.html(this.opts.subIndicatorsText)}}k()}this.$firstSub=this.$root.find("ul").each(function(){l.menuInit(a(this))}).eq(0);this.$firstLink=this.$root.find("a").eq(0);if(this.opts.markCurrentItem){var p=/(index|default)\.[^#\?\/]*/i,m=/#.*/,q=window.location.href.replace(p,""),o=q.replace(m,"");this.$root.find("a").each(function(){var s=this.href.replace(p,""),t=a(this);if(s==q||s==o){t.addClass("current");if(l.opts.markCurrentTree){t.parentsUntil("[data-smartmenus-id]","ul").each(function(){a(this).dataSM("parent-a").addClass("current")})}}})}this.wasCollapsible=this.isCollapsible()},destroy:function(m){if(!m){var n=".smartmenus";this.$root.removeData("smartmenus").removeAttr("data-smartmenus-id").removeDataSM("level").unbind(n).undelegate(n);n+=this.rootId;a(document).unbind(n);a(window).unbind(n);if(this.opts.subIndicators){this.$subArrow=null}}this.menuHideAll();var l=this;this.$root.find("ul").each(function(){var o=a(this);if(o.dataSM("scroll-arrows")){o.dataSM("scroll-arrows").remove()}if(o.dataSM("shown-before")){if(l.opts.subMenusMinWidth||l.opts.subMenusMaxWidth){o.css({width:"",minWidth:"",maxWidth:""}).removeClass("sm-nowrap")}if(o.dataSM("scroll-arrows")){o.dataSM("scroll-arrows").remove()}o.css({zIndex:"",top:"",left:"",marginLeft:"",marginTop:"",display:""})}if((o.attr("id")||"").indexOf(l.accessIdPrefix)==0){o.removeAttr("id")}}).removeDataSM("in-mega").removeDataSM("shown-before").removeDataSM("ie-shim").removeDataSM("scroll-arrows").removeDataSM("parent-a").removeDataSM("level").removeDataSM("beforefirstshowfired").removeAttr("role").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeAttr("aria-expanded");this.$root.find("a.has-submenu").each(function(){var o=a(this);if(o.attr("id").indexOf(l.accessIdPrefix)==0){o.removeAttr("id")}}).removeClass("has-submenu").removeDataSM("sub").removeAttr("aria-haspopup").removeAttr("aria-controls").removeAttr("aria-expanded").closest("li").removeDataSM("sub");if(this.opts.subIndicators){this.$root.find("span.sub-arrow").remove()}if(this.opts.markCurrentItem){this.$root.find("a.current").removeClass("current")}if(!m){this.$root=null;this.$firstLink=null;this.$firstSub=null;if(this.$disableOverlay){this.$disableOverlay.remove();this.$disableOverlay=null}b.splice(a.inArray(this,b),1)}},disable:function(l){if(!this.disabled){this.menuHideAll();if(!l&&!this.opts.isPopup&&this.$root.is(":visible")){var m=this.$root.offset();this.$disableOverlay=a('
                  ').css({position:"absolute",top:m.top,left:m.left,width:this.$root.outerWidth(),height:this.$root.outerHeight(),zIndex:this.getStartZIndex(true),opacity:0}).appendTo(document.body)}this.disabled=true}},docClick:function(l){if(this.$touchScrollingSub){this.$touchScrollingSub=null;return}if(this.visibleSubMenus.length&&!a.contains(this.$root[0],l.target)||a(l.target).is("a")){this.menuHideAll()}},docTouchEnd:function(m){if(!this.lastTouch){return}if(this.visibleSubMenus.length&&(this.lastTouch.x2===undefined||this.lastTouch.x1==this.lastTouch.x2)&&(this.lastTouch.y2===undefined||this.lastTouch.y1==this.lastTouch.y2)&&(!this.lastTouch.target||!a.contains(this.$root[0],this.lastTouch.target))){if(this.hideTimeout){clearTimeout(this.hideTimeout);this.hideTimeout=0}var l=this;this.hideTimeout=setTimeout(function(){l.menuHideAll()},350)}this.lastTouch=null},docTouchMove:function(m){if(!this.lastTouch){return}var l=m.originalEvent.touches[0];this.lastTouch.x2=l.pageX;this.lastTouch.y2=l.pageY},docTouchStart:function(m){var l=m.originalEvent.touches[0];this.lastTouch={x1:l.pageX,y1:l.pageY,target:l.target}},enable:function(){if(this.disabled){if(this.$disableOverlay){this.$disableOverlay.remove();this.$disableOverlay=null}this.disabled=false}},getClosestMenu:function(m){var l=a(m).closest("ul");while(l.dataSM("in-mega")){l=l.parent().closest("ul")}return l[0]||null},getHeight:function(l){return this.getOffset(l,true)},getOffset:function(n,l){var m;if(n.css("display")=="none"){m={position:n[0].style.position,visibility:n[0].style.visibility};n.css({position:"absolute",visibility:"hidden"}).show()}var o=n[0].getBoundingClientRect&&n[0].getBoundingClientRect(),p=o&&(l?o.height||o.bottom-o.top:o.width||o.right-o.left);if(!p&&p!==0){p=l?n[0].offsetHeight:n[0].offsetWidth}if(m){n.hide().css(m)}return p},getStartZIndex:function(l){var m=parseInt(this[l?"$root":"$firstSub"].css("z-index"));if(!l&&isNaN(m)){m=parseInt(this.$root.css("z-index"))}return !isNaN(m)?m:1},getTouchPoint:function(l){return l.touches&&l.touches[0]||l.changedTouches&&l.changedTouches[0]||l},getViewport:function(l){var m=l?"Height":"Width",o=document.documentElement["client"+m],n=window["inner"+m];if(n){o=Math.min(o,n)}return o},getViewportHeight:function(){return this.getViewport(true)},getViewportWidth:function(){return this.getViewport()},getWidth:function(l){return this.getOffset(l)},handleEvents:function(){return !this.disabled&&this.isCSSOn()},handleItemEvents:function(l){return this.handleEvents()&&!this.isLinkInMegaMenu(l)},isCollapsible:function(){return this.$firstSub.css("position")=="static"},isCSSOn:function(){return this.$firstLink.css("display")=="block"},isFixed:function(){var l=this.$root.css("position")=="fixed";if(!l){this.$root.parentsUntil("body").each(function(){if(a(this).css("position")=="fixed"){l=true;return false}})}return l},isLinkInMegaMenu:function(l){return a(this.getClosestMenu(l[0])).hasClass("mega-menu")},isTouchMode:function(){return !f||this.opts.noMouseOver||this.isCollapsible()},itemActivate:function(p,l){var n=p.closest("ul"),q=n.dataSM("level");if(q>1&&(!this.activatedItems[q-2]||this.activatedItems[q-2][0]!=n.dataSM("parent-a")[0])){var m=this;a(n.parentsUntil("[data-smartmenus-id]","ul").get().reverse()).add(n).each(function(){m.itemActivate(a(this).dataSM("parent-a"))})}if(!this.isCollapsible()||l){this.menuHideSubMenus(!this.activatedItems[q-1]||this.activatedItems[q-1][0]!=p[0]?q-1:q)}this.activatedItems[q-1]=p;if(this.$root.triggerHandler("activate.smapi",p[0])===false){return}var o=p.dataSM("sub");if(o&&(this.isTouchMode()||(!this.opts.showOnClick||this.clickActivated))){this.menuShow(o)}},itemBlur:function(m){var l=a(m.currentTarget);if(!this.handleItemEvents(l)){return}this.$root.triggerHandler("blur.smapi",l[0])},itemClick:function(o){var n=a(o.currentTarget);if(!this.handleItemEvents(n)){return}if(this.$touchScrollingSub&&this.$touchScrollingSub[0]==n.closest("ul")[0]){this.$touchScrollingSub=null;o.stopPropagation();return false}if(this.$root.triggerHandler("click.smapi",n[0])===false){return false}var p=a(o.target).is("span.sub-arrow"),m=n.dataSM("sub"),l=m?m.dataSM("level")==2:false;if(m&&!m.is(":visible")){if(this.opts.showOnClick&&l){this.clickActivated=true}this.itemActivate(n);if(m.is(":visible")){this.focusActivated=true;return false}}else{if(this.isCollapsible()&&p){this.itemActivate(n);this.menuHide(m);return false}}if(this.opts.showOnClick&&l||n.hasClass("disabled")||this.$root.triggerHandler("select.smapi",n[0])===false){return false}},itemDown:function(m){var l=a(m.currentTarget);if(!this.handleItemEvents(l)){return}l.dataSM("mousedown",true)},itemEnter:function(n){var m=a(n.currentTarget);if(!this.handleItemEvents(m)){return}if(!this.isTouchMode()){if(this.showTimeout){clearTimeout(this.showTimeout);this.showTimeout=0}var l=this;this.showTimeout=setTimeout(function(){l.itemActivate(m)},this.opts.showOnClick&&m.closest("ul").dataSM("level")==1?1:this.opts.showTimeout)}this.$root.triggerHandler("mouseenter.smapi",m[0])},itemFocus:function(m){var l=a(m.currentTarget);if(!this.handleItemEvents(l)){return}if(this.focusActivated&&(!this.isTouchMode()||!l.dataSM("mousedown"))&&(!this.activatedItems.length||this.activatedItems[this.activatedItems.length-1][0]!=l[0])){this.itemActivate(l,true)}this.$root.triggerHandler("focus.smapi",l[0])},itemLeave:function(m){var l=a(m.currentTarget);if(!this.handleItemEvents(l)){return}if(!this.isTouchMode()){l[0].blur();if(this.showTimeout){clearTimeout(this.showTimeout);this.showTimeout=0}}l.removeDataSM("mousedown");this.$root.triggerHandler("mouseleave.smapi",l[0])},menuHide:function(m){if(this.$root.triggerHandler("beforehide.smapi",m[0])===false){return}m.stop(true,true);if(m.css("display")!="none"){var l=function(){m.css("z-index","")};if(this.isCollapsible()){if(this.opts.collapsibleHideFunction){this.opts.collapsibleHideFunction.call(this,m,l)}else{m.hide(this.opts.collapsibleHideDuration,l)}}else{if(this.opts.hideFunction){this.opts.hideFunction.call(this,m,l)}else{m.hide(this.opts.hideDuration,l)}}if(m.dataSM("ie-shim")){m.dataSM("ie-shim").remove().css({"-webkit-transform":"",transform:""})}if(m.dataSM("scroll")){this.menuScrollStop(m);m.css({"touch-action":"","-ms-touch-action":"","-webkit-transform":"",transform:""}).unbind(".smartmenus_scroll").removeDataSM("scroll").dataSM("scroll-arrows").hide()}m.dataSM("parent-a").removeClass("highlighted").attr("aria-expanded","false");m.attr({"aria-expanded":"false","aria-hidden":"true"});var n=m.dataSM("level");this.activatedItems.splice(n-1,1);this.visibleSubMenus.splice(a.inArray(m,this.visibleSubMenus),1);this.$root.triggerHandler("hide.smapi",m[0])}},menuHideAll:function(){if(this.showTimeout){clearTimeout(this.showTimeout);this.showTimeout=0}var m=this.opts.isPopup?1:0;for(var l=this.visibleSubMenus.length-1;l>=m;l--){this.menuHide(this.visibleSubMenus[l])}if(this.opts.isPopup){this.$root.stop(true,true);if(this.$root.is(":visible")){if(this.opts.hideFunction){this.opts.hideFunction.call(this,this.$root)}else{this.$root.hide(this.opts.hideDuration)}if(this.$root.dataSM("ie-shim")){this.$root.dataSM("ie-shim").remove()}}}this.activatedItems=[];this.visibleSubMenus=[];this.clickActivated=false;this.focusActivated=false;this.zIndexInc=0;this.$root.triggerHandler("hideAll.smapi")},menuHideSubMenus:function(n){for(var l=this.activatedItems.length-1;l>=n;l--){var m=this.activatedItems[l].dataSM("sub");if(m){this.menuHide(m)}}},menuIframeShim:function(l){if(e&&this.opts.overlapControlsInIE&&!l.dataSM("ie-shim")){l.dataSM("ie-shim",a(" -
                  - - -
                  -
                  -
                  -
                  AssemblyInfo.cs
                  -
                  -
                  -Go to the documentation of this file.
                  1 using System.Runtime.CompilerServices;
                  2 
                  3 [assembly: InternalsVisibleTo("Tgstation.Server.Client.Tests")]
                  4 [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
                  -
                  - - - - diff --git a/src_2_tgstation_8_server_8_host_2_assembly_info_8cs_source.html b/src_2_tgstation_8_server_8_host_2_assembly_info_8cs_source.html deleted file mode 100644 index 53064ae37d..0000000000 --- a/src_2_tgstation_8_server_8_host_2_assembly_info_8cs_source.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - -tgstation-server: src/Tgstation.Server.Host/AssemblyInfo.cs Source File - - - - - - - - - - -
                  -
                  -
                  - - - - - - -
                  -
                  tgstation-server -
                  -
                  The /tg/station 13 server suite
                  -
                  -
                  - - - - - - -
                  -
                  - - -
                  - -
                  - - - -
                  -
                  -
                  AssemblyInfo.cs
                  -
                  -
                  -Go to the documentation of this file.
                  1 using System.Runtime.CompilerServices;
                  2 
                  3 [assembly: InternalsVisibleTo("Tgstation.Server.Host.Tests")]
                  4 [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
                  -
                  - - - - diff --git a/src_2_tgstation_8_server_8_host_2_program_8cs.html b/src_2_tgstation_8_server_8_host_2_program_8cs.html index 11d7145cfe..d7da5ecb4d 100644 --- a/src_2_tgstation_8_server_8_host_2_program_8cs.html +++ b/src_2_tgstation_8_server_8_host_2_program_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Program.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@ - + - - + + + +
                  + + + +

                  Namespaces

                  namespace  Tgstation
                   
                  namespace  Tgstation.Server
                   
                  namespace  Tgstation.Server.Host
                   
                  @@ -114,7 +97,7 @@ Namespaces diff --git a/src_2_tgstation_8_server_8_host_2_program_8cs_source.html b/src_2_tgstation_8_server_8_host_2_program_8cs_source.html index fc8b8f6eb5..c15d229a12 100644 --- a/src_2_tgstation_8_server_8_host_2_program_8cs_source.html +++ b/src_2_tgstation_8_server_8_host_2_program_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host/Program.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
                  - + - - + + + +
                  Program.cs
                  -Go to the documentation of this file.
                  1 using System;
                  2 using System.Collections.Generic;
                  3 using System.Diagnostics;
                  4 using System.IO;
                  5 using System.Threading;
                  6 using System.Threading.Tasks;
                  7 
                  8 namespace Tgstation.Server.Host
                  9 {
                  13  static class Program
                  14  {
                  18 #pragma warning disable SA1401 // Fields must be private
                  19  internal static IServerFactory ServerFactory = new ServerFactory();
                  20 #pragma warning restore SA1401 // Fields must be private
                  21 
                  27  public static async Task<int> Main(string[] args)
                  28  {
                  29  var listArgs = new List<string>(args);
                  30 
                  31  // first arg is 100% always the update path, starting it otherwise is solely for debugging purposes
                  32  string updatePath;
                  33  if (listArgs.Count > 0)
                  34  {
                  35  updatePath = listArgs[0];
                  36  listArgs.RemoveAt(0);
                  37  if (listArgs.Remove("--attach-debugger"))
                  38  Debugger.Launch();
                  39  }
                  40  else
                  41  updatePath = null;
                  42  try
                  43  {
                  44  var server = ServerFactory.CreateServer(listArgs.ToArray(), updatePath);
                  45  try
                  46  {
                  47  using (var cts = new CancellationTokenSource())
                  48  {
                  49  void AppDomainHandler(object a, EventArgs b) => cts.Cancel();
                  50  AppDomain.CurrentDomain.ProcessExit += AppDomainHandler;
                  51  try
                  52  {
                  53  Console.CancelKeyPress += (a, b) =>
                  54  {
                  55  b.Cancel = true;
                  56  cts.Cancel();
                  57  };
                  58  await server.RunAsync(cts.Token).ConfigureAwait(false);
                  59  }
                  60  finally
                  61  {
                  62  AppDomain.CurrentDomain.ProcessExit -= AppDomainHandler;
                  63  }
                  64  }
                  65  }
                  66  catch (OperationCanceledException) { }
                  67  return server.RestartRequested ? 1 : 0;
                  68  }
                  69  catch (Exception e)
                  70  {
                  71  if (updatePath != null)
                  72  {
                  73  File.WriteAllText(updatePath, e.ToString());
                  74  return 2;
                  75  }
                  76 
                  77  throw;
                  78  }
                  79  }
                  80  }
                  81 }
                  - - -
                  Entrypoint for the Process
                  Definition: Program.cs:13
                  +Go to the documentation of this file.
                  1 using System;
                  2 using System.Collections.Generic;
                  3 using System.Diagnostics;
                  4 using System.IO;
                  5 using System.Threading;
                  6 using System.Threading.Tasks;
                  7 
                  8 namespace Tgstation.Server.Host
                  9 {
                  13  static class Program
                  14  {
                  18 #pragma warning disable SA1401 // Fields must be private
                  19  internal static IServerFactory ServerFactory = new ServerFactory();
                  20 #pragma warning restore SA1401 // Fields must be private
                  21 
                  27  public static async Task<int> Main(string[] args)
                  28  {
                  29  var listArgs = new List<string>(args);
                  30 
                  31  // first arg is 100% always the update path, starting it otherwise is solely for debugging purposes
                  32  string updatePath;
                  33  if (listArgs.Count > 0)
                  34  {
                  35  updatePath = listArgs[0];
                  36  listArgs.RemoveAt(0);
                  37  if (listArgs.Remove("--attach-debugger"))
                  38  Debugger.Launch();
                  39  }
                  40  else
                  41  updatePath = null;
                  42  try
                  43  {
                  44  var server = ServerFactory.CreateServer(listArgs.ToArray(), updatePath);
                  45  try
                  46  {
                  47  using (var cts = new CancellationTokenSource())
                  48  {
                  49  void AppDomainHandler(object a, EventArgs b) => cts.Cancel();
                  50  AppDomain.CurrentDomain.ProcessExit += AppDomainHandler;
                  51  try
                  52  {
                  53  Console.CancelKeyPress += (a, b) =>
                  54  {
                  55  b.Cancel = true;
                  56  cts.Cancel();
                  57  };
                  58  await server.RunAsync(cts.Token).ConfigureAwait(false);
                  59  }
                  60  finally
                  61  {
                  62  AppDomain.CurrentDomain.ProcessExit -= AppDomainHandler;
                  63  }
                  64  }
                  65  }
                  66  catch (OperationCanceledException) { }
                  67  return server.RestartRequested ? 1 : 0;
                  68  }
                  69  catch (Exception e)
                  70  {
                  71  if (updatePath != null)
                  72  {
                  73  File.WriteAllText(updatePath, e.ToString());
                  74  return 2;
                  75  }
                  76 
                  77  throw;
                  78  }
                  79  }
                  80  }
                  81 }
                  +
                  Entrypoint for the Process
                  Definition: Program.cs:13
                  -
                  Task RunAsync(CancellationToken cancellationToken)
                  Runs the IServer
                  -
                  IServer CreateServer(string[] args, string updatePath)
                  Create a IServer
                  -
                  static async Task< int > Main(string[] args)
                  Entrypoint for the Program
                  Definition: Program.cs:27
                  - +
                  Task RunAsync(CancellationToken cancellationToken)
                  Runs the IServer
                  +
                  IServer CreateServer(string[] args, string updatePath)
                  Create a IServer
                  +
                  static async Task< int > Main(string[] args)
                  Entrypoint for the Program
                  Definition: Program.cs:27
                  + +
                  static internal IServerFactory ServerFactory
                  The IServerFactory to use
                  Definition: Program.cs:19
                  diff --git a/src_2_tgstation_8_server_8_host_8_console_2_assembly_info_8cs_source.html b/src_2_tgstation_8_server_8_host_8_console_2_assembly_info_8cs_source.html deleted file mode 100644 index d67f60b3bb..0000000000 --- a/src_2_tgstation_8_server_8_host_8_console_2_assembly_info_8cs_source.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - -tgstation-server: src/Tgstation.Server.Host.Console/AssemblyInfo.cs Source File - - - - - - - - - - -
                  -
                  - - - - - - - -
                  -
                  tgstation-server -
                  -
                  The /tg/station 13 server suite
                  -
                  -
                  - - - - - - -
                  -
                  - - -
                  - -
                  - - -
                  -
                  -
                  -
                  AssemblyInfo.cs
                  -
                  -
                  -Go to the documentation of this file.
                  1 using System.Runtime.CompilerServices;
                  2 
                  3 [assembly: InternalsVisibleTo("Tgstation.Server.Host.Console.Tests")]
                  -
                  - - - - diff --git a/src_2_tgstation_8_server_8_host_8_console_2_program_8cs.html b/src_2_tgstation_8_server_8_host_8_console_2_program_8cs.html index 9ecc8fb1be..316a449093 100644 --- a/src_2_tgstation_8_server_8_host_8_console_2_program_8cs.html +++ b/src_2_tgstation_8_server_8_host_8_console_2_program_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Console/Program.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
                  - + - - + + + +
                  + + + + + +

                  Namespaces

                  namespace  Tgstation
                   
                  namespace  Tgstation.Server
                   
                  namespace  Tgstation.Server.Host
                   
                  namespace  Tgstation.Server.Host.Console
                   
                  @@ -114,7 +99,7 @@ Namespaces diff --git a/src_2_tgstation_8_server_8_host_8_console_2_program_8cs_source.html b/src_2_tgstation_8_server_8_host_8_console_2_program_8cs_source.html index a0c582aa9e..78f2823255 100644 --- a/src_2_tgstation_8_server_8_host_8_console_2_program_8cs_source.html +++ b/src_2_tgstation_8_server_8_host_8_console_2_program_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Console/Program.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
                  - + - - + + + +
                  Program.cs
                  -Go to the documentation of this file.
                  1 using Microsoft.Extensions.Logging;
                  2 using System;
                  3 using System.Collections.Generic;
                  4 using System.Threading;
                  5 using System.Threading.Tasks;
                  7 
                  8 namespace Tgstation.Server.Host.Console
                  9 {
                  13  static class Program
                  14  {
                  18  internal static IWatchdogFactory WatchdogFactory { get; set; } = new WatchdogFactory();
                  19 
                  25  internal static async Task Main(string[] args)
                  26  {
                  27  using (var loggerFactory = new LoggerFactory())
                  28  {
                  29  var arguments = new List<string>(args);
                  30  var trace = arguments.Remove("--trace-host-watchdog");
                  31  var debug = arguments.Remove("--debug-host-watchdog");
                  32 
                  33  loggerFactory.AddConsole(trace ? LogLevel.Trace : debug ? LogLevel.Debug : LogLevel.Information, true);
                  34 
                  35  if (trace && debug)
                  36  {
                  37  loggerFactory.CreateLogger(nameof(Program)).LogCritical("Please specify only 1 of --trace-host-watchdog or --debug-host-watchdog!");
                  38  return;
                  39  }
                  40 
                  41  using (var cts = new CancellationTokenSource())
                  42  {
                  43  void AppDomainHandler(object a, EventArgs b) => cts.Cancel();
                  44  AppDomain.CurrentDomain.ProcessExit += AppDomainHandler;
                  45  try
                  46  {
                  47  System.Console.CancelKeyPress += (a, b) =>
                  48  {
                  49  b.Cancel = true;
                  50  cts.Cancel();
                  51  };
                  52  await WatchdogFactory.CreateWatchdog(loggerFactory).RunAsync(false, arguments.ToArray(), cts.Token).ConfigureAwait(false);
                  53  }
                  54  finally
                  55  {
                  56  AppDomain.CurrentDomain.ProcessExit -= AppDomainHandler;
                  57  }
                  58  }
                  59  }
                  60  }
                  61  }
                  62 }
                  Contains the entrypoint for the application
                  Definition: Program.cs:13
                  - -
                  IWatchdog CreateWatchdog(ILoggerFactory loggerFactory)
                  Create a IWatchdog
                  +Go to the documentation of this file.
                  1 using Microsoft.Extensions.Logging;
                  2 using System;
                  3 using System.Collections.Generic;
                  4 using System.Threading;
                  5 using System.Threading.Tasks;
                  7 
                  9 {
                  13  static class Program
                  14  {
                  18  internal static IWatchdogFactory WatchdogFactory { get; set; } = new WatchdogFactory();
                  19 
                  25  internal static async Task Main(string[] args)
                  26  {
                  27  using (var loggerFactory = new LoggerFactory())
                  28  {
                  29  var arguments = new List<string>(args);
                  30  var trace = arguments.Remove("--trace-host-watchdog");
                  31  var debug = arguments.Remove("--debug-host-watchdog");
                  32 
                  33 #pragma warning disable CS0618 // Type or member is obsolete
                  34  loggerFactory.AddConsole(trace ? LogLevel.Trace : debug ? LogLevel.Debug : LogLevel.Information, true);
                  35 #pragma warning restore CS0618 // Type or member is obsolete
                  36 
                  37  if (trace && debug)
                  38  {
                  39  loggerFactory.CreateLogger(nameof(Program)).LogCritical("Please specify only 1 of --trace-host-watchdog or --debug-host-watchdog!");
                  40  return;
                  41  }
                  42 
                  43  using (var cts = new CancellationTokenSource())
                  44  {
                  45  void AppDomainHandler(object a, EventArgs b) => cts.Cancel();
                  46  AppDomain.CurrentDomain.ProcessExit += AppDomainHandler;
                  47  try
                  48  {
                  49  System.Console.CancelKeyPress += (a, b) =>
                  50  {
                  51  b.Cancel = true;
                  52  cts.Cancel();
                  53  };
                  54  await WatchdogFactory.CreateWatchdog(loggerFactory).RunAsync(false, arguments.ToArray(), cts.Token).ConfigureAwait(false);
                  55  }
                  56  finally
                  57  {
                  58  AppDomain.CurrentDomain.ProcessExit -= AppDomainHandler;
                  59  }
                  60  }
                  61  }
                  62  }
                  63  }
                  64 }
                  Contains the entrypoint for the application
                  Definition: Program.cs:13
                  +
                  IWatchdog CreateWatchdog(ILoggerFactory loggerFactory)
                  Create a IWatchdog
                  +
                  static internal async Task Main(string[] args)
                  Entrypoint for the application
                  Definition: Program.cs:25
                  +
                  static internal IWatchdogFactory WatchdogFactory
                  The IWatchdogFactory for the Program
                  Definition: Program.cs:18
                  + -
                  Task RunAsync(bool runConfigure, string[] args, CancellationToken cancellationToken)
                  Run the IWatchdog
                  - - +
                  Task RunAsync(bool runConfigure, string[] args, CancellationToken cancellationToken)
                  Run the IWatchdog
                  + + - - - + +
                  diff --git a/src_2_tgstation_8_server_8_host_8_service_2_program_8cs.html b/src_2_tgstation_8_server_8_host_8_service_2_program_8cs.html index e46fc10b2a..6a2b0bce57 100644 --- a/src_2_tgstation_8_server_8_host_8_service_2_program_8cs.html +++ b/src_2_tgstation_8_server_8_host_8_service_2_program_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Service/Program.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
                  - + - - + + + +
                  + + + + + +

                  Namespaces

                  namespace  Tgstation
                   
                  namespace  Tgstation.Server
                   
                  namespace  Tgstation.Server.Host
                   
                  namespace  Tgstation.Server.Host.Service
                   
                  @@ -114,7 +99,7 @@ Namespaces diff --git a/src_2_tgstation_8_server_8_host_8_service_2_program_8cs_source.html b/src_2_tgstation_8_server_8_host_8_service_2_program_8cs_source.html index ca4e3fed1d..7866cb7cc6 100644 --- a/src_2_tgstation_8_server_8_host_8_service_2_program_8cs_source.html +++ b/src_2_tgstation_8_server_8_host_8_service_2_program_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: src/Tgstation.Server.Host.Service/Program.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
                  - + - - + + + +
                  Program.cs
                  -Go to the documentation of this file.
                  1 using McMaster.Extensions.CommandLineUtils;
                  2 using Microsoft.Extensions.Logging;
                  3 using System;
                  4 using System.Collections.Specialized;
                  5 using System.Configuration.Install;
                  6 using System.Diagnostics;
                  7 using System.Globalization;
                  8 using System.Linq;
                  9 using System.Reflection;
                  10 using System.Security.Principal;
                  11 using System.ServiceProcess;
                  12 using System.Threading.Tasks;
                  13 using System.Windows.Forms;
                  15 
                  16 namespace Tgstation.Server.Host.Service
                  17 {
                  21  sealed class Program
                  22  {
                  23 #pragma warning disable SA1401 // Fields should be private
                  24  internal static IWatchdogFactory WatchdogFactory = new WatchdogFactory();
                  28 #pragma warning restore SA1401 // Fields should be private
                  29 
                  33  [Option(ShortName = "u")]
                  34  public bool Uninstall { get; }
                  35 
                  39  [Option(ShortName = "i")]
                  40  public bool Install { get; set; }
                  41 
                  45  [Option(ShortName = "c")]
                  46  public bool Configure { get; set; }
                  47 
                  51  [Option(ShortName = "t")]
                  52  public bool Trace { get; set; }
                  53 
                  57  [Option(ShortName = "d")]
                  58  public bool Debug { get; set; }
                  59 
                  64  static bool IsAdministrator()
                  65  {
                  66  var user = WindowsIdentity.GetCurrent();
                  67  var principal = new WindowsPrincipal(user);
                  68  return principal.IsInRole(WindowsBuiltInRole.Administrator);
                  69  }
                  70 
                  74  static Task<int> Main(string[] args) => CommandLineApplication.ExecuteAsync<Program>(args);
                  75 
                  80  public async Task OnExecuteAsync()
                  81  {
                  82  if (Environment.UserInteractive)
                  83  {
                  84  if (!Install && !Uninstall && !Configure)
                  85  {
                  86  var result = MessageBox.Show("You are running the TGS windows service executable directly. It should only be run by the service control manager. Would you like to install and configure the service in this location?", "TGS Service", MessageBoxButtons.YesNo);
                  87  if (result != DialogResult.Yes)
                  88  return;
                  89  Install = true;
                  90  Configure = true;
                  91  }
                  92 
                  93  if (!IsAdministrator())
                  94  {
                  95  // try to restart as admin
                  96  // its windows, first arg is .exe name guaranteed
                  97  var exe = Environment.GetCommandLineArgs().First();
                  98  var startInfo = new ProcessStartInfo
                  99  {
                  100  UseShellExecute = true,
                  101  Verb = "runas",
                  102  Arguments = String.Format(CultureInfo.InvariantCulture, "{0} {1}", Install ? "-i" : Uninstall ? "-u" : String.Empty, Configure ? "-c" : String.Empty),
                  103  FileName = exe,
                  104  WorkingDirectory = Environment.CurrentDirectory,
                  105  };
                  106  using (Process.Start(startInfo))
                  107  return;
                  108  }
                  109  }
                  110 
                  111  using (var loggerFactory = new LoggerFactory())
                  112  {
                  113  if (Configure)
                  114  await WatchdogFactory.CreateWatchdog(loggerFactory).RunAsync(true, Array.Empty<string>(), default).ConfigureAwait(false);
                  115 
                  116  if (Install)
                  117  {
                  118  if (Uninstall)
                  119  return; // oh no, it's retarded...
                  120  using (var processInstaller = new ServiceProcessInstaller())
                  121  using (var installer = new ServiceInstaller())
                  122  {
                  123  processInstaller.Account = ServiceAccount.LocalSystem;
                  124 
                  125  installer.Context = new InstallContext("tgs-4-install.log", new string[] { String.Format(CultureInfo.InvariantCulture, "/assemblypath={0}", Assembly.GetEntryAssembly().Location) });
                  126  installer.Description = "/tg/station 13 server v4 running as a windows service";
                  127  installer.DisplayName = "/tg/station server 4";
                  128  installer.DelayedAutoStart = true;
                  129  installer.StartType = ServiceStartMode.Automatic;
                  130  installer.ServicesDependedOn = new string[] { "Tcpip", "Dhcp", "Dnscache" };
                  131  installer.ServiceName = ServerService.Name;
                  132  installer.Parent = processInstaller;
                  133 
                  134  var state = new ListDictionary();
                  135  installer.Install(state);
                  136  }
                  137  }
                  138  else if (Uninstall)
                  139  using (var installer = new ServiceInstaller())
                  140  {
                  141  installer.Context = new InstallContext("tgs-4-uninstall.log", null);
                  142  installer.ServiceName = ServerService.Name;
                  143  installer.Uninstall(null);
                  144  }
                  145  else if (!Configure)
                  146  ServiceBase.Run(new ServerService(WatchdogFactory, loggerFactory, Trace ? LogLevel.Trace : Debug ? LogLevel.Debug : LogLevel.Information));
                  147  }
                  148  }
                  149  }
                  150 }
                  async Task OnExecuteAsync()
                  Command line handler, always runs
                  Definition: Program.cs:80
                  -
                  static bool IsAdministrator()
                  Check if the running user is a system administrator
                  Definition: Program.cs:64
                  - +Go to the documentation of this file.
                  1 using McMaster.Extensions.CommandLineUtils;
                  2 using Microsoft.Extensions.Logging;
                  3 using System;
                  4 using System.Collections.Specialized;
                  5 using System.Configuration.Install;
                  6 using System.Diagnostics;
                  7 using System.Globalization;
                  8 using System.Linq;
                  9 using System.Reflection;
                  10 using System.Security.Principal;
                  11 using System.ServiceProcess;
                  12 using System.Threading.Tasks;
                  13 using System.Windows.Forms;
                  15 
                  17 {
                  21  sealed class Program
                  22  {
                  23 #pragma warning disable SA1401 // Fields should be private
                  24  internal static IWatchdogFactory WatchdogFactory = new WatchdogFactory();
                  28 #pragma warning restore SA1401 // Fields should be private
                  29 
                  33  [Option(ShortName = "u")]
                  34  public bool Uninstall { get; }
                  35 
                  39  [Option(ShortName = "i")]
                  40  public bool Install { get; set; }
                  41 
                  45  [Option(ShortName = "c")]
                  46  public bool Configure { get; set; }
                  47 
                  51  [Option(ShortName = "t")]
                  52  public bool Trace { get; set; }
                  53 
                  57  [Option(ShortName = "d")]
                  58  public bool Debug { get; set; }
                  59 
                  64  static bool IsAdministrator()
                  65  {
                  66  var user = WindowsIdentity.GetCurrent();
                  67  var principal = new WindowsPrincipal(user);
                  68  return principal.IsInRole(WindowsBuiltInRole.Administrator);
                  69  }
                  70 
                  74  static Task<int> Main(string[] args) => CommandLineApplication.ExecuteAsync<Program>(args);
                  75 
                  80  public async Task OnExecuteAsync()
                  81  {
                  82  if (Environment.UserInteractive)
                  83  {
                  84  if (!Install && !Uninstall && !Configure)
                  85  {
                  86  var result = MessageBox.Show("You are running the TGS windows service executable directly. It should only be run by the service control manager. Would you like to install and configure the service in this location?", "TGS Service", MessageBoxButtons.YesNo);
                  87  if (result != DialogResult.Yes)
                  88  return;
                  89  Install = true;
                  90  Configure = true;
                  91  }
                  92 
                  93  if (!IsAdministrator())
                  94  {
                  95  // try to restart as admin
                  96  // its windows, first arg is .exe name guaranteed
                  97  var exe = Environment.GetCommandLineArgs().First();
                  98  var startInfo = new ProcessStartInfo
                  99  {
                  100  UseShellExecute = true,
                  101  Verb = "runas",
                  102  Arguments = String.Format(CultureInfo.InvariantCulture, "{0} {1}", Install ? "-i" : Uninstall ? "-u" : String.Empty, Configure ? "-c" : String.Empty),
                  103  FileName = exe,
                  104  WorkingDirectory = Environment.CurrentDirectory,
                  105  };
                  106  using (Process.Start(startInfo))
                  107  return;
                  108  }
                  109  }
                  110 
                  111  using (var loggerFactory = new LoggerFactory())
                  112  {
                  113  if (Configure)
                  114  await WatchdogFactory.CreateWatchdog(loggerFactory).RunAsync(true, Array.Empty<string>(), default).ConfigureAwait(false);
                  115 
                  116  if (Install)
                  117  {
                  118  if (Uninstall)
                  119  return; // oh no, it's retarded...
                  120  using (var processInstaller = new ServiceProcessInstaller())
                  121  using (var installer = new ServiceInstaller())
                  122  {
                  123  processInstaller.Account = ServiceAccount.LocalSystem;
                  124 
                  125  installer.Context = new InstallContext("tgs-4-install.log", new string[] { String.Format(CultureInfo.InvariantCulture, "/assemblypath={0}", Assembly.GetEntryAssembly().Location) });
                  126  installer.Description = "/tg/station 13 server v4 running as a windows service";
                  127  installer.DisplayName = "/tg/station server 4";
                  128  installer.DelayedAutoStart = true;
                  129  installer.StartType = ServiceStartMode.Automatic;
                  130  installer.ServicesDependedOn = new string[] { "Tcpip", "Dhcp", "Dnscache" };
                  131  installer.ServiceName = ServerService.Name;
                  132  installer.Parent = processInstaller;
                  133 
                  134  var state = new ListDictionary();
                  135  installer.Install(state);
                  136  }
                  137  }
                  138  else if (Uninstall)
                  139  using (var installer = new ServiceInstaller())
                  140  {
                  141  installer.Context = new InstallContext("tgs-4-uninstall.log", null);
                  142  installer.ServiceName = ServerService.Name;
                  143  installer.Uninstall(null);
                  144  }
                  145  else if (!Configure)
                  146  using (var service = new ServerService(WatchdogFactory, loggerFactory, Trace ? LogLevel.Trace : Debug ? LogLevel.Debug : LogLevel.Information))
                  147  ServiceBase.Run(service);
                  148  }
                  149  }
                  150  }
                  151 }
                  bool Uninstall
                  The –uninstall or -u option
                  Definition: Program.cs:34
                  +
                  static Task< int > Main(string[] args)
                  Entrypoint for the application
                  +
                  async Task OnExecuteAsync()
                  Command line handler, always runs
                  Definition: Program.cs:80
                  +
                  static bool IsAdministrator()
                  Check if the running user is a system administrator
                  Definition: Program.cs:64
                  +
                  bool Debug
                  The –debug or -d option. Enables debug logs
                  Definition: Program.cs:58
                  +
                  static internal IWatchdogFactory WatchdogFactory
                  The IWatchdogFactory for the Program
                  Definition: Program.cs:27
                  +
                  bool Configure
                  The –configure or -c option
                  Definition: Program.cs:46
                  +
                  IWatchdog CreateWatchdog(ILoggerFactory loggerFactory)
                  Create a IWatchdog
                  - -
                  Contains the entrypoint for the application
                  Definition: Program.cs:21
                  -
                  const string Name
                  The canonical windows service name
                  -
                  Represents a IWatchdog as a ServiceBase
                  - +
                  Task RunAsync(bool runConfigure, string[] args, CancellationToken cancellationToken)
                  Run the IWatchdog
                  +
                  bool Install
                  The –install or -i option
                  Definition: Program.cs:40
                  + +
                  Contains the entrypoint for the application
                  Definition: Program.cs:21
                  +
                  const string Name
                  The canonical windows service name
                  +
                  bool Trace
                  The –trace or -t option. Enables trace logs
                  Definition: Program.cs:52
                  + +
                  Represents a IWatchdog as a ServiceBase
                  + - - - + +
                  diff --git a/src_2_tgstation_8_server_8_host_8_service_2_properties_2_assembly_info_8cs_source.html b/src_2_tgstation_8_server_8_host_8_service_2_properties_2_assembly_info_8cs_source.html deleted file mode 100644 index c8e17fe51d..0000000000 --- a/src_2_tgstation_8_server_8_host_8_service_2_properties_2_assembly_info_8cs_source.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - -tgstation-server: src/Tgstation.Server.Host.Service/Properties/AssemblyInfo.cs Source File - - - - - - - - - - -
                  -
                  - - - - - - - -
                  -
                  tgstation-server -
                  -
                  The /tg/station 13 server suite
                  -
                  -
                  - - - - - - -
                  -
                  - - -
                  - -
                  - - -
                  -
                  -
                  -
                  AssemblyInfo.cs
                  -
                  -
                  -Go to the documentation of this file.
                  1 using System.Reflection;
                  2 using System.Runtime.CompilerServices;
                  3 using System.Runtime.InteropServices;
                  4 
                  5 [assembly: AssemblyTitle("Tgstation.Server.Host.Service")]
                  6 [assembly: ComVisible(false)]
                  7 [assembly: Guid("29927416-3b78-49a7-a560-5ccaa638b6b4")]
                  8 [assembly: InternalsVisibleTo("Tgstation.Server.Host.Service.Tests")]
                  9 
                  10 [assembly: AssemblyVersion("4.0.1.4")]
                  11 [assembly: AssemblyFileVersion("4.0.1.4")]
                  -
                  - - - - diff --git a/src_2_tgstation_8_server_8_host_8_watchdog_2_assembly_info_8cs_source.html b/src_2_tgstation_8_server_8_host_8_watchdog_2_assembly_info_8cs_source.html deleted file mode 100644 index 730f8b45dd..0000000000 --- a/src_2_tgstation_8_server_8_host_8_watchdog_2_assembly_info_8cs_source.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - -tgstation-server: src/Tgstation.Server.Host.Watchdog/AssemblyInfo.cs Source File - - - - - - - - - - -
                  -
                  - - - - - - - -
                  -
                  tgstation-server -
                  -
                  The /tg/station 13 server suite
                  -
                  -
                  - - - - - - -
                  -
                  - - -
                  - -
                  - - -
                  -
                  -
                  -
                  AssemblyInfo.cs
                  -
                  -
                  -Go to the documentation of this file.
                  1 using System.Runtime.CompilerServices;
                  2 
                  3 [assembly: InternalsVisibleTo("Tgstation.Server.Host.Watchdog.Tests")]
                  4 [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
                  -
                  - - - - diff --git a/tabs.css b/tabs.css index 9cf578f23a..8ea7d54961 100644 --- a/tabs.css +++ b/tabs.css @@ -1,60 +1 @@ -.tabs, .tabs2, .tabs3 { - background-image: url('tab_b.png'); - width: 100%; - z-index: 101; - font-size: 13px; - font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; -} - -.tabs2 { - font-size: 10px; -} -.tabs3 { - font-size: 9px; -} - -.tablist { - margin: 0; - padding: 0; - display: table; -} - -.tablist li { - float: left; - display: table-cell; - background-image: url('tab_b.png'); - line-height: 36px; - list-style: none; -} - -.tablist a { - display: block; - padding: 0 20px; - font-weight: bold; - background-image:url('tab_s.png'); - background-repeat:no-repeat; - background-position:right; - color: #283A5D; - text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); - text-decoration: none; - outline: none; -} - -.tabs3 .tablist a { - padding: 0 10px; -} - -.tablist a:hover { - background-image: url('tab_h.png'); - background-repeat:repeat-x; - color: #fff; - text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); - text-decoration: none; -} - -.tablist li.current a { - background-image: url('tab_a.png'); - background-repeat:repeat-x; - color: #fff; - text-shadow: 0px 1px 1px rgba(0, 0, 0, 1.0); -} +.sm{position:relative;z-index:9999}.sm,.sm ul,.sm li{display:block;list-style:none;margin:0;padding:0;line-height:normal;direction:ltr;text-align:left;-webkit-tap-highlight-color:rgba(0,0,0,0)}.sm-rtl,.sm-rtl ul,.sm-rtl li{direction:rtl;text-align:right}.sm>li>h1,.sm>li>h2,.sm>li>h3,.sm>li>h4,.sm>li>h5,.sm>li>h6{margin:0;padding:0}.sm ul{display:none}.sm li,.sm a{position:relative}.sm a{display:block}.sm a.disabled{cursor:not-allowed}.sm:after{content:"\00a0";display:block;height:0;font:0/0 serif;clear:both;visibility:hidden;overflow:hidden}.sm,.sm *,.sm *:before,.sm *:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}.sm-dox{background-image:url("tab_b.png")}.sm-dox a,.sm-dox a:focus,.sm-dox a:hover,.sm-dox a:active{padding:0 12px;padding-right:43px;font-family:"Lucida Grande","Geneva","Helvetica",Arial,sans-serif;font-size:13px;font-weight:bold;line-height:36px;text-decoration:none;text-shadow:0 1px 1px rgba(255,255,255,0.9);color:#283a5d;outline:0}.sm-dox a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:white;text-shadow:0 1px 1px black}.sm-dox a.current{color:#d23600}.sm-dox a.disabled{color:#bbb}.sm-dox a span.sub-arrow{position:absolute;top:50%;margin-top:-14px;left:auto;right:3px;width:28px;height:28px;overflow:hidden;font:bold 12px/28px monospace !important;text-align:center;text-shadow:none;background:rgba(255,255,255,0.5);-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.sm-dox a.highlighted span.sub-arrow:before{display:block;content:'-'}.sm-dox>li:first-child>a,.sm-dox>li:first-child>:not(ul) a{-moz-border-radius:5px 5px 0 0;-webkit-border-radius:5px;border-radius:5px 5px 0 0}.sm-dox>li:last-child>a,.sm-dox>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul{-moz-border-radius:0 0 5px 5px;-webkit-border-radius:0;border-radius:0 0 5px 5px}.sm-dox>li:last-child>a.highlighted,.sm-dox>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>a.highlighted,.sm-dox>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>ul>li:last-child>*:not(ul) a.highlighted{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.sm-dox ul{background:rgba(162,162,162,0.1)}.sm-dox ul a,.sm-dox ul a:focus,.sm-dox ul a:hover,.sm-dox ul a:active{font-size:12px;border-left:8px solid transparent;line-height:36px;text-shadow:none;background-color:white;background-image:none}.sm-dox ul a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:white;text-shadow:0 1px 1px black}.sm-dox ul ul a,.sm-dox ul ul a:hover,.sm-dox ul ul a:focus,.sm-dox ul ul a:active{border-left:16px solid transparent}.sm-dox ul ul ul a,.sm-dox ul ul ul a:hover,.sm-dox ul ul ul a:focus,.sm-dox ul ul ul a:active{border-left:24px solid transparent}.sm-dox ul ul ul ul a,.sm-dox ul ul ul ul a:hover,.sm-dox ul ul ul ul a:focus,.sm-dox ul ul ul ul a:active{border-left:32px solid transparent}.sm-dox ul ul ul ul ul a,.sm-dox ul ul ul ul ul a:hover,.sm-dox ul ul ul ul ul a:focus,.sm-dox ul ul ul ul ul a:active{border-left:40px solid transparent}@media(min-width:768px){.sm-dox ul{position:absolute;width:12em}.sm-dox li{float:left}.sm-dox.sm-rtl li{float:right}.sm-dox ul li,.sm-dox.sm-rtl ul li,.sm-dox.sm-vertical li{float:none}.sm-dox a{white-space:nowrap}.sm-dox ul a,.sm-dox.sm-vertical a{white-space:normal}.sm-dox .sm-nowrap>li>a,.sm-dox .sm-nowrap>li>:not(ul) a{white-space:nowrap}.sm-dox{padding:0 10px;background-image:url("tab_b.png");line-height:36px}.sm-dox a span.sub-arrow{top:50%;margin-top:-2px;right:12px;width:0;height:0;border-width:4px;border-style:solid dashed dashed dashed;border-color:#283a5d transparent transparent transparent;background:transparent;-moz-border-radius:0;-webkit-border-radius:0;border-radius:0}.sm-dox a,.sm-dox a:focus,.sm-dox a:active,.sm-dox a:hover,.sm-dox a.highlighted{padding:0 12px;background-image:url("tab_s.png");background-repeat:no-repeat;background-position:right;-moz-border-radius:0 !important;-webkit-border-radius:0;border-radius:0 !important}.sm-dox a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:white;text-shadow:0 1px 1px black}.sm-dox a:hover span.sub-arrow{border-color:white transparent transparent transparent}.sm-dox a.has-submenu{padding-right:24px}.sm-dox li{border-top:0}.sm-dox>li>ul:before,.sm-dox>li>ul:after{content:'';position:absolute;top:-18px;left:30px;width:0;height:0;overflow:hidden;border-width:9px;border-style:dashed dashed solid dashed;border-color:transparent transparent #bbb transparent}.sm-dox>li>ul:after{top:-16px;left:31px;border-width:8px;border-color:transparent transparent #fff transparent}.sm-dox ul{border:1px solid #bbb;padding:5px 0;background:#fff;-moz-border-radius:5px !important;-webkit-border-radius:5px;border-radius:5px !important;-moz-box-shadow:0 5px 9px rgba(0,0,0,0.2);-webkit-box-shadow:0 5px 9px rgba(0,0,0,0.2);box-shadow:0 5px 9px rgba(0,0,0,0.2)}.sm-dox ul a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-color:transparent transparent transparent #555;border-style:dashed dashed dashed solid}.sm-dox ul a,.sm-dox ul a:hover,.sm-dox ul a:focus,.sm-dox ul a:active,.sm-dox ul a.highlighted{color:#555;background-image:none;border:0 !important;color:#555;background-image:none}.sm-dox ul a:hover{background-image:url("tab_a.png");background-repeat:repeat-x;color:white;text-shadow:0 1px 1px black}.sm-dox ul a:hover span.sub-arrow{border-color:transparent transparent transparent white}.sm-dox span.scroll-up,.sm-dox span.scroll-down{position:absolute;display:none;visibility:hidden;overflow:hidden;background:#fff;height:36px}.sm-dox span.scroll-up:hover,.sm-dox span.scroll-down:hover{background:#eee}.sm-dox span.scroll-up:hover span.scroll-up-arrow,.sm-dox span.scroll-up:hover span.scroll-down-arrow{border-color:transparent transparent #d23600 transparent}.sm-dox span.scroll-down:hover span.scroll-down-arrow{border-color:#d23600 transparent transparent transparent}.sm-dox span.scroll-up-arrow,.sm-dox span.scroll-down-arrow{position:absolute;top:0;left:50%;margin-left:-6px;width:0;height:0;overflow:hidden;border-width:6px;border-style:dashed dashed solid dashed;border-color:transparent transparent #555 transparent}.sm-dox span.scroll-down-arrow{top:8px;border-style:solid dashed dashed dashed;border-color:#555 transparent transparent transparent}.sm-dox.sm-rtl a.has-submenu{padding-right:12px;padding-left:24px}.sm-dox.sm-rtl a span.sub-arrow{right:auto;left:12px}.sm-dox.sm-rtl.sm-vertical a.has-submenu{padding:10px 20px}.sm-dox.sm-rtl.sm-vertical a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-rtl>li>ul:before{left:auto;right:30px}.sm-dox.sm-rtl>li>ul:after{left:auto;right:31px}.sm-dox.sm-rtl ul a.has-submenu{padding:10px 20px !important}.sm-dox.sm-rtl ul a span.sub-arrow{right:auto;left:8px;border-style:dashed solid dashed dashed;border-color:transparent #555 transparent transparent}.sm-dox.sm-vertical{padding:10px 0;-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.sm-dox.sm-vertical a{padding:10px 20px}.sm-dox.sm-vertical a:hover,.sm-dox.sm-vertical a:focus,.sm-dox.sm-vertical a:active,.sm-dox.sm-vertical a.highlighted{background:#fff}.sm-dox.sm-vertical a.disabled{background-image:url("tab_b.png")}.sm-dox.sm-vertical a span.sub-arrow{right:8px;top:50%;margin-top:-5px;border-width:5px;border-style:dashed dashed dashed solid;border-color:transparent transparent transparent #555}.sm-dox.sm-vertical>li>ul:before,.sm-dox.sm-vertical>li>ul:after{display:none}.sm-dox.sm-vertical ul a{padding:10px 20px}.sm-dox.sm-vertical ul a:hover,.sm-dox.sm-vertical ul a:focus,.sm-dox.sm-vertical ul a:active,.sm-dox.sm-vertical ul a.highlighted{background:#eee}.sm-dox.sm-vertical ul a.disabled{background:#fff}} \ No newline at end of file diff --git a/tests_2_tgstation_8_server_8_host_8_service_8_tests_2_properties_2_assembly_info_8cs_source.html b/tests_2_tgstation_8_server_8_host_8_service_8_tests_2_properties_2_assembly_info_8cs_source.html deleted file mode 100644 index 4050ec5efc..0000000000 --- a/tests_2_tgstation_8_server_8_host_8_service_8_tests_2_properties_2_assembly_info_8cs_source.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - -tgstation-server: tests/Tgstation.Server.Host.Service.Tests/Properties/AssemblyInfo.cs Source File - - - - - - - - - - -
                  -
                  - - - - - - - -
                  -
                  tgstation-server -
                  -
                  The /tg/station 13 server suite
                  -
                  -
                  - - - - - - -
                  -
                  - - -
                  - -
                  - - -
                  -
                  -
                  -
                  AssemblyInfo.cs
                  -
                  -
                  -Go to the documentation of this file.
                  1 using System.Reflection;
                  2 using System.Runtime.InteropServices;
                  3 
                  4 [assembly: AssemblyTitle("Tgstation.Server.Host.Service.Tests")]
                  5 [assembly: ComVisible(false)]
                  6 
                  7 [assembly: Guid("aa80a190-52e2-4be3-bfeb-1f148d9e9007")]
                  8 
                  9 [assembly: AssemblyVersion("4.0.0.0")]
                  10 [assembly: AssemblyFileVersion("4.0.0.0")]
                  11 [assembly: AssemblyInformationalVersion("4.0.0.0")]
                  -
                  - - - - diff --git a/tools_2_release_notes_2_program_8cs.html b/tools_2_release_notes_2_program_8cs.html index 9dd548eaac..269402e15f 100644 --- a/tools_2_release_notes_2_program_8cs.html +++ b/tools_2_release_notes_2_program_8cs.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tools/ReleaseNotes/Program.cs File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
                  - + - - + + + +
                  diff --git a/tools_2_release_notes_2_program_8cs_source.html b/tools_2_release_notes_2_program_8cs_source.html index 3e4d2f9446..22b77cd57c 100644 --- a/tools_2_release_notes_2_program_8cs_source.html +++ b/tools_2_release_notes_2_program_8cs_source.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tools/ReleaseNotes/Program.cs Source File @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
                  - + - - + + + +
                  Program.cs
                  -Go to the documentation of this file.
                  1 using Octokit;
                  2 using System;
                  3 using System.Collections.Generic;
                  4 using System.Globalization;
                  5 using System.IO;
                  6 using System.Linq;
                  7 using System.Text;
                  8 using System.Threading.Tasks;
                  9 
                  10 namespace ReleaseNotes
                  11 {
                  15  static class Program
                  16  {
                  20  static async Task<int> Main(string[] args)
                  21  {
                  22  if (args.Length < 1)
                  23  {
                  24  Console.WriteLine("Missing version argument!");
                  25  return 1;
                  26  }
                  27 
                  28  var versionString = args[0];
                  29  if (!Version.TryParse(versionString, out var version))
                  30  {
                  31  Console.WriteLine("Invalid version: " + versionString);
                  32  return 2;
                  33  }
                  34 
                  35  var doNotCloseMilestone = args.Length >= 2 && args[1].ToUpperInvariant() == "--NO-CLOSE";
                  36 
                  37  const string ReleaseNotesEnvVar = "TGS_RELEASE_NOTES_TOKEN";
                  38  var githubToken = Environment.GetEnvironmentVariable(ReleaseNotesEnvVar);
                  39  if (String.IsNullOrWhiteSpace(githubToken))
                  40  {
                  41  Console.WriteLine("Missing " + ReleaseNotesEnvVar + " environment variable!");
                  42  return 3;
                  43  }
                  44 
                  45  try
                  46  {
                  47  var client = new GitHubClient(new ProductHeaderValue("tgs_release_notes"));
                  48  client.Credentials = new Credentials(githubToken);
                  49 
                  50  const string RepoOwner = "tgstation";
                  51  const string RepoName = "tgstation-server";
                  52 
                  53  var releasesTask = client.Repository.Release.GetAll(RepoOwner, RepoName);
                  54 
                  55  Console.WriteLine("Getting pull requests in milestone " + versionString + "...");
                  56  var milestonePRs = await client.Search.SearchIssues(new SearchIssuesRequest
                  57  {
                  58  Milestone = versionString,
                  59  Type = IssueTypeQualifier.PullRequest,
                  60  Repos = { { RepoOwner, RepoName } }
                  61  }).ConfigureAwait(false);
                  62 
                  63  if (milestonePRs.IncompleteResults)
                  64  {
                  65  Console.WriteLine("Incomplete results for milestone PRs query!");
                  66  return 5;
                  67  }
                  68  Console.WriteLine(milestonePRs.Items.Count + " total pull requests");
                  69 
                  70  Task<Milestone> milestoneTask = null;
                  71  var milestoneTaskLock = new object();
                  72  var releaseDictionary = new Dictionary<int, List<string>>();
                  73  var authorizedUsers = new Dictionary<long, Task<bool>>();
                  74 
                  75  async Task GetReleaseNotesFromPR(Issue pullRequest)
                  76  {
                  77  //need to check it was merged
                  78  var fullPR = await client.Repository.PullRequest.Get(RepoOwner, RepoName, pullRequest.Number).ConfigureAwait(false);
                  79 
                  80  async Task<Milestone> GetMilestone()
                  81  {
                  82  if (fullPR.Milestone == null)
                  83  return null;
                  84  return await client.Issue.Milestone.Get(RepoOwner, RepoName, fullPR.Milestone.Number);
                  85  };
                  86 
                  87  lock (milestoneTaskLock)
                  88  if (milestoneTask == null)
                  89  milestoneTask = GetMilestone();
                  90 
                  91  if (!fullPR.Merged)
                  92  return;
                  93 
                  94  async Task BuildNotesFromComment(string comment, User user)
                  95  {
                  96  var commentSplits = comment.Split('\n');
                  97  var notesOpen = false;
                  98  var notesClosed = false;
                  99  var notes = new List<string>();
                  100  foreach (var line in commentSplits)
                  101  {
                  102  var trimmedLine = line.Trim();
                  103  if (!notesOpen)
                  104  {
                  105  notesOpen = trimmedLine.StartsWith(":cl:", StringComparison.Ordinal);
                  106  notesClosed = false;
                  107  continue;
                  108  }
                  109  if (trimmedLine.StartsWith("/:cl:", StringComparison.Ordinal))
                  110  {
                  111  notesClosed = true;
                  112  notesOpen = false;
                  113  continue;
                  114  }
                  115  if (trimmedLine.Length == 0)
                  116  continue;
                  117  notes.Add(trimmedLine);
                  118  }
                  119  if (!notesClosed || notes.Count == 0)
                  120  return;
                  121 
                  122  Task<bool> authTask;
                  123  TaskCompletionSource<bool> ourTcs = null;
                  124  lock (authorizedUsers)
                  125  {
                  126  if (!authorizedUsers.TryGetValue(user.Id, out authTask))
                  127  {
                  128  ourTcs = new TaskCompletionSource<bool>();
                  129  authTask = ourTcs.Task;
                  130  authorizedUsers.Add(user.Id, authTask);
                  131  }
                  132  }
                  133 
                  134  if (ourTcs != null)
                  135  try
                  136  {
                  137  //check if the user has access
                  138  var perm = await client.Repository.Collaborator.ReviewPermission(RepoOwner, RepoName, user.Login).ConfigureAwait(false);
                  139  ourTcs.SetResult(perm.Permission == PermissionLevel.Write || perm.Permission == PermissionLevel.Admin);
                  140  }
                  141  catch
                  142  {
                  143  ourTcs.SetResult(false);
                  144  throw;
                  145  }
                  146 
                  147  var authorized = await authTask.ConfigureAwait(false);
                  148  if (!authorized)
                  149  return;
                  150 
                  151  lock (releaseDictionary)
                  152  {
                  153  foreach (var I in notes)
                  154  Console.WriteLine("#" + fullPR.Number + " - " + I + " (@" + user.Login + ")");
                  155  if (releaseDictionary.TryGetValue(fullPR.Number, out var currentValues))
                  156  currentValues.AddRange(notes);
                  157  else
                  158  releaseDictionary.Add(fullPR.Number, notes);
                  159  }
                  160  }
                  161 
                  162  var comments = await client.Issue.Comment.GetAllForIssue(RepoOwner, RepoName, fullPR.Number).ConfigureAwait(false);
                  163  await Task.WhenAll(BuildNotesFromComment(fullPR.Body, fullPR.User), Task.WhenAll(comments.Select(x => BuildNotesFromComment(x.Body, x.User)))).ConfigureAwait(false);
                  164  }
                  165 
                  166  var tasks = new List<Task>();
                  167  foreach (var I in milestonePRs.Items)
                  168  tasks.Add(GetReleaseNotesFromPR(I));
                  169 
                  170  var releases = await releasesTask.ConfigureAwait(false);
                  171 
                  172  var releasingSuite = version.Major;
                  173 
                  174  Version highestReleaseVersion = null;
                  175  Release highestRelease = null;
                  176  foreach (var I in releases)
                  177  {
                  178  if (!Version.TryParse(I.TagName.Replace("tgstation-server-v", String.Empty), out var currentReleaseVersion))
                  179  {
                  180  Console.WriteLine("WARNING: Unable to determine version of release " + I.HtmlUrl);
                  181  continue;
                  182  }
                  183 
                  184  if (currentReleaseVersion.Major == releasingSuite && (highestReleaseVersion == null || currentReleaseVersion > highestReleaseVersion))
                  185  {
                  186  highestReleaseVersion = currentReleaseVersion;
                  187  highestRelease = I;
                  188  }
                  189  }
                  190 
                  191  if (highestReleaseVersion == null)
                  192  {
                  193  Console.WriteLine("Unable to determine highest release version for suite " + releasingSuite + "!");
                  194  return 6;
                  195  }
                  196 
                  197  var oldNotes = highestRelease.Body;
                  198 
                  199  var splits = new List<string>(oldNotes.Split('\n'));
                  200  //trim away all the lines that don't start with #
                  201 
                  202  string keepThisRelease;
                  203  if (version.Revision == 0)
                  204  if (version.Build == 0)
                  205  keepThisRelease = "# ";
                  206  else
                  207  keepThisRelease = "## ";
                  208  else
                  209  keepThisRelease = "### ";
                  210 
                  211  for (; !splits[0].StartsWith(keepThisRelease, StringComparison.Ordinal); splits.RemoveAt(0))
                  212  if (splits.Count == 1)
                  213  {
                  214  Console.WriteLine("Error formatting release notes: Can't detemine notes start!");
                  215  return 7;
                  216  }
                  217 
                  218  oldNotes = String.Join('\n', splits);
                  219 
                  220  string prefix;
                  221  switch (releasingSuite)
                  222  {
                  223  case 3:
                  224  prefix = "The /tg/station server suite";
                  225  break;
                  226  default:
                  227  prefix = "See https://tgstation.github.io/tgstation-server for installation instructions";
                  228  break;
                  229  }
                  230 
                  231  var newNotes = new StringBuilder(prefix);
                  232  newNotes.Append(Environment.NewLine);
                  233  newNotes.Append(Environment.NewLine);
                  234  if (version.Revision == 0)
                  235  if (version.Build == 0)
                  236  {
                  237  newNotes.Append("# [Version ");
                  238  newNotes.Append(version.Minor);
                  239  }
                  240  else
                  241  {
                  242  newNotes.Append("## [Changelog for ");
                  243  newNotes.Append(version.Build);
                  244  newNotes.Append(".x");
                  245  }
                  246  else
                  247  {
                  248  newNotes.Append("### [Patch ");
                  249  newNotes.Append(version.Revision);
                  250  }
                  251  newNotes.Append("](");
                  252  var milestone = await milestoneTask.ConfigureAwait(false);
                  253  if (milestone == null)
                  254  {
                  255  Console.WriteLine("Unable to detemine milestone!");
                  256  return 9;
                  257  }
                  258  newNotes.Append(milestone.HtmlUrl);
                  259  newNotes.Append("?closed=1)");
                  260  newNotes.Append(Environment.NewLine);
                  261 
                  262  await Task.WhenAll(tasks).ConfigureAwait(false);
                  263 
                  264  if (releaseDictionary.Count == 0)
                  265  {
                  266  Console.WriteLine("No release notes for this milestone!");
                  267  return 8;
                  268  }
                  269 
                  270  foreach (var I in releaseDictionary)
                  271  foreach (var note in I.Value)
                  272  {
                  273  newNotes.Append(Environment.NewLine);
                  274  newNotes.Append("- ");
                  275  newNotes.Append(note);
                  276  newNotes.Append(" (#");
                  277  newNotes.Append(I.Key);
                  278  newNotes.Append(')');
                  279  }
                  280 
                  281  newNotes.Append(Environment.NewLine);
                  282  newNotes.Append(Environment.NewLine);
                  283  newNotes.Append(oldNotes);
                  284 
                  285  Console.WriteLine("Writing out new release notes...");
                  286  var releaseNotes = newNotes.ToString();
                  287  await File.WriteAllTextAsync("release_notes.md", releaseNotes).ConfigureAwait(false);
                  288 
                  289  if (doNotCloseMilestone)
                  290  Console.WriteLine("Not closing milestone due to parameter!");
                  291  else
                  292  {
                  293  Console.WriteLine("Closing milestone...");
                  294  await client.Issue.Milestone.Update(RepoOwner, RepoName, milestone.Number, new MilestoneUpdate
                  295  {
                  296  State = ItemState.Closed
                  297  }).ConfigureAwait(false);
                  298  }
                  299 
                  300  return 0;
                  301  }
                  302  catch (Exception e)
                  303  {
                  304  Console.WriteLine(e);
                  305  return 4;
                  306  }
                  307  }
                  308  }
                  309 }
                  - - -
                  static async Task< int > Main(string[] args)
                  The entrypoint for the Program
                  Definition: Program.cs:20
                  -
                  Contains the application entrypoint
                  Definition: Program.cs:15
                  +Go to the documentation of this file.
                  1 using Octokit;
                  2 using System;
                  3 using System.Collections.Generic;
                  4 using System.Globalization;
                  5 using System.IO;
                  6 using System.Linq;
                  7 using System.Text;
                  8 using System.Threading.Tasks;
                  9 
                  10 namespace ReleaseNotes
                  11 {
                  15  static class Program
                  16  {
                  20  static async Task<int> Main(string[] args)
                  21  {
                  22  if (args.Length < 1)
                  23  {
                  24  Console.WriteLine("Missing version argument!");
                  25  return 1;
                  26  }
                  27 
                  28  var versionString = args[0];
                  29  if (!Version.TryParse(versionString, out var version))
                  30  {
                  31  Console.WriteLine("Invalid version: " + versionString);
                  32  return 2;
                  33  }
                  34 
                  35  var doNotCloseMilestone = args.Length >= 2 && args[1].ToUpperInvariant() == "--NO-CLOSE";
                  36 
                  37  const string ReleaseNotesEnvVar = "TGS_RELEASE_NOTES_TOKEN";
                  38  var githubToken = Environment.GetEnvironmentVariable(ReleaseNotesEnvVar);
                  39  if (String.IsNullOrWhiteSpace(githubToken))
                  40  {
                  41  Console.WriteLine("Missing " + ReleaseNotesEnvVar + " environment variable!");
                  42  return 3;
                  43  }
                  44 
                  45  try
                  46  {
                  47  var client = new GitHubClient(new ProductHeaderValue("tgs_release_notes"));
                  48  client.Credentials = new Credentials(githubToken);
                  49 
                  50  const string RepoOwner = "tgstation";
                  51  const string RepoName = "tgstation-server";
                  52 
                  53  var releasesTask = client.Repository.Release.GetAll(RepoOwner, RepoName);
                  54 
                  55  Console.WriteLine("Getting pull requests in milestone " + versionString + "...");
                  56  var milestonePRs = await client.Search.SearchIssues(new SearchIssuesRequest
                  57  {
                  58  Milestone = versionString,
                  59  Type = IssueTypeQualifier.PullRequest,
                  60  Repos = { { RepoOwner, RepoName } }
                  61  }).ConfigureAwait(false);
                  62 
                  63  if (milestonePRs.IncompleteResults)
                  64  {
                  65  Console.WriteLine("Incomplete results for milestone PRs query!");
                  66  return 5;
                  67  }
                  68  Console.WriteLine(milestonePRs.Items.Count + " total pull requests");
                  69 
                  70  Task<Milestone> milestoneTask = null;
                  71  var milestoneTaskLock = new object();
                  72  var releaseDictionary = new Dictionary<int, List<string>>();
                  73  var authorizedUsers = new Dictionary<long, Task<bool>>();
                  74 
                  75  async Task GetReleaseNotesFromPR(Issue pullRequest)
                  76  {
                  77  //need to check it was merged
                  78  var fullPR = await client.Repository.PullRequest.Get(RepoOwner, RepoName, pullRequest.Number).ConfigureAwait(false);
                  79 
                  80  async Task<Milestone> GetMilestone()
                  81  {
                  82  if (fullPR.Milestone == null)
                  83  return null;
                  84  return await client.Issue.Milestone.Get(RepoOwner, RepoName, fullPR.Milestone.Number);
                  85  };
                  86 
                  87  lock (milestoneTaskLock)
                  88  if (milestoneTask == null)
                  89  milestoneTask = GetMilestone();
                  90 
                  91  if (!fullPR.Merged)
                  92  return;
                  93 
                  94  async Task BuildNotesFromComment(string comment, User user)
                  95  {
                  96  var commentSplits = comment.Split('\n');
                  97  var notesOpen = false;
                  98  var notesClosed = false;
                  99  var notes = new List<string>();
                  100  foreach (var line in commentSplits)
                  101  {
                  102  var trimmedLine = line.Trim();
                  103  if (!notesOpen)
                  104  {
                  105  notesOpen = trimmedLine.StartsWith(":cl:", StringComparison.Ordinal);
                  106  notesClosed = false;
                  107  continue;
                  108  }
                  109  if (trimmedLine.StartsWith("/:cl:", StringComparison.Ordinal))
                  110  {
                  111  notesClosed = true;
                  112  notesOpen = false;
                  113  continue;
                  114  }
                  115  if (trimmedLine.Length == 0)
                  116  continue;
                  117  notes.Add(trimmedLine);
                  118  }
                  119  if (!notesClosed || notes.Count == 0)
                  120  return;
                  121 
                  122  Task<bool> authTask;
                  123  TaskCompletionSource<bool> ourTcs = null;
                  124  lock (authorizedUsers)
                  125  {
                  126  if (!authorizedUsers.TryGetValue(user.Id, out authTask))
                  127  {
                  128  ourTcs = new TaskCompletionSource<bool>();
                  129  authTask = ourTcs.Task;
                  130  authorizedUsers.Add(user.Id, authTask);
                  131  }
                  132  }
                  133 
                  134  if (ourTcs != null)
                  135  try
                  136  {
                  137  //check if the user has access
                  138  var perm = await client.Repository.Collaborator.ReviewPermission(RepoOwner, RepoName, user.Login).ConfigureAwait(false);
                  139  ourTcs.SetResult(perm.Permission == PermissionLevel.Write || perm.Permission == PermissionLevel.Admin);
                  140  }
                  141  catch
                  142  {
                  143  ourTcs.SetResult(false);
                  144  throw;
                  145  }
                  146 
                  147  var authorized = await authTask.ConfigureAwait(false);
                  148  if (!authorized)
                  149  return;
                  150 
                  151  lock (releaseDictionary)
                  152  {
                  153  foreach (var I in notes)
                  154  Console.WriteLine("#" + fullPR.Number + " - " + I + " (@" + user.Login + ")");
                  155  if (releaseDictionary.TryGetValue(fullPR.Number, out var currentValues))
                  156  currentValues.AddRange(notes);
                  157  else
                  158  releaseDictionary.Add(fullPR.Number, notes);
                  159  }
                  160  }
                  161 
                  162  var comments = await client.Issue.Comment.GetAllForIssue(RepoOwner, RepoName, fullPR.Number).ConfigureAwait(false);
                  163  await Task.WhenAll(BuildNotesFromComment(fullPR.Body, fullPR.User), Task.WhenAll(comments.Select(x => BuildNotesFromComment(x.Body, x.User)))).ConfigureAwait(false);
                  164  }
                  165 
                  166  var tasks = new List<Task>();
                  167  foreach (var I in milestonePRs.Items)
                  168  tasks.Add(GetReleaseNotesFromPR(I));
                  169 
                  170  var releases = await releasesTask.ConfigureAwait(false);
                  171 
                  172  var releasingSuite = version.Major;
                  173 
                  174  Version highestReleaseVersion = null;
                  175  Release highestRelease = null;
                  176  foreach (var I in releases)
                  177  {
                  178  if (!Version.TryParse(I.TagName.Replace("tgstation-server-v", String.Empty), out var currentReleaseVersion))
                  179  {
                  180  Console.WriteLine("WARNING: Unable to determine version of release " + I.HtmlUrl);
                  181  continue;
                  182  }
                  183 
                  184  if (currentReleaseVersion.Major == releasingSuite && (highestReleaseVersion == null || currentReleaseVersion > highestReleaseVersion))
                  185  {
                  186  highestReleaseVersion = currentReleaseVersion;
                  187  highestRelease = I;
                  188  }
                  189  }
                  190 
                  191  if (highestReleaseVersion == null)
                  192  {
                  193  Console.WriteLine("Unable to determine highest release version for suite " + releasingSuite + "!");
                  194  return 6;
                  195  }
                  196 
                  197  var oldNotes = highestRelease.Body;
                  198 
                  199  var splits = new List<string>(oldNotes.Split('\n'));
                  200  //trim away all the lines that don't start with #
                  201 
                  202  string keepThisRelease;
                  203  if (version.Revision == 0)
                  204  if (version.Build == 0)
                  205  keepThisRelease = "# ";
                  206  else
                  207  keepThisRelease = "## ";
                  208  else
                  209  keepThisRelease = "### ";
                  210 
                  211  for (; !splits[0].StartsWith(keepThisRelease, StringComparison.Ordinal); splits.RemoveAt(0))
                  212  if (splits.Count == 1)
                  213  {
                  214  Console.WriteLine("Error formatting release notes: Can't detemine notes start!");
                  215  return 7;
                  216  }
                  217 
                  218  oldNotes = String.Join('\n', splits);
                  219 
                  220  string prefix;
                  221  switch (releasingSuite)
                  222  {
                  223  case 3:
                  224  prefix = "The /tg/station server suite";
                  225  break;
                  226  default:
                  227  prefix = "See https://tgstation.github.io/tgstation-server for installation instructions";
                  228  break;
                  229  }
                  230 
                  231  var newNotes = new StringBuilder(prefix);
                  232  newNotes.Append(Environment.NewLine);
                  233  newNotes.Append(Environment.NewLine);
                  234  if (version.Revision == 0)
                  235  if (version.Build == 0)
                  236  {
                  237  newNotes.Append("# [Version ");
                  238  newNotes.Append(version.Minor);
                  239  }
                  240  else
                  241  {
                  242  newNotes.Append("## [Changelog for ");
                  243  newNotes.Append(version.Build);
                  244  newNotes.Append(".x");
                  245  }
                  246  else
                  247  {
                  248  newNotes.Append("### [Patch ");
                  249  newNotes.Append(version.Revision);
                  250  }
                  251  newNotes.Append("](");
                  252  var milestone = await milestoneTask.ConfigureAwait(false);
                  253  if (milestone == null)
                  254  {
                  255  Console.WriteLine("Unable to detemine milestone!");
                  256  return 9;
                  257  }
                  258  newNotes.Append(milestone.HtmlUrl);
                  259  newNotes.Append("?closed=1)");
                  260  newNotes.Append(Environment.NewLine);
                  261 
                  262  await Task.WhenAll(tasks).ConfigureAwait(false);
                  263 
                  264  if (releaseDictionary.Count == 0)
                  265  {
                  266  Console.WriteLine("No release notes for this milestone!");
                  267  return 8;
                  268  }
                  269 
                  270  foreach (var I in releaseDictionary)
                  271  foreach (var note in I.Value)
                  272  {
                  273  newNotes.Append(Environment.NewLine);
                  274  newNotes.Append("- ");
                  275  newNotes.Append(note);
                  276  newNotes.Append(" (#");
                  277  newNotes.Append(I.Key);
                  278  newNotes.Append(')');
                  279  }
                  280 
                  281  newNotes.Append(Environment.NewLine);
                  282  newNotes.Append(Environment.NewLine);
                  283  newNotes.Append(oldNotes);
                  284 
                  285  Console.WriteLine("Writing out new release notes...");
                  286  var releaseNotes = newNotes.ToString();
                  287  await File.WriteAllTextAsync("release_notes.md", releaseNotes).ConfigureAwait(false);
                  288 
                  289  if (doNotCloseMilestone)
                  290  Console.WriteLine("Not closing milestone due to parameter!");
                  291  else
                  292  {
                  293  Console.WriteLine("Closing milestone...");
                  294  await client.Issue.Milestone.Update(RepoOwner, RepoName, milestone.Number, new MilestoneUpdate
                  295  {
                  296  State = ItemState.Closed
                  297  }).ConfigureAwait(false);
                  298  }
                  299 
                  300  return 0;
                  301  }
                  302  catch (Exception e)
                  303  {
                  304  Console.WriteLine(e);
                  305  return 4;
                  306  }
                  307  }
                  308  }
                  309 }
                  +
                  static async Task< int > Main(string[] args)
                  The entrypoint for the Program
                  Definition: Program.cs:20
                  +
                  Contains the application entrypoint
                  Definition: Program.cs:15
                  diff --git a/tools_2_release_notes_2_r_e_a_d_m_e_8md.html b/tools_2_release_notes_2_r_e_a_d_m_e_8md.html index 2279fe9642..197adb6330 100644 --- a/tools_2_release_notes_2_r_e_a_d_m_e_8md.html +++ b/tools_2_release_notes_2_r_e_a_d_m_e_8md.html @@ -1,9 +1,10 @@ - + - + + tgstation-server: tools/ReleaseNotes/README.md File Reference @@ -11,9 +12,6 @@ - @@ -33,41 +31,22 @@
                  - + - - + + + +
                  tools/ReleaseNotes/README.md File Reference
                  diff --git a/tools_2_release_notes_2_r_e_a_d_m_e_8md_source.html b/tools_2_release_notes_2_r_e_a_d_m_e_8md_source.html deleted file mode 100644 index e1de813c7e..0000000000 --- a/tools_2_release_notes_2_r_e_a_d_m_e_8md_source.html +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - -tgstation-server: tools/ReleaseNotes/README.md Source File - - - - - - - - - - -
                  -
                  - - - - - - - -
                  -
                  tgstation-server -
                  -
                  The /tg/station 13 server suite
                  -
                  -
                  - - - - - -
                  - -
                  -
                  - - -
                  - -
                  - -
                  -
                  -
                  tools/ReleaseNotes/README.md
                  -
                  -
                  -Go to the documentation of this file.
                  1 This is a small tool to generate TGS release notes from PR descriptions
                  2 
                  3 Requires environment variable `TGS_RELEASE_NOTES_TOKEN`
                  4 
                  5 Run it with `dotnet run <version> [--no-close (optionally doesn't close the milestone, USE WHILE DEBUGGING)]`
                  6 
                  7 Will close the release milestone and output `release_notes.md` with the updated release notes
                  - - - -