torrust_index_backend/lib.rs
1//! Documentation for [Torrust Tracker Index Backend](https://github.com/torrust/torrust-index-backend) API.
2//!
3//! This is the backend API for [Torrust Tracker Index](https://github.com/torrust/torrust-index).
4//!
5//! It is written in Rust and uses the [Axum](https://github.com/tokio-rs/axum) framework. It is designed to be
6//! used with by the [Torrust Tracker Index Frontend](https://github.com/torrust/torrust-index-frontend).
7//!
8//! If you are looking for information on how to use the API, please see the
9//! [API v1](crate::web::api::v1) section of the documentation.
10//!
11//! # Table of contents
12//!
13//! - [Features](#features)
14//! - [Services](#services)
15//! - [Installation](#installation)
16//! - [Minimum requirements](#minimum-requirements)
17//! - [Prerequisites](#prerequisites)
18//! - [Install from sources](#install-from-sources)
19//! - [Run with docker](#run-with-docker)
20//! - [Development](#development)
21//! - [Configuration](#configuration)
22//! - [Usage](#usage)
23//! - [API](#api)
24//! - [Tracker Statistics Importer](#tracker-statistics-importer)
25//! - [Upgrader](#upgrader)
26//! - [Contributing](#contributing)
27//! - [Documentation](#documentation)
28//!
29//! # Features
30//!
31//! - Torrent categories
32//! - Image proxy cache for torrent descriptions
33//! - User registration and authentication
34//! - DB Support for `SQLite` and `MySQl`
35//!
36//! # Services
37//!
38//! From the end-user perspective the Torrust Tracker exposes three different services.
39//!
40//! - A REST [API](crate::web::api::v1)
41//!
42//! From the administrator perspective, the Torrust Index Backend exposes:
43//!
44//! - A console command to update torrents statistics from the associated tracker
45//! - A console command to upgrade the database schema from version `1.0.0` to `2.0.0`
46//!
47//! # Installation
48//!
49//! ## Minimum requirements
50//!
51//! - Rust Stable `1.68`
52//!
53//! ## Prerequisites
54//!
55//! In order the run the backend you will need a running torrust tracker. In the
56//! configuration you need to fill the `backend` section with the following:
57//!
58//! ```toml
59//! [tracker]
60//! url = "udp://localhost:6969"
61//! mode = "Public"
62//! api_url = "http://localhost:1212"
63//! token = "MyAccessToken"
64//! token_valid_seconds = 7257600
65//! ```
66//!
67//! Refer to the [`config::tracker`](crate::config::Tracker) documentation for more information.
68//!
69//! You can follow the tracker installation instructions [here](https://docs.rs/torrust-tracker)
70//! or you can use the docker to run both the tracker and the backend. Refer to the
71//! [Run with docker](#run-with-docker) section for more information.
72//!
73//! If you are using `SQLite3` as database driver, you will need to install the
74//! following dependency:
75//!
76//! ```text
77//! sudo apt-get install libsqlite3-dev
78//! ```
79//!
80//! > **NOTICE**: those are the commands for `Ubuntu`. If you are using a
81//! different OS, you will need to install the equivalent packages. Please
82//! refer to the documentation of your OS.
83//!
84//! With the default configuration you will need to create the `storage` directory:
85//!
86//! ```text
87//! storage/
88//! └── database
89//! └── data.db
90//! ```
91//!
92//! The default configuration expects a directory `./storage/database` to be writable by the app process.
93//!
94//! By default the backend uses `SQLite` and the database file name `data.db`.
95//!
96//! ## Install from sources
97//!
98//! ```text
99//! git clone git@github.com:torrust/torrust-index-backend.git \
100//! && cd torrust-index-backend \
101//! && cargo build --release \
102//! && mkdir -p ./storage/database
103//! ```
104//!
105//! Then you can run it with: `./target/release/main`
106//!
107//! ## Run with docker
108//!
109//! You can run the backend with a pre-built docker image:
110//!
111//! ```text
112//! mkdir -p ./storage/database \
113//! && export TORRUST_IDX_BACK_USER_UID=1000 \
114//! && docker run -it \
115//! --user="$TORRUST_IDX_BACK_USER_UID" \
116//! --publish 3001:3001/tcp \
117//! --volume "$(pwd)/storage":"/app/storage" \
118//! torrust/index-backend
119//! ```
120//!
121//! For more information about using docker visit the [tracker docker documentation](https://github.com/torrust/torrust-index-backend/tree/develop/docker).
122//!
123//! ## Development
124//!
125//! We are using the [The Rust SQL Toolkit](https://github.com/launchbadge/sqlx)
126//! [(sqlx)](https://github.com/launchbadge/sqlx) for database migrations.
127//!
128//! You can install it with:
129//!
130//! ```text
131//! cargo install sqlx-cli
132//! ```
133//!
134//! To initialize the database run:
135//!
136//! ```text
137//! echo "DATABASE_URL=sqlite://data.db?mode=rwc" > .env
138//! sqlx db setup
139//! ```
140//!
141//! The `sqlx db setup` command will create the database specified in your
142//! `DATABASE_URL` and run any pending migrations.
143//!
144//! > **WARNING**: The `.env` file is also used by docker-compose.
145//!
146//! > **NOTICE**: Refer to the [sqlx-cli](https://github.com/launchbadge/sqlx/tree/main/sqlx-cli)
147//! documentation for other commands to create new migrations or run them.
148//!
149//! > **NOTICE**: You can run the backend with [tmux](https://github.com/tmux/tmux/wiki) with `tmux new -s torrust-index-backend`.
150//!
151//! # Configuration
152//! In order to run the backend you need to provide the configuration. If you run the backend without providing the configuration,
153//! the tracker will generate the default configuration the first time you run it. It will generate a `config.toml` file with
154//! in the root directory.
155//!
156//! The default configuration is:
157//!
158//! ```toml
159//! [website]
160//! name = "Torrust"
161//!
162//! [tracker]
163//! url = "udp://localhost:6969"
164//! mode = "Public"
165//! api_url = "http://localhost:1212"
166//! token = "MyAccessToken"
167//! token_valid_seconds = 7257600
168//!
169//! [net]
170//! port = 3001
171//!
172//! [auth]
173//! email_on_signup = "Optional"
174//! min_password_length = 6
175//! max_password_length = 64
176//! secret_key = "MaxVerstappenWC2021"
177//!
178//! [database]
179//! connect_url = "sqlite://data.db?mode=rwc"
180//!
181//! [mail]
182//! email_verification_enabled = false
183//! from = "example@email.com"
184//! reply_to = "noreply@email.com"
185//! username = ""
186//! password = ""
187//! server = ""
188//! port = 25
189//!
190//! [image_cache]
191//! max_request_timeout_ms = 1000
192//! capacity = 128000000
193//! entry_size_limit = 4000000
194//! user_quota_period_seconds = 3600
195//! user_quota_bytes = 64000000
196//!
197//! [api]
198//! default_torrent_page_size = 10
199//! max_torrent_page_size = 30
200//!
201//! [tracker_statistics_importer]
202//! torrent_info_update_interval = 3600
203//! ```
204//!
205//! For more information about configuration you can visit the documentation for the [`config`](crate::config) module.
206//!
207//! Alternatively to the `config.toml` file you can use one environment variable `TORRUST_IDX_BACK_CONFIG` to pass the configuration to the tracker:
208//!
209//! ```text
210//! TORRUST_IDX_BACK_CONFIG=$(cat config.toml)
211//! cargo run
212//! ```
213//!
214//! In the previous example you are just setting the env var with the contents of the `config.toml` file.
215//!
216//! The env var contains the same data as the `config.toml`. It's particularly useful in you are [running the backend with docker](https://github.com/torrust/torrust-index-backend/tree/develop/docker).
217//!
218//! > **NOTICE**: The `TORRUST_IDX_BACK_CONFIG` env var has priority over the `config.toml` file.
219//!
220//! > **NOTICE**: You can also change the location for the configuration file with the `TORRUST_IDX_BACK_CONFIG_PATH` env var.
221//!
222//! # Usage
223//!
224//! ## API
225//!
226//! Running the backend with the default configuration will expose the REST API on port 3001: <http://localhost:3001>
227//!
228//! ## Tracker Statistics Importer
229//!
230//! This console command allows you to manually import the tracker statistics.
231//!
232//! For more information about this command you can visit the documentation for
233//! the [`Import tracker statistics`](crate::console::commands::import_tracker_statistics) module.
234//!
235//! ## Upgrader
236//!
237//! This console command allows you to manually upgrade the application from one
238//! version to another.
239//!
240//! For more information about this command you can visit the documentation for
241//! the [`Upgrade app from version 1.0.0 to 2.0.0`](crate::upgrades::from_v1_0_0_to_v2_0_0::upgrader) module.
242//!
243//! # Contributing
244//!
245//! If you want to contribute to this documentation you can:
246//!
247//! - [Open a new discussion](https://github.com/torrust/torrust-index-backend/discussions)
248//! - [Open a new issue](https://github.com/torrust/torrust-index-backend/issues).
249//! - [Open a new pull request](https://github.com/torrust/torrust-index-backend/pulls).
250//!
251//! # Documentation
252//!
253//! You can find this documentation on [docs.rs](https://docs.rs/torrust-index-backend/).
254//!
255//! If you want to contribute to this documentation you can [open a new pull request](https://github.com/torrust/torrust-index-backend/pulls).
256//!
257//! In addition to the production code documentation you can find a lot of
258//! examples in the [tests](https://github.com/torrust/torrust-index-backend/tree/develop/tests/e2e/contexts) directory.
259pub mod app;
260pub mod bootstrap;
261pub mod cache;
262pub mod common;
263pub mod config;
264pub mod console;
265pub mod databases;
266pub mod errors;
267pub mod mailer;
268pub mod models;
269pub mod services;
270pub mod tracker;
271pub mod ui;
272pub mod upgrades;
273pub mod utils;
274pub mod web;
275
276trait AsCSV {
277 fn as_csv<T>(&self) -> Result<Option<Vec<T>>, ()>
278 where
279 T: std::str::FromStr;
280}
281
282impl<S> AsCSV for Option<S>
283where
284 S: AsRef<str>,
285{
286 fn as_csv<T>(&self) -> Result<Option<Vec<T>>, ()>
287 where
288 T: std::str::FromStr,
289 {
290 match self {
291 Some(ref s) if !s.as_ref().trim().is_empty() => {
292 let mut acc = vec![];
293 for s in s.as_ref().split(',') {
294 let item = s.trim().parse::<T>().map_err(|_| ())?;
295 acc.push(item);
296 }
297 if acc.is_empty() {
298 Ok(None)
299 } else {
300 Ok(Some(acc))
301 }
302 }
303 _ => Ok(None),
304 }
305 }
306}