44c6130
ZhenYi
refactor: update database handling and introduce BlobStore trait for improved abstraction and flexibility
44c6130
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<proto::v1::ChangePasswordResponse, KenAuthError>;
async fn get_mfa_status(
&self,
user_id: i64,
) -> Result<proto::v1::GetMfaStatusResponse, KenAuthError>;
async fn configure_totp(
&self,
user_id: i64,
name: &str,
client_ip: &str,
) -> Result<proto::v1::ConfigureTotpResponse, KenAuthError>;
async fn enable_totp(
&self,
user_id: i64,
code: &str,
password_hash: &str,
client_ip: &str,
) -> Result<proto::v1::EnableTotpResponse, KenAuthError>;
async fn disable_totp(
&self,
user_id: i64,
code: &str,
client_ip: &str,
) -> Result<proto::v1::DisableTotpResponse, KenAuthError>;
async fn regenerate_recovery_codes(
&self,
user_id: i64,
password_hash: &str,
client_ip: &str,
) -> Result<proto::v1::RegenerateRecoveryCodesResponse, KenAuthError>;
async fn list_user_ssh_keys(
&self,
user_id: i64,
include_revoked: bool,
page: proto::common::v1::PageRequest,
) -> Result<proto::v1::ListUserSshKeysResponse, KenAuthError>;
async fn add_ssh_key(
&self,
user_id: i64,
name: &str,
public_key: &str,
description: &str,
client_ip: &str,
) -> Result<proto::v1::AddSshKeyResponse, KenAuthError>;
async fn revoke_ssh_key(
&self,
user_id: i64,
key_id: &str,
reason: &str,
bump_security_version: bool,
) -> Result<proto::v1::RevokeSshKeyResponse, KenAuthError>;
async fn list_user_sessions(
&self,
user_id: i64,
include_revoked: bool,
include_expired: bool,
page: proto::common::v1::PageRequest,
) -> Result<proto::v1::ListUserSessionsResponse, KenAuthError>;
async fn revoke_user_sessions(
&self,
user_id: i64,
except_session_id: &str,
reason: &str,
bump_security_version: bool,
) -> Result<proto::v1::RevokeUserSessionsResponse, KenAuthError>;
async fn get_session(
&self,
user_id: i64,
version: i32,
session_id: &str,
) -> Result<proto::internal::v1::AuthorityAccess, KenAuthError>;
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<i64>,
) -> Result<Vec<proto::internal::v1::AuthorityUser>, KenAuthError>;
async fn get_user_status(
&self,
user_id: i64,
) -> Result<proto::common::v1::UserStatus, KenAuthError>;
async fn get_user_public_by_ref(
&self,
key: proto::common::v1::user_ref::Key,
) -> Result<proto::common::v1::UserPublic, KenAuthError>;
async fn get_authority_user(
&self,
user_id: i64,
) -> Result<proto::internal::v1::AuthorityUser, KenAuthError>;
async fn update_authority_user(
&self,
user_id: i64,
username: Option<String>,
displayname: Option<String>,
clear_displayname: bool,
public_show_email: Option<bool>,
version: i32,
) -> Result<proto::internal::v1::AuthorityUser, KenAuthError>;
async fn batch_get_user_public(
&self,
user_ids: Vec<i64>,
) -> Result<Vec<proto::common::v1::UserPublic>, KenAuthError>;
async fn get_user_public(
&self,
user_id: i64,
) -> Result<proto::common::v1::UserPublic, KenAuthError>;
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<Option<proto::common::v1::Principal>, KenAuthError>;
async fn ensure_bot_user(
&self,
username: &str,
displayname: &str,
system: bool,
) -> Result<proto::common::v1::UserPublic, KenAuthError>;
async fn ensure_bot_member(
&self,
organization_id: &str,
user_id: i64,
role_keys: Vec<String>,
role_ids: Vec<String>,
) -> Result<proto::v1::OrganizationMemberInfo, KenAuthError>;
async fn get_organization(
&self,
actor_user_id: i64,
organization_id: &str,
slug: &str,
) -> Result<proto::v1::GetOrganizationResponse, KenAuthError>;
async fn get_member(
&self,
actor_user_id: i64,
organization_id: &str,
user_id: i64,
) -> Result<Option<proto::v1::OrganizationMemberInfo>, KenAuthError>;
async fn list_members(
&self,
actor_user_id: i64,
organization_id: &str,
include_inactive: bool,
include_banned: bool,
page: proto::common::v1::PageRequest,
) -> Result<proto::v1::ListMembersResponse, KenAuthError>;
async fn list_organizations(
&self,
actor_user_id: i64,
user_id: i64,
include_archived: bool,
page: proto::common::v1::PageRequest,
) -> Result<proto::v1::ListOrganizationsResponse, KenAuthError>;
async fn list_public_organizations(
&self,
query: &str,
page: proto::common::v1::PageRequest,
) -> Result<proto::v1::ListPublicOrganizationsResponse, KenAuthError>;
async fn check_permissions(
&self,
actor_user_id: i64,
organization_id: &str,
user_id: i64,
permissions: Vec<String>,
) -> Result<proto::v1::CheckPermissionsResponse, KenAuthError>;
async fn create_organization(
&self,
actor_user_id: i64,
slug: &str,
name: &str,
description: &str,
avatar_url: &str,
join_policy: Option<i32>,
allow_join: Option<bool>,
require_email_verified: Option<bool>,
require_mfa: Option<bool>,
welcome_message: Option<String>,
member_must_enable_2fa: Option<bool>,
allow_invite: Option<bool>,
allow_join_level: Option<i32>,
) -> Result<proto::v1::CreateOrganizationResponse, KenAuthError>;
async fn update_organization(
&self,
actor_user_id: i64,
organization_id: &str,
name: Option<String>,
description: Option<String>,
avatar_url: Option<String>,
expected_version: i32,
join_policy: Option<i32>,
allow_join: Option<bool>,
require_email_verified: Option<bool>,
require_mfa: Option<bool>,
welcome_message: Option<String>,
member_must_enable_2fa: Option<bool>,
allow_invite: Option<bool>,
allow_join_level: Option<i32>,
) -> Result<proto::v1::OrganizationInfo, KenAuthError>;
async fn archive_organization(
&self,
actor_user_id: i64,
organization_id: &str,
reason: &str,
) -> Result<(), KenAuthError>;
async fn restore_organization(
&self,
actor_user_id: i64,
organization_id: &str,
) -> Result<(), KenAuthError>;
async fn delete_organization(
&self,
actor_user_id: i64,
organization_id: &str,
force: bool,
reason: &str,
) -> Result<(), KenAuthError>;
async fn add_member(
&self,
actor_user_id: i64,
organization_id: &str,
user_id: i64,
role: i32,
role_keys: Vec<String>,
) -> Result<(proto::v1::OrganizationMemberInfo, bool), KenAuthError>;
async fn remove_member(
&self,
actor_user_id: i64,
organization_id: &str,
user_id: i64,
reason: &str,
) -> Result<bool, KenAuthError>;
async fn leave_organization(
&self,
actor_user_id: i64,
organization_id: &str,
) -> Result<bool, KenAuthError>;
async fn update_member(
&self,
actor_user_id: i64,
organization_id: &str,
user_id: i64,
alias_name: Option<Option<String>>,
alias_avatar_url: Option<Option<String>>,
message_notifications: Option<String>,
muted: Option<bool>,
mute_until: Option<Option<prost_types::Timestamp>>,
mobile_push: Option<bool>,
suppress_everyone: Option<bool>,
suppress_roles: Option<bool>,
hide_muted_channels: Option<bool>,
) -> Result<proto::v1::OrganizationMemberInfo, KenAuthError>;
async fn ban_member(
&self,
actor_user_id: i64,
organization_id: &str,
user_id: i64,
reason: &str,
) -> Result<proto::v1::OrganizationMemberInfo, KenAuthError>;
async fn unban_member(
&self,
actor_user_id: i64,
organization_id: &str,
user_id: i64,
) -> Result<proto::v1::OrganizationMemberInfo, KenAuthError>;
async fn update_ban(
&self,
actor_user_id: i64,
organization_id: &str,
user_id: i64,
reason: Option<Option<String>>,
expires_at: Option<Option<prost_types::Timestamp>>,
allow_speak: Option<bool>,
allow_push_repo: Option<bool>,
allow_comment_any: Option<bool>,
) -> Result<proto::v1::OrganizationMemberInfo, KenAuthError>;
async fn create_role(
&self,
actor_user_id: i64,
organization_id: &str,
key: &str,
name: &str,
description: &str,
rank: i32,
self_assignable: bool,
permissions: Vec<String>,
) -> Result<proto::v1::OrganizationRoleInfo, KenAuthError>;
async fn update_role(
&self,
actor_user_id: i64,
organization_id: &str,
role_id: &str,
name: Option<String>,
description: Option<String>,
rank: Option<i32>,
self_assignable: Option<bool>,
expected_version: i32,
) -> Result<proto::v1::OrganizationRoleInfo, KenAuthError>;
async fn set_role_permissions(
&self,
actor_user_id: i64,
organization_id: &str,
role_id: &str,
permissions: Vec<String>,
) -> Result<proto::v1::OrganizationRoleInfo, KenAuthError>;
async fn delete_role(
&self,
actor_user_id: i64,
organization_id: &str,
role_id: &str,
) -> Result<bool, KenAuthError>;
async fn assign_role(
&self,
actor_user_id: i64,
organization_id: &str,
user_id: i64,
role_id: &str,
) -> Result<proto::v1::OrganizationMemberInfo, KenAuthError>;
async fn unassign_role(
&self,
actor_user_id: i64,
organization_id: &str,
user_id: i64,
role_id: &str,
) -> Result<proto::v1::OrganizationMemberInfo, KenAuthError>;
async fn create_invite(
&self,
actor_user_id: i64,
organization_id: &str,
method: i32,
max_uses: i32,
expires_at: Option<prost_types::Timestamp>,
role_ids: Vec<String>,
target_user_id: i64,
email: &str,
) -> Result<(proto::v1::OrganizationInviteInfo, String), KenAuthError>;
async fn revoke_invite(
&self,
actor_user_id: i64,
organization_id: &str,
invite_id: &str,
) -> Result<bool, KenAuthError>;
async fn redeem_invite(
&self,
actor_user_id: i64,
token: &str,
) -> Result<proto::v1::RedeemInviteResponse, KenAuthError>;
async fn create_join_rule(
&self,
actor_user_id: i64,
organization_id: &str,
role_id: &str,
trigger: &str,
matcher: &str,
enabled: bool,
) -> Result<proto::v1::JoinRuleInfo, KenAuthError>;
async fn update_join_rule(
&self,
actor_user_id: i64,
organization_id: &str,
rule_id: &str,
role_id: Option<String>,
trigger: Option<String>,
matcher: Option<String>,
enabled: Option<bool>,
) -> Result<proto::v1::JoinRuleInfo, KenAuthError>;
async fn delete_join_rule(
&self,
actor_user_id: i64,
organization_id: &str,
rule_id: &str,
) -> Result<bool, KenAuthError>;
async fn create_join_request(
&self,
actor_user_id: i64,
organization_id: &str,
note: &str,
) -> Result<proto::v1::JoinRequestInfo, KenAuthError>;
async fn withdraw_join_request(
&self,
actor_user_id: i64,
organization_id: &str,
request_id: &str,
) -> Result<proto::v1::JoinRequestInfo, KenAuthError>;
async fn approve_join_request(
&self,
actor_user_id: i64,
organization_id: &str,
request_id: &str,
) -> Result<
(
proto::v1::JoinRequestInfo,
Option<proto::v1::OrganizationMemberInfo>,
),
KenAuthError,
>;
async fn reject_join_request(
&self,
actor_user_id: i64,
organization_id: &str,
request_id: &str,
note: &str,
) -> Result<proto::v1::JoinRequestInfo, KenAuthError>;
}