Skip to main content

fur_cli/security/
lock.rs

1use std::fs;
2use std::path::Path;
3
4use clap::Parser;
5use rpassword::read_password;
6
7use crate::security::{io, state};
8
9#[derive(Parser, Clone)]
10pub struct LockArgs {
11    #[arg(long)]
12    pub hide: bool,
13}
14
15pub fn run_lock(args: LockArgs) {
16
17    if state::is_locked() {
18        println!("🔒 Project already locked.");
19        return;
20    }
21
22    let pass = if args.hide {
23        println!("🔑 Enter password:");
24        read_password().unwrap()
25    } else {
26        io::read_visible_password()
27    };
28
29    create_lockcheck();
30
31    encrypt_project(&pass);
32
33    state::write_lock();
34
35    println!("🔐 Project encrypted.");
36}
37
38fn create_lockcheck() {
39    let path = Path::new(".fur/.lockcheck");
40    fs::write(path, "FUR_LOCK_CHECK_V1").unwrap();
41}
42
43fn encrypt_project(password: &str) {
44
45    encrypt_dir(".fur/messages", password);
46    encrypt_dir(".fur/threads", password);
47
48    encrypt_file(".fur/index.json", password);
49    encrypt_file(".fur/.lockcheck", password);
50
51    encrypt_markdowns(password);
52}
53
54fn encrypt_dir(dir: &str, password: &str) {
55
56    let path = Path::new(dir);
57
58    if let Ok(entries) = fs::read_dir(path) {
59
60        for e in entries.flatten() {
61
62            let p = e.path();
63
64            if p.is_file() {
65                io::encrypt_file(&p, password);
66            }
67        }
68    }
69}
70
71fn encrypt_file(path: &str, password: &str) {
72
73    let p = Path::new(path);
74
75    if p.exists() {
76        io::encrypt_file(p, password);
77    }
78}
79
80fn encrypt_markdowns(password: &str) {
81
82    let chats = Path::new("chats");
83
84    if !chats.exists() {
85        return;
86    }
87
88    if let Ok(entries) = fs::read_dir(chats) {
89
90        for e in entries.flatten() {
91
92            let p = e.path();
93
94            if p.is_file() {
95                io::encrypt_file(&p, password);
96            }
97        }
98    }
99}