summaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2025-09-22 16:49:51 +0800
committer魏曹先生 <1992414357@qq.com>2025-09-22 16:49:51 +0800
commitb0ae3b3b5c8b005b3f7cb2b26b17ae521a38c669 (patch)
treeecb8883f1c53ea1602d50c8a57d59d8d3b2a177c /crates
parent23f09dabe279233a960786d5048266de7f216c12 (diff)
Modify the file structure
Diffstat (limited to 'crates')
-rw-r--r--crates/env/src/member/manager.rs105
-rw-r--r--crates/env/src/vault.rs2
-rw-r--r--crates/env/src/vault/manage.rs1
-rw-r--r--crates/env/src/workspace.rs3
-rw-r--r--crates/env/src/workspace/local.rs (renamed from crates/env/src/local.rs)0
-rw-r--r--crates/env/src/workspace/local/config.rs (renamed from crates/env/src/local/config.rs)0
-rw-r--r--crates/env/src/workspace/local/manage.rs (renamed from crates/env/src/local/manage.rs)0
-rw-r--r--crates/env/src/workspace/member.rs (renamed from crates/env/src/member.rs)29
-rw-r--r--crates/env/src/workspace/vault.rs109
-rw-r--r--crates/env/src/workspace/vault/config.rs (renamed from crates/env/src/vault/config.rs)16
-rw-r--r--crates/env/src/workspace/vault/member.rs105
11 files changed, 242 insertions, 128 deletions
diff --git a/crates/env/src/member/manager.rs b/crates/env/src/member/manager.rs
deleted file mode 100644
index a6a2b50..0000000
--- a/crates/env/src/member/manager.rs
+++ /dev/null
@@ -1,105 +0,0 @@
-use std::{
- fs,
- io::{Error, ErrorKind},
- path::PathBuf,
-};
-
-use cfg_file::config::ConfigFile;
-
-use crate::{
- constants::{SERVER_FILE_MEMBER_INFO, SERVER_FILE_MEMBER_PUB},
- current::current_vault_path,
- member::Member,
- vault::config::MemberUuid,
-};
-
-pub struct VaultMemberManager;
-
-const UUID_PARAM: &str = "{member_uuid}";
-
-impl VaultMemberManager {
- /// Read member from configuration file
- pub async fn member(uuid: MemberUuid) -> Result<Member, std::io::Error> {
- if let Some(cfg_file) = Self::member_cfg(uuid)? {
- let member = Member::read_from(cfg_file).await?;
- return Ok(member);
- }
-
- Err(Error::new(ErrorKind::NotFound, "Member not found!"))
- }
-
- /// Register a member to vault
- pub async fn register_member_to_vault(member: Member) -> Result<(), std::io::Error> {
- // Ensure member not exist
- if let Some(_) = Self::member_cfg(member.uuid())? {
- return Err(Error::new(
- ErrorKind::DirectoryNotEmpty,
- format!("Member `{}` already registered!", member.id()),
- ));
- }
-
- // Wrtie config file to member dir
- let member_cfg_path = Self::member_cfg_path(member.uuid())?;
- Member::write_to(&member, member_cfg_path).await?;
-
- Ok(())
- }
-
- /// Remove member from vault
- pub fn remove_member_from_vault(uuid: MemberUuid) -> Result<(), std::io::Error> {
- // Ensure member exist
- if let Some(member_cfg_path) = Self::member_cfg(uuid)? {
- fs::remove_file(member_cfg_path)?;
- }
-
- Ok(())
- }
-
- /// Try to get the member's configuration file to determine if the member exists
- pub fn member_cfg(uuid: MemberUuid) -> Result<Option<PathBuf>, std::io::Error> {
- let cfg_file = Self::member_cfg_path(uuid)?;
- if cfg_file.exists() {
- Ok(Some(cfg_file))
- } else {
- Ok(None)
- }
- }
-
- /// Try to get the member's public key file to determine if the member has login permission
- pub fn member_key(uuid: MemberUuid) -> Result<Option<PathBuf>, std::io::Error> {
- let key_file = Self::member_key_path(uuid)?;
- if key_file.exists() {
- Ok(Some(key_file))
- } else {
- Ok(None)
- }
- }
-
- /// Get the member's configuration file path, but do not check if the file exists
- pub fn member_cfg_path(uuid: MemberUuid) -> Result<PathBuf, std::io::Error> {
- // Has vault
- let Some(vault) = current_vault_path() else {
- return Err(Error::new(ErrorKind::NotFound, "Vault not found!"));
- };
-
- let path =
- vault.join(SERVER_FILE_MEMBER_INFO.replace(UUID_PARAM, uuid.to_string().as_str()));
- Ok(path)
- }
-
- /// Get the member's public key file path, but do not check if the file exists
- pub fn member_key_path(uuid: MemberUuid) -> Result<PathBuf, std::io::Error> {
- // Has vault
- let Some(vault) = current_vault_path() else {
- return Err(Error::new(ErrorKind::NotFound, "Vault not found!"));
- };
-
- let path =
- vault.join(SERVER_FILE_MEMBER_PUB.replace(UUID_PARAM, uuid.to_string().as_str()));
- Ok(path)
- }
-}
-
-pub struct UserMemberManager;
-
-impl UserMemberManager {}
diff --git a/crates/env/src/vault.rs b/crates/env/src/vault.rs
deleted file mode 100644
index 72092c2..0000000
--- a/crates/env/src/vault.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-pub mod config;
-pub mod manage;
diff --git a/crates/env/src/vault/manage.rs b/crates/env/src/vault/manage.rs
deleted file mode 100644
index 8b13789..0000000
--- a/crates/env/src/vault/manage.rs
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/crates/env/src/workspace.rs b/crates/env/src/workspace.rs
new file mode 100644
index 0000000..d59a6e0
--- /dev/null
+++ b/crates/env/src/workspace.rs
@@ -0,0 +1,3 @@
+pub mod local;
+pub mod member;
+pub mod vault;
diff --git a/crates/env/src/local.rs b/crates/env/src/workspace/local.rs
index 72092c2..72092c2 100644
--- a/crates/env/src/local.rs
+++ b/crates/env/src/workspace/local.rs
diff --git a/crates/env/src/local/config.rs b/crates/env/src/workspace/local/config.rs
index ddb7dd0..ddb7dd0 100644
--- a/crates/env/src/local/config.rs
+++ b/crates/env/src/workspace/local/config.rs
diff --git a/crates/env/src/local/manage.rs b/crates/env/src/workspace/local/manage.rs
index 8b13789..8b13789 100644
--- a/crates/env/src/local/manage.rs
+++ b/crates/env/src/workspace/local/manage.rs
diff --git a/crates/env/src/member.rs b/crates/env/src/workspace/member.rs
index 0a25151..b81bd82 100644
--- a/crates/env/src/member.rs
+++ b/crates/env/src/workspace/member.rs
@@ -1,17 +1,16 @@
-pub mod manager;
+use std::collections::HashMap;
use cfg_file::ConfigFile;
use serde::{Deserialize, Serialize};
use string_proc::camel_case;
-use uuid::Uuid;
#[derive(Debug, Eq, Clone, ConfigFile, Serialize, Deserialize)]
pub struct Member {
- /// Member ID, used to intuitively display the name to other members
+ /// Member ID, the unique identifier of the member
id: String,
- /// Member Uuid, used to ensure the uniqueness of this member
- uuid: Uuid,
+ /// Member metadata
+ metadata: HashMap<String, String>,
}
impl Default for Member {
@@ -22,7 +21,7 @@ impl Default for Member {
impl PartialEq for Member {
fn eq(&self, other: &Self) -> bool {
- self.uuid == other.uuid
+ self.id == other.id
}
}
@@ -41,10 +40,9 @@ impl std::convert::AsRef<str> for Member {
impl Member {
/// Create member struct by id
pub fn new(new_id: impl Into<String>) -> Self {
- let uuid = Uuid::new_v4();
Self {
id: camel_case!(new_id.into()),
- uuid,
+ metadata: HashMap::new(),
}
}
@@ -53,8 +51,17 @@ impl Member {
self.id.clone()
}
- /// Get member uuid
- pub fn uuid(&self) -> Uuid {
- self.uuid
+ /// Get metadata
+ pub fn metadata(&self, key: impl Into<String>) -> Option<&String> {
+ self.metadata.get(&key.into())
+ }
+
+ /// Set metadata
+ pub fn set_metadata(
+ &mut self,
+ key: impl AsRef<str>,
+ value: impl Into<String>,
+ ) -> Option<String> {
+ self.metadata.insert(key.as_ref().to_string(), value.into())
}
}
diff --git a/crates/env/src/workspace/vault.rs b/crates/env/src/workspace/vault.rs
new file mode 100644
index 0000000..b00ba80
--- /dev/null
+++ b/crates/env/src/workspace/vault.rs
@@ -0,0 +1,109 @@
+use std::{
+ env::current_dir,
+ fs::{self, create_dir_all},
+ path::PathBuf,
+};
+
+use cfg_file::config::ConfigFile;
+
+use crate::{
+ constants::{
+ SERVER_FILE_README, SERVER_FILE_VAULT, SERVER_PATH_MEMBER_PUB, SERVER_PATH_MEMBERS,
+ SERVER_PATH_SHEETS, SERVER_PATH_VIRTUAL_FILE_ROOT,
+ },
+ current::{current_vault_path, find_vault_path},
+ workspace::vault::config::VaultConfig,
+};
+
+pub mod config;
+pub mod member;
+pub mod vitrual_file;
+
+pub type MemberId = String;
+
+pub struct Vault {
+ config: VaultConfig,
+ vault_path: PathBuf,
+}
+
+impl Vault {
+ /// Get vault path
+ pub fn vault_path(&self) -> &PathBuf {
+ &self.vault_path
+ }
+
+ /// Initialize vault
+ pub fn init(config: VaultConfig, vault_path: impl Into<PathBuf>) -> Option<Self> {
+ let Some(vault_path) = find_vault_path(vault_path) else {
+ return None;
+ };
+ Some(Self { config, vault_path })
+ }
+
+ /// Initialize vault
+ pub fn init_current_dir(config: VaultConfig) -> Option<Self> {
+ let Some(vault_path) = current_vault_path() else {
+ return None;
+ };
+ Some(Self { config, vault_path })
+ }
+
+ /// Setup vault
+ pub async fn setup_vault(vault_path: impl Into<PathBuf>) -> Result<(), std::io::Error> {
+ let vault_path: PathBuf = vault_path.into();
+
+ // 1. Setup main config
+ let config = VaultConfig::default();
+ VaultConfig::write_to(&config, vault_path.join(SERVER_FILE_VAULT)).await?;
+
+ // 2. Setup sheets directory
+ create_dir_all(vault_path.join(SERVER_PATH_SHEETS))?;
+
+ // 3. Setup key directory
+ create_dir_all(vault_path.join(SERVER_PATH_MEMBER_PUB))?;
+
+ // 4. Setup member directory
+ create_dir_all(vault_path.join(SERVER_PATH_MEMBERS))?;
+
+ // 5. Setup storage directory
+ create_dir_all(vault_path.join(SERVER_PATH_VIRTUAL_FILE_ROOT))?;
+
+ // Final, generate README.md
+ let readme_content = format!(
+ "\
+ # JustEnoughVCS Server Setup
+
+ This directory contains the server configuration and data for `JustEnoughVCS`.
+
+ ## User Authentication
+ To allow users to connect to this server, place their public keys in the `{}` directory.
+ Each public key file should correspond to a registered user.
+
+ ## File Storage
+ All version-controlled files (Virtual File) are stored in the `{}` directory.
+
+ ## License
+ This software is distributed under the MIT License.
+
+ ## Support
+ Repository: `https://github.com/JustEnoughVCS/VersionControl`
+ Please report any issues or questions on the GitHub issue tracker.
+
+ ## Thanks :)
+ Thank you for using `JustEnoughVCS!`
+ ",
+ SERVER_PATH_MEMBER_PUB, SERVER_PATH_VIRTUAL_FILE_ROOT
+ )
+ .trim()
+ .to_string();
+ fs::write(vault_path.join(SERVER_FILE_README), readme_content)?;
+
+ Ok(())
+ }
+
+ /// Setup vault in current directory
+ pub async fn setup_vault_current_dir() -> Result<(), std::io::Error> {
+ Self::setup_vault(current_dir()?).await?;
+ Ok(())
+ }
+}
diff --git a/crates/env/src/vault/config.rs b/crates/env/src/workspace/vault/config.rs
index f4e97e6..983a9e5 100644
--- a/crates/env/src/vault/config.rs
+++ b/crates/env/src/workspace/vault/config.rs
@@ -1,11 +1,9 @@
use cfg_file::ConfigFile;
use serde::{Deserialize, Serialize};
-use uuid::Uuid;
use crate::constants::SERVER_FILE_VAULT;
-use crate::member::Member;
-
-pub type MemberUuid = Uuid;
+use crate::workspace::member::Member;
+use crate::workspace::vault::MemberId;
#[derive(Default, Serialize, Deserialize, ConfigFile)]
#[cfg_file(path = SERVER_FILE_VAULT)]
@@ -13,8 +11,8 @@ pub struct VaultConfig {
/// Vault name, which can be used as the project name and generally serves as a hint
vault_name: String,
- /// Vault admin Uuids, a list of member Uuids representing administrator identities
- vault_admin_list: Vec<MemberUuid>,
+ /// Vault admin id, a list of member id representing administrator identities
+ vault_admin_list: Vec<MemberId>,
}
impl VaultConfig {
@@ -25,7 +23,7 @@ impl VaultConfig {
// Add admin
pub fn add_admin(&mut self, member: &Member) {
- let uuid = member.uuid();
+ let uuid = member.id();
if !self.vault_admin_list.contains(&uuid) {
self.vault_admin_list.push(uuid);
}
@@ -33,7 +31,7 @@ impl VaultConfig {
// Remove admin
pub fn remove_admin(&mut self, member: &Member) {
- let uuid = member.uuid();
- self.vault_admin_list.retain(|&x| x != uuid);
+ let id = member.id();
+ self.vault_admin_list.retain(|x| x != &id);
}
}
diff --git a/crates/env/src/workspace/vault/member.rs b/crates/env/src/workspace/vault/member.rs
new file mode 100644
index 0000000..45452c5
--- /dev/null
+++ b/crates/env/src/workspace/vault/member.rs
@@ -0,0 +1,105 @@
+use std::{
+ fs,
+ io::{Error, ErrorKind},
+ path::PathBuf,
+};
+
+use cfg_file::config::ConfigFile;
+
+use crate::{
+ constants::{SERVER_FILE_MEMBER_INFO, SERVER_FILE_MEMBER_PUB},
+ workspace::{
+ member::Member,
+ vault::{MemberId, Vault},
+ },
+};
+
+const ID_PARAM: &str = "{member_id}";
+
+/// Member Manage
+impl Vault {
+ /// Read member from configuration file
+ pub async fn member(&self, id: MemberId) -> Result<Member, std::io::Error> {
+ if let Some(cfg_file) = self.member_cfg(id) {
+ let member = Member::read_from(cfg_file).await?;
+ return Ok(member);
+ }
+
+ Err(Error::new(ErrorKind::NotFound, "Member not found!"))
+ }
+
+ /// Update member info
+ pub async fn update_member(&self, member: Member) -> Result<(), std::io::Error> {
+ // Ensure member exist
+ if let Some(_) = self.member_cfg(member.id()) {
+ let member_cfg_path = self.member_cfg_path(member.id());
+ Member::write_to(&member, member_cfg_path).await?;
+ return Ok(());
+ }
+
+ Err(Error::new(ErrorKind::NotFound, "Member not found!"))
+ }
+
+ /// Register a member to vault
+ pub async fn register_member_to_vault(&self, member: Member) -> Result<(), std::io::Error> {
+ // Ensure member not exist
+ if let Some(_) = self.member_cfg(member.id()) {
+ return Err(Error::new(
+ ErrorKind::DirectoryNotEmpty,
+ format!("Member `{}` already registered!", member.id()),
+ ));
+ }
+
+ // Wrtie config file to member dir
+ let member_cfg_path = self.member_cfg_path(member.id());
+ Member::write_to(&member, member_cfg_path).await?;
+
+ Ok(())
+ }
+
+ /// Remove member from vault
+ pub fn remove_member_from_vault(&self, id: MemberId) -> Result<(), std::io::Error> {
+ // Ensure member exist
+ if let Some(member_cfg_path) = self.member_cfg(id) {
+ fs::remove_file(member_cfg_path)?;
+ }
+
+ Ok(())
+ }
+
+ /// Try to get the member's configuration file to determine if the member exists
+ pub fn member_cfg(&self, id: MemberId) -> Option<PathBuf> {
+ let cfg_file = self.member_cfg_path(id);
+ if cfg_file.exists() {
+ Some(cfg_file)
+ } else {
+ None
+ }
+ }
+
+ /// Try to get the member's public key file to determine if the member has login permission
+ pub fn member_key(&self, id: MemberId) -> Option<PathBuf> {
+ let key_file = self.member_key_path(id);
+ if key_file.exists() {
+ Some(key_file)
+ } else {
+ None
+ }
+ }
+
+ /// Get the member's configuration file path, but do not check if the file exists
+ pub fn member_cfg_path(&self, id: MemberId) -> PathBuf {
+ let path = self
+ .vault_path
+ .join(SERVER_FILE_MEMBER_INFO.replace(ID_PARAM, id.to_string().as_str()));
+ path
+ }
+
+ /// 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 {
+ let path = self
+ .vault_path
+ .join(SERVER_FILE_MEMBER_PUB.replace(ID_PARAM, id.to_string().as_str()));
+ path
+ }
+}