Skip to main content

didbot_scope/
warning.rs

1//! How an atom written in a form the permission spec does not define is
2//! read.
3
4use std::fmt;
5
6/// One way an atom's form departs from the permission spec, and how this
7/// grammar reads it anyway. A spec form carries none.
8#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
9pub enum ScopeWarning {
10    /// A `repo:` collection or `rpc:` method ending `.*`, such as
11    /// `app.bsky.*`: the NSIDs under that prefix, at any depth.
12    PartialWildcard(String),
13    /// An `rpc:` scope with no `aud`: every audience.
14    NoAudience,
15    /// An `rpc:` scope for every method at every audience: as it is written.
16    EveryMethodAndAudience,
17    /// An `rpc:` `aud` that is neither `*` nor a DID with a service
18    /// fragment: that audience alone, compared as written.
19    NotAServiceReference(String),
20    /// `action=manage` on a `repo:` scope: no record operation, so the
21    /// scope adds no write.
22    RepoManage,
23    /// A comma list of actions, such as `action=create,update`: each action
24    /// in it, as the repeated parameter would name them.
25    ActionList,
26    /// A parameter the scope's kind does not take: ignored.
27    UnknownParameter(String),
28    /// A list parameter written both after the `:` and by name, such as
29    /// `blob:image/png?accept=text/html`: every value.
30    RepeatedList(String),
31    /// A parameter that takes one value given more than once: the first.
32    RepeatedValue(String),
33    /// An atom that names no scope this grammar reads, for the reason given:
34    /// an unknown kind, such as `space:*`, or a value its kind does not
35    /// define, such as `account:status`. It is kept as written, as
36    /// [`crate::Scope::Unknown`], and admits only itself.
37    Unreadable(String),
38}
39
40impl fmt::Display for ScopeWarning {
41    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42        match self {
43            Self::PartialWildcard(pattern) => write!(
44                f,
45                "`{pattern}` is a partial wildcard, read as the NSIDs under that prefix"
46            ),
47            Self::NoAudience => f.write_str("no `aud`, read as every audience"),
48            Self::EveryMethodAndAudience => {
49                f.write_str("every method at every audience, read as written")
50            }
51            Self::NotAServiceReference(aud) => write!(
52                f,
53                "`aud` `{aud}` is not `*` or a DID with a service fragment, read as that \
54                 audience alone"
55            ),
56            Self::RepoManage => {
57                f.write_str("`action=manage` names no record operation, so it adds no write")
58            }
59            Self::ActionList => f.write_str("a comma list of actions, read as each action in it"),
60            Self::UnknownParameter(name) => {
61                write!(
62                    f,
63                    "`{name}` is not a parameter of this kind, and is ignored"
64                )
65            }
66            Self::RepeatedList(name) => write!(
67                f,
68                "`{name}` is written both after the `:` and by name, and every value is read"
69            ),
70            Self::RepeatedValue(name) => {
71                write!(f, "`{name}` is given more than once, and the first is read")
72            }
73            Self::Unreadable(reason) => write!(f, "not a scope this server reads: {reason}"),
74        }
75    }
76}