Files
AstralRinth/src/file_hosting/authorization.rs
Aeledfyr 95339a8338 Create a mock file host for dev, Fix mod creation route (#38)
* fix(mod-creation): fix actix server data & mod creation route

* feat(file-host): implement mock file hosting

This implements a mock file hosting system backed by the system's
filesystem.  It mirrors the API of the backblaze integration, but
puts the files directly on disk in the path specified by the
MOCK_FILE_PATH environment variable (defaults to /tmp/modrinth).

The mock file hosting is enabled by default using cargo features
to allow people to work on modrinth without access to a valid
backblaze account and setup.  To enable backblaze, specify the
cargo feature "backblaze" when running, ex. `cargo run --features
backblaze`.

* feat(file-hosting): implement basic backblaze API error handling

* fix(mod-creation): fix extension parsing, use base62 ids for paths
fix(file-hosting): reduce unnecessary allocations

* fix: fix auth with docker mongodb

* fix: fix failing checks

* fix: remove testing files
2020-07-16 21:06:58 -07:00

129 lines
4.1 KiB
Rust

use crate::file_hosting::FileHostingError;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct AuthorizationPermissions {
bucket_id: Option<String>,
bucket_name: Option<String>,
capabilities: Vec<String>,
name_prefix: Option<String>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct AuthorizationData {
pub absolute_minimum_part_size: i32,
pub account_id: String,
pub allowed: AuthorizationPermissions,
pub api_url: String,
pub authorization_token: String,
pub download_url: String,
pub recommended_part_size: i32,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "camelCase")]
pub struct UploadUrlData {
pub bucket_id: String,
pub upload_url: String,
pub authorization_token: String,
}
#[cfg(feature = "backblaze")]
pub async fn authorize_account(
key_id: String,
application_key: String,
) -> Result<AuthorizationData, FileHostingError> {
let combined_key = format!("{}:{}", key_id, application_key);
let formatted_key = format!("Basic {}", base64::encode(combined_key));
let response = reqwest::Client::new()
.get("https://api.backblazeb2.com/b2api/v2/b2_authorize_account")
.header(reqwest::header::CONTENT_TYPE, "application/json")
.header(reqwest::header::AUTHORIZATION, formatted_key)
.send()
.await?;
if response.status().is_success() {
Ok(response.json().await?)
} else {
Err(FileHostingError::BackblazeError(response.json().await?))
}
}
#[cfg(feature = "backblaze")]
pub async fn get_upload_url(
authorization_data: AuthorizationData,
bucket_id: String,
) -> Result<UploadUrlData, FileHostingError> {
let response = reqwest::Client::new()
.post(&format!("{}/b2api/v2/b2_get_upload_url", authorization_data.api_url).to_string())
.header(reqwest::header::CONTENT_TYPE, "application/json")
.header(
reqwest::header::AUTHORIZATION,
authorization_data.authorization_token,
)
.body(
serde_json::json!({
"bucketId": bucket_id,
})
.to_string(),
)
.send()
.await?;
if response.status().is_success() {
Ok(response.json().await?)
} else {
Err(FileHostingError::BackblazeError(response.json().await?))
}
}
#[cfg(not(feature = "backblaze"))]
pub async fn authorize_account(
_key_id: String,
_application_key: String,
) -> Result<AuthorizationData, FileHostingError> {
Ok(AuthorizationData {
absolute_minimum_part_size: 5000000,
account_id: String::from("MOCK_ACCOUNT_ID"),
allowed: AuthorizationPermissions {
bucket_id: None,
bucket_name: None,
capabilities: vec![
String::from("listKeys"),
String::from("writeKeys"),
String::from("deleteKeys"),
String::from("listAllBucketNames"),
String::from("listBuckets"),
String::from("writeBuckets"),
String::from("deleteBuckets"),
String::from("readBuckets"),
String::from("listFiles"),
String::from("readFiles"),
String::from("shareFiles"),
String::from("writeFiles"),
String::from("deleteFiles"),
],
name_prefix: None,
},
api_url: String::from("https://api.example.com"),
authorization_token: String::from("MOCK_AUTH_TOKEN"),
download_url: String::from("https://download.example.com"),
recommended_part_size: 100000000,
})
}
#[cfg(not(feature = "backblaze"))]
pub async fn get_upload_url(
_authorization_data: AuthorizationData,
_bucket_id: String,
) -> Result<UploadUrlData, FileHostingError> {
Ok(UploadUrlData {
bucket_id: String::from("MOCK_BUCKET_ID"),
upload_url: String::from("https://download.example.com"),
authorization_token: String::from("MOCK_AUTH_TOKEN"),
})
}