forked from lavina/lavina
Check if user is a member before inserting a membership (#62)
It would typically fail on insertion due to uniqueness constraints: user id - room id. Reviewed-on: lavina/lavina#62 Co-authored-by: Mikhail <mikhail@liamets.dev> Co-committed-by: Mikhail <mikhail@liamets.dev>
This commit is contained in:
parent
7f2c6a1013
commit
5512a74999
|
@ -1,8 +1,29 @@
|
|||
use crate::player::PlayerConnection;
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::repo::Storage;
|
||||
|
||||
impl Storage {
|
||||
#[tracing::instrument(skip(self), name = "Storage::is_room_member")]
|
||||
pub async fn is_room_member(&self, room_id: u32, player_id: u32) -> Result<bool> {
|
||||
let mut executor = self.conn.lock().await;
|
||||
let res: (u32,) = sqlx::query_as(
|
||||
"
|
||||
select
|
||||
count(*)
|
||||
from
|
||||
memberships
|
||||
where
|
||||
user_id = ? and room_id = ?;
|
||||
",
|
||||
)
|
||||
.bind(player_id)
|
||||
.bind(room_id)
|
||||
.fetch_one(&mut *executor)
|
||||
.await?;
|
||||
Ok(res.0 > 0)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self), name = "Storage::add_room_member")]
|
||||
pub async fn add_room_member(&self, room_id: u32, player_id: u32) -> Result<()> {
|
||||
let mut executor = self.conn.lock().await;
|
||||
|
|
|
@ -14,6 +14,7 @@ use crate::repo::Storage;
|
|||
/// Opaque room id
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
|
||||
pub struct RoomId(Str);
|
||||
|
||||
impl RoomId {
|
||||
pub fn from(str: impl Into<Str>) -> Result<RoomId> {
|
||||
let bytes = str.into();
|
||||
|
@ -36,6 +37,7 @@ impl RoomId {
|
|||
/// Shared data structure for storing metadata about rooms.
|
||||
#[derive(Clone)]
|
||||
pub struct RoomRegistry(Arc<AsyncRwLock<RoomRegistryInner>>);
|
||||
|
||||
impl RoomRegistry {
|
||||
pub fn new(metrics: &mut MetricRegistry, storage: Storage) -> Result<RoomRegistry> {
|
||||
let metric_active_rooms = IntGauge::new("chat_rooms_active", "Number of alive room actors")?;
|
||||
|
@ -141,6 +143,7 @@ impl RoomRegistryInner {
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct RoomHandle(Arc<AsyncRwLock<Room>>);
|
||||
|
||||
impl RoomHandle {
|
||||
#[tracing::instrument(skip(self, player_handle), name = "RoomHandle::subscribe")]
|
||||
pub async fn subscribe(&self, player_id: &PlayerId, player_handle: PlayerHandle) {
|
||||
|
@ -154,7 +157,9 @@ impl RoomHandle {
|
|||
let mut lock = self.0.write().await;
|
||||
tracing::info!("Adding a new member to a room");
|
||||
let room_storage_id = lock.storage_id;
|
||||
if !lock.storage.is_room_member(room_storage_id, player_storage_id).await.unwrap() {
|
||||
lock.storage.add_room_member(room_storage_id, player_storage_id).await.unwrap();
|
||||
}
|
||||
lock.members.insert(player_id.clone());
|
||||
let update = Updates::RoomJoined {
|
||||
room_id: lock.room_id.clone(),
|
||||
|
@ -230,6 +235,7 @@ struct Room {
|
|||
topic: Str,
|
||||
storage: Storage,
|
||||
}
|
||||
|
||||
impl Room {
|
||||
#[tracing::instrument(skip(self, body, created_at), name = "Room::send_message")]
|
||||
async fn send_message(&mut self, author_id: &PlayerId, body: Str, created_at: DateTime<Utc>) -> Result<()> {
|
||||
|
|
Loading…
Reference in New Issue