fix: guest membership
This commit is contained in:
parent
80c03483ee
commit
9acb688379
2 changed files with 50 additions and 2 deletions
|
|
@ -35,12 +35,30 @@ pub async fn get_user_membership(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new membership (join a realm).
|
/// Create a new membership (join a realm).
|
||||||
|
/// This function is idempotent - if the membership already exists, it returns the existing id.
|
||||||
pub async fn create_membership(
|
pub async fn create_membership(
|
||||||
pool: &PgPool,
|
pool: &PgPool,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
realm_id: Uuid,
|
realm_id: Uuid,
|
||||||
role: RealmRole,
|
role: RealmRole,
|
||||||
) -> Result<Uuid, AppError> {
|
) -> Result<Uuid, AppError> {
|
||||||
|
// Check if membership already exists
|
||||||
|
let existing: Option<(Uuid,)> = sqlx::query_as(
|
||||||
|
r#"
|
||||||
|
SELECT id FROM realm.memberships
|
||||||
|
WHERE user_id = $1 AND realm_id = $2
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.bind(user_id)
|
||||||
|
.bind(realm_id)
|
||||||
|
.fetch_optional(pool)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if let Some((id,)) = existing {
|
||||||
|
return Ok(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new membership
|
||||||
let (membership_id,): (Uuid,) = sqlx::query_as(
|
let (membership_id,): (Uuid,) = sqlx::query_as(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO realm.memberships (realm_id, user_id, role)
|
INSERT INTO realm.memberships (realm_id, user_id, role)
|
||||||
|
|
@ -54,7 +72,7 @@ pub async fn create_membership(
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Update member count on the realm
|
// Only increment count for new memberships
|
||||||
sqlx::query("UPDATE realm.realms SET member_count = member_count + 1 WHERE id = $1")
|
sqlx::query("UPDATE realm.realms SET member_count = member_count + 1 WHERE id = $1")
|
||||||
.bind(realm_id)
|
.bind(realm_id)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
|
|
@ -64,12 +82,30 @@ pub async fn create_membership(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new membership using a connection (for RLS support).
|
/// Create a new membership using a connection (for RLS support).
|
||||||
|
/// This function is idempotent - if the membership already exists, it returns the existing id.
|
||||||
pub async fn create_membership_conn(
|
pub async fn create_membership_conn(
|
||||||
conn: &mut sqlx::PgConnection,
|
conn: &mut sqlx::PgConnection,
|
||||||
user_id: Uuid,
|
user_id: Uuid,
|
||||||
realm_id: Uuid,
|
realm_id: Uuid,
|
||||||
role: RealmRole,
|
role: RealmRole,
|
||||||
) -> Result<Uuid, AppError> {
|
) -> Result<Uuid, AppError> {
|
||||||
|
// Check if membership already exists
|
||||||
|
let existing: Option<(Uuid,)> = sqlx::query_as(
|
||||||
|
r#"
|
||||||
|
SELECT id FROM realm.memberships
|
||||||
|
WHERE user_id = $1 AND realm_id = $2
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.bind(user_id)
|
||||||
|
.bind(realm_id)
|
||||||
|
.fetch_optional(&mut *conn)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if let Some((id,)) = existing {
|
||||||
|
return Ok(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create new membership
|
||||||
let (membership_id,): (Uuid,) = sqlx::query_as(
|
let (membership_id,): (Uuid,) = sqlx::query_as(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO realm.memberships (realm_id, user_id, role)
|
INSERT INTO realm.memberships (realm_id, user_id, role)
|
||||||
|
|
@ -83,7 +119,7 @@ pub async fn create_membership_conn(
|
||||||
.fetch_one(&mut *conn)
|
.fetch_one(&mut *conn)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Update member count on the realm
|
// Only increment count for new memberships
|
||||||
sqlx::query("UPDATE realm.realms SET member_count = member_count + 1 WHERE id = $1")
|
sqlx::query("UPDATE realm.realms SET member_count = member_count + 1 WHERE id = $1")
|
||||||
.bind(realm_id)
|
.bind(realm_id)
|
||||||
.execute(&mut *conn)
|
.execute(&mut *conn)
|
||||||
|
|
|
||||||
|
|
@ -368,6 +368,7 @@ pub async fn signup(
|
||||||
/// Creates a real user account with the 'guest' tag. Guests are regular users
|
/// Creates a real user account with the 'guest' tag. Guests are regular users
|
||||||
/// with limited capabilities (no prop pickup, etc.) that can be reaped after 24 hours.
|
/// with limited capabilities (no prop pickup, etc.) that can be reaped after 24 hours.
|
||||||
pub async fn guest_login(
|
pub async fn guest_login(
|
||||||
|
rls_conn: crate::auth::RlsConn,
|
||||||
State(pool): State<PgPool>,
|
State(pool): State<PgPool>,
|
||||||
session: Session,
|
session: Session,
|
||||||
Json(req): Json<GuestLoginRequest>,
|
Json(req): Json<GuestLoginRequest>,
|
||||||
|
|
@ -393,6 +394,17 @@ pub async fn guest_login(
|
||||||
// Create guest user (no password) - trigger creates avatar automatically
|
// Create guest user (no password) - trigger creates avatar automatically
|
||||||
let user_id = users::create_guest_user(&pool, &guest_name).await?;
|
let user_id = users::create_guest_user(&pool, &guest_name).await?;
|
||||||
|
|
||||||
|
// Set RLS context to the new guest user for membership creation
|
||||||
|
rls_conn
|
||||||
|
.set_user_id(user_id)
|
||||||
|
.await
|
||||||
|
.map_err(|e| AppError::Internal(format!("Failed to set RLS context: {}", e)))?;
|
||||||
|
|
||||||
|
// Create membership for the guest so their position can be persisted
|
||||||
|
let mut conn = rls_conn.acquire().await;
|
||||||
|
memberships::create_membership_conn(&mut *conn, user_id, realm.id, RealmRole::Member).await?;
|
||||||
|
drop(conn);
|
||||||
|
|
||||||
// Set up tower session (same as regular user login)
|
// Set up tower session (same as regular user login)
|
||||||
session
|
session
|
||||||
.insert(SESSION_USER_ID_KEY, user_id)
|
.insert(SESSION_USER_ID_KEY, user_id)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue