Skip to main content

sim_table_fs/
capabilities.rs

1//! Capability names used by filesystem-backed tables.
2
3use sim_kernel::{CapabilityName, Cx, Error, Result};
4
5/// The capability gating filesystem-backed tables (`table.fs`).
6pub fn table_fs_capability() -> CapabilityName {
7    CapabilityName::new("table.fs")
8}
9
10/// The capability gating filesystem table reads (`fs/read`).
11pub fn table_fs_read_capability() -> CapabilityName {
12    CapabilityName::new("fs/read")
13}
14
15/// The capability gating filesystem table writes (`fs/write`).
16pub fn table_fs_write_capability() -> CapabilityName {
17    CapabilityName::new("fs/write")
18}
19
20/// The capability gating filesystem table directory creation (`fs/write`).
21pub fn table_fs_mkdir_capability() -> CapabilityName {
22    table_fs_write_capability()
23}
24
25/// The capability gating filesystem table directory removal (`fs/write`).
26pub fn table_fs_rmdir_capability() -> CapabilityName {
27    table_fs_write_capability()
28}
29
30/// The capability gating patch-only filesystem leaf edits (`edit`).
31pub fn table_fs_edit_capability() -> CapabilityName {
32    CapabilityName::new("edit")
33}
34
35/// The capability gating filesystem tree search (`find`).
36pub fn table_fs_find_capability() -> CapabilityName {
37    CapabilityName::new("find")
38}
39
40pub(crate) fn require_table_fs_read(cx: &Cx) -> Result<()> {
41    require_with_aliases(cx, table_fs_read_capability(), fs_read_aliases())
42}
43
44pub(crate) fn require_table_fs_write(cx: &Cx) -> Result<()> {
45    require_with_aliases(cx, table_fs_write_capability(), fs_write_aliases())
46}
47
48pub(crate) fn require_table_fs_edit(cx: &Cx) -> Result<()> {
49    cx.require(&table_fs_edit_capability())
50}
51
52pub(crate) fn require_table_fs_find(cx: &Cx) -> Result<()> {
53    cx.require(&table_fs_find_capability())
54}
55
56fn fs_read_aliases() -> &'static [&'static str] {
57    &["table.fs.read", "stream.file.read", "file-read"]
58}
59
60fn fs_write_aliases() -> &'static [&'static str] {
61    &[
62        "table.fs.write",
63        "table.fs.mkdir",
64        "table.fs.rmdir",
65        "stream.file.write",
66        "file-write",
67    ]
68}
69
70fn require_with_aliases(
71    cx: &Cx,
72    canonical: CapabilityName,
73    aliases: &'static [&'static str],
74) -> Result<()> {
75    if cx.capabilities().contains(&canonical)
76        || aliases
77            .iter()
78            .any(|alias| cx.capabilities().contains(&CapabilityName::new(*alias)))
79    {
80        Ok(())
81    } else {
82        Err(Error::CapabilityDenied {
83            capability: canonical,
84        })
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use super::{
91        table_fs_capability, table_fs_edit_capability, table_fs_find_capability,
92        table_fs_mkdir_capability, table_fs_read_capability, table_fs_rmdir_capability,
93        table_fs_write_capability,
94    };
95
96    #[test]
97    fn capability_tokens_are_stable() {
98        assert_eq!(table_fs_capability().as_str(), "table.fs");
99        assert_eq!(table_fs_read_capability().as_str(), "fs/read");
100        assert_eq!(table_fs_write_capability().as_str(), "fs/write");
101        assert_eq!(table_fs_mkdir_capability().as_str(), "fs/write");
102        assert_eq!(table_fs_rmdir_capability().as_str(), "fs/write");
103        assert_eq!(table_fs_edit_capability().as_str(), "edit");
104        assert_eq!(table_fs_find_capability().as_str(), "find");
105    }
106}