aboutsummaryrefslogtreecommitdiffstats
path: root/src/api
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-09 17:35:12 +0000
committertv <tv@krebsco.de>2026-11-09 19:10:26 +0100
commit5f7e29cec4333715346b4bf3195633db93449d9d (patch)
tree3574cb120e01c4272452666aeb518ac0d24e8e90 /src/api
parent3bf93bc192bf362b58b2161ac05da0bb8323bf43 (diff)
auth: whoami says what the request may do
`GET /auth/whoami` lists the user's capabilities (`caps`) and its token's `limit`, if any, side by side; what the request may do is what both give, as endpoints decide it. It says so now (`may`): the capabilities, or with a limit each capability met with each of the limit's (`Capability::meet`): at the deeper of the two paths, a `*` of one taking the other's key there, with the rights both name; nothing where the paths part, no right is shared, or the path is protocol data one of them doesn't name.
Diffstat (limited to 'src/api')
-rw-r--r--src/api/login.rs13
1 files changed, 13 insertions, 0 deletions
diff --git a/src/api/login.rs b/src/api/login.rs
index 0dc74e5..694ad0a 100644
--- a/src/api/login.rs
+++ b/src/api/login.rs
@@ -715,6 +715,18 @@ pub(crate) async fn whoami(
let swarm = state.swarm_id().await;
let replica = state.doc.read().await;
let entry = registry::user(&replica.doc, &user.0);
+ // What the request may do: the user's capabilities, and with a token saying less,
+ // what both give (`Capability::meet`), as `api::access::authorize` decides.
+ let may = entry.as_ref().map(|entry| {
+ match token.as_ref().and_then(|token| token.claims.limit.as_ref()) {
+ None => entry.caps.values().cloned().collect::<Vec<_>>(),
+ Some(limit) => entry
+ .caps
+ .values()
+ .flat_map(|cap| limit.iter().filter_map(|outer| cap.meet(outer)))
+ .collect(),
+ }
+ });
let token = token.map(|Extension(token)| {
json!({
"issuer": token.claims.issuer,
@@ -732,6 +744,7 @@ pub(crate) async fn whoami(
"via": via.0,
"registry": registry::exists(&replica.doc),
"caps": entry.as_ref().map(|entry| &entry.caps),
+ "may": may,
"disabled": entry.as_ref().map(|entry| entry.disabled),
"token": token,
}))