Skip to content

Commit 499a61a

Browse files
authored
feat: add admin picker when editing .mega_cedar.json (#2147)
* feat: upgrade SeaORM 2.0 dense entities and related deps Migrate callisto to dense codegen, keep polymorphic joins in entity_ext, bump russh and remove lazy_static/ed25519-dalek, and normalize webhook event enum labels to underscores with Enum rs_type call-site fixes. * feat: add admin picker when editing .mega_cedar.json Let Cedar admins select org members in BlobEditor and regenerate entity-store JSON via POST /api/v1/admin/cedar/generate before commit.
1 parent 5ab3c8c commit 499a61a

128 files changed

Lines changed: 2135 additions & 1507 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Cargo.lock

Lines changed: 1041 additions & 418 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,30 +44,30 @@ libvault-core = "0.1.0"
4444
#====
4545
anyhow = "1.0.103"
4646
serde = { version = "1.0.228", features = ["derive"] }
47-
serde_json = "1.0.150"
47+
serde_json = "1.0.151"
4848
serde_urlencoded = "0.7"
4949
tracing = "0.1.44"
5050
tracing-subscriber = "0.3.23"
5151
tracing-appender = "0.2.5"
52-
thiserror = "2.0.18"
53-
clap = "4.6.1"
52+
thiserror = "2.0.19"
53+
clap = "4.6.4"
5454

5555
#====
56-
tokio = "1.52.3"
56+
tokio = "1.53.1"
5757
tokio-stream = "0.1.18"
58-
tokio-util = "0.7.18"
58+
tokio-util = "0.7.19"
5959
async-trait = "0.1.89"
6060
async-stream = "0.3.6"
6161
async-recursion = "1.1.1"
6262
futures = "0.3.32"
6363
futures-util = "0.3.32"
6464
axum = { version = "0.8.9", features = ["macros", "json"] }
6565
axum-extra = "0.12.6"
66-
russh = "0.61.2"
66+
russh = "0.62.3"
6767
tower-http = "0.7.0"
6868
tower = "0.5.3"
6969
tower-sessions = { version = "0.15", features = ["memory-store"] }
70-
time = { version = "0.3.51", features = ["serde"] }
70+
time = { version = "0.3.54", features = ["serde"] }
7171
lettre = { version = "0.11", default-features = false, features = [
7272
"builder",
7373
"smtp-transport",
@@ -77,8 +77,8 @@ lettre = { version = "0.11", default-features = false, features = [
7777
"rustls-platform-verifier",
7878
] }
7979
#====
80-
sea-orm = "1.1.20"
81-
sea-orm-migration = "1.1.20"
80+
sea-orm = "2.0.0"
81+
sea-orm-migration = "2.0.0"
8282

8383
#====
8484
rand = "0.10.2"
@@ -94,10 +94,8 @@ hmac = "0.13"
9494
idgenerator = "2.0.0"
9595
config = "0.15.25"
9696
reqwest = "0.13.4"
97-
lazy_static = "1.5.0"
9897
uuid = "1.23.5"
9998
regex = "1.13.0"
100-
ed25519-dalek = "2.2.0"
10199
ctrlc = "3.5.2"
102100
cedar-policy = "4.11.2"
103101
secp256k1 = "0.31.1"

ceres/src/model/admin.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use serde::Serialize;
1+
use serde::{Deserialize, Serialize};
22
use utoipa::ToSchema;
33

44
#[derive(Serialize, ToSchema)]
@@ -10,3 +10,15 @@ pub struct IsAdminResponse {
1010
pub struct AdminListResponse {
1111
pub admins: Vec<String>,
1212
}
13+
14+
/// Request body for generating `.mega_cedar.json` content from admin usernames.
15+
#[derive(Debug, Deserialize, ToSchema)]
16+
pub struct GenerateCedarRequest {
17+
pub admins: Vec<String>,
18+
}
19+
20+
/// Response containing generated `.mega_cedar.json` content.
21+
#[derive(Serialize, ToSchema)]
22+
pub struct GenerateCedarResponse {
23+
pub content: String,
24+
}

ceres/src/model/webhook.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use utoipa::ToSchema;
77
pub struct CreateWebhookRequest {
88
pub target_url: String,
99
pub secret: String,
10-
/// Event types: "cl.created", "cl.updated", "cl.merged", "cl.closed", "cl.reopened", "cl.comment.created", "*"
10+
/// Event types: "cl_created", "cl_updated", "cl_merged", "cl_closed", "cl_reopened", "cl_comment_created", "all"
1111
pub event_types: Vec<String>,
1212
pub path_filter: Option<String>,
1313
pub active: Option<bool>,
@@ -39,7 +39,7 @@ impl From<WebhookWithEventTypes> for WebhookResponse {
3939
event_types: value
4040
.event_types
4141
.into_iter()
42-
.map(|e| e.to_value())
42+
.map(|e| e.to_value().value.into_owned())
4343
.collect(),
4444
path_filter: m.path_filter,
4545
active: m.active,
@@ -52,7 +52,8 @@ impl From<WebhookWithEventTypes> for WebhookResponse {
5252
pub fn parse_webhook_event_types(raw: Vec<String>) -> Result<Vec<WebhookEventTypeEnum>, String> {
5353
raw.into_iter()
5454
.map(|s| {
55-
WebhookEventTypeEnum::try_from_value(&s).map_err(|_| format!("invalid event type: {s}"))
55+
WebhookEventTypeEnum::try_from(s.as_str())
56+
.map_err(|_| format!("invalid event type: {s}"))
5657
})
5758
.collect()
5859
}
@@ -66,7 +67,7 @@ mod tests {
6667

6768
#[test]
6869
fn parse_webhook_event_types_accepts_known_values() {
69-
let parsed = parse_webhook_event_types(vec!["cl.created".to_string(), "all".to_string()])
70+
let parsed = parse_webhook_event_types(vec!["cl_created".to_string(), "all".to_string()])
7071
.expect("valid event types");
7172
assert_eq!(parsed.len(), 2);
7273
assert_eq!(parsed[0], WebhookEventTypeEnum::ClCreated);
@@ -75,7 +76,7 @@ mod tests {
7576

7677
#[test]
7778
fn parse_webhook_event_types_rejects_unknown_values() {
78-
let err = parse_webhook_event_types(vec!["not.a.real.event".to_string()])
79+
let err = parse_webhook_event_types(vec!["not_a_real_event".to_string()])
7980
.expect_err("invalid event type");
8081
assert!(err.contains("invalid event type"));
8182
}
@@ -104,7 +105,7 @@ mod tests {
104105
let response = WebhookResponse::from(value);
105106
assert_eq!(response.id, 42);
106107
assert_eq!(response.target_url, "https://example.com/hook");
107-
assert_eq!(response.event_types, vec!["cl.created".to_string()]);
108+
assert_eq!(response.event_types, vec!["cl_created".to_string()]);
108109
assert_eq!(response.path_filter.as_deref(), Some("/project"));
109110
assert!(response.active);
110111
}

jupiter-migrate/README.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,30 @@ After schema changes, regenerate callisto entities (adjust connection URL for yo
2525
sea-orm-cli generate entity \
2626
-u postgres://postgres:postgres@localhost:5432/mono \
2727
-o jupiter/callisto/src \
28-
--with-serde both
28+
--with-serde both \
29+
--entity-format dense
2930
```
3031

3132
Review generated diffs in `jupiter/callisto/src/` before committing.
3233

34+
**Do not edit CLI-generated entity files** for polymorphic/link joins or `Model::new` helpers — those live only in `entity_ext/`. Regenerating must overwrite table models cleanly.
35+
36+
**After every regen:**
37+
38+
1. Re-add `pub mod entity_ext;` to `jupiter/callisto/src/mod.rs` (codegen overwrites this file).
39+
2. Keep `sea_orm_active_enums.rs` webhook variant names readable (`ClCreated`, not CLI-mangled names). `rs_type = "Enum"` is correct for SeaORM 2.0 — call sites that need a string use `to_value().value` or `TryFrom<&str>`.
40+
3. Leave `entity_ext/` alone — it owns:
41+
- `Model::new` helpers and ID utilities
42+
- Polymorphic / link-based `Relation` + `Related` (no DB FKs), including:
43+
- `item_labels` / `item_assignees`: dual `belongs_to` on `item_id``mega_cl` and `mega_issue`
44+
- `mega_cl` / `mega_issue`: `has_many` labels (via), assignees, conversations
45+
- `mega_conversation`: link joins to CL/Issue; `has_many` reactions
46+
- `reactions`: `belongs_to` conversation
47+
- `mega_code_review_thread`: `belongs_to` `mega_cl` on `link`
48+
- `label`: `has_many` `item_labels`
49+
50+
Join call sites that need those relations use `callisto::entity_ext::<table>::Relation`, not the generated entity `Relation`.
51+
3352
## Library API
3453

3554
```rust

jupiter-migrate/src/migration/m20250314_025943_init.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ impl MigrationTrait for Migration {
5656
DatabaseBackend::Sqlite | DatabaseBackend::MySql => {
5757
// Do not create enum in sqlite
5858
}
59+
_ => {}
5960
}
6061

6162
manager

jupiter-migrate/src/migration/m20250613_033821_alter_user_id.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ impl MigrationTrait for Migration {
5454
}
5555

5656
DatabaseBackend::Sqlite => {}
57+
_ => {}
5758
}
5859

5960
Ok(())

jupiter-migrate/src/migration/m20250618_065050_add_label.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ impl MigrationTrait for Migration {
2020
.await?;
2121
}
2222
DatabaseBackend::Sqlite | DatabaseBackend::MySql => {}
23+
_ => {}
2324
}
2425

2526
manager

jupiter-migrate/src/migration/m20250702_072055_add_item_assignees.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ impl MigrationTrait for Migration {
1919
.await?;
2020
}
2121
DatabaseBackend::Sqlite | DatabaseBackend::MySql => {}
22+
_ => {}
2223
}
2324

2425
manager

jupiter-migrate/src/migration/m20250804_151214_alter_builds_end_at.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ impl MigrationTrait for Migration {
2121
.await?;
2222
}
2323
DatabaseBackend::Sqlite | DatabaseBackend::MySql => {}
24+
_ => {}
2425
}
2526

2627
Ok(())
@@ -43,6 +44,7 @@ impl MigrationTrait for Migration {
4344
.await?;
4445
}
4546
DatabaseBackend::Sqlite | DatabaseBackend::MySql => {}
47+
_ => {}
4648
}
4749

4850
Ok(())

0 commit comments

Comments
 (0)