Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions context/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use std::sync::Arc;
use jupiter::tests::test_storage;
Comment thread
yyk808 marked this conversation as resolved.

Comment on lines +2 to 3

Copilot AI Jul 18, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move test-related import inside the mock method or use conditional compilation to avoid importing test utilities in production code.

Suggested change
use jupiter::tests::test_storage;

Copilot uses AI. Check for mistakes.
/// This is the main application context for the Mono application.
/// It holds shared state and configuration for the application.
Expand All @@ -22,8 +23,10 @@ pub struct AppContext {
impl AppContext {
/// Creates a new application context with the given configuration.
pub async fn new(config: common::config::Config) -> Self {

let config = Arc::new(config);


let storage = jupiter::storage::Storage::new(config.clone()).await;

let storage_for_vault = storage.clone();
Expand All @@ -33,6 +36,7 @@ impl AppContext {
.await
.expect("VaultCore::new panicked");


#[cfg(feature = "p2p")]
let client = gemini::p2p::client::P2PClient::new(storage.clone(), vault.clone());

Expand All @@ -45,9 +49,42 @@ impl AppContext {
#[cfg(feature = "p2p")]
client,
}


}

pub fn wrapped_context(&self) -> Arc<Self> {
Arc::new(self.clone())
}

pub async fn mock(config: common::config::Config) -> Self {

let config = Arc::new(config);

// use Existing test method
let storage = test_storage(config.base_dir.clone()).await;

let storage_for_vault = storage.clone();
let temp_dir = config.base_dir.clone().join("vault");
let key_path = temp_dir.join("core_key.json");
std::fs::create_dir_all(&temp_dir).expect("Mock: Failed to create vault dir");

let vault = tokio::task::spawn_blocking(move || {
vault::integration::vault_core::VaultCore::config(storage_for_vault, key_path)
})
.await
.expect("VaultCore::config panicked");

#[cfg(feature = "p2p")]
let client = gemini::p2p::client::P2PClient::new(storage.clone(), vault.clone());

Self {
storage,
vault,
config,
#[cfg(feature = "p2p")]
client,
}
}
}

1 change: 1 addition & 0 deletions monobean/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ home = "0.5.11"
smallvec = "1.14.0"
directories = "6.0.0"
tracing-appender = "0.2.3"
toml = "0.8.22"

[build-dependencies]
glib-build-tools = "0.20.0"
Expand Down
6 changes: 3 additions & 3 deletions monobean/resources/gtk/theme_selector.ui
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</style>
<property name="group">light</property>
<property name="focus-on-click">false</property>
<property name="action-name">win.style-variant</property>
<property name="action-name">style.style-variant</property>
<property name="action-target">'system'</property>
<property name="tooltip-text" translatable="yes">Use system style</property>
<property name="icon-name">monobean-lasso-select-symbolic</property>
Expand All @@ -30,7 +30,7 @@
<class name="light" />
</style>
<property name="focus-on-click">false</property>
<property name="action-name">win.style-variant</property>
<property name="action-name">style.style-variant</property>
<property name="action-target">'light'</property>
<property name="tooltip-text" translatable="yes">Light style</property>
<property name="icon-name">monobean-lasso-select-symbolic</property>
Expand All @@ -44,7 +44,7 @@
</style>
<property name="group">light</property>
<property name="focus-on-click">false</property>
<property name="action-name">win.style-variant</property>
<property name="action-name">style.style-variant</property>
<property name="action-target">'dark'</property>
<property name="tooltip-text" translatable="yes">Dark style</property>
<property name="icon-name">monobean-lasso-select-symbolic</property>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
<choice value='light' />
<choice value='dark' />
</choices>
<default>'system'</default>
<!-- <default>'system'</default> -->
<default>'light'</default>
<summary>Settings theme</summary>
</key>

Expand Down
111 changes: 63 additions & 48 deletions monobean/src/core/mega_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,11 @@ impl MegaCore {

let config = self.config.read().await.clone();


#[cfg(test)]
let inner = MegaContext::mock(config.clone()).await;

#[cfg(not(test))]
let inner = MegaContext::new(config.clone()).await;

let http_ctx = inner.clone();
Expand Down Expand Up @@ -465,11 +470,14 @@ mod tests {
use crate::config::APP_NAME;
use crate::config::MEGA_CONFIG_PATH;
use async_channel::bounded;
use common::config::DbConfig;
use common::config::LogConfig;
use common::config::{AuthConfig, DbConfig, LFSConfig, MonoConfig, PackConfig};
use gtk::gio;
use gtk::glib;
// use std::net::{IpAddr, Ipv4Addr};

use std::fs;
use std::net::{IpAddr, Ipv4Addr};

use tempfile::TempDir;

#[allow(dead_code)]
Expand All @@ -488,9 +496,21 @@ mod tests {
db_path: temp_base.path().to_path_buf().join("test.db"),
..Default::default()
},
..Default::default()
monorepo: MonoConfig::default(),
pack: PackConfig::default(),
authentication: AuthConfig::default(),
lfs: LFSConfig::default(),
oauth: None,
};

// make config saved in temp dir
let config_dir = temp_base.path().join("etc");
fs::create_dir_all(&config_dir).unwrap();
let config_path = config_dir.join("config.toml");
let toml_str = toml::to_string(&config).unwrap();
fs::write(&config_path, toml_str).unwrap();
let config = Config::new(config_path.to_str().unwrap()).unwrap();

let core = MegaCore::new(tx, cmd_rx, config);
core.init().await;
core
Expand All @@ -515,51 +535,46 @@ mod tests {
let _ = Config::load_str(content.as_str()).expect("Failed to parse mega core settings");
}

// #[tokio::test]
// async fn test_launch_http() {
// let temp_base = TempDir::new().unwrap();

// // 设置环境变量,让 mega_base() 返回临时目录
// unsafe {
// std::env::set_var("MEGA_BASE_DIR", temp_base.path());
// }

// let core = test_core(&temp_base).await;

// core.process_command(MegaCommands::MegaStart(
// Some(SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 8080)),
// None,
// P2pOptions::default(),
// ))
// .await;
// assert!(core.http_options.read().await.is_some());
// assert!(!core.ssh_options.read().await.is_some());

// core.process_command(MegaCommands::MegaShutdown).await;
// assert!(core.http_options.read().await.is_none());
// assert!(core.ssh_options.read().await.is_none());
// }

// #[tokio::test]
// async fn test_launch_ssh() {
// let temp_base = TempDir::new().unwrap();
// unsafe {
// std::env::set_var("MEGA_BASE_DIR", temp_base.path());
// }
// let core = test_core(&temp_base).await;
// core.process_command(MegaCommands::MegaStart(
// None,
// Some(SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 2222)),
// P2pOptions::default(),
// ))
// .await;
// assert!(core.http_options.read().await.is_none());
// assert!(core.ssh_options.read().await.is_some());

// core.process_command(MegaCommands::MegaShutdown).await;
// assert!(core.http_options.read().await.is_none());
// assert!(core.ssh_options.read().await.is_none());
// }

#[tokio::test]
async fn test_launch_http() {
let temp_base = TempDir::new().unwrap();

let core = test_core(&temp_base).await;

core.process_command(MegaCommands::MegaStart(
Some(SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 8080)),
None,
P2pOptions::default(),
))
.await;
assert!(core.http_options.read().await.is_some());
assert!(!core.ssh_options.read().await.is_some());

core.process_command(MegaCommands::MegaShutdown).await;
assert!(core.http_options.read().await.is_none());
assert!(core.ssh_options.read().await.is_none());
}

#[tokio::test]
async fn test_launch_ssh() {
let temp_base = TempDir::new().unwrap();

let core = test_core(&temp_base).await;
core.process_command(MegaCommands::MegaStart(
None,
Some(SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 2222)),
P2pOptions::default(),
))
.await;
assert!(core.http_options.read().await.is_none());
assert!(core.ssh_options.read().await.is_some());

core.process_command(MegaCommands::MegaShutdown).await;
assert!(core.http_options.read().await.is_none());
assert!(core.ssh_options.read().await.is_none());
}


#[tokio::test]
async fn test_run_with_config() {}
Expand Down
30 changes: 29 additions & 1 deletion monobean/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ use crate::components::{mega_tab::MegaTab, repo_tab::RepoTab};
use crate::config::PREFIX;
use crate::CONTEXT;
use adw::glib::Priority;
use adw::prelude::{Cast, ObjectExt, SettingsExtManual, ToValue};
use adw::prelude::{
ActionMapExt, Cast, ObjectExt, SettingsExt, SettingsExtManual, StaticVariantType, ToValue,
ToVariant,
};
use adw::subclass::prelude::*;
use adw::{gio, ColorScheme, StyleManager, Toast};
use gtk::gio::Settings;
use gtk::gio::{SimpleAction, SimpleActionGroup};
use gtk::glib;
use gtk::prelude::{GtkWindowExt, WidgetExt};
use gtk::CompositeTemplate;
Expand Down Expand Up @@ -203,6 +207,30 @@ impl MonobeanWindow {
let popover = popover.downcast::<PopoverMenu>().unwrap();
let theme = ThemeSelector::new();
popover.add_child(&theme, "theme");

// popoverMenu cont find win.(action) change the action group
let action_group = SimpleActionGroup::new();

// style-variant action
let settings = self.settings().clone();
let action = SimpleAction::new_stateful(
"style-variant",
Some(&String::static_variant_type()),
&settings.string("style-variant").to_variant(),
);
action.connect_activate(move |action, parameter| {
if let Some(param) = parameter {
let value = param.get::<String>().unwrap();
action.set_state(&value.to_variant());
settings
.set_string("style-variant", &value)
.expect("Failed to set style-variant in GSettings");
}
});

action_group.add_action(&action);

popover.insert_action_group("style", Some(&action_group));
}

pub fn add_toast(&self, message: String) {
Expand Down
15 changes: 13 additions & 2 deletions vault/src/integration/vault_core.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

use crate::integration::jupiter_backend::JupiterBackend;
use common::errors::MegaError;
use jupiter::storage::Storage;
Expand All @@ -6,6 +7,7 @@ use std::{
sync::{Arc, RwLock},
};


use rusty_vault::{
core::Core,
logical::{Operation, Request, Response},
Expand All @@ -17,6 +19,8 @@ use tracing::log;

const CORE_KEY_FILE: &str = "core_key.json"; // where the core key is stored, like `root_token`



#[derive(Debug, Clone, Serialize, Deserialize)]
struct CoreKey {
secret_shares: Vec<Vec<u8>>,
Expand Down Expand Up @@ -53,9 +57,10 @@ impl VaultCore {
tracing::info!("{key_path:?}");
std::fs::create_dir_all(&dir).expect("Failed to create vault directory");
Self::config(ctx.clone(), key_path)

}

fn config(ctx: Storage, key_path: PathBuf) -> Self {
pub fn config(ctx: Storage, key_path: PathBuf) -> Self {
let backend: Arc<dyn Backend> = Arc::new(JupiterBackend::new(ctx));
let barrier = barrier_aes_gcm::AESGCMBarrier::new(Arc::clone(&backend));
let seal_config = rusty_vault::core::SealConfig {
Expand All @@ -70,24 +75,29 @@ impl VaultCore {
};
let core = Arc::new(RwLock::new(core));


let key = {
let mut managed_core = core.write().unwrap();
managed_core
.config(core.clone(), None)
.expect("Failed to configure vault core");

let core_key = if !key_path.exists() {


let result = managed_core
.init(&seal_config)
.expect("Failed to initialize vault");
let core_key = CoreKey {
secret_shares: Vec::from(&result.secret_shares[..]),
root_token: result.root_token,
};

println!(
"[vault] Creating new core_key.json at: {}",
key_path.display()
);

let file = std::fs::File::create(&key_path).unwrap();
serde_json::to_writer_pretty(file, &core_key).unwrap();
core_key
Expand Down Expand Up @@ -201,7 +211,8 @@ mod tests {
"Vault core should be initialized"
);
}



#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
async fn test_vault_api() {
let temp_dir = tempfile::tempdir().expect("Failed to create temporary directory");
Expand Down
Loading