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}