168 lines
4.4 KiB
Rust
168 lines
4.4 KiB
Rust
use std::{collections::HashMap, sync::Arc};
|
|
|
|
use axum::async_trait;
|
|
use como_core::projects::ProjectService;
|
|
use como_domain::{
|
|
projects::{mutation::CreateProjectMutation, queries::GetProjectQuery, ProjectDto},
|
|
user::ContextUserExt,
|
|
Context,
|
|
};
|
|
use tokio::sync::Mutex;
|
|
|
|
use crate::database::ConnectionPool;
|
|
|
|
pub struct DefaultProjectService {
|
|
pool: ConnectionPool,
|
|
}
|
|
|
|
impl DefaultProjectService {
|
|
pub fn new(connection_pool: ConnectionPool) -> Self {
|
|
Self {
|
|
pool: connection_pool,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl ProjectService for DefaultProjectService {
|
|
async fn get_project(
|
|
&self,
|
|
context: &Context,
|
|
query: GetProjectQuery,
|
|
) -> anyhow::Result<ProjectDto> {
|
|
let user_id = context.get_user_id().ok_or(anyhow::anyhow!("no user id"))?;
|
|
|
|
let rec = sqlx::query!(
|
|
r#"
|
|
SELECT id, name, description, user_id
|
|
FROM projects
|
|
WHERE id = $1 and user_id = $2
|
|
"#,
|
|
query.project_id,
|
|
&user_id
|
|
)
|
|
.fetch_one(&self.pool)
|
|
.await?;
|
|
|
|
Ok(ProjectDto {
|
|
id: rec.id,
|
|
name: rec.name,
|
|
description: rec.description,
|
|
user_id: rec.user_id,
|
|
})
|
|
}
|
|
async fn get_projects(&self, context: &Context) -> anyhow::Result<Vec<ProjectDto>> {
|
|
let user_id = context.get_user_id().ok_or(anyhow::anyhow!("no user id"))?;
|
|
|
|
let recs = sqlx::query!(
|
|
r#"
|
|
SELECT id, name, description, user_id
|
|
FROM projects
|
|
WHERE user_id = $1
|
|
LIMIT 500
|
|
"#,
|
|
&user_id
|
|
)
|
|
.fetch_all(&self.pool)
|
|
.await?;
|
|
|
|
Ok(recs
|
|
.into_iter()
|
|
.map(|rec| ProjectDto {
|
|
id: rec.id,
|
|
name: rec.name,
|
|
description: rec.description,
|
|
user_id: rec.user_id,
|
|
})
|
|
.collect::<_>())
|
|
}
|
|
async fn create_project(
|
|
&self,
|
|
context: &Context,
|
|
request: CreateProjectMutation,
|
|
) -> anyhow::Result<ProjectDto> {
|
|
let user_id = context.get_user_id().ok_or(anyhow::anyhow!("no user id"))?;
|
|
|
|
let rec = sqlx::query!(
|
|
r#"
|
|
INSERT INTO projects (id, name, description, user_id, created_at, updated_at)
|
|
VALUES ($1, $2, $3, $4, $5, $6)
|
|
RETURNING id
|
|
"#,
|
|
uuid::Uuid::new_v4(),
|
|
request.name,
|
|
request.description,
|
|
&user_id,
|
|
chrono::Utc::now().naive_utc(),
|
|
chrono::Utc::now().naive_utc(),
|
|
)
|
|
.fetch_one(&self.pool)
|
|
.await?;
|
|
|
|
Ok(ProjectDto {
|
|
id: rec.id,
|
|
name: request.name,
|
|
description: request.description,
|
|
user_id: user_id.clone(),
|
|
})
|
|
}
|
|
}
|
|
|
|
pub struct MemoryProjectService {
|
|
project_store: Arc<Mutex<HashMap<String, ProjectDto>>>,
|
|
}
|
|
|
|
impl MemoryProjectService {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
project_store: Arc::new(Mutex::new(HashMap::new())),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl ProjectService for MemoryProjectService {
|
|
async fn get_project(
|
|
&self,
|
|
_context: &Context,
|
|
query: GetProjectQuery,
|
|
) -> anyhow::Result<ProjectDto> {
|
|
let ps = self.project_store.lock().await;
|
|
Ok(ps
|
|
.get(&query.project_id.to_string())
|
|
.ok_or(anyhow::anyhow!("could not find project"))?
|
|
.clone())
|
|
}
|
|
async fn get_projects(&self, context: &Context) -> anyhow::Result<Vec<ProjectDto>> {
|
|
let user_id = context.get_user_id().ok_or(anyhow::anyhow!("no user id"))?;
|
|
|
|
Ok(self
|
|
.project_store
|
|
.lock()
|
|
.await
|
|
.values()
|
|
.filter(|p| p.user_id == user_id)
|
|
.cloned()
|
|
.collect::<_>())
|
|
}
|
|
|
|
async fn create_project(
|
|
&self,
|
|
context: &Context,
|
|
mutation: CreateProjectMutation,
|
|
) -> anyhow::Result<ProjectDto> {
|
|
let user_id = context.get_user_id().ok_or(anyhow::anyhow!("no user id"))?;
|
|
|
|
let mut ps = self.project_store.lock().await;
|
|
let project = ProjectDto {
|
|
id: uuid::Uuid::new_v4(),
|
|
name: mutation.name,
|
|
description: None,
|
|
user_id,
|
|
};
|
|
|
|
ps.insert(project.id.to_string(), project.clone());
|
|
Ok(project)
|
|
}
|
|
}
|