summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2025-09-25 17:20:13 +0800
committer魏曹先生 <1992414357@qq.com>2025-09-25 17:20:13 +0800
commite18134cc74e8f2ec3a88704074f94c74944db2bc (patch)
treeb1dc3cca87f46b8db6bf5956e74e8b27f3a49f6e /crates
parent647cc441eece20218d7387f37d94042e88042057 (diff)
Move `workspace` mod to `data`
Diffstat (limited to 'crates')
-rw-r--r--crates/vcs/src/data.rs (renamed from crates/vcs/src/workspace.rs)0
-rw-r--r--crates/vcs/src/data/local.rs (renamed from crates/vcs/src/workspace/local.rs)2
-rw-r--r--crates/vcs/src/data/local/config.rs (renamed from crates/vcs/src/workspace/local/config.rs)2
-rw-r--r--crates/vcs/src/data/member.rs (renamed from crates/vcs/src/workspace/member.rs)0
-rw-r--r--crates/vcs/src/data/user.rs28
-rw-r--r--crates/vcs/src/data/user/accounts.rs161
-rw-r--r--crates/vcs/src/data/vault.rs (renamed from crates/vcs/src/workspace/vault.rs)2
-rw-r--r--crates/vcs/src/data/vault/config.rs (renamed from crates/vcs/src/workspace/vault/config.rs)4
-rw-r--r--crates/vcs/src/data/vault/member.rs (renamed from crates/vcs/src/workspace/vault/member.rs)51
-rw-r--r--crates/vcs/src/data/vault/virtual_file.rs (renamed from crates/vcs/src/workspace/vault/virtual_file.rs)2
-rw-r--r--crates/vcs/src/workspace/user.rs1
-rw-r--r--crates/vcs/src/workspace/user/accounts.rs1
12 files changed, 238 insertions, 16 deletions
diff --git a/crates/vcs/src/workspace.rs b/crates/vcs/src/data.rs
index 63411a6..63411a6 100644
--- a/crates/vcs/src/workspace.rs
+++ b/crates/vcs/src/data.rs
diff --git a/crates/vcs/src/workspace/local.rs b/crates/vcs/src/data/local.rs
index 8399b6d..1c99832 100644
--- a/crates/vcs/src/workspace/local.rs
+++ b/crates/vcs/src/data/local.rs
@@ -6,7 +6,7 @@ use tokio::fs;
use crate::{
constants::{CLIENT_FILE_README, CLIENT_FILE_WORKSPACE},
current::{current_local_path, find_local_path},
- workspace::local::config::LocalConfig,
+ data::local::config::LocalConfig,
};
pub mod config;
diff --git a/crates/vcs/src/workspace/local/config.rs b/crates/vcs/src/data/local/config.rs
index d641880..e024569 100644
--- a/crates/vcs/src/workspace/local/config.rs
+++ b/crates/vcs/src/data/local/config.rs
@@ -4,7 +4,7 @@ use std::net::SocketAddr;
use crate::constants::CLIENT_FILE_WORKSPACE;
use crate::constants::PORT;
-use crate::workspace::vault::MemberId;
+use crate::data::vault::MemberId;
#[derive(Serialize, Deserialize, ConfigFile)]
#[cfg_file(path = CLIENT_FILE_WORKSPACE)]
diff --git a/crates/vcs/src/workspace/member.rs b/crates/vcs/src/data/member.rs
index 208c78c..208c78c 100644
--- a/crates/vcs/src/workspace/member.rs
+++ b/crates/vcs/src/data/member.rs
diff --git a/crates/vcs/src/data/user.rs b/crates/vcs/src/data/user.rs
new file mode 100644
index 0000000..0abd098
--- /dev/null
+++ b/crates/vcs/src/data/user.rs
@@ -0,0 +1,28 @@
+use crate::current::current_doc_dir;
+use std::path::PathBuf;
+
+pub mod accounts;
+
+pub struct UserDirectory {
+ local_path: PathBuf,
+}
+
+impl UserDirectory {
+ /// Create a user ditectory struct from the current system's document directory
+ pub fn current_doc_dir() -> Option<Self> {
+ Some(UserDirectory {
+ local_path: current_doc_dir()?,
+ })
+ }
+
+ /// Create a user directory struct from a specified directory path
+ /// Returns None if the directory does not exist
+ pub fn from_path<P: Into<PathBuf>>(path: P) -> Option<Self> {
+ let local_path = path.into();
+ if local_path.exists() {
+ Some(UserDirectory { local_path })
+ } else {
+ None
+ }
+ }
+}
diff --git a/crates/vcs/src/data/user/accounts.rs b/crates/vcs/src/data/user/accounts.rs
new file mode 100644
index 0000000..83ebda9
--- /dev/null
+++ b/crates/vcs/src/data/user/accounts.rs
@@ -0,0 +1,161 @@
+use std::{
+ fs,
+ io::{Error, ErrorKind},
+ path::PathBuf,
+};
+
+use cfg_file::config::ConfigFile;
+
+use crate::{
+ constants::{USER_FILE_ACCOUNTS, USER_FILE_KEY, USER_FILE_MEMBER},
+ data::{member::Member, user::UserDirectory, vault::MemberId},
+};
+
+const SELF_ID: &str = "{self_id}";
+
+/// Account Management
+impl UserDirectory {
+ /// Read account from configuration file
+ pub async fn account(&self, id: &MemberId) -> Result<Member, std::io::Error> {
+ if let Some(cfg_file) = self.account_cfg(id) {
+ let member = Member::read_from(cfg_file).await?;
+ return Ok(member);
+ }
+
+ Err(Error::new(ErrorKind::NotFound, "Account not found!"))
+ }
+
+ /// List all account IDs in the user directory
+ pub fn account_ids(&self) -> Result<Vec<MemberId>, std::io::Error> {
+ let accounts_path = self
+ .local_path
+ .join(USER_FILE_ACCOUNTS.replace(SELF_ID, ""));
+
+ if !accounts_path.exists() {
+ return Ok(Vec::new());
+ }
+
+ let mut account_ids = Vec::new();
+
+ for entry in fs::read_dir(accounts_path)? {
+ let entry = entry?;
+ let path = entry.path();
+
+ if path.is_file()
+ && let Some(file_name) = path.file_stem().and_then(|s| s.to_str())
+ && path.extension().and_then(|s| s.to_str()) == Some("toml")
+ {
+ // Remove the "_private" suffix from key files if present
+ let account_id = file_name.replace("_private", "");
+ account_ids.push(account_id);
+ }
+ }
+
+ Ok(account_ids)
+ }
+
+ /// Get all accounts
+ /// This method will read and deserialize account information, please pay attention to performance issues
+ pub async fn accounts(&self) -> Result<Vec<Member>, std::io::Error> {
+ let mut accounts = Vec::new();
+
+ for account_id in self.account_ids()? {
+ if let Ok(account) = self.account(&account_id).await {
+ accounts.push(account);
+ }
+ }
+
+ Ok(accounts)
+ }
+
+ /// Update account info
+ pub async fn update_account(&self, member: Member) -> Result<(), std::io::Error> {
+ // Ensure account exist
+ if self.account_cfg(&member.id()).is_some() {
+ let account_cfg_path = self.account_cfg_path(&member.id());
+ Member::write_to(&member, account_cfg_path).await?;
+ return Ok(());
+ }
+
+ Err(Error::new(ErrorKind::NotFound, "Account not found!"))
+ }
+
+ /// Register an account to user directory
+ pub async fn register_account(&self, member: Member) -> Result<(), std::io::Error> {
+ // Ensure account not exist
+ if self.account_cfg(&member.id()).is_some() {
+ return Err(Error::new(
+ ErrorKind::DirectoryNotEmpty,
+ format!("Account `{}` already registered!", member.id()),
+ ));
+ }
+
+ // Ensure accounts directory exists
+ let accounts_dir = self
+ .local_path
+ .join(USER_FILE_ACCOUNTS.replace(SELF_ID, ""));
+ if !accounts_dir.exists() {
+ fs::create_dir_all(&accounts_dir)?;
+ }
+
+ // Write config file to accounts dir
+ let account_cfg_path = self.account_cfg_path(&member.id());
+ Member::write_to(&member, account_cfg_path).await?;
+
+ Ok(())
+ }
+
+ /// Remove account from user directory
+ pub fn remove_account(&self, id: &MemberId) -> Result<(), std::io::Error> {
+ // Remove config file if exists
+ if let Some(account_cfg_path) = self.account_cfg(id) {
+ fs::remove_file(account_cfg_path)?;
+ }
+
+ // Remove private key file if exists
+ if let Some(private_key_path) = self.account_private_key(id)
+ && private_key_path.exists()
+ {
+ fs::remove_file(private_key_path)?;
+ }
+
+ Ok(())
+ }
+
+ /// Try to get the account's configuration file to determine if the account exists
+ pub fn account_cfg(&self, id: &MemberId) -> Option<PathBuf> {
+ let cfg_file = self.account_cfg_path(id);
+ if cfg_file.exists() {
+ Some(cfg_file)
+ } else {
+ None
+ }
+ }
+
+ /// Try to get the account's private key file to determine if the account has a private key
+ pub fn account_private_key(&self, id: &MemberId) -> Option<PathBuf> {
+ let key_file = self.account_private_key_path(id);
+ if key_file.exists() {
+ Some(key_file)
+ } else {
+ None
+ }
+ }
+
+ /// Check if account has private key
+ pub fn has_private_key(&self, id: &MemberId) -> bool {
+ self.account_private_key(id).is_some()
+ }
+
+ /// Get the account's configuration file path, but do not check if the file exists
+ pub fn account_cfg_path(&self, id: &MemberId) -> PathBuf {
+ self.local_path
+ .join(USER_FILE_MEMBER.replace(SELF_ID, id.to_string().as_str()))
+ }
+
+ /// Get the account's private key file path, but do not check if the file exists
+ pub fn account_private_key_path(&self, id: &MemberId) -> PathBuf {
+ self.local_path
+ .join(USER_FILE_KEY.replace(SELF_ID, id.to_string().as_str()))
+ }
+}
diff --git a/crates/vcs/src/workspace/vault.rs b/crates/vcs/src/data/vault.rs
index 7f52c9c..9b400bb 100644
--- a/crates/vcs/src/workspace/vault.rs
+++ b/crates/vcs/src/data/vault.rs
@@ -12,7 +12,7 @@ use crate::{
SERVER_PATH_SHEETS, SERVER_PATH_VF_ROOT,
},
current::{current_vault_path, find_vault_path},
- workspace::vault::config::VaultConfig,
+ data::vault::config::VaultConfig,
};
pub mod config;
diff --git a/crates/vcs/src/workspace/vault/config.rs b/crates/vcs/src/data/vault/config.rs
index 5414e4d..11917de 100644
--- a/crates/vcs/src/workspace/vault/config.rs
+++ b/crates/vcs/src/data/vault/config.rs
@@ -2,8 +2,8 @@ use cfg_file::ConfigFile;
use serde::{Deserialize, Serialize};
use crate::constants::SERVER_FILE_VAULT;
-use crate::workspace::member::Member;
-use crate::workspace::vault::MemberId;
+use crate::data::member::Member;
+use crate::data::vault::MemberId;
#[derive(Serialize, Deserialize, ConfigFile)]
#[cfg_file(path = SERVER_FILE_VAULT)]
diff --git a/crates/vcs/src/workspace/vault/member.rs b/crates/vcs/src/data/vault/member.rs
index 2d00081..9482d30 100644
--- a/crates/vcs/src/workspace/vault/member.rs
+++ b/crates/vcs/src/data/vault/member.rs
@@ -7,8 +7,8 @@ use std::{
use cfg_file::config::ConfigFile;
use crate::{
- constants::{SERVER_FILE_MEMBER_INFO, SERVER_FILE_MEMBER_PUB},
- workspace::{
+ constants::{SERVER_FILE_MEMBER_INFO, SERVER_FILE_MEMBER_PUB, SERVER_PATH_MEMBERS},
+ data::{
member::Member,
vault::{MemberId, Vault},
},
@@ -28,6 +28,45 @@ impl Vault {
Err(Error::new(ErrorKind::NotFound, "Member not found!"))
}
+ /// List all member IDs in the vault
+ pub fn member_ids(&self) -> Result<Vec<MemberId>, std::io::Error> {
+ let members_path = self.vault_path.join(SERVER_PATH_MEMBERS);
+
+ if !members_path.exists() {
+ return Ok(Vec::new());
+ }
+
+ let mut member_ids = Vec::new();
+
+ for entry in fs::read_dir(members_path)? {
+ let entry = entry?;
+ let path = entry.path();
+
+ if path.is_file()
+ && let Some(file_name) = path.file_stem().and_then(|s| s.to_str())
+ && path.extension().and_then(|s| s.to_str()) == Some("toml")
+ {
+ member_ids.push(file_name.to_string());
+ }
+ }
+
+ Ok(member_ids)
+ }
+
+ /// Get all members
+ /// This method will read and deserialize member information, please pay attention to performance issues
+ pub async fn members(&self) -> Result<Vec<Member>, std::io::Error> {
+ let mut members = Vec::new();
+
+ for member_id in self.member_ids()? {
+ if let Ok(member) = self.member(&member_id).await {
+ members.push(member);
+ }
+ }
+
+ Ok(members)
+ }
+
/// Update member info
pub async fn update_member(&self, member: Member) -> Result<(), std::io::Error> {
// Ensure member exist
@@ -89,17 +128,13 @@ impl Vault {
/// Get the member's configuration file path, but do not check if the file exists
pub fn member_cfg_path(&self, id: &MemberId) -> PathBuf {
-
- self
- .vault_path
+ self.vault_path
.join(SERVER_FILE_MEMBER_INFO.replace(ID_PARAM, id.to_string().as_str()))
}
/// Get the member's public key file path, but do not check if the file exists
pub fn member_key_path(&self, id: &MemberId) -> PathBuf {
-
- self
- .vault_path
+ self.vault_path
.join(SERVER_FILE_MEMBER_PUB.replace(ID_PARAM, id.to_string().as_str()))
}
}
diff --git a/crates/vcs/src/workspace/vault/virtual_file.rs b/crates/vcs/src/data/vault/virtual_file.rs
index c83f700..04b5236 100644
--- a/crates/vcs/src/workspace/vault/virtual_file.rs
+++ b/crates/vcs/src/data/vault/virtual_file.rs
@@ -16,7 +16,7 @@ use crate::{
SERVER_FILE_VF_META, SERVER_FILE_VF_VERSION_INSTANCE, SERVER_PATH_VF_ROOT,
SERVER_PATH_VF_STORAGE, SERVER_PATH_VF_TEMP,
},
- workspace::vault::{MemberId, Vault},
+ data::vault::{MemberId, Vault},
};
pub type VirtualFileId = String;
diff --git a/crates/vcs/src/workspace/user.rs b/crates/vcs/src/workspace/user.rs
deleted file mode 100644
index 9bb4894..0000000
--- a/crates/vcs/src/workspace/user.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub mod accounts;
diff --git a/crates/vcs/src/workspace/user/accounts.rs b/crates/vcs/src/workspace/user/accounts.rs
deleted file mode 100644
index 8b13789..0000000
--- a/crates/vcs/src/workspace/user/accounts.rs
+++ /dev/null
@@ -1 +0,0 @@
-