Skip to content
Clone

refactor(space): refresh crate across features, handler, authz and metrics

zhenyi committed
parent a83f492 commit 2aecc38 Browse files

6 files changed

+1 −50

File tree 6
Modified lib/space/features/authz.rs View lib/space/features/authz.rs
@@ -52,12 +52,6 @@
5252 }
5353}
5454
55/// Resolve the caller's effective permissions for a space.
56///
57/// - Space owner always holds every permission.
58/// - A non-expired ban denies access regardless of membership.
59/// - Otherwise the caller must be an active member; permissions are the union
60/// of all permissions granted by the roles assigned to the caller.
6155pub async fn effective_permissions<C>(
6256 db: &C,
6357 space_id: Uuid,
@@ -113,7 +107,6 @@
113107 Ok((space, Permissions { granted }))
114108}
115109
116/// Require a specific permission for `caller` on `space_id`.
117110pub async fn require_perm(
118111 svc: &SpaceService,
119112 caller: Uuid,
Modified lib/space/handler/middleware/metrics.rs View lib/space/handler/middleware/metrics.rs
@@ -2,12 +2,6 @@
22use axum::middleware::Next;
33use axum::response::Response;
44
5/// HTTP-level metrics layer for the `space` crate.
6///
7/// Emits `space_http_requests_total{route,method,status_class}` (counter) and
8/// `space_http_request_duration_seconds{route,method,status_class}` (histogram)
9/// on every request that traverses the router. Uses `MatchedPath` so the
10/// `route` label stays low-cardinality (no space-id path params).
115pub async fn metrics_layer(req: Request, next: Next) -> Response {
126 crate::metrics::ensure_described();
137
Modified lib/space/handler/openapi.rs View lib/space/handler/openapi.rs
@@ -36,19 +36,16 @@
3636 (name = "space", description = "Space, membership, roles, invites, bans, channels, channel members and overwrite endpoints.")
3737 ),
3838 paths(
39 // === spaces ===
4039 crate::handler::spaces::create::handler,
4140 crate::handler::spaces::get::handler,
4241 crate::handler::spaces::list::handler,
4342 crate::handler::spaces::update::handler,
4443 crate::handler::spaces::delete::handler,
45 // === members ===
4644 crate::handler::members::add::handler,
4745 crate::handler::members::get::handler,
4846 crate::handler::members::list::handler,
4947 crate::handler::members::remove::handler,
5048 crate::handler::members::update::handler,
51 // === roles ===
5249 crate::handler::roles::create::handler,
5350 crate::handler::roles::get::handler,
5451 crate::handler::roles::list::handler,
@@ -56,27 +53,22 @@
5653 crate::handler::roles::delete::handler,
5754 crate::handler::roles::assign::handler,
5855 crate::handler::roles::unassign::handler,
59 // === invites ===
6056 crate::handler::invites::create::handler,
6157 crate::handler::invites::list::handler,
6258 crate::handler::invites::revoke::handler,
6359 crate::handler::invites::accept::handler,
64 // === bans ===
6560 crate::handler::bans::ban::handler,
6661 crate::handler::bans::get::handler,
6762 crate::handler::bans::list::handler,
6863 crate::handler::bans::update::handler,
6964 crate::handler::bans::unban::handler,
70 // === channels ===
7165 crate::handler::channels::get::handler,
7266 crate::handler::channels::list::handler,
73 // === channel members ===
7467 crate::handler::channel_members::add::handler,
7568 crate::handler::channel_members::get::handler,
7669 crate::handler::channel_members::list::handler,
7770 crate::handler::channel_members::update::handler,
7871 crate::handler::channel_members::remove::handler,
79 // === overwrites ===
8072 crate::handler::overwrites::set_role::handler,
8173 crate::handler::overwrites::remove_role::handler,
8274 crate::handler::overwrites::list_role::handler,
Modified lib/space/config.rs View lib/space/config.rs
@@ -1,10 +1,7 @@
1//! Runtime configuration for the space domain.
2
31use std::sync::Arc;
42
53use serde::{Deserialize, Serialize};
64
7/// Configuration knobs for the space domain.
85#[derive(Debug, Clone, Serialize, Deserialize)]
96pub struct SpaceConfig {
107 #[serde(default = "default_max_pagination")]
@@ -83,6 +80,5 @@
8380 }
8481}
8582
86/// Shared, cheaply-cloneable space configuration.
8783#[allow(dead_code)]
8884pub type SharedSpaceConfig = Arc<SpaceConfig>;
No newline at end of file
Modified lib/space/error.rs View lib/space/error.rs
@@ -73,8 +73,7 @@
7373 )
7474 }
7575
76 /// Bounded label for metrics. Keep stable and low-cardinality.
77 pub fn error_kind(&self) -> &'static str {
76 pub fn error_kind(&self) -> &'static str {
7877 match self {
7978 SpaceError::BadRequest(_) => "bad_request",
8079 SpaceError::Unauthorized(_) => "unauthorized",
Modified lib/space/metrics.rs View lib/space/metrics.rs
@@ -1,45 +1,33 @@
1//! Tracing layer for the `space` crate.
2//!
3//! Emits metrics through the `metrics` facade. No exporter is installed here;
4//! the host binary is responsible for binding a recorder. All labels are
5//! bounded to keep cardinality low (no `space_id`/`user_id`/`role_id`).
6
71use std::time::Instant;
82
93use metrics::{counter, describe_counter, describe_histogram, histogram};
104
115use crate::error::SpaceError;
126
13// ── Feature constants (one per usecase) ───────────────────────────────────
147
15// spaces
168pub const FEATURE_SPACES_CREATE: &str = "spaces_create";
179pub const FEATURE_SPACES_GET: &str = "spaces_get";
1810pub const FEATURE_SPACES_UPDATE: &str = "spaces_update";
1911pub const FEATURE_SPACES_DELETE: &str = "spaces_delete";
2012pub const FEATURE_SPACES_LIST: &str = "spaces_list";
2113
22// bans
2314pub const FEATURE_BANS_CREATE: &str = "bans_create";
2415pub const FEATURE_BANS_GET: &str = "bans_get";
2516pub const FEATURE_BANS_UPDATE: &str = "bans_update";
2617pub const FEATURE_BANS_REMOVE: &str = "bans_remove";
2718pub const FEATURE_BANS_LIST: &str = "bans_list";
2819
29// invites
3020pub const FEATURE_INVITES_CREATE: &str = "invites_create";
3121pub const FEATURE_INVITES_REVOKE: &str = "invites_revoke";
3222pub const FEATURE_INVITES_ACCEPT: &str = "invites_accept";
3323pub const FEATURE_INVITES_LIST: &str = "invites_list";
3424
35// members
3625pub const FEATURE_MEMBERS_ADD: &str = "members_add";
3726pub const FEATURE_MEMBERS_GET: &str = "members_get";
3827pub const FEATURE_MEMBERS_UPDATE: &str = "members_update";
3928pub const FEATURE_MEMBERS_REMOVE: &str = "members_remove";
4029pub const FEATURE_MEMBERS_LIST: &str = "members_list";
4130
42// roles
4331pub const FEATURE_ROLES_CREATE: &str = "roles_create";
4432pub const FEATURE_ROLES_GET: &str = "roles_get";
4533pub const FEATURE_ROLES_UPDATE: &str = "roles_update";
@@ -48,19 +36,16 @@
4836pub const FEATURE_ROLES_ASSIGN: &str = "roles_assign";
4937pub const FEATURE_ROLES_UNASSIGN: &str = "roles_unassign";
5038
51// channels
5239pub const FEATURE_CHANNELS_GET: &str = "channels_get";
5340pub const FEATURE_CHANNELS_LIST: &str = "channels_list";
5441pub const FEATURE_CHANNELS_ENSURE: &str = "channels_ensure";
5542
56// channel_members
5743pub const FEATURE_CHANNEL_MEMBERS_ADD: &str = "channel_members_add";
5844pub const FEATURE_CHANNEL_MEMBERS_GET: &str = "channel_members_get";
5945pub const FEATURE_CHANNEL_MEMBERS_UPDATE: &str = "channel_members_update";
6046pub const FEATURE_CHANNEL_MEMBERS_REMOVE: &str = "channel_members_remove";
6147pub const FEATURE_CHANNEL_MEMBERS_LIST: &str = "channel_members_list";
6248
63// overwrites
6449pub const FEATURE_OVERWRITES_SET_ROLE: &str = "overwrites_set_role";
6550pub const FEATURE_OVERWRITES_REMOVE_ROLE: &str = "overwrites_remove_role";
6651pub const FEATURE_OVERWRITES_LIST_ROLE: &str = "overwrites_list_role";
@@ -68,11 +53,9 @@
6853pub const FEATURE_OVERWRITES_REMOVE_USER: &str = "overwrites_remove_user";
6954pub const FEATURE_OVERWRITES_LIST_USER: &str = "overwrites_list_user";
7055
71// ── Outcome labels (bounded enums) ────────────────────────────────────────
7256
7357pub const OUTCOME_SUCCESS: &str = "success";
7458
75// ── Metric description registration (Once) ────────────────────────────────
7659
7760static DESCRIBE_ONCE: std::sync::Once = std::sync::Once::new();
7861
@@ -109,9 +92,7 @@
10992 );
11093}
11194
112// ── Timer (RAII) ──────────────────────────────────────────────────────────
11395
114/// Records the usecase execution duration on drop.
11596pub struct Timer {
11697 pub feature: &'static str,
11798 pub start: Instant,
@@ -138,10 +119,7 @@
138119 }
139120}
140121
141// ── Generic outcome counter ───────────────────────────────────────────────
142122
143/// Bump invocation counter (always) and, on `Err`, an error counter labeled
144/// by `SpaceError::error_kind()`. Drop semantics of `_timer` capture latency.
145123pub fn record_outcome<T>(feature: &'static str, result: &Result<T, SpaceError>) {
146124 match result {
147125 Ok(_) => {
@@ -170,7 +148,6 @@
170148 }
171149}
172150
173// ── Invite accept helper ──────────────────────────────────────────────────
174151
175152#[derive(Debug, Clone, Copy)]
176153pub enum InviteAcceptOutcome {