mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2025-08-21 04:12:56 +00:00
Add enterprise config support via env vars & Windows registry
This commit is contained in:
parent
b88b78a08e
commit
d02d6b5870
@ -208,6 +208,30 @@ internal sealed class Program
|
|||||||
await rust.AppIsReady();
|
await rust.AppIsReady();
|
||||||
programLogger.LogInformation("The AI Studio server is ready.");
|
programLogger.LogInformation("The AI Studio server is ready.");
|
||||||
|
|
||||||
|
//
|
||||||
|
// Read the enterprise environment for the current user's configuration:
|
||||||
|
//
|
||||||
|
var enterpriseConfigServerUrl = await RUST_SERVICE.EnterpriseEnvConfigServerUrl();
|
||||||
|
var enterpriseConfigId = await RUST_SERVICE.EnterpriseEnvConfigId();
|
||||||
|
switch (enterpriseConfigServerUrl)
|
||||||
|
{
|
||||||
|
case null when enterpriseConfigId == Guid.Empty:
|
||||||
|
programLogger.LogInformation("AI Studio runs without an enterprise configuration.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case null:
|
||||||
|
programLogger.LogWarning($"AI Studio runs with an enterprise configuration id ('{enterpriseConfigId}'), but the configuration server URL is not set.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case not null when enterpriseConfigId == Guid.Empty:
|
||||||
|
programLogger.LogWarning($"AI Studio runs with an enterprise configuration server URL ('{enterpriseConfigServerUrl}'), but the configuration ID is not set.");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
programLogger.LogInformation($"AI Studio runs with an enterprise configuration id ('{enterpriseConfigId}') and configuration server URL ('{enterpriseConfigServerUrl}').");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
TaskScheduler.UnobservedTaskException += (sender, taskArgs) =>
|
TaskScheduler.UnobservedTaskException += (sender, taskArgs) =>
|
||||||
{
|
{
|
||||||
programLogger.LogError(taskArgs.Exception, $"Unobserved task exception by sender '{sender ?? "n/a"}'.");
|
programLogger.LogError(taskArgs.Exception, $"Unobserved task exception by sender '{sender ?? "n/a"}'.");
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
namespace AIStudio.Tools.Services;
|
||||||
|
|
||||||
|
public sealed partial class RustService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to read the enterprise environment for the current user's configuration ID.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// Returns the empty Guid when the environment is not set or the request fails.
|
||||||
|
/// Otherwise, the configuration ID.
|
||||||
|
/// </returns>
|
||||||
|
public async Task<Guid> EnterpriseEnvConfigId()
|
||||||
|
{
|
||||||
|
var result = await this.http.GetAsync("/system/enterprise/config/id");
|
||||||
|
if (!result.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
this.logger!.LogError($"Failed to query the enterprise configuration ID: '{result.StatusCode}'");
|
||||||
|
return Guid.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
Guid.TryParse(await result.Content.ReadAsStringAsync(), out var configurationId);
|
||||||
|
return configurationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tries to read the enterprise environment for the current user's configuration server URL.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// Returns null when the environment is not set or the request fails.
|
||||||
|
/// Otherwise, the configuration server URL.
|
||||||
|
/// </returns>
|
||||||
|
public async Task<string?> EnterpriseEnvConfigServerUrl()
|
||||||
|
{
|
||||||
|
var result = await this.http.GetAsync("/system/enterprise/config/server");
|
||||||
|
if (!result.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
this.logger!.LogError($"Failed to query the enterprise configuration server URL: '{result.StatusCode}'");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var serverUrl = await result.Content.ReadAsStringAsync();
|
||||||
|
return string.IsNullOrWhiteSpace(serverUrl) ? null : serverUrl;
|
||||||
|
}
|
||||||
|
}
|
32
runtime/Cargo.lock
generated
32
runtime/Cargo.lock
generated
@ -2632,6 +2632,7 @@ dependencies = [
|
|||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"calamine",
|
"calamine",
|
||||||
"cbc",
|
"cbc",
|
||||||
|
"cfg-if",
|
||||||
"cipher",
|
"cipher",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
"file-format",
|
"file-format",
|
||||||
@ -2660,6 +2661,7 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"url",
|
"url",
|
||||||
|
"windows-registry 0.5.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3978,7 +3980,7 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
"windows-registry",
|
"windows-registry 0.4.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -5949,15 +5951,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3"
|
checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-result",
|
"windows-result",
|
||||||
"windows-strings",
|
"windows-strings 0.3.1",
|
||||||
"windows-targets 0.53.0",
|
"windows-targets 0.53.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-result"
|
name = "windows-registry"
|
||||||
version = "0.3.2"
|
version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
|
checksum = "b3bab093bdd303a1240bb99b8aba8ea8a69ee19d34c9e2ef9594e708a4878820"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link",
|
||||||
|
"windows-result",
|
||||||
|
"windows-strings 0.4.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-result"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
@ -5971,6 +5984,15 @@ dependencies = [
|
|||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-strings"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
|
||||||
|
dependencies = [
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.42.0"
|
version = "0.42.0"
|
||||||
|
@ -37,6 +37,7 @@ file-format = "0.27.0"
|
|||||||
calamine = "0.27.0"
|
calamine = "0.27.0"
|
||||||
pdfium-render = "0.8.31"
|
pdfium-render = "0.8.31"
|
||||||
sys-locale = "0.3.2"
|
sys-locale = "0.3.2"
|
||||||
|
cfg-if = "1.0.0"
|
||||||
|
|
||||||
# Fixes security vulnerability downstream, where the upstream is not fixed yet:
|
# Fixes security vulnerability downstream, where the upstream is not fixed yet:
|
||||||
url = "2.5"
|
url = "2.5"
|
||||||
@ -50,5 +51,8 @@ reqwest = { version = "0.12.15", features = ["native-tls-vendored"] }
|
|||||||
# Fixes security vulnerability downstream, where the upstream is not fixed yet:
|
# Fixes security vulnerability downstream, where the upstream is not fixed yet:
|
||||||
openssl = "0.10.72"
|
openssl = "0.10.72"
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
|
windows-registry = "0.5.2"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
custom-protocol = ["tauri/custom-protocol"]
|
custom-protocol = ["tauri/custom-protocol"]
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
|
use std::env;
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
|
use log::info;
|
||||||
use rocket::get;
|
use rocket::get;
|
||||||
use sys_locale::get_locale;
|
use sys_locale::get_locale;
|
||||||
use crate::api_token::APIToken;
|
use crate::api_token::APIToken;
|
||||||
@ -44,3 +46,97 @@ pub fn read_user_language(_token: APIToken) -> String {
|
|||||||
String::from("en-US")
|
String::from("en-US")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/system/enterprise/config/id")]
|
||||||
|
pub fn read_enterprise_env_config_id(_token: APIToken) -> Option<String> {
|
||||||
|
//
|
||||||
|
// When we are on a Windows machine, we try to read the enterprise config from
|
||||||
|
// the Windows registry. In case we can't find the registry key, or we are on a
|
||||||
|
// macOS or Linux machine, we try to read the enterprise config from the
|
||||||
|
// environment variables.
|
||||||
|
//
|
||||||
|
// The registry key is:
|
||||||
|
// HKEY_CURRENT_USER\Software\github\MindWork AI Studio\Enterprise IT
|
||||||
|
//
|
||||||
|
// In this registry key, we expect the following values:
|
||||||
|
// - config_id
|
||||||
|
//
|
||||||
|
// The environment variable is:
|
||||||
|
// MINDWORK_AI_STUDIO_ENTERPRISE_CONFIG_ID
|
||||||
|
//
|
||||||
|
get_enterprise_configuration(
|
||||||
|
"config_id",
|
||||||
|
"MINDWORK_AI_STUDIO_ENTERPRISE_CONFIG_ID",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[get("/system/enterprise/config/server")]
|
||||||
|
pub fn read_enterprise_env_config_server_url(_token: APIToken) -> Option<String> {
|
||||||
|
//
|
||||||
|
// When we are on a Windows machine, we try to read the enterprise config from
|
||||||
|
// the Windows registry. In case we can't find the registry key, or we are on a
|
||||||
|
// macOS or Linux machine, we try to read the enterprise config from the
|
||||||
|
// environment variables.
|
||||||
|
//
|
||||||
|
// The registry key is:
|
||||||
|
// HKEY_CURRENT_USER\Software\github\MindWork AI Studio\Enterprise IT
|
||||||
|
//
|
||||||
|
// In this registry key, we expect the following values:
|
||||||
|
// - config_server_url
|
||||||
|
//
|
||||||
|
// The environment variable is:
|
||||||
|
// MINDWORK_AI_STUDIO_ENTERPRISE_CONFIG_SERVER_URL
|
||||||
|
//
|
||||||
|
get_enterprise_configuration(
|
||||||
|
"config_server_url",
|
||||||
|
"MINDWORK_AI_STUDIO_ENTERPRISE_CONFIG_SERVER_URL",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_enterprise_configuration(reg_value: &str, env_name: &str) -> Option<String> {
|
||||||
|
info!("Trying to read the enterprise environment for some predefined configuration.");
|
||||||
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(target_os = "windows")] {
|
||||||
|
info!(r"Detected a Windows machine, trying to read the registry key 'HKEY_CURRENT_USER\Software\github\MindWork AI Studio\Enterprise IT' or the environment variables");
|
||||||
|
use windows_registry::*;
|
||||||
|
let key_path = r"Software\github\MindWork AI Studio\Enterprise IT";
|
||||||
|
let key = match CURRENT_USER.open(key_path) {
|
||||||
|
Ok(key) => key,
|
||||||
|
Err(_) => {
|
||||||
|
info!(r"Could not read the registry key HKEY_CURRENT_USER\Software\github\MindWork AI Studio\Enterprise IT. Falling back to environment variables.");
|
||||||
|
return match env::var(env_name) {
|
||||||
|
Ok(val) => {
|
||||||
|
info!("Falling back to the environment variable '{}' was successful.", env_name);
|
||||||
|
Some(val)
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
info!("Falling back to the environment variable '{}' was not successful. It appears that this is not an enterprise environment.", env_name);
|
||||||
|
None
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
match key.get_string(reg_value) {
|
||||||
|
Ok(val) => Some(val),
|
||||||
|
Err(_) => {
|
||||||
|
info!(r"We could read the registry key 'HKEY_CURRENT_USER\Software\github\MindWork AI Studio\Enterprise IT', but the value '{}' could not be read. Falling back to environment variables.", reg_value);
|
||||||
|
match env::var(env_name) {
|
||||||
|
Ok(val) => {
|
||||||
|
info!("Falling back to the environment variable '{}' was successful.", env_name);
|
||||||
|
Some(val)
|
||||||
|
},
|
||||||
|
Err(_) => {
|
||||||
|
info!("Falling back to the environment variable '{}' was not successful. It appears that this is not an enterprise environment.", env_name);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// In the case of macOS or Linux, we just read the environment variable:
|
||||||
|
info!(r"Detected a Unix machine, trying to read the environment variable '{}'.", env_name)
|
||||||
|
env::var(env_name).ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -78,6 +78,8 @@ pub fn start_runtime_api() {
|
|||||||
crate::environment::get_data_directory,
|
crate::environment::get_data_directory,
|
||||||
crate::environment::get_config_directory,
|
crate::environment::get_config_directory,
|
||||||
crate::environment::read_user_language,
|
crate::environment::read_user_language,
|
||||||
|
crate::environment::read_enterprise_env_config_id,
|
||||||
|
crate::environment::read_enterprise_env_config_server_url,
|
||||||
crate::file_data::extract_data,
|
crate::file_data::extract_data,
|
||||||
crate::file_data::read_pdf,
|
crate::file_data::read_pdf,
|
||||||
crate::log::get_log_paths,
|
crate::log::get_log_paths,
|
||||||
|
Loading…
Reference in New Issue
Block a user