Get rid of unwrap usage in backend

This commit is contained in:
Felix Ableitner 2024-02-27 18:04:39 +01:00
parent d22654261f
commit 6dd1711e11
17 changed files with 48 additions and 40 deletions

View File

@ -23,6 +23,7 @@ hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"]
[lints.clippy] [lints.clippy]
dbg_macro = "deny" dbg_macro = "deny"
unwrap_used = "deny"
[dependencies] [dependencies]
activitypub_federation = { git = "https://github.com/LemmyNet/activitypub-federation-rust.git", branch = "optional-activity-queue", features = [ activitypub_federation = { git = "https://github.com/LemmyNet/activitypub-federation-rust.git", branch = "optional-activity-queue", features = [

View File

@ -6,6 +6,7 @@ use crate::backend::error::MyResult;
use crate::backend::federation::activities::create_article::CreateArticle; use crate::backend::federation::activities::create_article::CreateArticle;
use crate::backend::federation::activities::submit_article_update; use crate::backend::federation::activities::submit_article_update;
use crate::backend::utils::generate_article_version; use crate::backend::utils::generate_article_version;
use crate::common::utils::extract_domain;
use crate::common::utils::http_protocol_str; use crate::common::utils::http_protocol_str;
use crate::common::validation::can_edit_article; use crate::common::validation::can_edit_article;
use crate::common::LocalUserView; use crate::common::LocalUserView;
@ -38,10 +39,9 @@ pub(in crate::backend::api) async fn create_article(
let local_instance = DbInstance::read_local_instance(&data)?; let local_instance = DbInstance::read_local_instance(&data)?;
let ap_id = ObjectId::parse(&format!( let ap_id = ObjectId::parse(&format!(
"{}://{}:{}/article/{}", "{}://{}/article/{}",
http_protocol_str(), http_protocol_str(),
local_instance.ap_id.inner().host_str().unwrap(), extract_domain(&local_instance.ap_id),
local_instance.ap_id.inner().port().unwrap(),
create_article.title create_article.title
))?; ))?;
let form = DbArticleForm { let form = DbArticleForm {
@ -177,10 +177,9 @@ pub(in crate::backend::api) async fn fork_article(
let local_instance = DbInstance::read_local_instance(&data)?; let local_instance = DbInstance::read_local_instance(&data)?;
let ap_id = ObjectId::parse(&format!( let ap_id = ObjectId::parse(&format!(
"{}://{}:{}/article/{}", "{}://{}/article/{}",
http_protocol_str(), http_protocol_str(),
local_instance.ap_id.inner().domain().unwrap(), extract_domain(&local_instance.ap_id),
local_instance.ap_id.inner().port().unwrap(),
&fork_form.new_title &fork_form.new_title
))?; ))?;
let form = DbArticleForm { let form = DbArticleForm {
@ -227,7 +226,12 @@ pub(super) async fn resolve_article(
) -> MyResult<Json<ArticleView>> { ) -> MyResult<Json<ArticleView>> {
let article: DbArticle = ObjectId::from(query.id).dereference(&data).await?; let article: DbArticle = ObjectId::from(query.id).dereference(&data).await?;
let edits = DbEdit::read_for_article(&article, &data)?; let edits = DbEdit::read_for_article(&article, &data)?;
let latest_version = edits.last().unwrap().edit.hash.clone(); let latest_version = edits
.last()
.expect("has at least one edit")
.edit
.hash
.clone();
Ok(Json(ArticleView { Ok(Json(ArticleView {
article, article,
edits, edits,

View File

@ -1,9 +1,9 @@
use crate::backend::error::MyResult;
use config::Config; use config::Config;
use doku::Document; use doku::Document;
use serde::Deserialize; use serde::Deserialize;
use smart_default::SmartDefault; use smart_default::SmartDefault;
use std::net::SocketAddr; use std::net::SocketAddr;
use crate::backend::error::MyResult;
#[derive(Debug, Deserialize, PartialEq, Eq, Clone, Document, SmartDefault)] #[derive(Debug, Deserialize, PartialEq, Eq, Clone, Document, SmartDefault)]
#[serde(default)] #[serde(default)]

View File

@ -16,7 +16,6 @@ use diesel::{
}; };
use std::ops::DerefMut; use std::ops::DerefMut;
#[derive(Debug, Clone, Insertable, AsChangeset)] #[derive(Debug, Clone, Insertable, AsChangeset)]
#[diesel(table_name = article, check_for_backend(diesel::pg::Pg))] #[diesel(table_name = article, check_for_backend(diesel::pg::Pg))]
pub struct DbArticleForm { pub struct DbArticleForm {

View File

@ -10,14 +10,12 @@ use crate::common::{ApiConflict, DbArticle};
use activitypub_federation::config::Data; use activitypub_federation::config::Data;
use diesel::ExpressionMethods; use diesel::ExpressionMethods;
use diesel::{ use diesel::{
delete, insert_into, Identifiable, Insertable, QueryDsl, Queryable, RunQueryDsl, delete, insert_into, Identifiable, Insertable, QueryDsl, Queryable, RunQueryDsl, Selectable,
Selectable,
}; };
use diffy::{apply, merge, Patch}; use diffy::{apply, merge, Patch};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::ops::DerefMut; use std::ops::DerefMut;
/// A local only object which represents a merge conflict. It is created /// A local only object which represents a merge conflict. It is created
/// when a local user edit conflicts with another concurrent edit. /// when a local user edit conflicts with another concurrent edit.
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Queryable, Selectable, Identifiable)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Queryable, Selectable, Identifiable)]

View File

@ -10,7 +10,6 @@ use diesel::{insert_into, AsChangeset, Insertable, QueryDsl, RunQueryDsl};
use diffy::create_patch; use diffy::create_patch;
use std::ops::DerefMut; use std::ops::DerefMut;
#[derive(Debug, Clone, Insertable, AsChangeset)] #[derive(Debug, Clone, Insertable, AsChangeset)]
#[diesel(table_name = edit, check_for_backend(diesel::pg::Pg))] #[diesel(table_name = edit, check_for_backend(diesel::pg::Pg))]
pub struct DbEditForm { pub struct DbEditForm {

View File

@ -8,13 +8,10 @@ use activitypub_federation::fetch::collection_id::CollectionId;
use activitypub_federation::fetch::object_id::ObjectId; use activitypub_federation::fetch::object_id::ObjectId;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use diesel::ExpressionMethods; use diesel::ExpressionMethods;
use diesel::{ use diesel::{insert_into, AsChangeset, Insertable, JoinOnDsl, QueryDsl, RunQueryDsl};
insert_into, AsChangeset, Insertable, JoinOnDsl, QueryDsl, RunQueryDsl,
};
use std::fmt::Debug; use std::fmt::Debug;
use std::ops::DerefMut; use std::ops::DerefMut;
#[derive(Debug, Clone, Insertable, AsChangeset)] #[derive(Debug, Clone, Insertable, AsChangeset)]
#[diesel(table_name = instance, check_for_backend(diesel::pg::Pg))] #[diesel(table_name = instance, check_for_backend(diesel::pg::Pg))]
pub struct DbInstanceForm { pub struct DbInstanceForm {

View File

@ -5,9 +5,8 @@ use diesel::r2d2::ConnectionManager;
use diesel::r2d2::Pool; use diesel::r2d2::Pool;
use diesel::PgConnection; use diesel::PgConnection;
use diesel::{QueryDsl, RunQueryDsl}; use diesel::{QueryDsl, RunQueryDsl};
use std::ops::Deref;
use std::ops::DerefMut; use std::ops::DerefMut;
use std::sync::{Arc, Mutex};
pub mod article; pub mod article;
pub mod conflict; pub mod conflict;

View File

@ -15,7 +15,6 @@ use diesel::{ExpressionMethods, JoinOnDsl};
use diesel::{PgTextExpressionMethods, QueryDsl}; use diesel::{PgTextExpressionMethods, QueryDsl};
use std::ops::DerefMut; use std::ops::DerefMut;
#[derive(Debug, Clone, Insertable, AsChangeset)] #[derive(Debug, Clone, Insertable, AsChangeset)]
#[diesel(table_name = local_user, check_for_backend(diesel::pg::Pg))] #[diesel(table_name = local_user, check_for_backend(diesel::pg::Pg))]
pub struct DbLocalUserForm { pub struct DbLocalUserForm {

View File

@ -36,7 +36,7 @@ pub struct VerifyUrlData(pub IbisConfig);
impl UrlVerifier for VerifyUrlData { impl UrlVerifier for VerifyUrlData {
/// Check domain against allowlist and blocklist from config file. /// Check domain against allowlist and blocklist from config file.
async fn verify(&self, url: &Url) -> Result<(), ActivityPubError> { async fn verify(&self, url: &Url) -> Result<(), ActivityPubError> {
let domain = url.domain().unwrap(); let domain = url.domain().expect("url has domain");
if let Some(allowlist) = &self.0.federation.allowlist { if let Some(allowlist) = &self.0.federation.allowlist {
let allowlist = allowlist.split(',').collect::<Vec<_>>(); let allowlist = allowlist.split(',').collect::<Vec<_>>();
if !allowlist.contains(&domain) { if !allowlist.contains(&domain) {

View File

@ -57,13 +57,9 @@ impl DbInstance {
{ {
let mut inboxes: Vec<_> = DbInstance::read_followers(self.id, data)? let mut inboxes: Vec<_> = DbInstance::read_followers(self.id, data)?
.iter() .iter()
.map(|f| Url::parse(&f.inbox_url).unwrap()) .map(|f| f.inbox_url())
.collect(); .collect();
inboxes.extend( inboxes.extend(extra_recipients.into_iter().map(|i| i.inbox_url()));
extra_recipients
.into_iter()
.map(|i| Url::parse(&i.inbox_url).unwrap()),
);
send_activity(self, activity, inboxes, data).await?; send_activity(self, activity, inboxes, data).await?;
Ok(()) Ok(())
} }
@ -140,6 +136,6 @@ impl Actor for DbInstance {
} }
fn inbox(&self) -> Url { fn inbox(&self) -> Url {
Url::parse(&self.inbox_url).unwrap() self.inbox_url()
} }
} }

View File

@ -89,6 +89,6 @@ impl Actor for DbPerson {
} }
fn inbox(&self) -> Url { fn inbox(&self) -> Url {
Url::parse(&self.inbox_url).unwrap() self.inbox_url()
} }
} }

View File

@ -23,7 +23,7 @@ use axum::{middleware::Next, response::Response, Router};
use chrono::Local; use chrono::Local;
use diesel::r2d2::ConnectionManager; use diesel::r2d2::ConnectionManager;
use diesel::r2d2::Pool; use diesel::r2d2::Pool;
use diesel::Connection;
use diesel::PgConnection; use diesel::PgConnection;
use diesel_migrations::embed_migrations; use diesel_migrations::embed_migrations;
use diesel_migrations::EmbeddedMigrations; use diesel_migrations::EmbeddedMigrations;
@ -31,7 +31,7 @@ use diesel_migrations::MigrationHarness;
use leptos::*; use leptos::*;
use leptos_axum::{generate_route_list, LeptosRoutes}; use leptos_axum::{generate_route_list, LeptosRoutes};
use log::info; use log::info;
use std::sync::{Arc, Mutex};
use tower::Layer; use tower::Layer;
use tower_http::cors::CorsLayer; use tower_http::cors::CorsLayer;
use tower_http::services::{ServeDir, ServeFile}; use tower_http::services::{ServeDir, ServeFile};
@ -57,10 +57,7 @@ pub async fn start(config: IbisConfig) -> MyResult<()> {
.get()? .get()?
.run_pending_migrations(MIGRATIONS) .run_pending_migrations(MIGRATIONS)
.expect("run migrations"); .expect("run migrations");
let data = IbisData { let data = IbisData { db_pool, config };
db_pool,
config,
};
let data = FederationConfig::builder() let data = FederationConfig::builder()
.domain(data.config.federation.domain.clone()) .domain(data.config.federation.domain.clone())
.url_verifier(Box::new(VerifyUrlData(data.config.clone()))) .url_verifier(Box::new(VerifyUrlData(data.config.clone())))
@ -74,7 +71,7 @@ pub async fn start(config: IbisConfig) -> MyResult<()> {
setup(&data.to_request_data()).await?; setup(&data.to_request_data()).await?;
} }
let conf = get_configuration(Some("Cargo.toml")).await.unwrap(); let conf = get_configuration(Some("Cargo.toml")).await?;
let mut leptos_options = conf.leptos_options; let mut leptos_options = conf.leptos_options;
leptos_options.site_addr = data.config.bind; leptos_options.site_addr = data.config.bind;
let routes = generate_route_list(App); let routes = generate_route_list(App);
@ -186,7 +183,9 @@ async fn federation_routes_middleware<B>(request: Request<B>, next: Next<B>) ->
if uri.ends_with('/') && uri.len() > 1 { if uri.ends_with('/') && uri.len() > 1 {
uri.pop(); uri.pop();
} }
parts.uri = uri.parse().unwrap(); parts.uri = uri
.parse()
.expect("can parse uri after dropping trailing slash");
let request = Request::from_parts(parts, body); let request = Request::from_parts(parts, body);
next.run(request).await next.run(request).await

View File

@ -98,7 +98,8 @@ impl EditVersion {
let mut sha256 = Sha256::new(); let mut sha256 = Sha256::new();
sha256.update(diff); sha256.update(diff);
let hash_bytes = sha256.finalize(); let hash_bytes = sha256.finalize();
let uuid = Uuid::from_slice(&hash_bytes.as_slice()[..16]).unwrap(); let uuid =
Uuid::from_slice(&hash_bytes.as_slice()[..16]).expect("hash is correct size for uuid");
EditVersion(uuid) EditVersion(uuid)
} }
@ -167,6 +168,12 @@ pub struct DbPerson {
pub local: bool, pub local: bool,
} }
impl DbPerson {
pub fn inbox_url(&self) -> Url {
Url::parse(&self.inbox_url).expect("can parse inbox url")
}
}
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub struct CreateArticleData { pub struct CreateArticleData {
pub title: String, pub title: String,
@ -246,6 +253,12 @@ pub struct DbInstance {
pub local: bool, pub local: bool,
} }
impl DbInstance {
pub fn inbox_url(&self) -> Url {
Url::parse(&self.inbox_url).expect("can parse inbox url")
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
#[cfg_attr(feature = "ssr", derive(Queryable))] #[cfg_attr(feature = "ssr", derive(Queryable))]
#[cfg_attr(feature = "ssr", diesel(table_name = article, check_for_backend(diesel::pg::Pg)))] #[cfg_attr(feature = "ssr", diesel(table_name = article, check_for_backend(diesel::pg::Pg)))]

View File

@ -8,7 +8,7 @@ where
if let Some(port_) = url.inner().port() { if let Some(port_) = url.inner().port() {
port = format!(":{port_}"); port = format!(":{port_}");
} }
format!("{}{port}", url.inner().host_str().unwrap()) format!("{}{port}", url.inner().host_str().expect("has domain"))
} }
#[cfg(not(feature = "ssr"))] #[cfg(not(feature = "ssr"))]

View File

@ -57,7 +57,10 @@ fn backend_hostname() -> String {
} }
#[cfg(feature = "ssr")] #[cfg(feature = "ssr")]
{ {
backend_hostname = crate::backend::config::IbisConfig::read().unwrap().bind.to_string(); backend_hostname = crate::backend::config::IbisConfig::read()
.unwrap()
.bind
.to_string();
} }
backend_hostname backend_hostname
} }

View File

@ -1,4 +1,5 @@
#[cfg(feature = "ssr")] #[cfg(feature = "ssr")]
pub mod backend; pub mod backend;
pub mod common; pub mod common;
#[allow(clippy::unwrap_used)]
pub mod frontend; pub mod frontend;