feat: persist current workspace in user sessions

This commit is contained in:
a.tolmachev
2026-03-31 15:17:07 +03:00
parent 84f4437ce0
commit 86b61523bd
15 changed files with 331 additions and 57 deletions
+60 -5
View File
@@ -64,6 +64,7 @@ pub struct LoginPayload {
pub struct SessionResponse {
pub user: crank_core::User,
pub memberships: Vec<WorkspaceMembershipRecord>,
pub current_workspace_id: Option<String>,
}
#[derive(Clone, Debug, Deserialize)]
@@ -78,6 +79,11 @@ pub struct ChangePasswordPayload {
pub new_password: String,
}
#[derive(Clone, Debug, Deserialize)]
pub struct UpdateCurrentWorkspacePayload {
pub workspace_id: String,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct OperationPayload {
pub name: String,
@@ -546,8 +552,10 @@ impl AdminService {
.get_user_session(session_id, &secret_hash)
.await?
.map(|record| AuthenticatedSession {
session_id: record.session_id,
user: record.user,
memberships: record.memberships,
current_workspace_id: record.current_workspace_id,
});
Ok(session)
@@ -582,24 +590,31 @@ impl AdminService {
&session_cookie.value,
&self.auth_settings.session_secret,
);
let memberships = self
.registry
.list_workspaces_for_user(&user.user.id)
.await?;
let current_workspace_id = memberships
.first()
.map(|membership| membership.workspace.id.as_str().to_owned());
self.registry
.create_user_session(
&session_cookie.session_id,
&user.user.id,
memberships
.first()
.map(|membership| &membership.workspace.id),
&secret_hash,
&session_cookie.expires_at,
)
.await?;
let memberships = self
.registry
.list_workspaces_for_user(&user.user.id)
.await?;
Ok((
session_cookie,
SessionResponse {
user: user.user,
memberships,
current_workspace_id,
},
))
}
@@ -672,12 +687,16 @@ impl AdminService {
.map(|session| SessionResponse {
user: session.user,
memberships: session.memberships,
current_workspace_id: session
.current_workspace_id
.map(|id| id.as_str().to_owned()),
}))
}
pub async fn update_profile(
&self,
user_id: &crank_core::UserId,
current_workspace_id: Option<&WorkspaceId>,
payload: UpdateProfilePayload,
) -> Result<SessionResponse, ApiError> {
let display_name = payload.display_name.trim();
@@ -696,7 +715,43 @@ impl AdminService {
.await?;
let memberships = self.registry.list_workspaces_for_user(user_id).await?;
Ok(SessionResponse { user, memberships })
Ok(SessionResponse {
user,
memberships,
current_workspace_id: current_workspace_id.map(|id| id.as_str().to_owned()),
})
}
pub async fn set_current_workspace(
&self,
session_id: &UserSessionId,
user_id: &crank_core::UserId,
workspace_id: &WorkspaceId,
) -> Result<SessionResponse, ApiError> {
if !self
.user_has_workspace_access(user_id, workspace_id)
.await?
{
return Err(ApiError::forbidden("workspace access denied"));
}
self.registry
.set_user_session_current_workspace(session_id, workspace_id)
.await?;
let user = self
.registry
.get_auth_user_by_id(user_id)
.await?
.ok_or_else(|| ApiError::not_found(format!("user {} was not found", user_id.as_str())))?
.user;
let memberships = self.registry.list_workspaces_for_user(user_id).await?;
Ok(SessionResponse {
user,
memberships,
current_workspace_id: Some(workspace_id.as_str().to_owned()),
})
}
pub async fn change_password(