diff --git a/model/src/lib.rs b/model/src/lib.rs index 18175a2..168ae88 100644 --- a/model/src/lib.rs +++ b/model/src/lib.rs @@ -63,6 +63,11 @@ pub struct Group { pub users: Vec, } +#[derive(PartialEq, Eq, Debug, Serialize, Deserialize)] +pub struct CreateGroupRequest { + pub display_name: String, +} + #[derive(Clone, Serialize, Deserialize)] pub struct JWTClaims { pub exp: DateTime, diff --git a/src/domain/handler.rs b/src/domain/handler.rs index f0e65be..2eb33ce 100644 --- a/src/domain/handler.rs +++ b/src/domain/handler.rs @@ -10,6 +10,7 @@ pub trait BackendHandler: Clone + Send { async fn list_users(&self, request: ListUsersRequest) -> Result>; async fn list_groups(&self) -> Result>; async fn create_user(&self, request: CreateUserRequest) -> Result<()>; + async fn create_group(&self, request: CreateGroupRequest) -> Result; async fn get_user_groups(&self, user: String) -> Result>; } @@ -25,6 +26,7 @@ mockall::mock! { async fn list_users(&self, request: ListUsersRequest) -> Result>; async fn list_groups(&self) -> Result>; async fn create_user(&self, request: CreateUserRequest) -> Result<()>; + async fn create_group(&self, request: CreateGroupRequest) -> Result; async fn get_user_groups(&self, user: String) -> Result>; } } diff --git a/src/domain/sql_backend_handler.rs b/src/domain/sql_backend_handler.rs index 76abdf2..643814f 100644 --- a/src/domain/sql_backend_handler.rs +++ b/src/domain/sql_backend_handler.rs @@ -242,6 +242,22 @@ impl BackendHandler for SqlBackendHandler { sqlx::query(&query).execute(&self.sql_pool).await?; Ok(()) } + async fn create_group(&self, request: CreateGroupRequest) -> Result { + let query = Query::insert() + .into_table(Groups::Table) + .columns(vec![Groups::DisplayName]) + .values_panic(vec![request.display_name.as_str().into()]) + .to_string(DbQueryBuilder {}); + sqlx::query(&query).execute(&self.sql_pool).await?; + let query = Query::select() + .column(Groups::GroupId) + .from(Groups::Table) + .and_where(Expr::col(Groups::DisplayName).eq(request.display_name.as_str())) + .to_string(DbQueryBuilder {}); + let row = sqlx::query(&query).fetch_one(&self.sql_pool).await?; + Ok( + row.get::(&*Groups::GroupId.to_string())) + } } #[cfg(test)] @@ -271,16 +287,11 @@ mod tests { .unwrap(); } - async fn insert_group(sql_pool: &Pool, id: u32, name: &str) { - let query = Query::insert() - .into_table(Groups::Table) - .columns(vec![Groups::GroupId, Groups::DisplayName]) - .values_panic(vec![id.into(), name.into()]) - .to_string(DbQueryBuilder {}); - sqlx::query(&query).execute(sql_pool).await.unwrap(); + async fn insert_group(handler: &SqlBackendHandler, name: &str) -> i32 { + handler.create_group(CreateGroupRequest{display_name: name.to_string()}).await.unwrap() } - async fn insert_membership(sql_pool: &Pool, group_id: u32, user_id: &str) { + async fn insert_membership(sql_pool: &Pool, group_id: i32, user_id: &str) { let query = Query::insert() .into_table(Memberships::Table) .columns(vec![Memberships::UserId, Memberships::GroupId]) @@ -424,12 +435,12 @@ mod tests { insert_user(&handler, "bob", "bob00").await; insert_user(&handler, "patrick", "pass").await; insert_user(&handler, "John", "Pa33w0rd!").await; - insert_group(&sql_pool, 1, "Best Group").await; - insert_group(&sql_pool, 2, "Worst Group").await; - insert_membership(&sql_pool, 1, "bob").await; - insert_membership(&sql_pool, 1, "patrick").await; - insert_membership(&sql_pool, 2, "patrick").await; - insert_membership(&sql_pool, 2, "John").await; + let group_1 = insert_group(&handler, "Best Group").await; + let group_2 = insert_group(&handler, "Worst Group").await; + insert_membership(&sql_pool, group_1, "bob").await; + insert_membership(&sql_pool, group_1, "patrick").await; + insert_membership(&sql_pool, group_2, "patrick").await; + insert_membership(&sql_pool, group_2, "John").await; assert_eq!( handler.list_groups().await.unwrap(), vec![ @@ -453,11 +464,11 @@ mod tests { insert_user(&handler, "bob", "bob00").await; insert_user(&handler, "patrick", "pass").await; insert_user(&handler, "John", "Pa33w0rd!").await; - insert_group(&sql_pool, 1, "Group1").await; - insert_group(&sql_pool, 2, "Group2").await; - insert_membership(&sql_pool, 1, "bob").await; - insert_membership(&sql_pool, 1, "patrick").await; - insert_membership(&sql_pool, 2, "patrick").await; + let group_1 = insert_group(&handler, "Group1").await; + let group_2 = insert_group(&handler, "Group2").await; + insert_membership(&sql_pool, group_1, "bob").await; + insert_membership(&sql_pool, group_1, "patrick").await; + insert_membership(&sql_pool, group_2, "patrick").await; let mut bob_groups = HashSet::new(); bob_groups.insert("Group1".to_string()); let mut patrick_groups = HashSet::new(); diff --git a/src/domain/sql_tables.rs b/src/domain/sql_tables.rs index 9acd5e3..0c69b98 100644 --- a/src/domain/sql_tables.rs +++ b/src/domain/sql_tables.rs @@ -78,6 +78,7 @@ pub async fn init_table(pool: &Pool) -> sqlx::Result<()> { .col( ColumnDef::new(Groups::DisplayName) .string_len(255) + .unique_key() .not_null(), ) .to_string(DbQueryBuilder {}), diff --git a/src/infra/tcp_backend_handler.rs b/src/infra/tcp_backend_handler.rs index 8520776..1f869c7 100644 --- a/src/infra/tcp_backend_handler.rs +++ b/src/infra/tcp_backend_handler.rs @@ -28,6 +28,7 @@ mockall::mock! { async fn list_groups(&self) -> DomainResult>; async fn get_user_groups(&self, user: String) -> DomainResult>; async fn create_user(&self, request: CreateUserRequest) -> DomainResult<()>; + async fn create_group(&self, request: CreateGroupRequest) -> DomainResult; } #[async_trait] impl TcpBackendHandler for TestTcpBackendHandler {