mirror of
https://github.com/LemmyNet/lemmy.git
synced 2025-09-02 19:23:49 +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"
|
||||
version = "1.0.0-alpha.5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"diesel",
|
||||
"diesel-async",
|
||||
|
|
|
@ -25,6 +25,7 @@ full = [
|
|||
"lemmy_db_views_api_misc/full",
|
||||
"lemmy_db_views_person/full",
|
||||
"lemmy_db_views_readable_federation_state/full",
|
||||
"anyhow",
|
||||
]
|
||||
ts-rs = ["dep:ts-rs"]
|
||||
|
||||
|
@ -42,3 +43,4 @@ serde = { workspace = true }
|
|||
serde_with = { workspace = true }
|
||||
ts-rs = { workspace = true, optional = true }
|
||||
url = { workspace = true }
|
||||
anyhow = { workspace = true, optional = true }
|
||||
|
|
|
@ -40,7 +40,7 @@ impl SiteView {
|
|||
Ok(local_site)
|
||||
})
|
||||
.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 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_db_schema::{
|
||||
source::{
|
||||
|
@ -11,8 +16,9 @@ use lemmy_db_schema::{
|
|||
site::{Site, SiteInsertForm},
|
||||
},
|
||||
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_utils::{
|
||||
error::{LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||
|
@ -22,89 +28,100 @@ use tracing::info;
|
|||
use url::Url;
|
||||
|
||||
pub async fn setup_local_site(pool: &mut DbPool<'_>, settings: &Settings) -> LemmyResult<SiteView> {
|
||||
// Check to see if local_site exists
|
||||
if let Ok(site_view) = SiteView::read_local(pool).await {
|
||||
return Ok(site_view);
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
// Check to see if local_site exists, without the cache wrapper
|
||||
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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue