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}