Skip to content

Commit

Permalink
feat: add workspace member api
Browse files Browse the repository at this point in the history
  • Loading branch information
marverlous811 committed Nov 30, 2024
1 parent fbf6d8c commit 315bded
Show file tree
Hide file tree
Showing 24 changed files with 870 additions and 33 deletions.
7 changes: 6 additions & 1 deletion bin/admin-panel/src/database/migrations.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
use welds::migrations::prelude::*;

use super::models::{project::validate_project_table, workspace::validate_workspace_table};
use super::models::{
project::validate_project_table, workspace::validate_workspace_table,
workspace_invite::validate_workspace_members_invite_table, workspace_member::validate_workspace_members_table,
};

mod m20241102_init;

pub async fn check_tables(client: &dyn welds::Client) -> anyhow::Result<()> {
let mut errors = vec![];
errors.append(&mut validate_project_table(client).await?);
errors.append(&mut validate_workspace_table(client).await?);
errors.append(&mut validate_workspace_members_invite_table(client).await?);
errors.append(&mut validate_workspace_members_table(client).await?);

if !errors.is_empty() {
log::error!("Schema mismatch: found {:?} issues", errors);
Expand Down
2 changes: 1 addition & 1 deletion bin/admin-panel/src/database/migrations/m20241102_init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub fn m20241125_create_workspace(_: &TableState) -> Result<MigrationStep> {

pub fn m20241125_create_workspace_members(_: &TableState) -> Result<MigrationStep> {
let m = create_table("d_workspace_members")
.id(|c| c("id", Type::Int))
.id(|c| c("id", Type::String))
.column(|c| c("workspace_id", Type::String).create_index())
.column(|c| c("user_id", Type::String).create_index())
.column(|c| c("created_at", Type::IntBig))
Expand Down
2 changes: 2 additions & 0 deletions bin/admin-panel/src/database/models.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
pub mod project;
pub mod workspace;
pub mod workspace_invite;
pub mod workspace_member;
4 changes: 4 additions & 0 deletions bin/admin-panel/src/database/models/workspace.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
use serde::{Deserialize, Serialize};
use welds::{errors::Result, WeldsModel};

use super::{project::Project, workspace_member::WorkspaceMember};

#[derive(Debug, Clone, Serialize, Deserialize, WeldsModel)]
#[welds(table = "d_workspaces")]
#[welds(db(Sqlite, Postgres))]
#[welds(BeforeCreate(before_create))]
#[welds(BeforeUpdate(before_update))]
#[welds(HasMany(projects, Project, "workspace_id"))]
#[welds(HasMany(members, WorkspaceMember, "workspace_id"))]
pub struct Workspace {
#[welds(primary_key)]
pub id: String,
Expand Down
41 changes: 41 additions & 0 deletions bin/admin-panel/src/database/models/workspace_invite.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use serde::{Deserialize, Serialize};
use welds::{errors::Result, WeldsModel};

use super::workspace::Workspace;

#[derive(Debug, Clone, Serialize, Deserialize, WeldsModel)]
#[welds(table = "t_workspace_members_invite")]
#[welds(db(Sqlite, Postgres))]
#[welds(BeforeCreate(before_create))]
#[welds(BeforeUpdate(before_update))]
#[welds(BelongsTo(workspace, Workspace, "workspace_id"))]
pub struct WorkspaceMembersInvite {
#[welds(primary_key)]
pub id: i32,
pub workspace_id: String,
pub email: String,
pub expires: i64,
pub created_at: i64,
pub updated_at: i64,
}

pub async fn validate_workspace_members_invite_table(
client: &dyn welds::Client,
) -> anyhow::Result<Vec<welds::check::Issue>> {
let issues = welds::check::schema::<WorkspaceMembersInvite>(client).await?;
Ok(issues
.into_iter()
.filter(|i| i.level == welds::check::Level::Critical)
.collect())
}

fn before_create(workspace: &mut WorkspaceMembersInvite) -> Result<()> {
workspace.created_at = chrono::Utc::now().timestamp_millis();
workspace.updated_at = chrono::Utc::now().timestamp_millis();
Ok(())
}

fn before_update(workspace: &mut WorkspaceMembersInvite) -> Result<()> {
workspace.updated_at = chrono::Utc::now().timestamp_millis();
Ok(())
}
37 changes: 37 additions & 0 deletions bin/admin-panel/src/database/models/workspace_member.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use serde::{Deserialize, Serialize};
use welds::{errors::Result, WeldsModel};

#[derive(Debug, Clone, Serialize, Deserialize, WeldsModel)]
#[welds(table = "d_workspace_members")]
#[welds(db(Sqlite, Postgres))]
#[welds(BeforeCreate(before_create))]
#[welds(BeforeUpdate(before_update))]
#[welds(BelongsTo(workspace, super::workspace::Workspace, "workspace_id"))]
pub struct WorkspaceMember {
#[welds(primary_key)]
pub id: String,
pub workspace_id: String,
pub user_id: String,
pub created_at: i64,
pub updated_at: i64,
}

pub async fn validate_workspace_members_table(client: &dyn welds::Client) -> anyhow::Result<Vec<welds::check::Issue>> {
let issues = welds::check::schema::<WorkspaceMember>(client).await?;
Ok(issues
.into_iter()
.filter(|i| i.level == welds::check::Level::Critical)
.collect())
}

fn before_create(member: &mut WorkspaceMember) -> Result<()> {
member.id = uuid::Uuid::new_v4().to_string();
member.created_at = chrono::Utc::now().timestamp_millis();
member.updated_at = chrono::Utc::now().timestamp_millis();
Ok(())
}

fn before_update(member: &mut WorkspaceMember) -> Result<()> {
member.updated_at = chrono::Utc::now().timestamp_millis();
Ok(())
}
2 changes: 2 additions & 0 deletions bin/admin-panel/src/database/repositories.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
pub mod project;
pub mod workspace;
pub mod workspace_invite;
pub mod workspace_member;
9 changes: 5 additions & 4 deletions bin/admin-panel/src/database/repositories/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};

use crate::database::models::project::{Project, ProjectCodecs, ProjectOptions};

#[derive(Debug, Clone)]
#[derive(Debug, Clone, Default)]
pub struct ProjectFilterDto {
pub id: Option<String>,
pub workspace_id: Option<String>,
Expand Down Expand Up @@ -73,11 +73,12 @@ pub async fn get_project(client: Arc<dyn welds::Client>, filter: ProjectFilterDt

pub async fn update_project(
client: Arc<dyn welds::Client>,
id: String,
filter: ProjectFilterDto,
dto: UpdateProjectDto,
) -> anyhow::Result<Project> {
let project = Project::find_by_id(client.as_ref(), id).await?;
match project {
let query = build_query(filter);
let mut res = query.run(client.as_ref()).await?;
match res.pop() {
Some(mut project) => {
if let Some(name) = dto.name {
project.name = name;
Expand Down
8 changes: 7 additions & 1 deletion bin/admin-panel/src/database/repositories/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ use std::sync::Arc;

use serde::{Deserialize, Serialize};

use crate::database::models::workspace::Workspace;
use crate::database::models::{workspace::Workspace, workspace_member::WorkspaceMember};

#[derive(Debug, Clone, Default)]
pub struct WorkspaceFilterDto {
pub id: Option<String>,
pub name: Option<String>,
pub user_id: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
Expand Down Expand Up @@ -100,5 +101,10 @@ fn build_query(filter: WorkspaceFilterDto) -> welds::query::builder::QueryBuilde
if let Some(name) = filter.name {
query = query.where_col(|c| c.name.equal(name.clone()));
}

if let Some(user_id) = filter.user_id {
let member_query = WorkspaceMember::where_col(|c| c.user_id.equal(user_id.clone()));
query = query.where_relation(|w| w.members, member_query);
}
query
}
130 changes: 130 additions & 0 deletions bin/admin-panel/src/database/repositories/workspace_invite.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
use std::sync::Arc;

use crate::database::models::workspace_invite::WorkspaceMembersInvite;

#[derive(Debug, Clone)]
pub struct WorkspaceMembersInviteCreate {
pub workspace_id: String,
pub email: String,
pub expires: i64,
}

#[derive(Debug, Clone, Default)]
pub struct WorkspaceMembersInviteUpdateDto {
pub expires: Option<i64>,
}

#[derive(Debug, Clone, Default)]
pub struct WorkspaceMembersInviteFilter {
pub id: Option<i32>,
pub workspace_id: Option<String>,
pub email: Option<String>,
}

pub async fn create_workspace_member_invite(
client: Arc<dyn welds::Client>,
dto: WorkspaceMembersInviteCreate,
) -> anyhow::Result<WorkspaceMembersInvite> {
let mut invite = WorkspaceMembersInvite::new();
invite.workspace_id = dto.workspace_id.clone();
invite.email = dto.email.clone();
invite.expires = dto.expires;
invite.save(client.as_ref()).await?;
Ok(invite.into_inner())
}

pub async fn update_workspace_member_invite_by_id(
client: Arc<dyn welds::Client>,
id: i32,
dto: WorkspaceMembersInviteUpdateDto,
) -> anyhow::Result<WorkspaceMembersInvite> {
match WorkspaceMembersInvite::find_by_id(client.as_ref(), id).await? {
Some(mut invite) => {
if let Some(expires) = dto.expires {
invite.expires = expires;
}
invite.save(client.as_ref()).await?;
Ok(invite.into_inner())
}
None => anyhow::bail!("Invite not found"),
}
}

pub async fn get_workspace_member_invites(
client: Arc<dyn welds::Client>,
filter: WorkspaceMembersInviteFilter,
limit: Option<u64>,
offset: Option<u64>,
) -> anyhow::Result<Vec<WorkspaceMembersInvite>> {
let mut query = build_query(filter);
if let Some(limit) = limit {
query = query.limit(limit as i64);
}
if let Some(offset) = offset {
query = query.offset(offset as i64);
}
let res = query.run(client.as_ref()).await?;
Ok(res.into_iter().map(|p| p.into_inner()).collect())
}

pub async fn get_workspace_member_invite(
client: Arc<dyn welds::Client>,
filter: WorkspaceMembersInviteFilter,
) -> anyhow::Result<Option<WorkspaceMembersInvite>> {
let query = build_query(filter);
let mut res = query.run(client.as_ref()).await?;
match res.pop() {
Some(invite) => Ok(Some(invite.into_inner())),
None => Ok(None),
}
}

pub async fn count_workspace_member_invites(
client: Arc<dyn welds::Client>,
filter: WorkspaceMembersInviteFilter,
) -> anyhow::Result<u64> {
let query = build_query(filter);
let count = query.count(client.as_ref()).await?;
Ok(count)
}

pub async fn delete_workspace_invite(client: Arc<dyn welds::Client>, id: i32) -> anyhow::Result<bool> {
match WorkspaceMembersInvite::find_by_id(client.as_ref(), id).await? {
Some(mut invite) => {
invite.delete(client.as_ref()).await?;
Ok(true)
}
None => Ok(false),
}
}

pub async fn delete_many_workspace_invite(
client: Arc<dyn welds::Client>,
workspace_id: String,
ids: Vec<i32>,
) -> anyhow::Result<bool> {
for id in ids {
let filter = WorkspaceMembersInviteFilter {
id: Some(id),
workspace_id: Some(workspace_id.clone()),
..Default::default()
};
let query = build_query(filter);
query.delete(client.as_ref()).await?;
}
Ok(true)
}

fn build_query(filter: WorkspaceMembersInviteFilter) -> welds::query::builder::QueryBuilder<WorkspaceMembersInvite> {
let mut query = WorkspaceMembersInvite::all();
if let Some(id) = filter.id {
query = query.where_col(|c| c.id.equal(id));
}
if let Some(workspace_id) = filter.workspace_id {
query = query.where_col(|c| c.workspace_id.equal(workspace_id.clone()));
}
if let Some(email) = filter.email {
query = query.where_col(|c| c.email.equal(email.clone()));
}
query
}
Loading

0 comments on commit 315bded

Please sign in to comment.