Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
/.github
/.gitignore
/.vscode
/data_v2.db*
/data.db*
/bin/
/config-idx-back.toml.local
/config-tracker.toml.local
/config-idx-back.local.toml
/config-tracker.local.toml
/config.toml
/config.toml.local
/cspell.json
/data_v2.db*
/data.db
/data.db*
/docker/
/project-words.txt
/README.md
Expand Down
File renamed without changes.
File renamed without changes.
6 changes: 3 additions & 3 deletions docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ docker run -it \

### With docker-compose

The docker-compose configuration includes the MySQL service configuration. If you want to use MySQL instead of SQLite you have to change your `config.toml` or `config-idx-back.toml.local` configuration from:
The docker-compose configuration includes the MySQL service configuration. If you want to use MySQL instead of SQLite you have to change your `config.toml` or `config-idx-back.local.toml` configuration from:

```toml
connect_url = "sqlite://storage/database/data.db?mode=rwc"
Expand All @@ -64,8 +64,8 @@ Build and run it locally:

```s
TORRUST_IDX_BACK_USER_UID=${TORRUST_IDX_BACK_USER_UID:-1000} \
TORRUST_IDX_BACK_CONFIG=$(cat config-idx-back.toml.local) \
TORRUST_TRACKER_CONFIG=$(cat config-tracker.toml.local) \
TORRUST_IDX_BACK_CONFIG=$(cat config-idx-back.local.toml) \
TORRUST_TRACKER_CONFIG=$(cat config-tracker.local.toml) \
TORRUST_TRACKER_API_TOKEN=${TORRUST_TRACKER_API_TOKEN:-MyAccessToken} \
docker compose up -d --build
```
Expand Down
4 changes: 2 additions & 2 deletions docker/bin/e2e-env-up.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ TORRUST_IDX_BACK_USER_UID=${TORRUST_IDX_BACK_USER_UID:-1000} \
docker compose build

TORRUST_IDX_BACK_USER_UID=${TORRUST_IDX_BACK_USER_UID:-1000} \
TORRUST_IDX_BACK_CONFIG=$(cat config-idx-back.toml.local) \
TORRUST_TRACKER_CONFIG=$(cat config-tracker.toml.local) \
TORRUST_IDX_BACK_CONFIG=$(cat config-idx-back.local.toml) \
TORRUST_TRACKER_CONFIG=$(cat config-tracker.local.toml) \
TORRUST_TRACKER_API_TOKEN=${TORRUST_TRACKER_API_TOKEN:-MyAccessToken} \
docker compose up -d
23 changes: 16 additions & 7 deletions src/bootstrap/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
//! Initialize configuration from file or env var.
//!
//! All environment variables are prefixed with `TORRUST_IDX_BACK_`.
use std::env;

pub const CONFIG_PATH: &str = "./config.toml";
pub const CONFIG_ENV_VAR_NAME: &str = "TORRUST_IDX_BACK_CONFIG";
// Environment variables

/// The whole `config.toml` file content. It has priority over the config file.
pub const ENV_VAR_CONFIG: &str = "TORRUST_IDX_BACK_CONFIG";

// Default values

pub const ENV_VAR_DEFAULT_CONFIG_PATH: &str = "./config.toml";

use crate::config::Configuration;

Expand All @@ -11,14 +20,14 @@ use crate::config::Configuration;
///
/// Will panic if configuration is not found or cannot be parsed
pub async fn init_configuration() -> Configuration {
if env::var(CONFIG_ENV_VAR_NAME).is_ok() {
println!("Loading configuration from env var `{}`", CONFIG_ENV_VAR_NAME);
if env::var(ENV_VAR_CONFIG).is_ok() {
println!("Loading configuration from env var `{}`", ENV_VAR_CONFIG);

Configuration::load_from_env_var(CONFIG_ENV_VAR_NAME).unwrap()
Configuration::load_from_env_var(ENV_VAR_CONFIG).unwrap()
} else {
println!("Loading configuration from config file `{}`", CONFIG_PATH);
println!("Loading configuration from config file `{}`", ENV_VAR_DEFAULT_CONFIG_PATH);

match Configuration::load_from_file(CONFIG_PATH).await {
match Configuration::load_from_file(ENV_VAR_DEFAULT_CONFIG_PATH).await {
Ok(config) => config,
Err(error) => {
panic!("{}", error)
Expand Down
7 changes: 5 additions & 2 deletions src/routes/settings.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use actix_web::{web, HttpRequest, HttpResponse, Responder};

use crate::bootstrap::config::CONFIG_PATH;
use crate::bootstrap::config::ENV_VAR_DEFAULT_CONFIG_PATH;
use crate::common::WebAppData;
use crate::config::TorrustConfig;
use crate::errors::{ServiceError, ServiceResult};
Expand Down Expand Up @@ -60,7 +60,10 @@ pub async fn update_settings(
return Err(ServiceError::Unauthorized);
}

let _ = app_data.cfg.update_settings(payload.into_inner(), CONFIG_PATH).await;
let _ = app_data
.cfg
.update_settings(payload.into_inner(), ENV_VAR_DEFAULT_CONFIG_PATH)
.await;

let settings = app_data.cfg.settings.read().await;

Expand Down
7 changes: 5 additions & 2 deletions tests/common/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use serde::Serialize;

use super::connection_info::ConnectionInfo;
use super::contexts::category::forms::{AddCategoryForm, DeleteCategoryForm};
use super::contexts::settings::form::UpdateSettingsForm;
use super::contexts::settings::form::UpdateSettings;
use super::contexts::torrent::forms::UpdateTorrentFrom;
use super::contexts::torrent::requests::TorrentId;
use super::contexts::user::forms::{LoginForm, RegistrationForm, TokenRenewalForm, TokenVerificationForm, Username};
Expand All @@ -16,6 +16,9 @@ pub struct Client {
}

impl Client {
// todo: forms in POST requests can be passed by reference. It's already
// changed for the `update_settings` method.

pub fn unauthenticated(bind_address: &str) -> Self {
Self::new(ConnectionInfo::anonymous(bind_address))
}
Expand Down Expand Up @@ -80,7 +83,7 @@ impl Client {
self.http_client.get("settings", Query::empty()).await
}

pub async fn update_settings(&self, update_settings_form: UpdateSettingsForm) -> TextResponse {
pub async fn update_settings(&self, update_settings_form: &UpdateSettings) -> TextResponse {
self.http_client.post("settings", &update_settings_form).await
}

Expand Down
2 changes: 1 addition & 1 deletion tests/common/contexts/settings/form.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
use super::Settings;

pub type UpdateSettingsForm = Settings;
pub type UpdateSettings = Settings;
125 changes: 108 additions & 17 deletions tests/common/contexts/settings/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,28 @@ pub mod form;
pub mod responses;

use serde::{Deserialize, Serialize};
use torrust_index_backend::config::{
Auth as DomainAuth, Database as DomainDatabase, ImageCache as DomainImageCache, Mail as DomainMail, Network as DomainNetwork,
TorrustConfig as DomainSettings, Tracker as DomainTracker, Website as DomainWebsite,
};

#[derive(Deserialize, Serialize, PartialEq, Debug)]
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
pub struct Settings {
pub website: Website,
pub tracker: Tracker,
pub net: Net,
pub net: Network,
pub auth: Auth,
pub database: Database,
pub mail: Mail,
pub image_cache: ImageCache,
}

#[derive(Deserialize, Serialize, PartialEq, Debug)]
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
pub struct Website {
pub name: String,
}

#[derive(Deserialize, Serialize, PartialEq, Debug)]
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
pub struct Tracker {
pub url: String,
pub mode: String,
Expand All @@ -28,42 +32,129 @@ pub struct Tracker {
pub token_valid_seconds: u64,
}

#[derive(Deserialize, Serialize, PartialEq, Debug)]
pub struct Net {
pub port: u64,
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
pub struct Network {
pub port: u16,
pub base_url: Option<String>,
}

#[derive(Deserialize, Serialize, PartialEq, Debug)]
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
pub struct Auth {
pub email_on_signup: String,
pub min_password_length: u64,
pub max_password_length: u64,
pub min_password_length: usize,
pub max_password_length: usize,
pub secret_key: String,
}

#[derive(Deserialize, Serialize, PartialEq, Debug)]
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
pub struct Database {
pub connect_url: String,
pub torrent_info_update_interval: u64,
}

#[derive(Deserialize, Serialize, PartialEq, Debug)]
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
pub struct Mail {
pub email_verification_enabled: bool,
pub from: String,
pub reply_to: String,
pub username: String,
pub password: String,
pub server: String,
pub port: u64,
pub port: u16,
}

#[derive(Deserialize, Serialize, PartialEq, Debug)]
#[derive(Deserialize, Serialize, PartialEq, Debug, Clone)]
pub struct ImageCache {
pub max_request_timeout_ms: u64,
pub capacity: u64,
pub entry_size_limit: u64,
pub capacity: usize,
pub entry_size_limit: usize,
pub user_quota_period_seconds: u64,
pub user_quota_bytes: u64,
pub user_quota_bytes: usize,
}

impl From<DomainSettings> for Settings {
fn from(settings: DomainSettings) -> Self {
Settings {
website: Website::from(settings.website),
tracker: Tracker::from(settings.tracker),
net: Network::from(settings.net),
auth: Auth::from(settings.auth),
database: Database::from(settings.database),
mail: Mail::from(settings.mail),
image_cache: ImageCache::from(settings.image_cache),
}
}
}

impl From<DomainWebsite> for Website {
fn from(website: DomainWebsite) -> Self {
Website { name: website.name }
}
}

impl From<DomainTracker> for Tracker {
fn from(tracker: DomainTracker) -> Self {
Tracker {
url: tracker.url,
mode: format!("{:?}", tracker.mode),
api_url: tracker.api_url,
token: tracker.token,
token_valid_seconds: tracker.token_valid_seconds,
}
}
}

impl From<DomainNetwork> for Network {
fn from(net: DomainNetwork) -> Self {
Network {
port: net.port,
base_url: net.base_url,
}
}
}

impl From<DomainAuth> for Auth {
fn from(auth: DomainAuth) -> Self {
Auth {
email_on_signup: format!("{:?}", auth.email_on_signup),
min_password_length: auth.min_password_length,
max_password_length: auth.max_password_length,
secret_key: auth.secret_key,
}
}
}

impl From<DomainDatabase> for Database {
fn from(database: DomainDatabase) -> Self {
Database {
connect_url: database.connect_url,
torrent_info_update_interval: database.torrent_info_update_interval,
}
}
}

impl From<DomainMail> for Mail {
fn from(mail: DomainMail) -> Self {
Mail {
email_verification_enabled: mail.email_verification_enabled,
from: mail.from,
reply_to: mail.reply_to,
username: mail.username,
password: mail.password,
server: mail.server,
port: mail.port,
}
}
}

impl From<DomainImageCache> for ImageCache {
fn from(image_cache: DomainImageCache) -> Self {
ImageCache {
max_request_timeout_ms: image_cache.max_request_timeout_ms,
capacity: image_cache.capacity,
entry_size_limit: image_cache.entry_size_limit,
user_quota_period_seconds: image_cache.user_quota_period_seconds,
user_quota_bytes: image_cache.user_quota_bytes,
}
}
}
44 changes: 44 additions & 0 deletions tests/e2e/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//! Initialize configuration for the shared E2E tests environment from a
//! config file `config.toml` or env var.
//!
//! All environment variables are prefixed with `TORRUST_IDX_BACK_`.
use std::env;

use torrust_index_backend::config::Configuration;

// Environment variables

/// If present, E2E tests will run against a shared instance of the server
pub const ENV_VAR_E2E_SHARED: &str = "TORRUST_IDX_BACK_E2E_SHARED";

/// The whole `config.toml` file content. It has priority over the config file.
pub const ENV_VAR_E2E_CONFIG: &str = "TORRUST_IDX_BACK_E2E_CONFIG";

// Default values

pub const ENV_VAR_E2E_DEFAULT_CONFIG_PATH: &str = "./config-idx-back.local.toml";

/// Initialize configuration from file or env var.
///
/// # Panics
///
/// Will panic if configuration is not found or cannot be parsed
pub async fn init_shared_env_configuration() -> Configuration {
if env::var(ENV_VAR_E2E_CONFIG).is_ok() {
println!("Loading configuration for E2E env from env var `{}`", ENV_VAR_E2E_CONFIG);

Configuration::load_from_env_var(ENV_VAR_E2E_CONFIG).unwrap()
} else {
println!(
"Loading configuration for E2E env from config file `{}`",
ENV_VAR_E2E_DEFAULT_CONFIG_PATH
);

match Configuration::load_from_file(ENV_VAR_E2E_DEFAULT_CONFIG_PATH).await {
Ok(config) => config,
Err(error) => {
panic!("{}", error)
}
}
}
}
Loading