summaryrefslogtreecommitdiff
path: root/crates/vcs/src/data/vault.rs
blob: 5b34c6f3a7924bbf5b20950747387bb8f995a6eb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
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_VF_ROOT, VAULT_HOST_NAME,
    },
    current::{current_vault_path, find_vault_path},
    data::{member::Member, vault::config::VaultConfig},
};

pub mod config;
pub mod member;
pub mod sheets;
pub mod virtual_file;

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 vault_path = find_vault_path(vault_path)?;
        Some(Self { config, vault_path })
    }

    /// Initialize vault
    pub fn init_current_dir(config: VaultConfig) -> Option<Self> {
        let vault_path = current_vault_path()?;
        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();

        // Ensure directory is empty
        if vault_path.exists() && vault_path.read_dir()?.next().is_some() {
            return Err(std::io::Error::new(
                std::io::ErrorKind::DirectoryNotEmpty,
                "DirectoryNotEmpty",
            ));
        }

        // 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_VF_ROOT))?;

        let Some(vault) = Vault::init(config, &vault_path) else {
            return Err(std::io::Error::other(
                "Failed to initialize vault",
            ));
        };

        // 6. Create host member
        vault
            .register_member_to_vault(Member::new(VAULT_HOST_NAME))
            .await?;

        // 7. Setup reference sheet
        vault
            .create_sheet(&"ref".to_string(), &VAULT_HOST_NAME.to_string())
            .await?;

        // 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 be named `{{member_id}}.pem` (e.g., `juliet.pem`), and contain the user's public key in PEM format.

**ECDSA:**
```bash
openssl genpkey -algorithm ed25519 -out your_name_private.pem
openssl pkey -in your_name_private.pem -pubout -out your_name.pem
```

**RSA:**
```bash
openssl genpkey -algorithm RSA -out your_name_private.pem -pkeyopt rsa_keygen_bits:2048
openssl pkey -in your_name_private.pem -pubout -out your_name.pem
```

**DSA:**
```bash
openssl genpkey -algorithm DSA -out your_name_private.pem -pkeyopt dsa_paramgen_bits:2048
openssl pkey -in your_name_private.pem -pubout -out your_name.pem
```

Place only the `your_name.pem` file in the server's `./key/` directory, renamed to match the user's member ID.

## File Storage
All version-controlled files (Virtual File) are stored in the `{}` directory.

## License
This software is distributed under the MIT License. For complete license details, please see the main repository homepage.

## 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_VF_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(())
    }
}