use crate::user::User; use derive_more::{Display, Error}; use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)] pub struct Project { id: usize, name: String, description: Option, members: Vec, } pub mod services { use super::*; pub fn get_projects_belonging_to_user( project_adapter: &dyn SecondaryPortProject, owner: &User, ) -> ProjectResult> { project_adapter.get_projects_belonging_to_user(owner.id()) } pub fn create( project_adapter: &dyn SecondaryPortProject, owner: User, name: String, description: Option, ) -> ProjectResult { let id = project_adapter.create_project(&name, description.as_deref(), owner.id())?; Ok(Project::new(id, name, description, vec![owner])) } fn doer_is_member( project_adapter: &dyn SecondaryPortProject, project_id: usize, doer: &User, ) -> ProjectResult { let p = project_adapter.get_project_by_id(project_id)?; Ok(p.doer_is_member(doer)) } pub fn update_description( project_adapter: &dyn SecondaryPortProject, project_id: usize, doer: &User, new_description: String, ) -> ProjectResult { if doer_is_member(project_adapter, project_id, doer)? { let mut p = project_adapter.get_project_by_id(project_id)?; project_adapter.update_description(p.id, &new_description)?; p.update_description(new_description); Ok(p) } else { Err(ProjectError::Unauthorized) } } } impl Project { // getters pub fn id(&self) -> usize { self.id } pub fn name(&self) -> &str { &self.name } pub fn description(&self) -> Option<&str> { self.description.as_deref() } pub fn email(&self) -> &[User] { &self.members } fn new(id: usize, name: String, description: Option, members: Vec) -> Self { Self { id, name, description, members, } } fn update_description(&mut self, new_description: String) { self.description = Some(new_description) } fn doer_is_member(&self, doer: &User) -> bool { self.members.contains(doer) } pub fn load(id: usize, name: String, description: Option, members: Vec) -> Self { Self::new(id, name, description, members) } } pub type ProjectResult = Result; #[derive(Debug, Display, Error)] pub enum ProjectError { Unauthorized, } pub trait SecondaryPortProject { // returns ID of newly created Project fn create_project( &self, name: &str, description: Option<&str>, owner_id: usize, ) -> ProjectResult; fn update_description(&self, id: usize, new_description: &str) -> ProjectResult; // get user from DB fn get_project_by_id(&self, id: usize) -> ProjectResult; fn get_projects_belonging_to_user(&self, user_id: usize) -> ProjectResult>; }