diff --git a/.woodpecker.yml b/.woodpecker.yml index 6b9126bff..6e30293de 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -85,7 +85,6 @@ steps: - if [[ "$IGNORED" ]]; then echo "Ignored files present:\n$IGNORED\n"; exit 1; fi restore-cache: - group: format image: meltwater/drone-cache:v1 pull: true settings: @@ -105,7 +104,6 @@ steps: - ".cargo_home" - "target" - "api_tests/node_modules" - exit_code: true secrets: [MINIO_ENDPOINT, MINIO_WRITE_USER, MINIO_WRITE_PASSWORD, MINIO_BUCKET] when: *slow_check_paths @@ -232,7 +230,6 @@ steps: - ".cargo_home" - "target" - "api_tests/node_modules" - exit_code: true secrets: [MINIO_ENDPOINT, MINIO_WRITE_USER, MINIO_WRITE_PASSWORD, MINIO_BUCKET] when: diff --git a/Cargo.lock b/Cargo.lock index 0c3144d51..5589c610c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2523,7 +2523,7 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lemmy_api" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "activitypub_federation", "actix-web", @@ -2551,7 +2551,7 @@ dependencies = [ [[package]] name = "lemmy_api_common" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "activitypub_federation", "actix-web", @@ -2585,7 +2585,7 @@ dependencies = [ [[package]] name = "lemmy_api_crud" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "activitypub_federation", "actix-web", @@ -2607,7 +2607,7 @@ dependencies = [ [[package]] name = "lemmy_apub" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "activitypub_federation", "actix-web", @@ -2646,7 +2646,7 @@ dependencies = [ [[package]] name = "lemmy_db_schema" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "activitypub_federation", "async-trait", @@ -2682,7 +2682,7 @@ dependencies = [ [[package]] name = "lemmy_db_views" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "actix-web", "chrono", @@ -2701,7 +2701,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_actor" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "chrono", "diesel", @@ -2718,7 +2718,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_moderator" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "diesel", "diesel-async", @@ -2730,7 +2730,7 @@ dependencies = [ [[package]] name = "lemmy_federate" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "activitypub_federation", "anyhow", @@ -2753,7 +2753,7 @@ dependencies = [ [[package]] name = "lemmy_routes" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "activitypub_federation", "actix-web", @@ -2777,7 +2777,7 @@ dependencies = [ [[package]] name = "lemmy_server" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "activitypub_federation", "actix-cors", @@ -2819,7 +2819,7 @@ dependencies = [ [[package]] name = "lemmy_utils" -version = "0.19.0-rc.16" +version = "0.19.0" dependencies = [ "actix-web", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index a64a82bf7..75d2852c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace.package] -version = "0.19.0-rc.16" +version = "0.19.0" edition = "2021" description = "A link aggregator for the fediverse" license = "AGPL-3.0" @@ -84,16 +84,16 @@ unused_self = "deny" unwrap_used = "deny" [workspace.dependencies] -lemmy_api = { version = "=0.19.0-rc.16", path = "./crates/api" } -lemmy_api_crud = { version = "=0.19.0-rc.16", path = "./crates/api_crud" } -lemmy_apub = { version = "=0.19.0-rc.16", path = "./crates/apub" } -lemmy_utils = { version = "=0.19.0-rc.16", path = "./crates/utils" } -lemmy_db_schema = { version = "=0.19.0-rc.16", path = "./crates/db_schema" } -lemmy_api_common = { version = "=0.19.0-rc.16", path = "./crates/api_common" } -lemmy_routes = { version = "=0.19.0-rc.16", path = "./crates/routes" } -lemmy_db_views = { version = "=0.19.0-rc.16", path = "./crates/db_views" } -lemmy_db_views_actor = { version = "=0.19.0-rc.16", path = "./crates/db_views_actor" } -lemmy_db_views_moderator = { version = "=0.19.0-rc.16", path = "./crates/db_views_moderator" } +lemmy_api = { version = "=0.19.0", path = "./crates/api" } +lemmy_api_crud = { version = "=0.19.0", path = "./crates/api_crud" } +lemmy_apub = { version = "=0.19.0", path = "./crates/apub" } +lemmy_utils = { version = "=0.19.0", path = "./crates/utils" } +lemmy_db_schema = { version = "=0.19.0", path = "./crates/db_schema" } +lemmy_api_common = { version = "=0.19.0", path = "./crates/api_common" } +lemmy_routes = { version = "=0.19.0", path = "./crates/routes" } +lemmy_db_views = { version = "=0.19.0", path = "./crates/db_views" } +lemmy_db_views_actor = { version = "=0.19.0", path = "./crates/db_views_actor" } +lemmy_db_views_moderator = { version = "=0.19.0", path = "./crates/db_views_moderator" } activitypub_federation = { version = "0.5.0-beta.6", default-features = false, features = [ "actix-web", ] } @@ -164,7 +164,7 @@ lemmy_utils = { workspace = true } lemmy_db_schema = { workspace = true } lemmy_api_common = { workspace = true } lemmy_routes = { workspace = true } -lemmy_federate = { version = "0.19.0-rc.16", path = "crates/federate" } +lemmy_federate = { version = "0.19.0", path = "crates/federate" } activitypub_federation = { workspace = true } diesel = { workspace = true } diesel-async = { workspace = true } diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index 35bc8314a..aef399c59 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -59,52 +59,55 @@ impl Comment { ) -> Result { let conn = &mut get_conn(pool).await?; - // Insert, to get the id - let inserted_comment = insert_into(comment) - .values(comment_form) - .on_conflict(ap_id) - .do_update() - .set(comment_form) - .get_result::(conn) - .await; + conn + .build_transaction() + .run(|conn| { + Box::pin(async move { + // Insert, to get the id + let inserted_comment = insert_into(comment) + .values(comment_form) + .on_conflict(ap_id) + .do_update() + .set(comment_form) + .get_result::(conn) + .await?; - if let Ok(comment_insert) = inserted_comment { - let comment_id = comment_insert.id; + let comment_id = inserted_comment.id; - // You need to update the ltree column - let ltree = Ltree(if let Some(parent_path) = parent_path { - // The previous parent will already have 0 in it - // Append this comment id - format!("{}.{}", parent_path.0, comment_id) - } else { - // '0' is always the first path, append to that - format!("{}.{}", 0, comment_id) - }); + // You need to update the ltree column + let ltree = Ltree(if let Some(parent_path) = parent_path { + // The previous parent will already have 0 in it + // Append this comment id + format!("{}.{}", parent_path.0, comment_id) + } else { + // '0' is always the first path, append to that + format!("{}.{}", 0, comment_id) + }); - let updated_comment = diesel::update(comment.find(comment_id)) - .set(path.eq(ltree)) - .get_result::(conn) - .await; + let updated_comment = diesel::update(comment.find(comment_id)) + .set(path.eq(ltree)) + .get_result::(conn) + .await; - // Update the child count for the parent comment_aggregates - // You could do this with a trigger, but since you have to do this manually anyway, - // you can just have it here - if let Some(parent_path) = parent_path { - // You have to update counts for all parents, not just the immediate one - // TODO if the performance of this is terrible, it might be better to do this as part of a - // scheduled query... although the counts would often be wrong. - // - // The child_count query for reference: - // select c.id, c.path, count(c2.id) as child_count from comment c - // left join comment c2 on c2.path <@ c.path and c2.path != c.path - // group by c.id + // Update the child count for the parent comment_aggregates + // You could do this with a trigger, but since you have to do this manually anyway, + // you can just have it here + if let Some(parent_path) = parent_path { + // You have to update counts for all parents, not just the immediate one + // TODO if the performance of this is terrible, it might be better to do this as part of a + // scheduled query... although the counts would often be wrong. + // + // The child_count query for reference: + // select c.id, c.path, count(c2.id) as child_count from comment c + // left join comment c2 on c2.path <@ c.path and c2.path != c.path + // group by c.id - let parent_id = parent_path.0.split('.').nth(1); + let parent_id = parent_path.0.split('.').nth(1); - if let Some(parent_id) = parent_id { - let top_parent = format!("0.{}", parent_id); - let update_child_count_stmt = format!( - " + if let Some(parent_id) = parent_id { + let top_parent = format!("0.{}", parent_id); + let update_child_count_stmt = format!( + " update comment_aggregates ca set child_count = c.child_count from ( select c.id, c.path, count(c2.id) as child_count from comment c @@ -113,15 +116,15 @@ from ( group by c.id ) as c where ca.comment_id = c.id" - ); + ); - sql_query(update_child_count_stmt).execute(conn).await?; - } - } - updated_comment - } else { - inserted_comment - } + sql_query(update_child_count_stmt).execute(conn).await?; + } + } + updated_comment + }) as _ + }) + .await } pub async fn read_from_apub_id( pool: &mut DbPool<'_>, diff --git a/crates/db_schema/src/impls/instance.rs b/crates/db_schema/src/impls/instance.rs index 7da4ce354..7d63c9ffa 100644 --- a/crates/db_schema/src/impls/instance.rs +++ b/crates/db_schema/src/impls/instance.rs @@ -13,12 +13,17 @@ use crate::{ federation_queue_state::FederationQueueState, instance::{Instance, InstanceForm}, }, - utils::{functions::lower, get_conn, naive_now, now, DbPool}, + utils::{ + functions::{coalesce, lower}, + get_conn, + naive_now, + now, + DbPool, + }, }; use diesel::{ dsl::{count_star, insert_into}, result::Error, - sql_types::{Nullable, Timestamptz}, ExpressionMethods, NullableExpressionMethods, QueryDsl, @@ -157,5 +162,3 @@ impl Instance { .await } } - -sql_function! { fn coalesce(x: Nullable, y: Timestamptz) -> Timestamptz; } diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index d65fd2398..4f2f88cb2 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -1,4 +1,3 @@ -use super::instance::coalesce; use crate::{ newtypes::{CommunityId, DbUrl, PersonId, PostId}, schema::post::dsl::{ @@ -30,6 +29,7 @@ use crate::{ }, traits::{Crud, Likeable, Saveable}, utils::{ + functions::coalesce, get_conn, naive_now, DbPool, diff --git a/crates/db_views/src/local_user_view.rs b/crates/db_views/src/local_user_view.rs index dd0e3631b..cb9ab86c4 100644 --- a/crates/db_views/src/local_user_view.rs +++ b/crates/db_views/src/local_user_view.rs @@ -5,7 +5,14 @@ use diesel_async::RunQueryDsl; use lemmy_db_schema::{ newtypes::{LocalUserId, PersonId}, schema::{local_user, person, person_aggregates}, - utils::{functions::lower, DbConn, DbPool, ListFn, Queries, ReadFn}, + utils::{ + functions::{coalesce, lower}, + DbConn, + DbPool, + ListFn, + Queries, + ReadFn, + }, }; use lemmy_utils::error::{LemmyError, LemmyErrorType}; use std::future::{ready, Ready}; @@ -34,7 +41,9 @@ fn queries<'a>( let mut query = local_user::table.into_boxed(); query = match search { ReadBy::Id(local_user_id) => query.filter(local_user::id.eq(local_user_id)), - ReadBy::Email(from_email) => query.filter(local_user::email.eq(from_email)), + ReadBy::Email(from_email) => { + query.filter(lower(coalesce(local_user::email, "")).eq(from_email.to_lowercase())) + } _ => query, }; let mut query = query.inner_join(person::table); @@ -43,8 +52,8 @@ fn queries<'a>( ReadBy::Name(name) => query.filter(lower(person::name).eq(name.to_lowercase())), ReadBy::NameOrEmail(name_or_email) => query.filter( lower(person::name) - .eq(lower(name_or_email)) - .or(local_user::email.eq(name_or_email)), + .eq(lower(name_or_email.to_lowercase())) + .or(lower(coalesce(local_user::email, "")).eq(name_or_email.to_lowercase())), ), _ => query, }; diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 36dc0ee89..087bc1ec0 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -4,7 +4,6 @@ use diesel::{ dsl::{exists, not, IntervalDsl}, pg::Pg, result::Error, - sql_function, sql_types, BoolExpressionMethods, BoxableExpression, @@ -38,14 +37,23 @@ use lemmy_db_schema::{ post_read, post_saved, }, - utils::{fuzzy_search, get_conn, limit_and_offset, now, DbConn, DbPool, ListFn, Queries, ReadFn}, + utils::{ + functions::coalesce, + fuzzy_search, + get_conn, + limit_and_offset, + now, + DbConn, + DbPool, + ListFn, + Queries, + ReadFn, + }, ListingType, SortType, }; use tracing::debug; -sql_function!(fn coalesce(x: sql_types::Nullable, y: sql_types::BigInt) -> sql_types::BigInt); - #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum Ord { Desc, @@ -482,16 +490,10 @@ fn queries<'a>() -> Queries< query = query.filter(post_aggregates::published.gt(now() - interval)); } - let tie_breaker = match options.sort.unwrap_or(SortType::Hot) { - // A second time-based sort would not be very useful - SortType::New | SortType::Old | SortType::NewComments => None, - _ => Some((Ord::Desc, field!(published))), - }; - let sorts = [ Some((Ord::Desc, featured_field)), Some(main_sort), - tie_breaker, + Some((Ord::Desc, field!(post_id))), ]; let sorts_iter = sorts.iter().flatten(); diff --git a/crates/db_views_actor/src/person_view.rs b/crates/db_views_actor/src/person_view.rs index 16e9b3bc6..f42fa15cf 100644 --- a/crates/db_views_actor/src/person_view.rs +++ b/crates/db_views_actor/src/person_view.rs @@ -230,6 +230,7 @@ mod tests { #[tokio::test] #[serial] + #[allow(clippy::dbg_macro)] async fn exclude_deleted() { let pool = &build_db_pool_for_tests().await; let pool = &mut pool.into(); @@ -256,6 +257,7 @@ mod tests { .list(pool) .await .unwrap(); + dbg!(&list); assert_eq!(list.len(), 1); assert_eq!(list[0].person.id, data.bob.id); diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 712c3d8cf..4c1a67411 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -25,7 +25,7 @@ services: lemmy: # use "image" to pull down an already compiled lemmy. make sure to comment out "build". - # image: dessalines/lemmy:0.18.4 + # image: dessalines/lemmy:0.19.0 # platform: linux/x86_64 # no arm64 support. uncomment platform if using m1. # use "build" to build your local lemmy server image for development. make sure to comment out "image". # run: docker compose up --build @@ -55,7 +55,7 @@ services: lemmy-ui: # use "image" to pull down an already compiled lemmy-ui. make sure to comment out "build". - image: dessalines/lemmy-ui:0.19.0-rc.14 + image: dessalines/lemmy-ui:0.19.0 # platform: linux/x86_64 # no arm64 support. uncomment platform if using m1. # use "build" to build your local lemmy ui image for development. make sure to comment out "image". # run: docker compose up --build diff --git a/docker/federation/docker-compose.yml b/docker/federation/docker-compose.yml index 142267596..6e0e7f2d2 100644 --- a/docker/federation/docker-compose.yml +++ b/docker/federation/docker-compose.yml @@ -2,7 +2,7 @@ version: "3.7" x-ui-default: &ui-default init: true - image: dessalines/lemmy-ui:0.19.0-rc.3 + image: dessalines/lemmy-ui:0.19.0 # assuming lemmy-ui is cloned besides lemmy directory # build: # context: ../../../lemmy-ui