mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-11-23 06:58:52 +00:00
Merge branch 'main' into content_removal_remote_users
This commit is contained in:
commit
8da51cd6c1
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2755,6 +2755,7 @@ dependencies = [
|
|||
"diesel",
|
||||
"diesel-async",
|
||||
"lemmy_db_schema",
|
||||
"lemmy_utils",
|
||||
"pretty_assertions",
|
||||
"serde",
|
||||
"serde_with",
|
||||
|
|
|
@ -422,17 +422,19 @@ pub async fn send_password_reset_email(
|
|||
// Generate a random token
|
||||
let token = uuid::Uuid::new_v4().to_string();
|
||||
|
||||
// Insert the row
|
||||
let local_user_id = user.local_user.id;
|
||||
PasswordResetRequest::create_token(pool, local_user_id, token.clone()).await?;
|
||||
|
||||
let email = &user.local_user.email.clone().expect("email");
|
||||
let lang = get_interface_language(user);
|
||||
let subject = &lang.password_reset_subject(&user.person.name);
|
||||
let protocol_and_hostname = settings.get_protocol_and_hostname();
|
||||
let reset_link = format!("{}/password_change/{}", protocol_and_hostname, &token);
|
||||
let body = &lang.password_reset_body(reset_link, &user.person.name);
|
||||
send_email(subject, email, &user.person.name, body, settings).await
|
||||
send_email(subject, email, &user.person.name, body, settings).await?;
|
||||
|
||||
// Insert the row after successful send, to avoid using daily reset limit while
|
||||
// email sending is broken.
|
||||
let local_user_id = user.local_user.id;
|
||||
PasswordResetRequest::create_token(pool, local_user_id, token.clone()).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Send a verification email
|
||||
|
|
|
@ -104,6 +104,7 @@ pub async fn search(
|
|||
users = PersonQuery {
|
||||
sort,
|
||||
search_term: (Some(q)),
|
||||
listing_type: (listing_type),
|
||||
page: (page),
|
||||
limit: (limit),
|
||||
}
|
||||
|
@ -174,6 +175,7 @@ pub async fn search(
|
|||
PersonQuery {
|
||||
sort,
|
||||
search_term: (Some(q)),
|
||||
listing_type: (listing_type),
|
||||
page: (page),
|
||||
limit: (limit),
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ serial_test = { workspace = true }
|
|||
tokio = { workspace = true }
|
||||
pretty_assertions = { workspace = true }
|
||||
url.workspace = true
|
||||
lemmy_utils.workspace = true
|
||||
|
||||
[package.metadata.cargo-machete]
|
||||
ignored = ["strum"]
|
||||
|
|
|
@ -23,6 +23,7 @@ use lemmy_db_schema::{
|
|||
Queries,
|
||||
ReadFn,
|
||||
},
|
||||
ListingType,
|
||||
SortType,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -115,6 +116,15 @@ fn queries<'a>(
|
|||
|
||||
let (limit, offset) = limit_and_offset(options.page, options.limit)?;
|
||||
query = query.limit(limit).offset(offset);
|
||||
|
||||
if let Some(listing_type) = options.listing_type {
|
||||
query = match listing_type {
|
||||
// return nothing as its not possible to follow users
|
||||
ListingType::Subscribed => query.limit(0),
|
||||
ListingType::Local => query.filter(person::local.eq(true)),
|
||||
_ => query,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
query.load::<PersonView>(&mut conn).await
|
||||
|
@ -141,6 +151,7 @@ impl PersonView {
|
|||
pub struct PersonQuery {
|
||||
pub sort: Option<SortType>,
|
||||
pub search_term: Option<String>,
|
||||
pub listing_type: Option<ListingType>,
|
||||
pub page: Option<i64>,
|
||||
pub limit: Option<i64>,
|
||||
}
|
||||
|
@ -168,6 +179,7 @@ mod tests {
|
|||
traits::Crud,
|
||||
utils::build_db_pool_for_tests,
|
||||
};
|
||||
use lemmy_utils::error::LemmyResult;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
|
||||
|
@ -178,64 +190,59 @@ mod tests {
|
|||
bob_local_user: LocalUser,
|
||||
}
|
||||
|
||||
async fn init_data(pool: &mut DbPool<'_>) -> Data {
|
||||
let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string())
|
||||
.await
|
||||
.unwrap();
|
||||
async fn init_data(pool: &mut DbPool<'_>) -> LemmyResult<Data> {
|
||||
let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string()).await?;
|
||||
|
||||
let alice_form = PersonInsertForm::builder()
|
||||
.name("alice".to_string())
|
||||
.public_key("pubkey".to_string())
|
||||
.instance_id(inserted_instance.id)
|
||||
.local(Some(true))
|
||||
.build();
|
||||
let alice = Person::create(pool, &alice_form).await.unwrap();
|
||||
let alice = Person::create(pool, &alice_form).await?;
|
||||
let alice_local_user_form = LocalUserInsertForm::builder()
|
||||
.person_id(alice.id)
|
||||
.password_encrypted(String::new())
|
||||
.build();
|
||||
let alice_local_user = LocalUser::create(pool, &alice_local_user_form)
|
||||
.await
|
||||
.unwrap();
|
||||
let alice_local_user = LocalUser::create(pool, &alice_local_user_form).await?;
|
||||
|
||||
let bob_form = PersonInsertForm::builder()
|
||||
.name("bob".to_string())
|
||||
.bot_account(Some(true))
|
||||
.public_key("pubkey".to_string())
|
||||
.instance_id(inserted_instance.id)
|
||||
.local(Some(false))
|
||||
.build();
|
||||
let bob = Person::create(pool, &bob_form).await.unwrap();
|
||||
let bob = Person::create(pool, &bob_form).await?;
|
||||
let bob_local_user_form = LocalUserInsertForm::builder()
|
||||
.person_id(bob.id)
|
||||
.password_encrypted(String::new())
|
||||
.build();
|
||||
let bob_local_user = LocalUser::create(pool, &bob_local_user_form).await.unwrap();
|
||||
let bob_local_user = LocalUser::create(pool, &bob_local_user_form).await?;
|
||||
|
||||
Data {
|
||||
Ok(Data {
|
||||
alice,
|
||||
alice_local_user,
|
||||
bob,
|
||||
bob_local_user,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async fn cleanup(data: Data, pool: &mut DbPool<'_>) {
|
||||
LocalUser::delete(pool, data.alice_local_user.id)
|
||||
.await
|
||||
.unwrap();
|
||||
LocalUser::delete(pool, data.bob_local_user.id)
|
||||
.await
|
||||
.unwrap();
|
||||
Person::delete(pool, data.alice.id).await.unwrap();
|
||||
Person::delete(pool, data.bob.id).await.unwrap();
|
||||
Instance::delete(pool, data.bob.instance_id).await.unwrap();
|
||||
async fn cleanup(data: Data, pool: &mut DbPool<'_>) -> LemmyResult<()> {
|
||||
LocalUser::delete(pool, data.alice_local_user.id).await?;
|
||||
LocalUser::delete(pool, data.bob_local_user.id).await?;
|
||||
Person::delete(pool, data.alice.id).await?;
|
||||
Person::delete(pool, data.bob.id).await?;
|
||||
Instance::delete(pool, data.bob.instance_id).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn exclude_deleted() {
|
||||
async fn exclude_deleted() -> LemmyResult<()> {
|
||||
let pool = &build_db_pool_for_tests().await;
|
||||
let pool = &mut pool.into();
|
||||
let data = init_data(pool).await;
|
||||
let data = init_data(pool).await?;
|
||||
|
||||
Person::update(
|
||||
pool,
|
||||
|
@ -245,8 +252,7 @@ mod tests {
|
|||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
.await?;
|
||||
|
||||
let read = PersonView::read(pool, data.alice.id).await;
|
||||
assert_eq!(read.err(), Some(NotFound));
|
||||
|
@ -256,20 +262,19 @@ mod tests {
|
|||
..Default::default()
|
||||
}
|
||||
.list(pool)
|
||||
.await
|
||||
.unwrap();
|
||||
.await?;
|
||||
assert_length!(1, list);
|
||||
assert_eq!(list[0].person.id, data.bob.id);
|
||||
|
||||
cleanup(data, pool).await;
|
||||
cleanup(data, pool).await
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn list_banned() {
|
||||
async fn list_banned() -> LemmyResult<()> {
|
||||
let pool = &build_db_pool_for_tests().await;
|
||||
let pool = &mut pool.into();
|
||||
let data = init_data(pool).await;
|
||||
let data = init_data(pool).await?;
|
||||
|
||||
Person::update(
|
||||
pool,
|
||||
|
@ -279,22 +284,21 @@ mod tests {
|
|||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
.await?;
|
||||
|
||||
let list = PersonView::banned(pool).await.unwrap();
|
||||
let list = PersonView::banned(pool).await?;
|
||||
assert_length!(1, list);
|
||||
assert_eq!(list[0].person.id, data.alice.id);
|
||||
|
||||
cleanup(data, pool).await;
|
||||
cleanup(data, pool).await
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn list_admins() {
|
||||
async fn list_admins() -> LemmyResult<()> {
|
||||
let pool = &build_db_pool_for_tests().await;
|
||||
let pool = &mut pool.into();
|
||||
let data = init_data(pool).await;
|
||||
let data = init_data(pool).await?;
|
||||
|
||||
LocalUser::update(
|
||||
pool,
|
||||
|
@ -304,22 +308,45 @@ mod tests {
|
|||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
.await?;
|
||||
|
||||
let list = PersonView::admins(pool).await.unwrap();
|
||||
let list = PersonView::admins(pool).await?;
|
||||
assert_length!(1, list);
|
||||
assert_eq!(list[0].person.id, data.alice.id);
|
||||
|
||||
let is_admin = PersonView::read(pool, data.alice.id)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_admin;
|
||||
let is_admin = PersonView::read(pool, data.alice.id).await?.is_admin;
|
||||
assert!(is_admin);
|
||||
|
||||
let is_admin = PersonView::read(pool, data.bob.id).await.unwrap().is_admin;
|
||||
let is_admin = PersonView::read(pool, data.bob.id).await?.is_admin;
|
||||
assert!(!is_admin);
|
||||
|
||||
cleanup(data, pool).await;
|
||||
cleanup(data, pool).await
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn listing_type() -> LemmyResult<()> {
|
||||
let pool = &build_db_pool_for_tests().await;
|
||||
let pool = &mut pool.into();
|
||||
let data = init_data(pool).await?;
|
||||
|
||||
let list = PersonQuery {
|
||||
listing_type: Some(ListingType::Local),
|
||||
..Default::default()
|
||||
}
|
||||
.list(pool)
|
||||
.await?;
|
||||
assert_length!(1, list);
|
||||
assert_eq!(list[0].person.id, data.alice.id);
|
||||
|
||||
let list = PersonQuery {
|
||||
listing_type: Some(ListingType::All),
|
||||
..Default::default()
|
||||
}
|
||||
.list(pool)
|
||||
.await?;
|
||||
assert_length!(2, list);
|
||||
|
||||
cleanup(data, pool).await
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,14 +158,6 @@ impl InstanceWorker {
|
|||
latest_id
|
||||
};
|
||||
if id >= latest_id {
|
||||
if id > latest_id {
|
||||
tracing::error!(
|
||||
"{}: last successful id {} is higher than latest id {} in database (did the db get cleared?)",
|
||||
self.instance.domain,
|
||||
id.0,
|
||||
latest_id.0
|
||||
);
|
||||
}
|
||||
// no more work to be done, wait before rechecking
|
||||
tokio::select! {
|
||||
() = sleep(*WORK_FINISHED_RECHECK_DELAY) => {},
|
||||
|
|
|
@ -209,11 +209,7 @@ cfg_if! {
|
|||
impl fmt::Display for LemmyError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}: ", &self.error_type)?;
|
||||
// print anyhow including trace
|
||||
// https://docs.rs/anyhow/latest/anyhow/struct.Error.html#display-representations
|
||||
// this will print the anyhow trace (only if it exists)
|
||||
// and if RUST_BACKTRACE=1, also a full backtrace
|
||||
writeln!(f, "{:?}", self.inner)?;
|
||||
writeln!(f, "{}", self.inner)?;
|
||||
fmt::Display::fmt(&self.context, f)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue