mirror of
https://github.com/LemmyNet/lemmy.git
synced 2025-09-03 19:53:48 +00:00
Fix assumption that is_err always means the local site doesn't exist, which may cause the local site's keypair to be regenerated (#5724)
* Fix assumption that is_err always means the local site doesn't exst, which may cause things like keypairs to be overwritten * remove use of unstable feature * fix map_err * exists query and transaction
This commit is contained in:
parent
ba0099e7a2
commit
38e87f6dc4
4 changed files with 104 additions and 84 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -3794,6 +3794,7 @@ dependencies = [
|
||||||
name = "lemmy_db_views_site"
|
name = "lemmy_db_views_site"
|
||||||
version = "1.0.0-alpha.5"
|
version = "1.0.0-alpha.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
"diesel",
|
"diesel",
|
||||||
"diesel-async",
|
"diesel-async",
|
||||||
|
|
|
@ -25,6 +25,7 @@ full = [
|
||||||
"lemmy_db_views_api_misc/full",
|
"lemmy_db_views_api_misc/full",
|
||||||
"lemmy_db_views_person/full",
|
"lemmy_db_views_person/full",
|
||||||
"lemmy_db_views_readable_federation_state/full",
|
"lemmy_db_views_readable_federation_state/full",
|
||||||
|
"anyhow",
|
||||||
]
|
]
|
||||||
ts-rs = ["dep:ts-rs"]
|
ts-rs = ["dep:ts-rs"]
|
||||||
|
|
||||||
|
@ -42,3 +43,4 @@ serde = { workspace = true }
|
||||||
serde_with = { workspace = true }
|
serde_with = { workspace = true }
|
||||||
ts-rs = { workspace = true, optional = true }
|
ts-rs = { workspace = true, optional = true }
|
||||||
url = { workspace = true }
|
url = { workspace = true }
|
||||||
|
anyhow = { workspace = true, optional = true }
|
||||||
|
|
|
@ -40,7 +40,7 @@ impl SiteView {
|
||||||
Ok(local_site)
|
Ok(local_site)
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.map_err(|_e: Arc<LemmyError>| LemmyErrorType::LocalSiteNotSetup.into())
|
.map_err(|e: Arc<LemmyError>| anyhow::anyhow!("err getting local site: {e:?}").into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
use activitypub_federation::http_signatures::generate_actor_keypair;
|
use activitypub_federation::http_signatures::generate_actor_keypair;
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
|
use diesel::{
|
||||||
|
dsl::{exists, not, select},
|
||||||
|
query_builder::AsQuery,
|
||||||
|
};
|
||||||
|
use diesel_async::{scoped_futures::ScopedFutureExt, RunQueryDsl};
|
||||||
use lemmy_api_utils::utils::generate_inbox_url;
|
use lemmy_api_utils::utils::generate_inbox_url;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -11,8 +16,9 @@ use lemmy_db_schema::{
|
||||||
site::{Site, SiteInsertForm},
|
site::{Site, SiteInsertForm},
|
||||||
},
|
},
|
||||||
traits::{ApubActor, Crud},
|
traits::{ApubActor, Crud},
|
||||||
utils::DbPool,
|
utils::{get_conn, DbPool},
|
||||||
};
|
};
|
||||||
|
use lemmy_db_schema_file::schema::local_site;
|
||||||
use lemmy_db_views_site::SiteView;
|
use lemmy_db_views_site::SiteView;
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
|
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||||
|
@ -22,89 +28,100 @@ use tracing::info;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub async fn setup_local_site(pool: &mut DbPool<'_>, settings: &Settings) -> LemmyResult<SiteView> {
|
pub async fn setup_local_site(pool: &mut DbPool<'_>, settings: &Settings) -> LemmyResult<SiteView> {
|
||||||
// Check to see if local_site exists
|
let conn = &mut get_conn(pool).await?;
|
||||||
if let Ok(site_view) = SiteView::read_local(pool).await {
|
// Check to see if local_site exists, without the cache wrapper
|
||||||
return Ok(site_view);
|
if select(not(exists(local_site::table.as_query())))
|
||||||
|
.get_result(conn)
|
||||||
|
.await?
|
||||||
|
{
|
||||||
|
info!("No Local Site found, creating it.");
|
||||||
|
|
||||||
|
let domain = settings
|
||||||
|
.get_hostname_without_port()
|
||||||
|
.with_lemmy_type(LemmyErrorType::Unknown("must have domain".into()))?;
|
||||||
|
|
||||||
|
conn
|
||||||
|
.run_transaction(|conn| {
|
||||||
|
async move {
|
||||||
|
// Upsert this to the instance table
|
||||||
|
let instance = Instance::read_or_create(&mut conn.into(), domain).await?;
|
||||||
|
|
||||||
|
if let Some(setup) = &settings.setup {
|
||||||
|
let person_keypair = generate_actor_keypair()?;
|
||||||
|
let person_ap_id = Person::generate_local_actor_url(&setup.admin_username, settings)?;
|
||||||
|
|
||||||
|
// Register the user if there's a site setup
|
||||||
|
let person_form = PersonInsertForm {
|
||||||
|
ap_id: Some(person_ap_id.clone()),
|
||||||
|
inbox_url: Some(generate_inbox_url()?),
|
||||||
|
private_key: Some(person_keypair.private_key.into()),
|
||||||
|
..PersonInsertForm::new(
|
||||||
|
setup.admin_username.clone(),
|
||||||
|
person_keypair.public_key,
|
||||||
|
instance.id,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let person_inserted = Person::create(&mut conn.into(), &person_form).await?;
|
||||||
|
|
||||||
|
let local_user_form = LocalUserInsertForm {
|
||||||
|
email: setup.admin_email.clone(),
|
||||||
|
admin: Some(true),
|
||||||
|
..LocalUserInsertForm::new(person_inserted.id, Some(setup.admin_password.clone()))
|
||||||
|
};
|
||||||
|
LocalUser::create(&mut conn.into(), &local_user_form, vec![]).await?;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add an entry for the site table
|
||||||
|
let site_key_pair = generate_actor_keypair()?;
|
||||||
|
let site_ap_id = Url::parse(&settings.get_protocol_and_hostname())?;
|
||||||
|
|
||||||
|
let name = settings
|
||||||
|
.setup
|
||||||
|
.clone()
|
||||||
|
.map(|s| s.site_name)
|
||||||
|
.unwrap_or_else(|| "New Site".to_string());
|
||||||
|
let site_form = SiteInsertForm {
|
||||||
|
ap_id: Some(site_ap_id.clone().into()),
|
||||||
|
last_refreshed_at: Some(Utc::now()),
|
||||||
|
inbox_url: Some(generate_inbox_url()?),
|
||||||
|
private_key: Some(site_key_pair.private_key),
|
||||||
|
public_key: Some(site_key_pair.public_key),
|
||||||
|
..SiteInsertForm::new(name, instance.id)
|
||||||
|
};
|
||||||
|
let site = Site::create(&mut conn.into(), &site_form).await?;
|
||||||
|
|
||||||
|
// Finally create the local_site row
|
||||||
|
let local_site_form = LocalSiteInsertForm {
|
||||||
|
site_setup: Some(settings.setup.is_some()),
|
||||||
|
..LocalSiteInsertForm::new(site.id)
|
||||||
|
};
|
||||||
|
let local_site = LocalSite::create(&mut conn.into(), &local_site_form).await?;
|
||||||
|
|
||||||
|
// Create the rate limit table
|
||||||
|
let local_site_rate_limit_form = if cfg!(debug_assertions) {
|
||||||
|
LocalSiteRateLimitInsertForm {
|
||||||
|
message: Some(999),
|
||||||
|
post: Some(999),
|
||||||
|
register: Some(999),
|
||||||
|
image: Some(999),
|
||||||
|
comment: Some(999),
|
||||||
|
search: Some(999),
|
||||||
|
..LocalSiteRateLimitInsertForm::new(local_site.id)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LocalSiteRateLimitInsertForm::new(local_site.id)
|
||||||
|
};
|
||||||
|
// TODO these have to be set, because the database defaults are too low for the federation
|
||||||
|
// tests to pass, and there's no way to live update the rate limits without restarting the
|
||||||
|
// server.
|
||||||
|
// This can be removed once live rate limits are enabled.
|
||||||
|
LocalSiteRateLimit::create(&mut conn.into(), &local_site_rate_limit_form).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
.scope_boxed()
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
info!("No Local Site found, creating it.");
|
|
||||||
|
|
||||||
let domain = settings
|
|
||||||
.get_hostname_without_port()
|
|
||||||
.with_lemmy_type(LemmyErrorType::Unknown("must have domain".into()))?;
|
|
||||||
|
|
||||||
// Upsert this to the instance table
|
|
||||||
let instance = Instance::read_or_create(pool, domain).await?;
|
|
||||||
|
|
||||||
if let Some(setup) = &settings.setup {
|
|
||||||
let person_keypair = generate_actor_keypair()?;
|
|
||||||
let person_ap_id = Person::generate_local_actor_url(&setup.admin_username, settings)?;
|
|
||||||
|
|
||||||
// Register the user if there's a site setup
|
|
||||||
let person_form = PersonInsertForm {
|
|
||||||
ap_id: Some(person_ap_id.clone()),
|
|
||||||
inbox_url: Some(generate_inbox_url()?),
|
|
||||||
private_key: Some(person_keypair.private_key.into()),
|
|
||||||
..PersonInsertForm::new(
|
|
||||||
setup.admin_username.clone(),
|
|
||||||
person_keypair.public_key,
|
|
||||||
instance.id,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
let person_inserted = Person::create(pool, &person_form).await?;
|
|
||||||
|
|
||||||
let local_user_form = LocalUserInsertForm {
|
|
||||||
email: setup.admin_email.clone(),
|
|
||||||
admin: Some(true),
|
|
||||||
..LocalUserInsertForm::new(person_inserted.id, Some(setup.admin_password.clone()))
|
|
||||||
};
|
|
||||||
LocalUser::create(pool, &local_user_form, vec![]).await?;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add an entry for the site table
|
|
||||||
let site_key_pair = generate_actor_keypair()?;
|
|
||||||
let site_ap_id = Url::parse(&settings.get_protocol_and_hostname())?;
|
|
||||||
|
|
||||||
let name = settings
|
|
||||||
.setup
|
|
||||||
.clone()
|
|
||||||
.map(|s| s.site_name)
|
|
||||||
.unwrap_or_else(|| "New Site".to_string());
|
|
||||||
let site_form = SiteInsertForm {
|
|
||||||
ap_id: Some(site_ap_id.clone().into()),
|
|
||||||
last_refreshed_at: Some(Utc::now()),
|
|
||||||
inbox_url: Some(generate_inbox_url()?),
|
|
||||||
private_key: Some(site_key_pair.private_key),
|
|
||||||
public_key: Some(site_key_pair.public_key),
|
|
||||||
..SiteInsertForm::new(name, instance.id)
|
|
||||||
};
|
|
||||||
let site = Site::create(pool, &site_form).await?;
|
|
||||||
|
|
||||||
// Finally create the local_site row
|
|
||||||
let local_site_form = LocalSiteInsertForm {
|
|
||||||
site_setup: Some(settings.setup.is_some()),
|
|
||||||
..LocalSiteInsertForm::new(site.id)
|
|
||||||
};
|
|
||||||
let local_site = LocalSite::create(pool, &local_site_form).await?;
|
|
||||||
|
|
||||||
// Create the rate limit table
|
|
||||||
let local_site_rate_limit_form = if cfg!(debug_assertions) {
|
|
||||||
LocalSiteRateLimitInsertForm {
|
|
||||||
message: Some(999),
|
|
||||||
post: Some(999),
|
|
||||||
register: Some(999),
|
|
||||||
image: Some(999),
|
|
||||||
comment: Some(999),
|
|
||||||
search: Some(999),
|
|
||||||
..LocalSiteRateLimitInsertForm::new(local_site.id)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LocalSiteRateLimitInsertForm::new(local_site.id)
|
|
||||||
};
|
|
||||||
// TODO these have to be set, because the database defaults are too low for the federation
|
|
||||||
// tests to pass, and there's no way to live update the rate limits without restarting the
|
|
||||||
// server.
|
|
||||||
// This can be removed once live rate limits are enabled.
|
|
||||||
LocalSiteRateLimit::create(pool, &local_site_rate_limit_form).await?;
|
|
||||||
|
|
||||||
SiteView::read_local(pool).await
|
SiteView::read_local(pool).await
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue