use proto::auth as proto; use tonic::Status; #[derive(Debug, thiserror::Error)] pub enum KenAuthError { #[error("kenoauth is unavailable: {0}")] Unavailable(String), #[error("kenoauth rejected the request: {0}")] Rejected(String), #[error("kenoauth could not find the requested object")] NotFound, #[error("kenoauth rejected the credential")] Unauthenticated, #[error("kenoauth configuration is invalid: {0}")] Config(String), #[error("kenoauth request failed: {0}")] Internal(String), } impl KenAuthError { pub fn from_status(status: Status) -> Self { match status.code() { tonic::Code::Unavailable | tonic::Code::DeadlineExceeded => { Self::Unavailable(status.message().to_string()) } tonic::Code::Unauthenticated => Self::Unauthenticated, tonic::Code::NotFound => Self::NotFound, tonic::Code::PermissionDenied | tonic::Code::InvalidArgument | tonic::Code::FailedPrecondition | tonic::Code::AlreadyExists | tonic::Code::ResourceExhausted | tonic::Code::Aborted => Self::Rejected(status.message().to_string()), _ => Self::Internal(status.message().to_string()), } } pub fn is_not_found(&self) -> bool { matches!(self, Self::NotFound) } pub fn is_unauthenticated(&self) -> bool { matches!(self, Self::Unauthenticated) } } #[async_trait::async_trait] pub trait AuthApi: Send + Sync { async fn check_health(&self) -> Result<(), KenAuthError>; async fn change_password( &self, user_id: i64, old_password_hash: &str, new_password_hash: &str, keep_session_id: &str, client_ip: &str, ) -> Result; async fn get_mfa_status( &self, user_id: i64, ) -> Result; async fn configure_totp( &self, user_id: i64, name: &str, client_ip: &str, ) -> Result; async fn enable_totp( &self, user_id: i64, code: &str, password_hash: &str, client_ip: &str, ) -> Result; async fn disable_totp( &self, user_id: i64, code: &str, client_ip: &str, ) -> Result; async fn regenerate_recovery_codes( &self, user_id: i64, password_hash: &str, client_ip: &str, ) -> Result; async fn list_user_ssh_keys( &self, user_id: i64, include_revoked: bool, page: proto::common::v1::PageRequest, ) -> Result; async fn add_ssh_key( &self, user_id: i64, name: &str, public_key: &str, description: &str, client_ip: &str, ) -> Result; async fn revoke_ssh_key( &self, user_id: i64, key_id: &str, reason: &str, bump_security_version: bool, ) -> Result; async fn list_user_sessions( &self, user_id: i64, include_revoked: bool, include_expired: bool, page: proto::common::v1::PageRequest, ) -> Result; async fn revoke_user_sessions( &self, user_id: i64, except_session_id: &str, reason: &str, bump_security_version: bool, ) -> Result; async fn get_session( &self, user_id: i64, version: i32, session_id: &str, ) -> Result; async fn delete_account(&self, user_id: i64, reason: &str) -> Result<(), KenAuthError>; async fn cancel_account_deletion(&self, user_id: i64) -> Result<(), KenAuthError>; async fn purge_account(&self, user_id: i64) -> Result<(), KenAuthError>; async fn batch_get_authority_users( &self, user_ids: Vec, ) -> Result, KenAuthError>; async fn get_user_status( &self, user_id: i64, ) -> Result; async fn get_user_public_by_ref( &self, key: proto::common::v1::user_ref::Key, ) -> Result; async fn get_authority_user( &self, user_id: i64, ) -> Result; async fn update_authority_user( &self, user_id: i64, username: Option, displayname: Option, clear_displayname: bool, public_show_email: Option, version: i32, ) -> Result; async fn batch_get_user_public( &self, user_ids: Vec, ) -> Result, KenAuthError>; async fn get_user_public( &self, user_id: i64, ) -> Result; async fn revoke_session( &self, user_id: i64, session_id: &str, reason: &str, ) -> Result<(), KenAuthError>; async fn lookup_ssh_key( &self, public_key: &str, ) -> Result, KenAuthError>; async fn ensure_bot_user( &self, username: &str, displayname: &str, system: bool, ) -> Result; }