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 src/databases/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,8 @@ pub trait Database: Sync + Send {
) -> Result<i64, Error>;

/// Get `Torrent` from `InfoHash`.
async fn get_torrent_from_infohash(&self, infohash: &InfoHash) -> Result<Torrent, Error> {
let torrent_info = self.get_torrent_info_from_infohash(infohash).await?;
async fn get_torrent_from_info_hash(&self, info_hash: &InfoHash) -> Result<Torrent, Error> {
let torrent_info = self.get_torrent_info_from_info_hash(info_hash).await?;

let torrent_files = self.get_torrent_files_from_id(torrent_info.torrent_id).await?;

Expand Down Expand Up @@ -205,7 +205,7 @@ pub trait Database: Sync + Send {
async fn get_torrent_info_from_id(&self, torrent_id: i64) -> Result<DbTorrentInfo, Error>;

/// Get torrent's info as `DbTorrentInfo` from torrent `InfoHash`.
async fn get_torrent_info_from_infohash(&self, info_hash: &InfoHash) -> Result<DbTorrentInfo, Error>;
async fn get_torrent_info_from_info_hash(&self, info_hash: &InfoHash) -> Result<DbTorrentInfo, Error>;

/// Get all torrent's files as `Vec<TorrentFile>` from `torrent_id`.
async fn get_torrent_files_from_id(&self, torrent_id: i64) -> Result<Vec<TorrentFile>, Error>;
Expand All @@ -217,7 +217,7 @@ pub trait Database: Sync + Send {
async fn get_torrent_listing_from_id(&self, torrent_id: i64) -> Result<TorrentListing, Error>;

/// Get `TorrentListing` from `InfoHash`.
async fn get_torrent_listing_from_infohash(&self, infohash: &InfoHash) -> Result<TorrentListing, Error>;
async fn get_torrent_listing_from_info_hash(&self, info_hash: &InfoHash) -> Result<TorrentListing, Error>;

/// Get all torrents as `Vec<TorrentCompact>`.
async fn get_all_torrents_compact(&self) -> Result<Vec<TorrentCompact>, Error>;
Expand Down
8 changes: 4 additions & 4 deletions src/databases/mysql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -541,11 +541,11 @@ impl Database for Mysql {
.map_err(|_| database::Error::TorrentNotFound)
}

async fn get_torrent_info_from_infohash(&self, infohash: &InfoHash) -> Result<DbTorrentInfo, database::Error> {
async fn get_torrent_info_from_info_hash(&self, info_hash: &InfoHash) -> Result<DbTorrentInfo, database::Error> {
query_as::<_, DbTorrentInfo>(
"SELECT torrent_id, info_hash, name, pieces, piece_length, private, root_hash FROM torrust_torrents WHERE info_hash = ?",
)
.bind(infohash.to_hex_string().to_uppercase()) // `info_hash` is stored as uppercase hex string
.bind(info_hash.to_hex_string().to_uppercase()) // `info_hash` is stored as uppercase hex string
.fetch_one(&self.pool)
.await
.map_err(|_| database::Error::TorrentNotFound)
Expand Down Expand Up @@ -603,7 +603,7 @@ impl Database for Mysql {
.map_err(|_| database::Error::TorrentNotFound)
}

async fn get_torrent_listing_from_infohash(&self, infohash: &InfoHash) -> Result<TorrentListing, database::Error> {
async fn get_torrent_listing_from_info_hash(&self, info_hash: &InfoHash) -> Result<TorrentListing, database::Error> {
query_as::<_, TorrentListing>(
"SELECT tt.torrent_id, tp.username AS uploader, tt.info_hash, ti.title, ti.description, tt.category_id, DATE_FORMAT(tt.date_uploaded, '%Y-%m-%d %H:%i:%s') AS date_uploaded, tt.size AS file_size,
CAST(COALESCE(sum(ts.seeders),0) as signed) as seeders,
Expand All @@ -615,7 +615,7 @@ impl Database for Mysql {
WHERE tt.info_hash = ?
GROUP BY torrent_id"
)
.bind(infohash.to_hex_string().to_uppercase()) // `info_hash` is stored as uppercase hex string
.bind(info_hash.to_hex_string().to_uppercase()) // `info_hash` is stored as uppercase hex string
.fetch_one(&self.pool)
.await
.map_err(|_| database::Error::TorrentNotFound)
Expand Down
8 changes: 4 additions & 4 deletions src/databases/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -531,11 +531,11 @@ impl Database for Sqlite {
.map_err(|_| database::Error::TorrentNotFound)
}

async fn get_torrent_info_from_infohash(&self, infohash: &InfoHash) -> Result<DbTorrentInfo, database::Error> {
async fn get_torrent_info_from_info_hash(&self, info_hash: &InfoHash) -> Result<DbTorrentInfo, database::Error> {
query_as::<_, DbTorrentInfo>(
"SELECT torrent_id, info_hash, name, pieces, piece_length, private, root_hash FROM torrust_torrents WHERE info_hash = ?",
)
.bind(infohash.to_hex_string().to_uppercase()) // `info_hash` is stored as uppercase hex string
.bind(info_hash.to_hex_string().to_uppercase()) // `info_hash` is stored as uppercase hex string
.fetch_one(&self.pool)
.await
.map_err(|_| database::Error::TorrentNotFound)
Expand Down Expand Up @@ -593,7 +593,7 @@ impl Database for Sqlite {
.map_err(|_| database::Error::TorrentNotFound)
}

async fn get_torrent_listing_from_infohash(&self, infohash: &InfoHash) -> Result<TorrentListing, database::Error> {
async fn get_torrent_listing_from_info_hash(&self, info_hash: &InfoHash) -> Result<TorrentListing, database::Error> {
query_as::<_, TorrentListing>(
"SELECT tt.torrent_id, tp.username AS uploader, tt.info_hash, ti.title, ti.description, tt.category_id, tt.date_uploaded, tt.size AS file_size,
CAST(COALESCE(sum(ts.seeders),0) as signed) as seeders,
Expand All @@ -605,7 +605,7 @@ impl Database for Sqlite {
WHERE tt.info_hash = ?
GROUP BY ts.torrent_id"
)
.bind(infohash.to_string().to_uppercase()) // `info_hash` is stored as uppercase
.bind(info_hash.to_string().to_uppercase()) // `info_hash` is stored as uppercase
.fetch_one(&self.pool)
.await
.map_err(|_| database::Error::TorrentNotFound)
Expand Down
14 changes: 7 additions & 7 deletions src/models/info_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
//! See [BEP 3. The `BitTorrent` Protocol Specification](https://www.bittorrent.org/beps/bep_0003.html)
//! for the official specification.
//!
//! This modules provides a type that can be used to represent infohashes.
//! This modules provides a type that can be used to represent info-hashes.
//!
//! > **NOTICE**: It only supports Info Hash v1.
//!
//! Typically infohashes are represented as hex strings, but internally they are
//! Typically info-hashes are represented as hex strings, but internally they are
//! a 20-byte array.
//!
//! # Calculating the info-hash of a torrent file
Expand Down Expand Up @@ -109,7 +109,7 @@
//! }
//! ```
//!
//! The infohash is the [SHA1](https://en.wikipedia.org/wiki/SHA-1) hash
//! The info-hash is the [SHA1](https://en.wikipedia.org/wiki/SHA-1) hash
//! of the `info` attribute. That is, the SHA1 hash of:
//!
//! ```text
Expand Down Expand Up @@ -217,14 +217,14 @@ impl std::convert::From<[u8; 20]> for InfoHash {
/// Errors that can occur when converting from a `Vec<u8>` to an `InfoHash`.
#[derive(Error, Debug)]
pub enum ConversionError {
/// Not enough bytes for infohash. An infohash is 20 bytes.
#[error("not enough bytes for infohash: {message} {location}")]
/// Not enough bytes for info-hash. An info-hash is 20 bytes.
#[error("not enough bytes for info-hash: {message} {location}")]
NotEnoughBytes {
location: &'static Location<'static>,
message: String,
},
/// Too many bytes for infohash. An infohash is 20 bytes.
#[error("too many bytes for infohash: {message} {location}")]
/// Too many bytes for info-hash. An info-hash is 20 bytes.
#[error("too many bytes for info-hash: {message} {location}")]
TooManyBytes {
location: &'static Location<'static>,
message: String,
Expand Down
1 change: 1 addition & 0 deletions src/models/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub struct TokenResponse {
#[derive(Serialize, Deserialize, Debug)]
pub struct NewTorrentResponse {
pub torrent_id: i64,
pub info_hash: String,
}

#[allow(clippy::module_name_repetitions)]
Expand Down
30 changes: 17 additions & 13 deletions src/routes/torrent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,22 +133,25 @@ pub async fn upload(req: HttpRequest, payload: Multipart, app_data: WebAppData)

// respond with the newly uploaded torrent id
Ok(HttpResponse::Ok().json(OkResponse {
data: NewTorrentResponse { torrent_id },
data: NewTorrentResponse {
torrent_id,
info_hash: torrent_request.torrent.info_hash(),
},
}))
}

/// Returns the torrent as a byte stream `application/x-bittorrent`.
///
/// # Errors
///
/// Returns `ServiceError::BadRequest` if the torrent infohash is invalid.
/// Returns `ServiceError::BadRequest` if the torrent info-hash is invalid.
pub async fn download_torrent_handler(req: HttpRequest, app_data: WebAppData) -> ServiceResult<impl Responder> {
let info_hash = get_torrent_infohash_from_request(&req)?;
let info_hash = get_torrent_info_hash_from_request(&req)?;

// optional
let user = app_data.auth.get_user_compact_from_request(&req).await;

let mut torrent = app_data.database.get_torrent_from_infohash(&info_hash).await?;
let mut torrent = app_data.database.get_torrent_from_info_hash(&info_hash).await?;

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

Expand Down Expand Up @@ -196,9 +199,9 @@ pub async fn get(req: HttpRequest, app_data: WebAppData) -> ServiceResult<impl R

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

let infohash = get_torrent_infohash_from_request(&req)?;
let info_hash = get_torrent_info_hash_from_request(&req)?;

let torrent_listing = app_data.database.get_torrent_listing_from_infohash(&infohash).await?;
let torrent_listing = app_data.database.get_torrent_listing_from_info_hash(&info_hash).await?;

let torrent_id = torrent_listing.torrent_id;

Expand All @@ -215,7 +218,7 @@ pub async fn get(req: HttpRequest, app_data: WebAppData) -> ServiceResult<impl R
torrent_response.files = app_data.database.get_torrent_files_from_id(torrent_id).await?;

if torrent_response.files.len() == 1 {
let torrent_info = app_data.database.get_torrent_info_from_infohash(&infohash).await?;
let torrent_info = app_data.database.get_torrent_info_from_info_hash(&info_hash).await?;

torrent_response
.files
Expand Down Expand Up @@ -287,9 +290,9 @@ pub async fn get(req: HttpRequest, app_data: WebAppData) -> ServiceResult<impl R
pub async fn update(req: HttpRequest, payload: web::Json<Update>, app_data: WebAppData) -> ServiceResult<impl Responder> {
let user = app_data.auth.get_user_compact_from_request(&req).await?;

let infohash = get_torrent_infohash_from_request(&req)?;
let info_hash = get_torrent_info_hash_from_request(&req)?;

let torrent_listing = app_data.database.get_torrent_listing_from_infohash(&infohash).await?;
let torrent_listing = app_data.database.get_torrent_listing_from_info_hash(&info_hash).await?;

// check if user is owner or administrator
if torrent_listing.uploader != user.username && !user.administrator {
Expand Down Expand Up @@ -338,22 +341,23 @@ pub async fn delete(req: HttpRequest, app_data: WebAppData) -> ServiceResult<imp
return Err(ServiceError::Unauthorized);
}

let infohash = get_torrent_infohash_from_request(&req)?;
let info_hash = get_torrent_info_hash_from_request(&req)?;

// needed later for removing torrent from tracker whitelist
let torrent_listing = app_data.database.get_torrent_listing_from_infohash(&infohash).await?;
let torrent_listing = app_data.database.get_torrent_listing_from_info_hash(&info_hash).await?;

app_data.database.delete_torrent(torrent_listing.torrent_id).await?;

// remove info_hash from tracker whitelist
let _ = app_data
.tracker_service
.remove_info_hash_from_whitelist(torrent_listing.info_hash)
.remove_info_hash_from_whitelist(torrent_listing.info_hash.clone())
.await;

Ok(HttpResponse::Ok().json(OkResponse {
data: NewTorrentResponse {
torrent_id: torrent_listing.torrent_id,
info_hash: torrent_listing.info_hash,
},
}))
}
Expand Down Expand Up @@ -393,7 +397,7 @@ pub async fn get_torrents_handler(params: Query<Search>, app_data: WebAppData) -
Ok(HttpResponse::Ok().json(OkResponse { data: torrents_response }))
}

fn get_torrent_infohash_from_request(req: &HttpRequest) -> Result<InfoHash, ServiceError> {
fn get_torrent_info_hash_from_request(req: &HttpRequest) -> Result<InfoHash, ServiceError> {
match req.match_info().get("info_hash") {
None => Err(ServiceError::BadRequest),
Some(info_hash) => match InfoHash::from_str(info_hash) {
Expand Down
12 changes: 6 additions & 6 deletions tests/common/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,17 +93,17 @@ impl Client {
self.http_client.get("torrents", params).await
}

pub async fn get_torrent(&self, infohash: &InfoHash) -> TextResponse {
self.http_client.get(&format!("torrent/{infohash}"), Query::empty()).await
pub async fn get_torrent(&self, info_hash: &InfoHash) -> TextResponse {
self.http_client.get(&format!("torrent/{info_hash}"), Query::empty()).await
}

pub async fn delete_torrent(&self, infohash: &InfoHash) -> TextResponse {
self.http_client.delete(&format!("torrent/{infohash}")).await
pub async fn delete_torrent(&self, info_hash: &InfoHash) -> TextResponse {
self.http_client.delete(&format!("torrent/{info_hash}")).await
}

pub async fn update_torrent(&self, infohash: &InfoHash, update_torrent_form: UpdateTorrentFrom) -> TextResponse {
pub async fn update_torrent(&self, info_hash: &InfoHash, update_torrent_form: UpdateTorrentFrom) -> TextResponse {
self.http_client
.put(&format!("torrent/{infohash}"), &update_torrent_form)
.put(&format!("torrent/{info_hash}"), &update_torrent_form)
.await
}

Expand Down
2 changes: 1 addition & 1 deletion tests/common/contexts/torrent/fixtures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ impl TestTorrent {
}
}

pub fn infohash(&self) -> InfoHash {
pub fn info_hash(&self) -> InfoHash {
self.file_info.info_hash.clone()
}
}
Expand Down
1 change: 1 addition & 0 deletions tests/common/contexts/torrent/responses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ pub struct UploadedTorrentResponse {
#[derive(Deserialize, PartialEq, Debug)]
pub struct UploadedTorrent {
pub torrent_id: Id,
pub info_hash: String,
}

#[derive(Deserialize, PartialEq, Debug)]
Expand Down
Loading