You've already forked AstralRinth
forked from didirus/AstralRinth
R2 impl (#466)
* Add Cloudflare R2 impl * Bump actix version * Fix sec issues
This commit is contained in:
@@ -7,16 +7,16 @@ use std::time::Duration;
|
||||
pub async fn connect() -> Result<PgPool, sqlx::Error> {
|
||||
info!("Initializing database connection");
|
||||
let database_url =
|
||||
dotenv::var("DATABASE_URL").expect("`DATABASE_URL` not in .env");
|
||||
dotenvy::var("DATABASE_URL").expect("`DATABASE_URL` not in .env");
|
||||
let pool = PgPoolOptions::new()
|
||||
.min_connections(
|
||||
dotenv::var("DATABASE_MIN_CONNECTIONS")
|
||||
dotenvy::var("DATABASE_MIN_CONNECTIONS")
|
||||
.ok()
|
||||
.and_then(|x| x.parse().ok())
|
||||
.unwrap_or(0),
|
||||
)
|
||||
.max_connections(
|
||||
dotenv::var("DATABASE_MAX_CONNECTIONS")
|
||||
dotenvy::var("DATABASE_MAX_CONNECTIONS")
|
||||
.ok()
|
||||
.and_then(|x| x.parse().ok())
|
||||
.unwrap_or(16),
|
||||
@@ -28,7 +28,7 @@ pub async fn connect() -> Result<PgPool, sqlx::Error> {
|
||||
Ok(pool)
|
||||
}
|
||||
pub async fn check_for_migrations() -> Result<(), sqlx::Error> {
|
||||
let uri = dotenv::var("DATABASE_URL").expect("`DATABASE_URL` not in .env");
|
||||
let uri = dotenvy::var("DATABASE_URL").expect("`DATABASE_URL` not in .env");
|
||||
let uri = uri.as_str();
|
||||
if !Postgres::database_exists(uri).await? {
|
||||
info!("Creating database...");
|
||||
|
||||
@@ -21,7 +21,7 @@ impl FileHost for MockHost {
|
||||
file_bytes: Bytes,
|
||||
) -> Result<UploadFileData, FileHostingError> {
|
||||
let path =
|
||||
std::path::Path::new(&dotenv::var("MOCK_FILE_PATH").unwrap())
|
||||
std::path::Path::new(&dotenvy::var("MOCK_FILE_PATH").unwrap())
|
||||
.join(file_name.replace("../", ""));
|
||||
std::fs::create_dir_all(
|
||||
path.parent().ok_or(FileHostingError::InvalidFilename)?,
|
||||
@@ -49,7 +49,7 @@ impl FileHost for MockHost {
|
||||
file_name: &str,
|
||||
) -> Result<DeleteFileData, FileHostingError> {
|
||||
let path =
|
||||
std::path::Path::new(&dotenv::var("MOCK_FILE_PATH").unwrap())
|
||||
std::path::Path::new(&dotenvy::var("MOCK_FILE_PATH").unwrap())
|
||||
.join(file_name.replace("../", ""));
|
||||
std::fs::remove_file(path)?;
|
||||
|
||||
|
||||
@@ -23,9 +23,15 @@ impl S3Host {
|
||||
) -> Result<S3Host, FileHostingError> {
|
||||
let mut bucket = Bucket::new(
|
||||
bucket_name,
|
||||
Region::Custom {
|
||||
region: bucket_region.to_string(),
|
||||
endpoint: url.to_string(),
|
||||
if bucket_region == "r2" {
|
||||
Region::R2 {
|
||||
account_id: url.to_string(),
|
||||
}
|
||||
} else {
|
||||
Region::Custom {
|
||||
region: bucket_region.to_string(),
|
||||
endpoint: url.to_string(),
|
||||
}
|
||||
},
|
||||
Credentials::new(
|
||||
Some(access_token),
|
||||
|
||||
32
src/main.rs
32
src/main.rs
@@ -49,7 +49,7 @@ pub struct Pepper {
|
||||
|
||||
#[actix_rt::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
dotenv::dotenv().ok();
|
||||
dotenvy::dotenv().ok();
|
||||
env_logger::Builder::from_env(Env::default().default_filter_or("info"))
|
||||
.init();
|
||||
|
||||
@@ -65,11 +65,11 @@ async fn main() -> std::io::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
info!("Starting Labrinth on {}", dotenv::var("BIND_ADDR").unwrap());
|
||||
info!("Starting Labrinth on {}", dotenvy::var("BIND_ADDR").unwrap());
|
||||
|
||||
let search_config = search::SearchConfig {
|
||||
address: dotenv::var("MEILISEARCH_ADDR").unwrap(),
|
||||
key: dotenv::var("MEILISEARCH_KEY").unwrap(),
|
||||
address: dotenvy::var("MEILISEARCH_ADDR").unwrap(),
|
||||
key: dotenvy::var("MEILISEARCH_KEY").unwrap(),
|
||||
};
|
||||
|
||||
if config.reset_indices {
|
||||
@@ -97,25 +97,25 @@ async fn main() -> std::io::Result<()> {
|
||||
.expect("Database connection failed");
|
||||
|
||||
let storage_backend =
|
||||
dotenv::var("STORAGE_BACKEND").unwrap_or_else(|_| "local".to_string());
|
||||
dotenvy::var("STORAGE_BACKEND").unwrap_or_else(|_| "local".to_string());
|
||||
|
||||
let file_host: Arc<dyn file_hosting::FileHost + Send + Sync> =
|
||||
match storage_backend.as_str() {
|
||||
"backblaze" => Arc::new(
|
||||
file_hosting::BackblazeHost::new(
|
||||
&dotenv::var("BACKBLAZE_KEY_ID").unwrap(),
|
||||
&dotenv::var("BACKBLAZE_KEY").unwrap(),
|
||||
&dotenv::var("BACKBLAZE_BUCKET_ID").unwrap(),
|
||||
&dotenvy::var("BACKBLAZE_KEY_ID").unwrap(),
|
||||
&dotenvy::var("BACKBLAZE_KEY").unwrap(),
|
||||
&dotenvy::var("BACKBLAZE_BUCKET_ID").unwrap(),
|
||||
)
|
||||
.await,
|
||||
),
|
||||
"s3" => Arc::new(
|
||||
S3Host::new(
|
||||
&*dotenv::var("S3_BUCKET_NAME").unwrap(),
|
||||
&*dotenv::var("S3_REGION").unwrap(),
|
||||
&*dotenv::var("S3_URL").unwrap(),
|
||||
&*dotenv::var("S3_ACCESS_TOKEN").unwrap(),
|
||||
&*dotenv::var("S3_SECRET").unwrap(),
|
||||
&*dotenvy::var("S3_BUCKET_NAME").unwrap(),
|
||||
&*dotenvy::var("S3_REGION").unwrap(),
|
||||
&*dotenvy::var("S3_URL").unwrap(),
|
||||
&*dotenvy::var("S3_ACCESS_TOKEN").unwrap(),
|
||||
&*dotenvy::var("S3_SECRET").unwrap(),
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
@@ -253,7 +253,7 @@ async fn main() -> std::io::Result<()> {
|
||||
})
|
||||
.with_interval(std::time::Duration::from_secs(60))
|
||||
.with_max_requests(300)
|
||||
.with_ignore_key(dotenv::var("RATE_LIMIT_IGNORE_KEY").ok()),
|
||||
.with_ignore_key(dotenvy::var("RATE_LIMIT_IGNORE_KEY").ok()),
|
||||
)
|
||||
.app_data(web::Data::new(pool.clone()))
|
||||
.app_data(web::Data::new(file_host.clone()))
|
||||
@@ -268,7 +268,7 @@ async fn main() -> std::io::Result<()> {
|
||||
.service(web::scope("updates").configure(routes::updates))
|
||||
.default_service(web::get().to(routes::not_found))
|
||||
})
|
||||
.bind(dotenv::var("BIND_ADDR").unwrap())?
|
||||
.bind(dotenvy::var("BIND_ADDR").unwrap())?
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
@@ -310,7 +310,7 @@ fn check_env_vars() -> bool {
|
||||
|
||||
failed |= check_var::<String>("STORAGE_BACKEND");
|
||||
|
||||
let storage_backend = dotenv::var("STORAGE_BACKEND").ok();
|
||||
let storage_backend = dotenvy::var("STORAGE_BACKEND").ok();
|
||||
match storage_backend.as_deref() {
|
||||
Some("backblaze") => {
|
||||
failed |= check_var::<String>("BACKBLAZE_KEY_ID");
|
||||
|
||||
@@ -70,8 +70,8 @@ pub async fn count_download(
|
||||
let client = reqwest::Client::new();
|
||||
|
||||
client
|
||||
.post(format!("{}downloads", dotenv::var("ARIADNE_URL")?))
|
||||
.header("Modrinth-Admin", dotenv::var("ARIADNE_ADMIN_KEY")?)
|
||||
.post(format!("{}downloads", dotenvy::var("ARIADNE_URL")?))
|
||||
.header("Modrinth-Admin", dotenvy::var("ARIADNE_ADMIN_KEY")?)
|
||||
.json(&json!({
|
||||
"url": download_body.url,
|
||||
"project_id": download_body.hash
|
||||
|
||||
@@ -33,7 +33,7 @@ pub fn config(cfg: &mut ServiceConfig) {
|
||||
#[derive(Error, Debug)]
|
||||
pub enum AuthorizationError {
|
||||
#[error("Environment Error")]
|
||||
Env(#[from] dotenv::Error),
|
||||
Env(#[from] dotenvy::Error),
|
||||
#[error("An unknown database error occured: {0}")]
|
||||
SqlxDatabase(#[from] sqlx::Error),
|
||||
#[error("Database Error: {0}")]
|
||||
@@ -148,7 +148,7 @@ pub async fn init(
|
||||
|
||||
transaction.commit().await?;
|
||||
|
||||
let client_id = dotenv::var("GITHUB_CLIENT_ID")?;
|
||||
let client_id = dotenvy::var("GITHUB_CLIENT_ID")?;
|
||||
let url = format!(
|
||||
"https://github.com/login/oauth/authorize?client_id={}&state={}&scope={}",
|
||||
client_id,
|
||||
@@ -196,8 +196,8 @@ pub async fn auth_callback(
|
||||
.execute(&mut *transaction)
|
||||
.await?;
|
||||
|
||||
let client_id = dotenv::var("GITHUB_CLIENT_ID")?;
|
||||
let client_secret = dotenv::var("GITHUB_CLIENT_SECRET")?;
|
||||
let client_id = dotenvy::var("GITHUB_CLIENT_ID")?;
|
||||
let client_secret = dotenvy::var("GITHUB_CLIENT_SECRET")?;
|
||||
|
||||
let url = format!(
|
||||
"https://github.com/login/oauth/access_token?client_id={}&client_secret={}&code={}",
|
||||
|
||||
@@ -172,7 +172,7 @@ pub fn admin_config(cfg: &mut web::ServiceConfig) {
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum ApiError {
|
||||
#[error("Environment Error")]
|
||||
Env(#[from] dotenv::Error),
|
||||
Env(#[from] dotenvy::Error),
|
||||
#[error("Error while uploading file")]
|
||||
FileHosting(#[from] FileHostingError),
|
||||
#[error("Database Error: {0}")]
|
||||
|
||||
@@ -26,7 +26,7 @@ use validator::Validate;
|
||||
#[derive(Error, Debug)]
|
||||
pub enum CreateError {
|
||||
#[error("Environment Error")]
|
||||
EnvError(#[from] dotenv::Error),
|
||||
EnvError(#[from] dotenvy::Error),
|
||||
#[error("An unknown database error occurred")]
|
||||
SqlxDatabaseError(#[from] sqlx::Error),
|
||||
#[error("Database Error: {0}")]
|
||||
@@ -324,7 +324,7 @@ pub async fn project_create_inner(
|
||||
uploaded_files: &mut Vec<UploadedFile>,
|
||||
) -> Result<HttpResponse, CreateError> {
|
||||
// The base URL for files uploaded to backblaze
|
||||
let cdn_url = dotenv::var("CDN_URL")?;
|
||||
let cdn_url = dotenvy::var("CDN_URL")?;
|
||||
|
||||
// The currently logged in user
|
||||
let current_user =
|
||||
@@ -793,7 +793,7 @@ pub async fn project_create_inner(
|
||||
let _project_id = project_builder.insert(&mut *transaction).await?;
|
||||
|
||||
if status == ProjectStatus::Processing {
|
||||
if let Ok(webhook_url) = dotenv::var("MODERATION_DISCORD_WEBHOOK") {
|
||||
if let Ok(webhook_url) = dotenvy::var("MODERATION_DISCORD_WEBHOOK") {
|
||||
crate::util::webhook::send_discord_webhook(
|
||||
response.clone(),
|
||||
webhook_url,
|
||||
|
||||
@@ -478,7 +478,7 @@ pub async fn project_edit(
|
||||
.await?;
|
||||
|
||||
if let Ok(webhook_url) =
|
||||
dotenv::var("MODERATION_DISCORD_WEBHOOK")
|
||||
dotenvy::var("MODERATION_DISCORD_WEBHOOK")
|
||||
{
|
||||
crate::util::webhook::send_discord_webhook(
|
||||
Project::from(project_item.clone()),
|
||||
@@ -1008,7 +1008,7 @@ pub async fn project_icon_edit(
|
||||
if let Some(content_type) =
|
||||
crate::util::ext::get_image_content_type(&*ext.ext)
|
||||
{
|
||||
let cdn_url = dotenv::var("CDN_URL")?;
|
||||
let cdn_url = dotenvy::var("CDN_URL")?;
|
||||
let user = get_user_from_headers(req.headers(), &**pool).await?;
|
||||
let string = info.into_inner().0;
|
||||
|
||||
@@ -1136,7 +1136,7 @@ pub async fn delete_project_icon(
|
||||
}
|
||||
}
|
||||
|
||||
let cdn_url = dotenv::var("CDN_URL")?;
|
||||
let cdn_url = dotenvy::var("CDN_URL")?;
|
||||
if let Some(icon) = project_item.icon_url {
|
||||
let name = icon.split(&format!("{cdn_url}/")).nth(1);
|
||||
|
||||
@@ -1189,7 +1189,7 @@ pub async fn add_gallery_item(
|
||||
ApiError::Validation(validation_errors_to_string(err, None))
|
||||
})?;
|
||||
|
||||
let cdn_url = dotenv::var("CDN_URL")?;
|
||||
let cdn_url = dotenvy::var("CDN_URL")?;
|
||||
let user = get_user_from_headers(req.headers(), &**pool).await?;
|
||||
let string = info.into_inner().0;
|
||||
|
||||
@@ -1490,7 +1490,7 @@ pub async fn delete_gallery_item(
|
||||
})?
|
||||
.id;
|
||||
|
||||
let cdn_url = dotenv::var("CDN_URL")?;
|
||||
let cdn_url = dotenvy::var("CDN_URL")?;
|
||||
let name = item.url.split(&format!("{cdn_url}/")).nth(1);
|
||||
|
||||
if let Some(icon_path) = name {
|
||||
|
||||
@@ -53,7 +53,7 @@ pub async fn forge_updates(
|
||||
let mut response = ForgeUpdates {
|
||||
homepage: format!(
|
||||
"{}/mod/{}",
|
||||
dotenv::var("SITE_URL").unwrap_or_default(),
|
||||
dotenvy::var("SITE_URL").unwrap_or_default(),
|
||||
id
|
||||
),
|
||||
promos: HashMap::new(),
|
||||
|
||||
@@ -328,7 +328,7 @@ pub async fn user_icon_edit(
|
||||
if let Some(content_type) =
|
||||
crate::util::ext::get_image_content_type(&*ext.ext)
|
||||
{
|
||||
let cdn_url = dotenv::var("CDN_URL")?;
|
||||
let cdn_url = dotenvy::var("CDN_URL")?;
|
||||
let user = get_user_from_headers(req.headers(), &**pool).await?;
|
||||
let id_option =
|
||||
crate::database::models::User::get_id_from_username_or_id(
|
||||
|
||||
@@ -112,7 +112,7 @@ async fn version_create_inner(
|
||||
file_host: &dyn FileHost,
|
||||
uploaded_files: &mut Vec<UploadedFile>,
|
||||
) -> Result<HttpResponse, CreateError> {
|
||||
let cdn_url = dotenv::var("CDN_URL")?;
|
||||
let cdn_url = dotenvy::var("CDN_URL")?;
|
||||
|
||||
let mut initial_version_data = None;
|
||||
let mut version_builder = None;
|
||||
@@ -483,7 +483,7 @@ async fn upload_file_to_version_inner(
|
||||
uploaded_files: &mut Vec<UploadedFile>,
|
||||
version_id: models::VersionId,
|
||||
) -> Result<HttpResponse, CreateError> {
|
||||
let cdn_url = dotenv::var("CDN_URL")?;
|
||||
let cdn_url = dotenvy::var("CDN_URL")?;
|
||||
|
||||
let mut initial_file_data: Option<InitialFileData> = None;
|
||||
let mut file_builders: Vec<VersionFileBuilder> = Vec::new();
|
||||
|
||||
@@ -20,7 +20,7 @@ pub enum IndexingError {
|
||||
#[error("Database Error: {0}")]
|
||||
Database(#[from] crate::database::models::DatabaseError),
|
||||
#[error("Environment Error")]
|
||||
Env(#[from] dotenv::Error),
|
||||
Env(#[from] dotenvy::Error),
|
||||
#[error("Error while awaiting index creation task")]
|
||||
Task,
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ pub enum SearchError {
|
||||
#[error("Error while formatting strings: {0}")]
|
||||
FormatError(#[from] std::fmt::Error),
|
||||
#[error("Environment Error")]
|
||||
Env(#[from] dotenv::Error),
|
||||
Env(#[from] dotenvy::Error),
|
||||
#[error("Invalid index to sort by: {0}")]
|
||||
InvalidIndex(String),
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
pub fn parse_var<T: FromStr>(var: &'static str) -> Option<T> {
|
||||
dotenv::var(var).ok().and_then(|i| i.parse().ok())
|
||||
dotenvy::var(var).ok().and_then(|i| i.parse().ok())
|
||||
}
|
||||
pub fn parse_strings_from_var(var: &'static str) -> Option<Vec<String>> {
|
||||
dotenv::var(var)
|
||||
dotenvy::var(var)
|
||||
.ok()
|
||||
.and_then(|s| serde_json::from_str::<Vec<String>>(&s).ok())
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ pub async fn send_discord_webhook(
|
||||
let embed = DiscordEmbed {
|
||||
url: format!(
|
||||
"{}/{}/{}",
|
||||
dotenv::var("SITE_URL").unwrap_or_default(),
|
||||
dotenvy::var("SITE_URL").unwrap_or_default(),
|
||||
project.project_type,
|
||||
project
|
||||
.clone()
|
||||
|
||||
Reference in New Issue
Block a user