summaryrefslogtreecommitdiff
path: root/crates/vcs_data/src/data/local/member_held.rs
blob: 3f07232ecb40c31ad4c6d719a6246cb9dcd6773b (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
use std::{collections::HashMap, io::Error, path::PathBuf};

use cfg_file::ConfigFile;
use serde::{Deserialize, Serialize};

use crate::{
    constants::{CLIENT_FILE_MEMBER_HELD, CLIENT_FILE_MEMBER_HELD_NOSET},
    current::current_local_path,
    data::{member::MemberId, vault::virtual_file::VirtualFileId},
};

const ACCOUNT: &str = "{account}";

/// # Member Held Information
/// Records the files held by the member, used for permission validation
#[derive(Debug, Default, Clone, Serialize, Deserialize, ConfigFile)]
#[cfg_file(path = CLIENT_FILE_MEMBER_HELD_NOSET)]
pub struct MemberHeld {
    /// File holding status
    held_status: HashMap<VirtualFileId, HeldStatus>,
}

#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub enum HeldStatus {
    HeldWith(MemberId), // Held, status changes are sync to the client
    NotHeld,            // Not held, status changes are sync to the client

    #[default]
    WantedToKnow, // Holding status is unknown, notify server must inform client
}

impl MemberHeld {
    /// Get the path to the file holding the held status information for the given member.
    pub fn held_file_path(account: &MemberId) -> Result<PathBuf, std::io::Error> {
        let Some(local_path) = current_local_path() else {
            return Err(Error::new(
                std::io::ErrorKind::NotFound,
                "Workspace not found.",
            ));
        };
        Ok(local_path.join(CLIENT_FILE_MEMBER_HELD.replace(ACCOUNT, account)))
    }

    /// Get the member who holds the file with the given ID.
    pub fn file_holder(&self, vfid: &VirtualFileId) -> Option<&MemberId> {
        self.held_status.get(vfid).and_then(|status| match status {
            HeldStatus::HeldWith(id) => Some(id),
            _ => None,
        })
    }

    /// Update the held status of the files.
    pub fn update_held_status(&mut self, map: HashMap<VirtualFileId, Option<MemberId>>) {
        for (vfid, member_id) in map {
            self.held_status.insert(
                vfid,
                match member_id {
                    Some(member_id) => HeldStatus::HeldWith(member_id),
                    None => HeldStatus::NotHeld,
                },
            );
        }
    }
}