From cfe9e0041847359b5104088d063b8a686a14d132 Mon Sep 17 00:00:00 2001 From: "benjamin.747" Date: Mon, 10 Aug 2026 15:43:18 +0800 Subject: [PATCH] fix(identity): heal transitional CL reviewers without SQL Match approve against github_login-keyed rows and remap them on list, resync system reviewers when a CL is updated, and use github_login in auto conversation text instead of campsite public ids. --- Cargo.lock | 122 ++++++------ .../application/api_service/mono/reviewer.rs | 28 +++ ceres/src/application/code_edit/model.rs | 30 ++- jupiter/src/storage/cl_reviewer_storage.rs | 174 +++++++++++++++--- mono/src/api/router/reviewer_router.rs | 8 +- 5 files changed, 277 insertions(+), 85 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c038b1870..57bfb2bb1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -159,9 +159,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "android_system_properties" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +checksum = "ae221649c9976a6f6c56ae1facf410f3ddb33cc661c4b7b61020a912d4237fbc" dependencies = [ "libc", ] @@ -822,9 +822,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64" -version = "0.23.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b25655df2c3cdd83c5e5b293b88acd880332b2ddadd7c30ac43144fdc0033da9" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" [[package]] name = "base64ct" @@ -1058,9 +1058,9 @@ dependencies = [ [[package]] name = "blake3" -version = "1.8.5" +version = "1.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" +checksum = "76ae7bad254120e9e4c63bafc385310756f90c484eac0e36b8317cf09cb92a77" dependencies = [ "arrayref", "arrayvec 0.7.8", @@ -1251,12 +1251,12 @@ dependencies = [ [[package]] name = "bytecheck" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0caa33a2c0edca0419d15ac723dff03f1956f7978329b1e3b5fdaaaed9d3ca8b" +checksum = "26333eeac754f0ad8a6bcd0eb0ac012156302e4e16b852b72ee399aea4f12c29" dependencies = [ - "bytecheck_derive 0.8.2", - "ptr_meta 0.3.1", + "bytecheck_derive 0.8.3", + "ptr_meta 0.3.2", "rancor", "simdutf8", ] @@ -1274,13 +1274,13 @@ dependencies = [ [[package]] name = "bytecheck_derive" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89385e82b5d1821d2219e0b095efa2cc1f246cbf99080f3be46a1a85c0d392d9" +checksum = "46d07918caa9eeaaf06b7873925c53a61daac173539b4f7715090745e44e4e69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] @@ -1452,7 +1452,7 @@ dependencies = [ "rand 0.10.2", "regex", "reqwest 0.13.4", - "rkyv 0.8.17", + "rkyv 0.8.18", "saturn", "serde", "serde_json", @@ -1559,9 +1559,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.5" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301b56658598e48f3648647ac6fc887be7e7108eddfa4e9b63fcf3ec58c0cadf" +checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" dependencies = [ "clap_builder", "clap_derive", @@ -1569,9 +1569,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.6.5" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94a65403d1a1bd28f7dc68eb8506e8874808ee5eecb59298de588e2e1407a078" +checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" dependencies = [ "anstream", "anstyle", @@ -1581,9 +1581,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.6.8" +version = "4.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f84a88507dbd05c695f2cb5e8558e747179134005e9893882dec964190ed89" +checksum = "3be2ad0423bdbbb0e25bc89add796f3559706d4a95e1bc98e4d9662a957b6a19" dependencies = [ "clap", ] @@ -1676,7 +1676,7 @@ dependencies = [ "pgp", "redis", "regex", - "rkyv 0.8.17", + "rkyv 0.8.18", "sea-orm", "serde", "serde_json", @@ -2743,7 +2743,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "420b9da095f052ea597503e39073b5b3c522f7db933fbac202d91d24492693fd" dependencies = [ - "base64 0.23.0", + "base64 0.23.1", "memchr", ] @@ -3310,7 +3310,7 @@ dependencies = [ "num_cpus", "path-absolutize", "rayon", - "rkyv 0.8.17", + "rkyv 0.8.18", "serde", "serde_json", "sha1 0.11.0", @@ -3335,9 +3335,9 @@ checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" [[package]] name = "globset" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e47d37d2ae4464254884b60ab7071be2b876a9c35b696bd018ddcc76847309cd" +checksum = "07c34a9410465b45bd9787443bc7370f37735bad04b0f0cd57ff1a3186c98988" dependencies = [ "aho-corasick", "bstr", @@ -4248,7 +4248,7 @@ version = "0.1.0" dependencies = [ "api-model", "async-trait", - "base64 0.23.0", + "base64 0.23.1", "bytes", "callisto", "chrono", @@ -4322,9 +4322,9 @@ dependencies = [ [[package]] name = "keccak" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e24a010dd405bd7ed803e5253182815b41bf2e6a80cc3bfc066658e03a198aa" +checksum = "ffd9697dc4a9a62e2da93389f34400b77a28f0287711263cabb203b3ccb9c0e4" dependencies = [ "cfg-if", "cpufeatures 0.3.0", @@ -4419,7 +4419,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2c646bd5cc763b1087b15493e29a64be6147ba8f19342004fa52048ee596eae" dependencies = [ "async-trait", - "base64 0.23.0", + "base64 0.23.1", "email-encoding", "email_address", "fastrand", @@ -4578,9 +4578,9 @@ dependencies = [ [[package]] name = "libsqlite3-sys" -version = "0.30.1" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" +checksum = "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1" dependencies = [ "cc", "pkg-config", @@ -4973,7 +4973,7 @@ dependencies = [ "async-trait", "axum", "axum-extra", - "base64 0.23.0", + "base64 0.23.1", "bytes", "cedar-policy", "ceres", @@ -6446,11 +6446,11 @@ dependencies = [ [[package]] name = "ptr_meta" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9a0cf95a1196af61d4f1cbdab967179516d9a4a4312af1f31948f8f6224a79" +checksum = "743da816b98c921cdbe8628ef7381b76f25ecf4da599fc80aca90eae7ef70cc0" dependencies = [ - "ptr_meta_derive 0.3.1", + "ptr_meta_derive 0.3.2", ] [[package]] @@ -6466,13 +6466,13 @@ dependencies = [ [[package]] name = "ptr_meta_derive" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1" +checksum = "1c8d9ca532f185d5d4db7a7c9d51420b452168ea1c2b913953281bd6fe1fcbd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] @@ -6689,11 +6689,11 @@ dependencies = [ [[package]] name = "rancor" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daff8b7b3ccf5f7ba270b3e7a0a4d4c701c5797e38dec27c7e2c3dbb830fed1c" +checksum = "9b534442d0fcdb55d66f373d9cac6d33b6293a2335bc2136dbd06ce0e87d2572" dependencies = [ - "ptr_meta 0.3.1", + "ptr_meta 0.3.2", ] [[package]] @@ -6917,9 +6917,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.16" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" dependencies = [ "aho-corasick", "memchr", @@ -6953,7 +6953,7 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "663ba70707f96e871406fe10d68128412e619b06d1d47cb91c3a4c6501176240" dependencies = [ - "bytecheck 0.8.2", + "bytecheck 0.8.3", ] [[package]] @@ -7115,19 +7115,19 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.8.17" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "815cc8a37159a463064825246cadb07961e25cd9885908606f6d08a98d8f8874" +checksum = "d9776093b7ca170454ab1406954f7b7d97a57c51dc6c0642957fb2ef25c2d399" dependencies = [ - "bytecheck 0.8.2", + "bytecheck 0.8.3", "bytes", "hashbrown 0.17.1", "indexmap 2.14.0", "munge", - "ptr_meta 0.3.1", + "ptr_meta 0.3.2", "rancor", "rend 0.5.4", - "rkyv_derive 0.8.17", + "rkyv_derive 0.8.18", "tinyvec", "uuid", ] @@ -7145,13 +7145,13 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.8.17" +version = "0.8.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ed1a78a1b19d184b0daa629dd9a024573173ec7d485b287cb369fb3607cc1c" +checksum = "1c25ef604ac7dd839d44d64648952ea23c97866f124ff671b0ed2cf3ad9bb06e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] @@ -7241,7 +7241,7 @@ dependencies = [ "hmac 0.13.0", "inout 0.2.2", "internal-russh-num-bigint", - "keccak 0.2.0", + "keccak 0.2.1", "log", "md5", "ml-kem", @@ -8216,7 +8216,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be176f1a57ce4e3d31c1a166222d9768de5954f811601fb7ca06fc8203905ce1" dependencies = [ "digest 0.11.3", - "keccak 0.2.0", + "keccak 0.2.1", ] [[package]] @@ -8226,7 +8226,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc9bad02c26382724b2d2692c6f179285e4b54eeecd7968f52a50059c3c11759" dependencies = [ "digest 0.11.3", - "keccak 0.2.0", + "keccak 0.2.1", "sponge-cursor", ] @@ -8311,9 +8311,9 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "similar" -version = "3.1.1" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6505efef05804732ed8a3f2d4f279429eb485bd69d5b0cc6b19cc02005cda16" +checksum = "85ee016af5d736b69fc89e19254540fa4b5f5492853fb5503920f084011c78b6" dependencies = [ "bstr", ] @@ -10775,18 +10775,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.55" +version = "0.8.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a105cd7b140f6eeec8acff2ea38135d3cab283ada58540f629fe51e46696eb" +checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.55" +version = "0.8.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fe976fb70c78cd64cccfe3a6fc142244e8a77b70959b30faf9d0ac37ee228eb" +checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1" dependencies = [ "proc-macro2", "quote", diff --git a/ceres/src/application/api_service/mono/reviewer.rs b/ceres/src/application/api_service/mono/reviewer.rs index c35cd2afd..a8d0c2e71 100644 --- a/ceres/src/application/api_service/mono/reviewer.rs +++ b/ceres/src/application/api_service/mono/reviewer.rs @@ -31,6 +31,34 @@ impl ReviewerApplicationService { } pub async fn list_reviewers(&self, link: &str) -> Result { + // Heal transitional github_login-keyed system reviewers when the page loads. + // Prefer access_token mappings (public ids) over reviewer-table hints. + let mut login_to_id = self + .ctx + .storage() + .reviewer_storage() + .github_login_to_campsite_ids() + .await + .unwrap_or_default(); + if let Ok(from_tokens) = self + .ctx + .storage() + .user_storage() + .github_login_to_campsite_ids() + .await + { + login_to_id.extend(from_tokens); + } + if let Err(e) = self + .ctx + .storage() + .reviewer_storage() + .remap_transitional_reviewers(link, &login_to_id) + .await + { + tracing::warn!(cl_link = %link, error = %e, "Failed to remap transitional reviewers"); + } + let reviewers = self .ctx .storage() diff --git a/ceres/src/application/code_edit/model.rs b/ceres/src/application/code_edit/model.rs index 74094efc8..e03002bbf 100644 --- a/ceres/src/application/code_edit/model.rs +++ b/ceres/src/application/code_edit/model.rs @@ -175,6 +175,21 @@ async fn load_github_login_map(storage: &Storage) -> HashMap { map } +/// Prefer github_login for human-readable conversation text; persist actor remains campsite id. +async fn resolve_actor_display_name(storage: &Storage, campsite_user_id: &str) -> String { + let id = campsite_user_id.trim(); + if id.is_empty() { + return campsite_user_id.to_string(); + } + match storage.user_storage().github_login_to_campsite_ids().await { + Ok(map) => map + .into_iter() + .find_map(|(login, mapped_id)| (mapped_id == id).then_some(login)) + .unwrap_or_else(|| id.to_string()), + Err(_) => id.to_string(), + } +} + async fn fetch_campsite_github_login_map( storage: &Storage, ) -> Result, MegaError> { @@ -341,6 +356,7 @@ impl< ) -> Result<(), MegaError> { let cl_stg = storage.cl_storage(); let comment_stg = storage.conversation_storage(); + let display_name = resolve_actor_display_name(storage, username).await; let from_same = cl.from_hash == from_hash; let to_same = cl.to_hash == to_hash; @@ -355,7 +371,7 @@ impl< .add_conversation( &cl.link, username, - Some(self.formator.format(&cl, from_hash, to_hash, username)), + Some(self.formator.format(&cl, from_hash, to_hash, &display_name)), ConvTypeEnum::Comment, ) .await?; @@ -409,12 +425,13 @@ impl< ) .await?; self.assign_reviewer(storage, &cl).await?; + let display_name = resolve_actor_display_name(storage, username).await; storage .conversation_storage() .add_conversation( &cl.link, username, - Some(self.formator.format(&cl, from_hash, to_hash, username)), + Some(self.formator.format(&cl, from_hash, to_hash, &display_name)), ConvTypeEnum::Comment, ) .await?; @@ -448,6 +465,15 @@ impl< } let cl_model = fresh_or_fallback_cl(cl, fresh, to_hash); self.sync_cl_ref(storage, &cl_model, to_hash).await?; + // Re-resolve Cedar system reviewers so transitional github_login + // keys are replaced with campsite public ids on subsequent pushes. + if let Err(e) = self.assign_reviewer(storage, &cl_model).await { + tracing::warn!( + cl_link = %cl_model.link, + error = %e, + "Failed to resync system reviewers on CL update" + ); + } Ok(cl_model) } None => Ok(self diff --git a/jupiter/src/storage/cl_reviewer_storage.rs b/jupiter/src/storage/cl_reviewer_storage.rs index b823f2c0a..1735748b3 100644 --- a/jupiter/src/storage/cl_reviewer_storage.rs +++ b/jupiter/src/storage/cl_reviewer_storage.rs @@ -1,8 +1,10 @@ use std::{collections::HashMap, ops::Deref}; -use callisto::{entity_ext::generate_id, mega_cl_reviewer}; +use callisto::{access_token, entity_ext::generate_id, mega_cl_reviewer}; use common::errors::MegaError; -use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, IntoActiveModel, QueryFilter, Set}; +use sea_orm::{ + ActiveModelTrait, ColumnTrait, Condition, EntityTrait, IntoActiveModel, QueryFilter, Set, +}; use crate::storage::base_storage::{BaseStorage, StorageConnector}; @@ -138,18 +140,90 @@ impl ClReviewerStorage { cl_link: &str, campsite_user_id: &str, ) -> Result { - let is_reviewer = mega_cl_reviewer::Entity::find() + Ok(self + .find_actor_reviewer(cl_link, campsite_user_id) + .await? + .is_some()) + } + + /// Find the reviewer row for an actor campsite public id. + /// + /// Also matches transitional rows keyed by github_login (or with + /// `campsite_user_id == github_login`) and self-heals them to the public id. + pub async fn find_actor_reviewer( + &self, + cl_link: &str, + campsite_user_id: &str, + ) -> Result, MegaError> { + let campsite_user_id = campsite_user_id.trim(); + if campsite_user_id.is_empty() { + return Ok(None); + } + + if let Some(row) = mega_cl_reviewer::Entity::find() .filter(mega_cl_reviewer::Column::ClLink.eq(cl_link)) .filter(mega_cl_reviewer::Column::CampsiteUserId.eq(campsite_user_id)) .one(self.get_connection()) - .await - .map_err(|e| { - tracing::error!("Error finding the reviewer: {}", e); - e - })? - .is_some(); + .await? + { + return Ok(Some(row)); + } + + let github_login = self + .github_login_for_campsite_user(campsite_user_id) + .await?; + let Some(login) = github_login else { + return Ok(None); + }; - Ok(is_reviewer) + let row = mega_cl_reviewer::Entity::find() + .filter(mega_cl_reviewer::Column::ClLink.eq(cl_link)) + .filter( + Condition::any() + .add(mega_cl_reviewer::Column::GithubLogin.eq(&login)) + .add(mega_cl_reviewer::Column::CampsiteUserId.eq(&login)), + ) + .one(self.get_connection()) + .await?; + + let Some(row) = row else { + return Ok(None); + }; + + // Self-heal transitional handle keys to campsite public id. + if row.campsite_user_id != campsite_user_id { + tracing::info!( + cl_link, + from = %row.campsite_user_id, + to = %campsite_user_id, + github_login = %login, + "Remapping transitional CL reviewer campsite_user_id" + ); + let mut am = row.into_active_model(); + am.campsite_user_id = Set(campsite_user_id.to_string()); + am.github_login = Set(Some(login)); + am.updated_at = Set(chrono::Utc::now().naive_utc()); + let updated = am.update(self.get_connection()).await?; + return Ok(Some(updated)); + } + + Ok(Some(row)) + } + + async fn github_login_for_campsite_user( + &self, + campsite_user_id: &str, + ) -> Result, MegaError> { + let row = access_token::Entity::find() + .filter(access_token::Column::CampsiteUserId.eq(campsite_user_id)) + .filter(access_token::Column::GithubLogin.is_not_null()) + .one(self.get_connection()) + .await?; + Ok(row.and_then(|r| { + r.github_login + .map(|s| s.trim().to_string()) + .filter(|s| !s.is_empty()) + })) } pub async fn find_by_github_login( @@ -211,24 +285,82 @@ impl ClReviewerStorage { Ok(map) } + /// Remap reviewers still keyed by github_login (or equal to github_login) to + /// campsite public ids using `login_to_id`. Idempotent; used when listing a CL + /// so transitional rows heal without a manual SQL patch. + pub async fn remap_transitional_reviewers( + &self, + cl_link: &str, + login_to_id: &HashMap, + ) -> Result { + if login_to_id.is_empty() { + return Ok(0); + } + let rows = self.list_reviewers(cl_link).await?; + let mut updated = 0u64; + for row in rows { + let login_hint = row + .github_login + .as_deref() + .map(str::trim) + .filter(|s| !s.is_empty()) + .unwrap_or(row.campsite_user_id.trim()) + .to_string(); + let Some(target_id) = login_to_id.get(&login_hint).cloned() else { + continue; + }; + if target_id.is_empty() || row.campsite_user_id == target_id { + continue; + } + // Only remap obvious transitional keys (handle stored as id). + let is_transitional = row.campsite_user_id == login_hint + || row + .github_login + .as_deref() + .is_some_and(|g| g == row.campsite_user_id); + if !is_transitional { + continue; + } + + // Avoid unique collisions if a public-id row already exists. + let exists = mega_cl_reviewer::Entity::find() + .filter(mega_cl_reviewer::Column::ClLink.eq(cl_link)) + .filter(mega_cl_reviewer::Column::CampsiteUserId.eq(&target_id)) + .one(self.get_connection()) + .await? + .is_some(); + if exists { + mega_cl_reviewer::Entity::delete_by_id(row.id) + .exec(self.get_connection()) + .await?; + updated += 1; + continue; + } + + let mut am = row.into_active_model(); + am.campsite_user_id = Set(target_id); + am.github_login = Set(Some(login_hint)); + am.updated_at = Set(chrono::Utc::now().naive_utc()); + am.update(self.get_connection()).await?; + updated += 1; + } + Ok(updated) + } + pub async fn reviewer_change_state( &self, cl_link: &str, campsite_user_id: &str, approved: bool, ) -> Result<(), MegaError> { - let mut rev: mega_cl_reviewer::ActiveModel = mega_cl_reviewer::Entity::find() - .filter(mega_cl_reviewer::Column::ClLink.eq(cl_link)) - .filter(mega_cl_reviewer::Column::CampsiteUserId.eq(campsite_user_id)) - .one(self.get_connection()) - .await - .map_err(|e| { - tracing::error!("{}", e); - MegaError::Other(format!("fail to find reviewer {}", campsite_user_id)) - })? - .ok_or_else(|| MegaError::NotFound(format!("reviewer {} not found", campsite_user_id)))? - .into_active_model(); + let row = self + .find_actor_reviewer(cl_link, campsite_user_id) + .await? + .ok_or_else(|| { + MegaError::NotFound(format!("reviewer {} not found", campsite_user_id)) + })?; + let mut rev: mega_cl_reviewer::ActiveModel = row.into_active_model(); rev.approved = Set(approved); rev.updated_at = Set(chrono::Utc::now().naive_utc()); rev.update(self.get_connection()).await.map_err(|e| { diff --git a/mono/src/api/router/reviewer_router.rs b/mono/src/api/router/reviewer_router.rs index fe67b0d64..7174550c2 100644 --- a/mono/src/api/router/reviewer_router.rs +++ b/mono/src/api/router/reviewer_router.rs @@ -197,13 +197,19 @@ async fn reviewer_approve( .reviewer_change_state(&link, actor, payload.approved) .await?; + let display = user + .github_login + .as_deref() + .map(str::trim) + .filter(|s| !s.is_empty()) + .unwrap_or(actor); state .services() .conversation() .add_conversation( &link, actor, - Some(format!("{} approved the CL", actor)), + Some(format!("{} approved the CL", display)), ConvType::Approve, ) .await?;