/* Module `ports` specifies the API by which external modules interact with the user domain. All traits are bounded by `Send + Sync + 'static`, since their implementations must be shareable between request-handling threads. Trait methods are explicitly asynchronous, including `Send` bounds on response types, since the application is expected to always run in a multithreaded environment. */ use std::future::Future; use super::models::user::*; /// `ApiService` is the public API for the user domain. /// /// External modules must conform to this contract – the domain is not concerned with the /// implementation details or underlying technology of any external code. pub trait ApiService: Clone + Send + Sync + 'static { /// Asynchronously create a new [User]. /// /// # Errors /// /// - [CreateUserError::Duplicate] if an [User] with the same [EmailAddress] already exists. fn create_user( &self, req: CreateUserRequest, ) -> impl Future> + Send; // fn activate_user fn get_user_session( &self, session: &axum_session::SessionAnySession, // TODO: Get rid of this and make cleaner ) -> impl Future> + Send; fn activate_user_account( &self, token: ActivationToken, ) -> impl Future> + Send; fn user_login( &self, req: UserLoginRequest, ) -> impl Future> + Send; fn forgot_password(&self, email: &EmailAddress) -> impl Future + Send; fn reset_password( &self, token: &PasswordResetToken, password: &Password, ) -> impl Future> + Send; fn find_user_by_password_reset_token( &self, token: &PasswordResetToken, ) -> impl Future> + Send; // These shouldnt be here, _why_ are they here, and implement that here instead // fn find_user_by_email(self, email: EmailAddress) -> impl Future> + Send; // fn find_user_by_id(&self, user_id: uuid::Uuid) -> impl Future> + Send; } pub trait UserRepository: Clone + Send + Sync + 'static { // Create fn create_user( &self, req: CreateUserRequest, ) -> impl Future> + Send; fn create_activation_token( &self, ent: &User, ) -> impl Future> + Send; fn create_password_reset_token( &self, ent: &User, ) -> impl Future> + Send; // Read fn all_users(&self) -> impl Future> + Send; fn find_user_by_id( &self, id: uuid::Uuid, ) -> impl Future, anyhow::Error>> + Send; fn find_user_by_email( &self, email: &EmailAddress, ) -> impl Future, anyhow::Error>> + Send; fn find_user_by_activation_token( &self, token: &ActivationToken, ) -> impl Future, anyhow::Error>> + Send; fn find_user_by_password_reset_token( &self, token: &PasswordResetToken, ) -> impl Future, anyhow::Error>> + Send; // // Update fn update_user( &self, ent: &User, req: UpdateUserRequest, ) -> impl Future> + Send; // Delete // fn delete_user(&self, ent: User) -> impl Future> + Send; fn delete_activation_token_for_user( &self, ent: &User, ) -> impl Future> + Send; fn delete_password_reset_tokens_for_user( &self, ent: &User, ) -> impl Future> + Send; } pub trait UserNotifier: Clone + Send + Sync + 'static { fn user_created(&self, user: &User, token: &ActivationToken) -> impl Future + Send; fn forgot_password( &self, user: &User, token: &PasswordResetToken, ) -> impl Future + Send; }