diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..d3d4df4 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,9 @@ +# https://github.com/rust-lang/cargo/issues/5034#issuecomment-927105016 +[target.'cfg(feature = "cargo-clippy")'] +rustflags = [ + "-Aclippy::let_and_return", + "-Aclippy::map_entry", + "-Aclippy::or_fun_call", + "-Aclippy::redundant_field_names", + "-Aclippy::unused_unit", +] diff --git a/README.md b/README.md index 0745662..f77ae98 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,12 @@ cargo run cargo run --bin mitractl ``` +### Run linter + +``` +cargo clippy +``` + ### Run tests ``` diff --git a/src/activitypub/activity.rs b/src/activitypub/activity.rs index 1cb064d..fac3ad9 100644 --- a/src/activitypub/activity.rs +++ b/src/activitypub/activity.rs @@ -98,20 +98,19 @@ fn create_activity( ) -> Activity { let actor_id = get_actor_url( instance_url, - &actor_name, + actor_name, ); let activity_id = get_object_url( instance_url, &activity_uuid.unwrap_or(Uuid::new_v4()), ); - let activity = Activity { + Activity { context: json!(AP_CONTEXT), id: activity_id, activity_type: activity_type.to_string(), actor: actor_id, object: serde_json::to_value(object).unwrap(), - }; - activity + } } pub fn create_note( diff --git a/src/activitypub/fetcher.rs b/src/activitypub/fetcher.rs index ca0f78f..2ea0a3e 100644 --- a/src/activitypub/fetcher.rs +++ b/src/activitypub/fetcher.rs @@ -1,4 +1,4 @@ -use std::path::PathBuf; +use std::path::Path; use serde_json::Value; @@ -29,7 +29,7 @@ pub enum FetchError { pub async fn fetch_avatar_and_banner( actor: &Actor, - media_dir: &PathBuf, + media_dir: &Path, ) -> Result<(Option, Option), FetchError> { let avatar = match &actor.icon { Some(icon) => { @@ -57,7 +57,7 @@ pub async fn fetch_avatar_and_banner( pub async fn fetch_profile( username: &str, instance_host: &str, - media_dir: &PathBuf, + media_dir: &Path, ) -> Result { let actor_address = format!("{}@{}", &username, &instance_host); let webfinger_account_uri = format!("acct:{}", actor_address); @@ -80,7 +80,7 @@ pub async fn fetch_profile( pub async fn fetch_profile_by_actor_id( actor_url: &str, - media_dir: &PathBuf, + media_dir: &Path, ) -> Result { let actor_host = url::Url::parse(actor_url)? .host_str() @@ -115,7 +115,7 @@ pub async fn fetch_profile_by_actor_id( pub async fn fetch_attachment( url: &str, - output_dir: &PathBuf, + output_dir: &Path, ) -> Result { let response = reqwest::get(url).await?; let file_data = response.bytes().await?; diff --git a/src/activitypub/receiver.rs b/src/activitypub/receiver.rs index de4ad66..2d751e8 100644 --- a/src/activitypub/receiver.rs +++ b/src/activitypub/receiver.rs @@ -1,4 +1,4 @@ -use std::path::PathBuf; +use std::path::Path; use regex::Regex; use serde_json::Value; @@ -52,7 +52,7 @@ fn parse_actor_id( ); let url_regexp = Regex::new(&url_regexp_str) .map_err(|_| ValidationError("error"))?; - let url_caps = url_regexp.captures(&actor_id) + let url_caps = url_regexp.captures(actor_id) .ok_or(ValidationError("invalid actor ID"))?; let username = url_caps.name("username") .ok_or(ValidationError("invalid actor ID"))? @@ -71,7 +71,7 @@ fn parse_object_id( ); let url_regexp = Regex::new(&url_regexp_str) .map_err(|_| ValidationError("error"))?; - let url_caps = url_regexp.captures(&object_id) + let url_caps = url_regexp.captures(object_id) .ok_or(ValidationError("invalid object ID"))?; let object_uuid: Uuid = url_caps.name("uuid") .ok_or(ValidationError("invalid object ID"))? @@ -83,7 +83,7 @@ fn parse_object_id( async fn get_or_fetch_profile_by_actor_id( db_client: &impl GenericClient, actor_id: &str, - media_dir: &PathBuf, + media_dir: &Path, ) -> Result { let profile = match get_profile_by_actor_id(db_client, actor_id).await { Ok(profile) => profile, @@ -116,6 +116,7 @@ pub async fn process_note( // Fetch ancestors by going through inReplyTo references // TODO: fetch replies too + #[allow(clippy::while_let_loop)] loop { let object_id = match maybe_parent_object_id { Some(parent_object_id) => { @@ -237,7 +238,7 @@ pub async fn receive_activity( .and_then(|val| val.as_str()) .unwrap_or("Unknown") .to_owned(); - let db_client = &mut **get_database_client(&db_pool).await?; + let db_client = &mut **get_database_client(db_pool).await?; match (activity_type.as_str(), object_type.as_str()) { (ACCEPT, FOLLOW) => { let object: Object = serde_json::from_value(activity.object) @@ -313,7 +314,7 @@ pub async fn receive_activity( // Send activity let recipients = vec![source_actor]; - deliver_activity(&config, &target_user, new_activity, recipients); + deliver_activity(config, &target_user, new_activity, recipients); }, (UNDO, FOLLOW) => { let object: Object = serde_json::from_value(activity.object) diff --git a/src/bin/mitractl.rs b/src/bin/mitractl.rs index 76485bf..431d4a2 100644 --- a/src/bin/mitractl.rs +++ b/src/bin/mitractl.rs @@ -1,5 +1,4 @@ use clap::Clap; -use tokio; use uuid::Uuid; use mitra::config; @@ -82,7 +81,7 @@ async fn main() { }, SubCommand::ListInviteCodes(_) => { let invite_codes = get_invite_codes(db_client).await.unwrap(); - if invite_codes.len() == 0 { + if invite_codes.is_empty() { println!("no invite codes found"); return; } diff --git a/src/database/mod.rs b/src/database/mod.rs index 17d395e..1b93a15 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -3,15 +3,14 @@ pub mod migrate; pub type Pool = deadpool_postgres::Pool; pub fn create_pool(database_url: &str) -> Pool { - let pool = deadpool_postgres::Pool::new( + deadpool_postgres::Pool::new( deadpool_postgres::Manager::new( database_url.parse().expect("invalid database URL"), tokio_postgres::NoTls, ), // https://wiki.postgresql.org/wiki/Number_Of_Database_Connections num_cpus::get() * 2, - ); - pool + ) } use tokio_postgres::error::{Error as PgError, SqlState}; diff --git a/src/ethereum/contracts.rs b/src/ethereum/contracts.rs index 3c44146..aff8240 100644 --- a/src/ethereum/contracts.rs +++ b/src/ethereum/contracts.rs @@ -1,5 +1,5 @@ use std::fs; -use std::path::PathBuf; +use std::path::Path; pub const COLLECTIBLE: &str = "Collectible"; pub const MANAGER: &str = "Manager"; @@ -17,7 +17,7 @@ pub enum ArtifactError { } pub fn load_abi( - contract_dir: &PathBuf, + contract_dir: &Path, contract_name: &str, ) -> Result, ArtifactError> { let contract_artifact_path = contract_dir.join(format!("{}.json", contract_name)); diff --git a/src/ethereum/nft.rs b/src/ethereum/nft.rs index 41ae62f..d469dcf 100644 --- a/src/ethereum/nft.rs +++ b/src/ethereum/nft.rs @@ -74,7 +74,7 @@ pub async fn process_events( db_pool: &Pool, token_waitlist_map: &mut HashMap>, ) -> Result<(), EthereumError> { - let db_client = &**get_database_client(&db_pool).await?; + let db_client = &**get_database_client(db_pool).await?; // Create/update token waitlist map let token_waitlist = get_token_waitlist(db_client).await?; @@ -196,7 +196,7 @@ pub fn create_mint_signature( let contract_address = parse_address(&contract_config.address)?; let user_address = parse_address(user_address)?; let chain_id: U256 = contract_config.chain_id.into(); - let chain_id_token = Token::Uint(chain_id.into()); + let chain_id_token = Token::Uint(chain_id); let chain_id_bin = encode(&[chain_id_token]); let message = [ &chain_id_bin, diff --git a/src/ethereum/utils.rs b/src/ethereum/utils.rs index b07ad95..1a2de64 100644 --- a/src/ethereum/utils.rs +++ b/src/ethereum/utils.rs @@ -42,7 +42,7 @@ pub fn sign_message( signing_key: &str, message: &[u8], ) -> Result { - let key = SecretKey::from_str(&signing_key)?; + let key = SecretKey::from_str(signing_key)?; let message_hash = keccak256(message); let eip_191_message = [ "\x19Ethereum Signed Message:\n32".as_bytes(), diff --git a/src/http_signatures/verify.rs b/src/http_signatures/verify.rs index 859ff12..9077606 100644 --- a/src/http_signatures/verify.rs +++ b/src/http_signatures/verify.rs @@ -58,7 +58,7 @@ fn parse_http_signature( ); let signature_header_regexp = Regex::new(signature_header_regexp_raw).unwrap(); let signature_header_caps = signature_header_regexp - .captures(&signature_header) + .captures(signature_header) .ok_or(VerificationError::HeaderError("invalid signature header"))?; let key_id = signature_header_caps.name("key_id") .ok_or(VerificationError::ParseError("keyId parameter is missing"))? @@ -78,7 +78,7 @@ fn parse_http_signature( request_method.as_str().to_lowercase(), request_uri, ); - for header in headers_parameter.split(" ") { + for header in headers_parameter.split(' ') { if header == "(request-target)" { continue; } diff --git a/src/ipfs/utils.rs b/src/ipfs/utils.rs index e46edac..f51d2d4 100644 --- a/src/ipfs/utils.rs +++ b/src/ipfs/utils.rs @@ -12,7 +12,7 @@ pub struct ParseError; pub fn parse_ipfs_url(url: &str) -> Result { let regexp = Regex::new(r"ipfs://(?P\w+)").unwrap(); - let caps = regexp.captures(&url).ok_or(ParseError)?; + let caps = regexp.captures(url).ok_or(ParseError)?; let cid = caps.name("cid") .ok_or(ParseError)? .as_str().to_string(); diff --git a/src/mastodon_api/accounts/types.rs b/src/mastodon_api/accounts/types.rs index 4133522..681a680 100644 --- a/src/mastodon_api/accounts/types.rs +++ b/src/mastodon_api/accounts/types.rs @@ -1,4 +1,4 @@ -use std::path::PathBuf; +use std::path::Path; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; @@ -49,9 +49,9 @@ pub struct Account { impl Account { pub fn from_profile(profile: DbActorProfile, instance_url: &str) -> Self { let avatar_url = profile.avatar_file_name.as_ref() - .map(|name| get_file_url(instance_url, &name)); + .map(|name| get_file_url(instance_url, name)); let header_url = profile.banner_file_name.as_ref() - .map(|name| get_file_url(instance_url, &name)); + .map(|name| get_file_url(instance_url, name)); let fields = profile.extra_fields.unpack().into_iter() .map(|field| AccountField { name: field.name, value: field.value }) .collect(); @@ -126,17 +126,17 @@ pub struct AccountUpdateData { fn process_b64_image_field_value( form_value: Option, db_value: Option, - output_dir: &PathBuf, + output_dir: &Path, ) -> Result, FileError> { let maybe_file_name = match form_value { Some(b64_data) => { - if b64_data == "" { + if b64_data.is_empty() { // Remove file None } else { // Decode and save file let (file_name, _) = save_validated_b64_file( - &b64_data, &output_dir, "image/", + &b64_data, output_dir, "image/", )?; Some(file_name) } @@ -152,7 +152,7 @@ impl AccountUpdateData { self, current_avatar: &Option, current_banner: &Option, - media_dir: &PathBuf, + media_dir: &Path, ) -> Result { let avatar = process_b64_image_field_value( self.avatar, current_avatar.clone(), media_dir, diff --git a/src/mastodon_api/accounts/views.rs b/src/mastodon_api/accounts/views.rs index 0addd1f..928c068 100644 --- a/src/mastodon_api/accounts/views.rs +++ b/src/mastodon_api/accounts/views.rs @@ -49,21 +49,21 @@ pub async fn create_account( if !config.registrations_open { let invite_code = user_data.invite_code.as_ref() .ok_or(ValidationError("invite code is required"))?; - if !is_valid_invite_code(db_client, &invite_code).await? { - Err(ValidationError("invalid invite code"))?; + if !is_valid_invite_code(db_client, invite_code).await? { + return Err(ValidationError("invalid invite code").into()); } } if config.ethereum_contract.is_some() { let is_allowed = is_allowed_user(&config, &user_data.wallet_address).await .map_err(|_| HttpError::InternalError)?; if !is_allowed { - Err(ValidationError("not allowed to sign up"))?; + return Err(ValidationError("not allowed to sign up").into()); } } // Hash password and generate private key let password_hash = hash_password(&user_data.password) .map_err(|_| HttpError::InternalError)?; - let private_key = match web::block(move || generate_private_key()).await { + let private_key = match web::block(generate_private_key).await { Ok(private_key) => private_key, Err(_) => return Err(HttpError::InternalError), }; diff --git a/src/mastodon_api/instance/types.rs b/src/mastodon_api/instance/types.rs index 75e19a5..f82789d 100644 --- a/src/mastodon_api/instance/types.rs +++ b/src/mastodon_api/instance/types.rs @@ -27,7 +27,7 @@ impl From<&Config> for InstanceInfo { short_description: config.instance_short_description.clone(), description: config.instance_description.clone(), version: config.version.clone(), - registrations: config.registrations_open.clone(), + registrations: config.registrations_open, login_message: config.login_message.clone(), ethereum_explorer_url: config.ethereum_explorer_url.clone(), nft_contract_name: config.ethereum_contract.as_ref() diff --git a/src/mastodon_api/oauth/views.rs b/src/mastodon_api/oauth/views.rs index 8e3a1fe..3b91a42 100644 --- a/src/mastodon_api/oauth/views.rs +++ b/src/mastodon_api/oauth/views.rs @@ -18,8 +18,8 @@ async fn token_view( db_pool: web::Data, request_data: web::Json, ) -> Result { - if request_data.grant_type != "password".to_string() { - Err(ValidationError("unsupported grant type"))?; + if &request_data.grant_type != "password" { + return Err(ValidationError("unsupported grant type").into()); } let db_client = &**get_database_client(&db_pool).await?; let user = get_user_by_wallet_address( @@ -32,7 +32,7 @@ async fn token_view( ).map_err(|_| HttpError::InternalError)?; if !password_correct { // Invalid signature/password - Err(ValidationError("incorrect password"))?; + return Err(ValidationError("incorrect password").into()); } let access_token = generate_access_token(); let created_at = Utc::now(); diff --git a/src/mastodon_api/search/helpers.rs b/src/mastodon_api/search/helpers.rs index 8a61452..b9348f0 100644 --- a/src/mastodon_api/search/helpers.rs +++ b/src/mastodon_api/search/helpers.rs @@ -22,7 +22,7 @@ fn parse_profile_query(query: &str) -> .ok_or(ValidationError("invalid search query"))? .as_str().to_string(); let maybe_instance = acct_caps.name("instance") - .and_then(|val| Some(val.as_str().to_string())); + .map(|val| val.as_str().to_string()); Ok((username, maybe_instance)) } @@ -39,7 +39,7 @@ async fn search_profiles( }, }; let mut profiles = search_profile(db_client, &username, instance.as_ref()).await?; - if profiles.len() == 0 && instance.is_some() { + if profiles.is_empty() && instance.is_some() { let instance_host = instance.unwrap(); let media_dir = config.media_dir(); match fetch_profile(&username, &instance_host, &media_dir).await { diff --git a/src/mastodon_api/search/views.rs b/src/mastodon_api/search/views.rs index 9e2e827..5b8eca7 100644 --- a/src/mastodon_api/search/views.rs +++ b/src/mastodon_api/search/views.rs @@ -18,7 +18,7 @@ async fn search_view( ) -> Result { let db_client = &mut **get_database_client(&db_pool).await?; get_current_user(db_client, auth.token()).await?; - let results = search(&config, db_client, &query_params.q.trim()).await?; + let results = search(&config, db_client, query_params.q.trim()).await?; Ok(HttpResponse::Ok().json(results)) } diff --git a/src/mastodon_api/statuses/views.rs b/src/mastodon_api/statuses/views.rs index 4e61268..bd3b4e9 100644 --- a/src/mastodon_api/statuses/views.rs +++ b/src/mastodon_api/statuses/views.rs @@ -182,7 +182,7 @@ async fn favourite( let activity = create_activity_like( &config.instance_url(), ¤t_user.profile, - &object_id, + object_id, ); deliver_activity(&config, ¤t_user, activity, vec![remote_actor]); } @@ -238,7 +238,7 @@ async fn make_permanent( let image_path = config.media_dir().join(&attachment.file_name); let image_data = std::fs::read(image_path) .map_err(|_| HttpError::InternalError)?; - let image_cid = ipfs_store::add(&ipfs_api_url, image_data).await + let image_cid = ipfs_store::add(ipfs_api_url, image_data).await .map_err(|_| HttpError::InternalError)?; set_attachment_ipfs_cid(db_client, &attachment.id, &image_cid).await?; image_cid @@ -259,7 +259,7 @@ async fn make_permanent( let post_metadata_json = serde_json::to_string(&post_metadata) .map_err(|_| HttpError::InternalError)? .as_bytes().to_vec(); - let post_metadata_cid = ipfs_store::add(&ipfs_api_url, post_metadata_json).await + let post_metadata_cid = ipfs_store::add(ipfs_api_url, post_metadata_json).await .map_err(|_| HttpError::InternalError)?; // Update post @@ -284,14 +284,14 @@ async fn get_signature( let post = get_post_by_id(db_client, &status_id).await?; if post.author.id != current_user.id { // Users can only tokenize their own posts - Err(HttpError::NotFoundError("post"))?; + return Err(HttpError::NotFoundError("post")); } let ipfs_cid = post.ipfs_cid // Post metadata is not immutable .ok_or(HttpError::ValidationError("post is not immutable".into()))?; let token_uri = get_ipfs_url(&ipfs_cid); let signature = create_mint_signature( - &contract_config, + contract_config, ¤t_user.wallet_address, &token_uri, ).map_err(|_| HttpError::InternalError)?; diff --git a/src/models/cleanup.rs b/src/models/cleanup.rs index c51d336..7dfa337 100644 --- a/src/models/cleanup.rs +++ b/src/models/cleanup.rs @@ -13,7 +13,7 @@ pub struct DeletionQueue { impl DeletionQueue { pub async fn process(self, config: &Config) -> () { remove_files(self.files, &config.media_dir()); - if self.ipfs_objects.len() > 0 { + if self.ipfs_objects.is_empty() { match &config.ipfs_api_url { Some(ipfs_api_url) => { ipfs_store::remove(ipfs_api_url, self.ipfs_objects).await diff --git a/src/models/notifications/queries.rs b/src/models/notifications/queries.rs index 0173e5f..26af265 100644 --- a/src/models/notifications/queries.rs +++ b/src/models/notifications/queries.rs @@ -93,7 +93,7 @@ pub async fn get_notifications( &[&recipient_id], ).await?; let mut notifications: Vec = rows.iter() - .map(|row| Notification::try_from(row)) + .map(Notification::try_from) .collect::>()?; let posts = notifications.iter_mut() .filter_map(|item| item.post.as_mut()) diff --git a/src/models/posts/mentions.rs b/src/models/posts/mentions.rs index 78b545d..7563212 100644 --- a/src/models/posts/mentions.rs +++ b/src/models/posts/mentions.rs @@ -53,7 +53,7 @@ pub fn replace_mentions( ) -> String { let mention_re = Regex::new(MENTION_RE).unwrap(); let result = mention_re.replace_all(text, |caps: &Captures| { - let acct = pattern_to_acct(&caps, instance_host); + let acct = pattern_to_acct(caps, instance_host); match mention_map.get(&acct) { Some(profile) => { // Replace with a link diff --git a/src/models/posts/queries.rs b/src/models/posts/queries.rs index b23021c..4aabdfd 100644 --- a/src/models/posts/queries.rs +++ b/src/models/posts/queries.rs @@ -63,7 +63,7 @@ pub async fn get_home_timeline( &[¤t_user_id], ).await?; let posts: Vec = rows.iter() - .map(|row| Post::try_from(row)) + .map(Post::try_from) .collect::>()?; Ok(posts) } @@ -98,7 +98,7 @@ pub async fn get_posts_by_author( &[&account_id], ).await?; let posts: Vec = rows.iter() - .map(|row| Post::try_from(row)) + .map(Post::try_from) .collect::>()?; Ok(posts) } @@ -257,9 +257,9 @@ pub async fn get_thread( &[&post_id], ).await?; let posts: Vec = rows.iter() - .map(|row| Post::try_from(row)) + .map(Post::try_from) .collect::>()?; - if posts.len() == 0 { + if posts.is_empty() { return Err(DatabaseError::NotFound("post")); } Ok(posts) diff --git a/src/models/posts/types.rs b/src/models/posts/types.rs index 6c99eb0..3aa1185 100644 --- a/src/models/posts/types.rs +++ b/src/models/posts/types.rs @@ -125,7 +125,7 @@ impl PostCreateData { pub fn validate(&mut self) -> Result<(), ValidationError> { let content_safe = clean_html(&self.content); let content_trimmed = content_safe.trim(); - if content_trimmed == "" { + if content_trimmed.is_empty() { return Err(ValidationError("post can not be empty")); } self.content = content_trimmed.to_string(); diff --git a/src/models/profiles/types.rs b/src/models/profiles/types.rs index 65a25ac..983374e 100644 --- a/src/models/profiles/types.rs +++ b/src/models/profiles/types.rs @@ -148,7 +148,7 @@ impl ProfileUpdateData { field.value = clean_html(&field.value); field }) - .filter(|field| field.name.len() > 0) + .filter(|field| !field.name.is_empty()) .collect(); // Validate extra fields if self.extra_fields.len() >= 10 { diff --git a/src/models/relationships/queries.rs b/src/models/relationships/queries.rs index da48d6f..ccbb6e6 100644 --- a/src/models/relationships/queries.rs +++ b/src/models/relationships/queries.rs @@ -45,7 +45,7 @@ pub async fn get_relationships( &[&source_id, &target_ids], ).await?; let relationships = rows.iter() - .map(|row| Relationship::try_from(row)) + .map(Relationship::try_from) .collect::>()?; Ok(relationships) } diff --git a/src/models/users/queries.rs b/src/models/users/queries.rs index 739f0d2..a58ea12 100644 --- a/src/models/users/queries.rs +++ b/src/models/users/queries.rs @@ -123,7 +123,7 @@ pub async fn create_user( &[&invite_code], ).await?; if updated_count == 0 { - Err(DatabaseError::NotFound("invite code"))?; + return Err(DatabaseError::NotFound("invite code")); } } // Create profile diff --git a/src/utils/crypto.rs b/src/utils/crypto.rs index 9bf7d9e..516b601 100644 --- a/src/utils/crypto.rs +++ b/src/utils/crypto.rs @@ -34,7 +34,7 @@ pub fn serialize_private_key( pub fn deserialize_private_key( private_key_pem: &str, ) -> Result { - RsaPrivateKey::from_pkcs8_pem(&private_key_pem) + RsaPrivateKey::from_pkcs8_pem(private_key_pem) } pub fn get_public_key_pem( @@ -47,7 +47,7 @@ pub fn get_public_key_pem( pub fn deserialize_public_key( public_key_pem: &str, ) -> Result { - RsaPublicKey::from_public_key_pem(&public_key_pem.trim()) + RsaPublicKey::from_public_key_pem(public_key_pem.trim()) } pub fn sign_message( diff --git a/src/utils/files.rs b/src/utils/files.rs index eedef80..b2226af 100644 --- a/src/utils/files.rs +++ b/src/utils/files.rs @@ -1,6 +1,6 @@ use std::fs::{remove_file, File}; use std::io::prelude::*; -use std::path::PathBuf; +use std::path::Path; use mime_guess::get_mime_extensions_str; use mime_sniffer::MimeTypeSniffer; @@ -18,7 +18,7 @@ pub enum FileError { InvalidMediaType, } -pub fn save_file(data: Vec, output_dir: &PathBuf) -> Result { +pub fn save_file(data: Vec, output_dir: &Path) -> Result { let digest = Sha256::digest(&data); let mut file_name = hex::encode(digest); let maybe_extension = data.sniff_mime_type() @@ -34,13 +34,13 @@ pub fn save_file(data: Vec, output_dir: &PathBuf) -> Result) -> Option { +fn sniff_media_type(data: &[u8]) -> Option { data.sniff_mime_type().map(|val| val.to_string()) } pub fn save_b64_file( b64data: &str, - output_dir: &PathBuf, + output_dir: &Path, ) -> Result<(String, Option), FileError> { let data = base64::decode(b64data)?; let media_type = sniff_media_type(&data); @@ -50,7 +50,7 @@ pub fn save_b64_file( pub fn save_validated_b64_file( b64data: &str, - output_dir: &PathBuf, + output_dir: &Path, media_type_prefix: &str, ) -> Result<(String, String), FileError> { let data = base64::decode(b64data)?; @@ -67,7 +67,7 @@ pub fn get_file_url(instance_url: &str, file_name: &str) -> String { format!("{}/media/{}", instance_url, file_name) } -pub fn remove_files(files: Vec, from_dir: &PathBuf) -> () { +pub fn remove_files(files: Vec, from_dir: &Path) -> () { for file_name in files { let file_path = from_dir.join(&file_name); let file_path_str = file_path.to_string_lossy(); diff --git a/src/webfinger/views.rs b/src/webfinger/views.rs index 1a23e60..66356bc 100644 --- a/src/webfinger/views.rs +++ b/src/webfinger/views.rs @@ -6,7 +6,7 @@ use crate::activitypub::views::get_actor_url; use crate::activitypub::constants::ACTIVITY_CONTENT_TYPE; use crate::config::{Config, Instance}; use crate::database::{Pool, get_database_client}; -use crate::errors::HttpError; +use crate::errors::{HttpError, ValidationError}; use crate::models::users::queries::is_registered_user; use super::types::{ JRD_CONTENT_TYPE, @@ -24,22 +24,22 @@ async fn get_user_info( // https://datatracker.ietf.org/doc/html/rfc7565#section-7 let uri_regexp = Regex::new(r"acct:(?P\w+)@(?P.+)").unwrap(); let uri_caps = uri_regexp.captures(&query_params.resource) - .ok_or(HttpError::ValidationError("invalid query target".into()))?; + .ok_or(ValidationError("invalid query target"))?; let username = uri_caps.name("user") - .ok_or(HttpError::ValidationError("invalid query target".into()))? + .ok_or(ValidationError("invalid query target"))? .as_str(); let instance_host = uri_caps.name("instance") - .ok_or(HttpError::ValidationError("invalid query target".into()))? + .ok_or(ValidationError("invalid query target"))? .as_str(); if instance_host != instance.host() { // Wrong instance return Err(HttpError::NotFoundError("user")); } - if !is_registered_user(db_client, &username).await? { + if !is_registered_user(db_client, username).await? { return Err(HttpError::NotFoundError("user")); } - let actor_url = get_actor_url(&instance.url(), &username); + let actor_url = get_actor_url(&instance.url(), username); let link = Link { rel: "self".to_string(), link_type: Some(ACTIVITY_CONTENT_TYPE.to_string()),