registry: add sqlx checks for workspace and stream reads

This commit is contained in:
a.tolmachev
2026-04-12 20:49:12 +00:00
parent 57c73b5cb2
commit 6a909feb64
15 changed files with 1195 additions and 151 deletions
+96 -24
View File
@@ -2,74 +2,118 @@ use super::*;
impl PostgresRegistry {
pub async fn list_workspaces(&self) -> Result<Vec<WorkspaceRecord>, RegistryError> {
let rows = sqlx::query(
let rows = sqlx::query!(
"select
id,
slug,
display_name,
status,
settings_json,
to_char(created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as created_at,
to_char(updated_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as updated_at
to_char(created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as \"created_at!\",
to_char(updated_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as \"updated_at!\"
from workspaces
order by slug asc",
)
.fetch_all(&self.pool)
.await?;
rows.iter().map(map_workspace_record).collect()
rows.into_iter()
.map(|row| {
Ok(WorkspaceRecord {
workspace: Workspace {
id: WorkspaceId::new(row.id),
slug: row.slug,
display_name: row.display_name,
status: deserialize_enum_text(&row.status, "status")?,
settings: row.settings_json,
created_at: row.created_at,
updated_at: row.updated_at,
},
})
})
.collect()
}
pub async fn list_workspaces_for_user(
&self,
user_id: &UserId,
) -> Result<Vec<WorkspaceMembershipRecord>, RegistryError> {
let rows = sqlx::query(
let rows = sqlx::query!(
"select
w.id,
w.slug,
w.display_name,
w.status,
w.settings_json,
to_char(w.created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as created_at,
to_char(w.updated_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as updated_at,
to_char(w.created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as \"created_at!\",
to_char(w.updated_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as \"updated_at!\",
m.role
from memberships m
join workspaces w on w.id = m.workspace_id
where m.user_id = $1
order by w.slug asc",
user_id.as_str(),
)
.bind(user_id.as_str())
.fetch_all(&self.pool)
.await?;
rows.iter().map(map_workspace_membership_record).collect()
rows.into_iter()
.map(|row| {
Ok(WorkspaceMembershipRecord {
workspace: Workspace {
id: WorkspaceId::new(row.id),
slug: row.slug,
display_name: row.display_name,
status: deserialize_enum_text(&row.status, "status")?,
settings: row.settings_json,
created_at: row.created_at,
updated_at: row.updated_at,
},
role: deserialize_enum_text(&row.role, "role")?,
})
})
.collect()
}
pub async fn list_memberships(
&self,
workspace_id: &WorkspaceId,
) -> Result<Vec<MembershipRecord>, RegistryError> {
let rows = sqlx::query(
let rows = sqlx::query!(
"select
m.workspace_id,
m.user_id,
m.role,
to_char(m.created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as created_at,
to_char(m.created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as \"created_at!\",
u.email,
u.display_name,
u.status,
to_char(u.created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as user_created_at
to_char(u.created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as \"user_created_at!\"
from memberships m
join users u on u.id = m.user_id
where m.workspace_id = $1
order by u.email asc",
workspace_id.as_str(),
)
.bind(workspace_id.as_str())
.fetch_all(&self.pool)
.await?;
rows.iter().map(map_membership_record).collect()
rows.into_iter()
.map(|row| {
Ok(MembershipRecord {
workspace_id: WorkspaceId::new(row.workspace_id),
user: User {
id: UserId::new(row.user_id),
email: row.email,
display_name: row.display_name,
status: deserialize_enum_text(&row.status, "status")?,
created_at: row.user_created_at,
},
role: deserialize_enum_text(&row.role, "role")?,
created_at: row.created_at,
})
})
.collect()
}
pub async fn update_membership_role(
@@ -127,7 +171,7 @@ impl PostgresRegistry {
&self,
workspace_id: &WorkspaceId,
) -> Result<Vec<InvitationRecord>, RegistryError> {
let rows = sqlx::query(
let rows = sqlx::query!(
"select
id,
workspace_id,
@@ -135,17 +179,32 @@ impl PostgresRegistry {
role,
status,
token_hash,
to_char(expires_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as expires_at,
to_char(created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as created_at
to_char(expires_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as \"expires_at!\",
to_char(created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as \"created_at!\"
from invitation_tokens
where workspace_id = $1
order by created_at desc",
workspace_id.as_str(),
)
.bind(workspace_id.as_str())
.fetch_all(&self.pool)
.await?;
rows.iter().map(map_invitation_record).collect()
rows.into_iter()
.map(|row| {
Ok(InvitationRecord {
invitation: InvitationToken {
id: InvitationId::new(row.id),
workspace_id: WorkspaceId::new(row.workspace_id),
email: row.email,
role: deserialize_enum_text(&row.role, "role")?,
status: deserialize_enum_text(&row.status, "status")?,
token_hash: row.token_hash,
expires_at: row.expires_at,
created_at: row.created_at,
},
})
})
.collect()
}
pub async fn create_invitation(
@@ -220,23 +279,36 @@ impl PostgresRegistry {
&self,
workspace_id: &WorkspaceId,
) -> Result<Option<WorkspaceRecord>, RegistryError> {
let row = sqlx::query(
let row = sqlx::query!(
"select
id,
slug,
display_name,
status,
settings_json,
to_char(created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as created_at,
to_char(updated_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as updated_at
to_char(created_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as \"created_at!\",
to_char(updated_at at time zone 'UTC', 'YYYY-MM-DD\"T\"HH24:MI:SS\"Z\"') as \"updated_at!\"
from workspaces
where id = $1",
workspace_id.as_str(),
)
.bind(workspace_id.as_str())
.fetch_optional(&self.pool)
.await?;
row.as_ref().map(map_workspace_record).transpose()
row.map(|row| {
Ok(WorkspaceRecord {
workspace: Workspace {
id: WorkspaceId::new(row.id),
slug: row.slug,
display_name: row.display_name,
status: deserialize_enum_text(&row.status, "status")?,
settings: row.settings_json,
created_at: row.created_at,
updated_at: row.updated_at,
},
})
})
.transpose()
}
pub async fn create_workspace(