bucketwarden-server 0.1.0

BucketWarden storage server runtime.
Documentation
use super::*;

impl BucketWarden {
    pub fn console_api_login(
        &mut self,
        request: ConsoleApiLoginRequest,
    ) -> Result<ConsoleApiSession, RuntimeError> {
        self.browser_ui_login(BrowserUiLoginRequest {
            principal_id: request.principal_id,
            shared_secret: request.shared_secret,
        })
    }

    pub fn console_api_identity_providers(&self) -> ConsoleApiIdentityProviderList {
        ConsoleApiIdentityProviderList {
            default_provider_id: "custom-shared-secret".to_string(),
            providers: vec![
                ConsoleApiIdentityProvider {
                    provider_id: "custom-shared-secret".to_string(),
                    label: "Shared secret".to_string(),
                    method: "principal-shared-secret".to_string(),
                    enabled: true,
                    description: "Use a configured BucketWarden principal and shared secret."
                        .to_string(),
                },
                ConsoleApiIdentityProvider {
                    provider_id: "external-oidc".to_string(),
                    label: "External OIDC".to_string(),
                    method: "oidc".to_string(),
                    enabled: false,
                    description:
                        "Reserved provider slot for deployments that configure external OIDC."
                            .to_string(),
                },
            ],
        }
    }

    pub fn console_api_current_user(
        &self,
        access_key_id: &str,
    ) -> Result<ConsoleApiSession, RuntimeError> {
        self.browser_ui_current_user(access_key_id)
    }

    pub fn console_api_logout(&mut self, access_key_id: &str) -> Result<(), RuntimeError> {
        self.browser_ui_logout(access_key_id)
    }

    pub(crate) fn console_api_principal(
        &self,
        access_key_id: &str,
    ) -> Result<String, RuntimeError> {
        Ok(self
            .auth
            .resolve_credential(access_key_id, self.clock_epoch_seconds)?
            .principal_id)
    }

    pub fn console_api_error_envelope(
        &mut self,
        error: &RuntimeError,
        request_id: Option<&str>,
    ) -> ConsoleApiErrorEnvelope {
        let (status, code, retryable) = console_api_error_shape(error);
        ConsoleApiErrorEnvelope {
            code: code.to_string(),
            message: error.to_string(),
            retryable,
            status,
            request_id: request_id
                .map(str::to_string)
                .unwrap_or_else(|| self.next_console_api_request_id()),
        }
    }

    pub(crate) fn next_console_api_request_id(&mut self) -> String {
        let request_id = format!("bwui{:012}", self.next_request);
        self.next_request = self.next_request.saturating_add(1);
        request_id
    }
}

fn console_api_error_shape(error: &RuntimeError) -> (u16, &'static str, bool) {
    match error {
        RuntimeError::Auth(AuthError::ExpiredCredential(_)) | RuntimeError::ExpiredToken(_) => {
            (401, "SessionExpired", false)
        }
        RuntimeError::Auth(AuthError::RevokedCredential(_))
        | RuntimeError::Auth(AuthError::DisabledAccessKey(_)) => (401, "SessionInvalid", false),
        RuntimeError::InvalidToken(_) => (401, "AuthenticationFailed", false),
        RuntimeError::Auth(_) => (401, "AuthenticationFailed", false),
        RuntimeError::AccessDenied { .. } | RuntimeError::OperatorActionDenied { .. } => {
            (403, "PermissionDenied", false)
        }
        RuntimeError::NoSuchBucket(_) => (404, "NoSuchBucket", false),
        RuntimeError::NoSuchKey(_) => (404, "NoSuchKey", false),
        RuntimeError::NoSuchVersion { .. } => (404, "NoSuchVersion", false),
        RuntimeError::InvalidListParameter { .. } => (400, "InvalidListParameter", false),
        RuntimeError::InvalidObjectKey(_) => (400, "InvalidObjectKey", false),
        RuntimeError::InvalidBucketName(_) => (400, "InvalidBucketName", false),
        RuntimeError::QuotaExceeded { .. } => (429, "QuotaExceeded", true),
        RuntimeError::SnapshotIo(_) => (503, "StorageUnavailable", true),
        _ => (400, "InvalidRequest", false),
    }
}