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    if state::is_locked() {
17        println!("🔒 Project already locked.");
18        return;
19    }
20
21    let pass = if args.hide {
22        println!("🔑 Enter password:");
23        read_password().unwrap()
24    } else {
25        io::read_visible_password()
26    };
27
28    create_lockcheck();
29
30    encrypt_project(&pass);
31
32    state::write_lock();
33
34    println!("🔐 Project encrypted.");
35}
36
37fn create_lockcheck() {
38    let path = Path::new(".fur/.lockcheck");
39    fs::write(path, "FUR_LOCK_CHECK_V1").unwrap();
40}
41
42fn encrypt_project(password: &str) {
43    encrypt_dir(".fur/messages", password);
44    encrypt_dir(".fur/threads", password);
45
46    encrypt_file(".fur/index.json", password);
47    encrypt_file(".fur/.lockcheck", password);
48
49    encrypt_markdowns(password);
50}
51
52fn encrypt_dir(dir: &str, password: &str) {
53    let path = Path::new(dir);
54
55    if let Ok(entries) = fs::read_dir(path) {
56        for e in entries.flatten() {
57            let p = e.path();
58
59            if p.is_file() {
60                io::encrypt_file(&p, password);
61            }
62        }
63    }
64}
65
66fn encrypt_file(path: &str, password: &str) {
67    let p = Path::new(path);
68
69    if p.exists() {
70        io::encrypt_file(p, password);
71    }
72}
73
74fn encrypt_markdowns(password: &str) {
75    let chats = Path::new("chats");
76
77    if !chats.exists() {
78        return;
79    }
80
81    if let Ok(entries) = fs::read_dir(chats) {
82        for e in entries.flatten() {
83            let p = e.path();
84
85            if p.is_file() {
86                io::encrypt_file(&p, password);
87            }
88        }
89    }
90}