Return group member email from list_members (Groups p4 M4)
The group members endpoint now joins users and returns each member's
email alongside role and added-at, so a consumer's admin UI can identify
members instead of showing a bare user id. Threads email through
DbSyncGroupMember, GroupMemberResponse, and the synckit-client
GroupMember type.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5 files changed,
+14 insertions,
-4 deletions
| 118 |
118 |
|
pub group_id: SyncGroupId,
|
| 119 |
119 |
|
/// The member.
|
| 120 |
120 |
|
pub user_id: UserId,
|
|
121 |
+ |
/// The member's account email, joined from `users`. Surfaced so an admin panel
|
|
122 |
+ |
/// can show who a member is rather than a bare user id.
|
|
123 |
+ |
pub email: String,
|
| 121 |
124 |
|
/// `admin` | `member`. Reserved for the later per-key permission system; MVP
|
| 122 |
125 |
|
/// treats every member as a reader and writer.
|
| 123 |
126 |
|
pub role: String,
|
| 115 |
115 |
|
pub async fn list_members(pool: &PgPool, group_id: SyncGroupId) -> Result<Vec<DbSyncGroupMember>> {
|
| 116 |
116 |
|
let members = sqlx::query_as::<_, DbSyncGroupMember>(
|
| 117 |
117 |
|
r#"
|
| 118 |
|
- |
SELECT group_id, user_id, role, sealed_gck, gck_version, added_at
|
| 119 |
|
- |
FROM sync_group_members
|
| 120 |
|
- |
WHERE group_id = $1
|
| 121 |
|
- |
ORDER BY added_at ASC
|
|
118 |
+ |
SELECT m.group_id, m.user_id, u.email, m.role, m.sealed_gck, m.gck_version, m.added_at
|
|
119 |
+ |
FROM sync_group_members m
|
|
120 |
+ |
JOIN users u ON u.id = m.user_id
|
|
121 |
+ |
WHERE m.group_id = $1
|
|
122 |
+ |
ORDER BY m.added_at ASC
|
| 122 |
123 |
|
"#,
|
| 123 |
124 |
|
)
|
| 124 |
125 |
|
.bind(group_id)
|
| 258 |
258 |
|
.into_iter()
|
| 259 |
259 |
|
.map(|m| GroupMemberResponse {
|
| 260 |
260 |
|
user_id: m.user_id,
|
|
261 |
+ |
email: m.email,
|
| 261 |
262 |
|
role: m.role,
|
| 262 |
263 |
|
added_at: m.added_at,
|
| 263 |
264 |
|
})
|
| 266 |
266 |
|
pub(crate) struct GroupMemberResponse {
|
| 267 |
267 |
|
#[schema(value_type = String)]
|
| 268 |
268 |
|
user_id: UserId,
|
|
269 |
+ |
/// The member's account email, so an admin panel can identify them.
|
|
270 |
+ |
email: String,
|
| 269 |
271 |
|
role: String,
|
| 270 |
272 |
|
#[schema(value_type = String)]
|
| 271 |
273 |
|
added_at: DateTime<Utc>,
|
| 272 |
272 |
|
pub struct GroupMember {
|
| 273 |
273 |
|
/// The member's account id.
|
| 274 |
274 |
|
pub user_id: UserId,
|
|
275 |
+ |
/// The member's account email, so a consumer's admin UI can identify them
|
|
276 |
+ |
/// rather than showing a bare user id.
|
|
277 |
+ |
pub email: String,
|
| 275 |
278 |
|
/// `"admin"` or `"member"`.
|
| 276 |
279 |
|
pub role: String,
|
| 277 |
280 |
|
/// When they were added.
|