use secrecy::Secret; use serde::{Deserialize, Serialize}; use crate::{ authenticated::UserAuthenticationToken, error::{InstanceError, OperationError}, object::Object, object_backend::ObjectBackend, operation::{GiteratedOperation, OperationState}, repository::{Repository, RepositoryVisibility}, user::{Password, User}, }; use super::Instance; /// An account registration request. /// /// # Authentication /// - Instance Authentication /// - **ONLY ACCEPTED WHEN SAME-INSTANCE** #[derive(Clone, Debug, Serialize, Deserialize)] pub struct RegisterAccountRequest { pub username: String, pub email: Option, pub password: Secret, } impl GiteratedOperation for RegisterAccountRequest { type Success = UserAuthenticationToken; type Failure = InstanceError; } #[derive(Clone, Debug, Serialize, Deserialize)] pub struct RegisterAccountResponse(pub UserAuthenticationToken); /// An authentication token request. /// /// AKA Login Request /// /// # Authentication /// - Instance Authentication /// - Identifies the Instance to issue the token for /// # Authorization /// - Credentials ([`crate::backend::AuthBackend`]-based) /// - Identifies the User account to issue a token for /// - Decrypts user private key to issue to #[derive(Clone, Debug, Serialize, Deserialize)] pub struct AuthenticationTokenRequest { pub instance: Instance, pub username: String, pub password: Secret, } impl GiteratedOperation for AuthenticationTokenRequest { type Success = UserAuthenticationToken; type Failure = InstanceError; } /// An authentication token extension request. /// /// # Authentication /// - Instance Authentication /// - Identifies the Instance to issue the token for /// - User Authentication /// - Authenticates the validity of the token /// # Authorization /// - Token-based /// - Validates authorization using token's authenticity #[derive(Clone, Debug, Serialize, Deserialize)] pub struct TokenExtensionRequest { pub token: UserAuthenticationToken, } impl GiteratedOperation for TokenExtensionRequest { type Success = Option; type Failure = InstanceError; } /// A request to create a repository. /// /// # Authentication /// - Instance Authentication /// - Used to validate User token `issued_for` /// - User Authentication /// - Used to source owning user /// - Used to authorize user token against user's instance /// # Authorization /// - Instance Authorization /// - Used to authorize action using User token requiring a correct `issued_for` and valid issuance from user's instance /// - User Authorization /// - Potential User permissions checks #[derive(Clone, Debug, Serialize, Deserialize)] pub struct RepositoryCreateRequest { pub instance: Option, pub name: String, pub description: Option, pub visibility: RepositoryVisibility, pub default_branch: String, pub owner: User, } impl GiteratedOperation for RepositoryCreateRequest { type Success = Repository; type Failure = InstanceError; } impl + std::fmt::Debug, OS> Object { pub async fn register_account( &mut self, email: Option<&str>, username: &str, password: &Secret, operation_state: &mut OS, ) -> Result> { self.request::( RegisterAccountRequest { username: username.to_string(), email: email.map(|s| s.to_string()), password: password.clone(), }, operation_state, ) .await } pub async fn authentication_token( &mut self, username: &str, password: &Secret, operation_state: &mut OS, ) -> Result> { self.request::( AuthenticationTokenRequest { instance: self.inner.clone(), username: username.to_string(), password: password.clone(), }, operation_state, ) .await } pub async fn authentication_token_for( &mut self, instance: &Instance, username: &str, password: &Secret, operation_state: &mut OS, ) -> Result> { self.request::( AuthenticationTokenRequest { instance: instance.clone(), username: username.to_string(), password: password.clone(), }, operation_state, ) .await } pub async fn token_extension( &mut self, token: &UserAuthenticationToken, operation_state: &mut OS, ) -> Result, OperationError> { self.request::( TokenExtensionRequest { token: token.clone(), }, operation_state, ) .await } pub async fn create_repository( &mut self, instance: &Instance, name: &str, visibility: &RepositoryVisibility, default_branch: &str, owner: &User, operation_state: &mut OS, ) -> Result> { self.request::( RepositoryCreateRequest { instance: Some(instance.clone()), name: name.to_string(), description: None, visibility: visibility.clone(), default_branch: default_branch.to_string(), owner: owner.clone(), }, operation_state, ) .await } }