aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/access/mod.rs5
-rw-r--r--src/api/access.rs24
2 files changed, 28 insertions, 1 deletions
diff --git a/src/access/mod.rs b/src/access/mod.rs
index e04be02..ad50c72 100644
--- a/src/access/mod.rs
+++ b/src/access/mod.rs
@@ -192,6 +192,11 @@ impl Caps {
.is_none_or(|limit| limit.iter().any(|cap| cap.reaches(right, path)))
}
+ /// Whether a token's limit narrows them (`within`).
+ pub(crate) fn limited(&self) -> bool {
+ self.limit.is_some()
+ }
+
pub(crate) fn is_empty(&self) -> bool {
self.caps.is_empty() || self.limit.as_ref().is_some_and(Vec::is_empty)
}
diff --git a/src/api/access.rs b/src/api/access.rs
index 6d26139..6977a0a 100644
--- a/src/api/access.rs
+++ b/src/api/access.rs
@@ -252,8 +252,13 @@ enum Need {
Store,
/// Looking at this node (its figures, peers, dashboard): any capability.
Observe,
- /// Logging in, refreshing, asking who one is: any registered user.
+ /// Logging in, refreshing, asking who one is, ending one's session: any registered
+ /// user.
Auth,
+ /// Changing what one logs in with (one's keys), or ending every token one has: a
+ /// user not narrowed by a token's limit. A token handed over to read the member list
+ /// for five minutes adds no key that logs in as its user.
+ Credentials,
/// A right on protocol data.
Protocol(Right, Vec<String>),
}
@@ -271,6 +276,8 @@ fn needed(method: &Method, path: &str, node: &str) -> Need {
let local = |right, name: &str| protocol(right, &[meta::LOCAL, node, name]);
if under("/store") || under("/stream") {
Need::Store
+ } else if (under("/auth/keys") && !looking) || path == "/auth/logout" {
+ Need::Credentials
} else if under("/auth") {
Need::Auth
} else if (path == "/peers" && looking) || path == "/admin/stats" || under("/admin/dashboard") {
@@ -307,6 +314,10 @@ fn needed(method: &Method, path: &str, node: &str) -> Need {
fn allowed(need: Need, access: &Access) -> bool {
match need {
Need::Store | Need::Auth => true,
+ Need::Credentials => match access {
+ Access::Everything => true,
+ Access::Caps(caps) => !caps.limited(),
+ },
Need::Observe => match access {
Access::Everything => true,
Access::Caps(caps) => !caps.is_empty(),
@@ -413,6 +424,17 @@ mod tests {
assert!(allowed(need(&Method::GET, "/admin/stats"), &handed));
assert!(allowed(need(&Method::GET, "/peers"), &handed));
for (method, at) in [
+ (Method::POST, "/auth/refresh"),
+ (Method::DELETE, "/auth/session"),
+ (Method::GET, "/auth/whoami"),
+ (Method::GET, "/auth/keys"),
+ ] {
+ assert!(allowed(need(&method, at), &handed), "{method} {at}");
+ }
+ for (method, at) in [
+ (Method::PUT, "/auth/keys/laptop"),
+ (Method::DELETE, "/auth/keys/laptop"),
+ (Method::POST, "/auth/logout"),
(Method::DELETE, "/peers/continuum:00"),
(Method::POST, "/admin/remakes"),
(Method::GET, "/admin/document"),