diff --git a/ansible/VERSION b/ansible/VERSION index 060b6164..2430a573 100644 --- a/ansible/VERSION +++ b/ansible/VERSION @@ -1 +1 @@ -v0.8.7 +v0.8.10 diff --git a/docker/dev/docker-compose.yml b/docker/dev/docker-compose.yml index 27f76b1b..a09fb8eb 100644 --- a/docker/dev/docker-compose.yml +++ b/docker/dev/docker-compose.yml @@ -16,7 +16,7 @@ services: - postgres - iframely lemmy-ui: - image: dessalines/lemmy-ui:v0.8.7 + image: dessalines/lemmy-ui:v0.8.10 ports: - "1235:1234" restart: always diff --git a/docker/federation/docker-compose.yml b/docker/federation/docker-compose.yml index e9bd6652..e32dfe2d 100644 --- a/docker/federation/docker-compose.yml +++ b/docker/federation/docker-compose.yml @@ -29,7 +29,7 @@ services: - ./volumes/pictrs_alpha:/mnt lemmy-alpha-ui: - image: dessalines/lemmy-ui:v0.8.7 + image: dessalines/lemmy-ui:v0.8.10 environment: - LEMMY_INTERNAL_HOST=lemmy-alpha:8541 - LEMMY_EXTERNAL_HOST=localhost:8541 @@ -68,7 +68,7 @@ services: - ./volumes/postgres_alpha:/var/lib/postgresql/data lemmy-beta-ui: - image: dessalines/lemmy-ui:v0.8.7 + image: dessalines/lemmy-ui:v0.8.10 environment: - LEMMY_INTERNAL_HOST=lemmy-beta:8551 - LEMMY_EXTERNAL_HOST=localhost:8551 @@ -107,7 +107,7 @@ services: - ./volumes/postgres_beta:/var/lib/postgresql/data lemmy-gamma-ui: - image: dessalines/lemmy-ui:v0.8.7 + image: dessalines/lemmy-ui:v0.8.10 environment: - LEMMY_INTERNAL_HOST=lemmy-gamma:8561 - LEMMY_EXTERNAL_HOST=localhost:8561 @@ -147,7 +147,7 @@ services: # An instance with only an allowlist for beta lemmy-delta-ui: - image: dessalines/lemmy-ui:v0.8.7 + image: dessalines/lemmy-ui:v0.8.10 environment: - LEMMY_INTERNAL_HOST=lemmy-delta:8571 - LEMMY_EXTERNAL_HOST=localhost:8571 @@ -187,7 +187,7 @@ services: # An instance who has a blocklist, with lemmy-alpha blocked lemmy-epsilon-ui: - image: dessalines/lemmy-ui:v0.8.7 + image: dessalines/lemmy-ui:v0.8.10 environment: - LEMMY_INTERNAL_HOST=lemmy-epsilon:8581 - LEMMY_EXTERNAL_HOST=localhost:8581 diff --git a/docker/prod/docker-compose.yml b/docker/prod/docker-compose.yml index 0e87c31b..c3d61a64 100644 --- a/docker/prod/docker-compose.yml +++ b/docker/prod/docker-compose.yml @@ -12,7 +12,7 @@ services: restart: always lemmy: - image: dessalines/lemmy:v0.8.7 + image: dessalines/lemmy:v0.8.10 ports: - "127.0.0.1:8536:8536" restart: always @@ -26,7 +26,7 @@ services: - iframely lemmy-ui: - image: dessalines/lemmy-ui:v0.8.7 + image: dessalines/lemmy-ui:v0.8.10 ports: - "1235:1234" restart: always diff --git a/docker/travis/docker_push.sh b/docker/travis/docker_push.sh index 21716661..ba77f026 100644 --- a/docker/travis/docker_push.sh +++ b/docker/travis/docker_push.sh @@ -1,5 +1,5 @@ #!/bin/sh echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin docker tag dessalines/lemmy:travis \ - dessalines/lemmy:v0.8.7 -docker push dessalines/lemmy:v0.8.7 + dessalines/lemmy:v0.8.10 +docker push dessalines/lemmy:v0.8.10 diff --git a/docs/src/about_guide.md b/docs/src/about_guide.md index 3c5e34b4..d9f8adb0 100644 --- a/docs/src/about_guide.md +++ b/docs/src/about_guide.md @@ -12,9 +12,10 @@ Start typing... Type | Description --- | --- -Hot | Shows *trending* posts, based on the score, and the most recent comment time. -New | Newest posts. -Top | Shows the highest scoring posts in the given time frame. +Active | Trending sort based on the score, and the most recent comment time. +Hot | Trending sort based on the score, and the post creation time. +New | Newest items. +Top | The highest scoring items in the given time frame. For more detail, check the [Post and Comment Ranking details](about_ranking.md). diff --git a/docs/src/about_ranking.md b/docs/src/about_ranking.md index 854b4da8..30f76ec1 100644 --- a/docs/src/about_ranking.md +++ b/docs/src/about_ranking.md @@ -1,17 +1,22 @@ # Trending / Hot / Best Sorting algorithm - -An expected feature in link aggregators is a kind of "Trending" sort which shows users a mixture of new posts / comments and popular ones, making for a display order which highlights the most currently active parts of the site / thread. This keeps the experience fresh and makes sure the site stays moving. Various flaws can be found in the ways that popular link aggregators like Reddit have implemented "Hot" or "Trending" sorts, so Lemmy has its own algorithm. - -## Goals and Considerations +## Goals - During the day, new posts and comments should be near the top, so they can be voted on. - After a day or so, the time factor should go away. - Use a log scale, since votes tend to snowball, and so the first 10 votes are just as important as the next hundred. -| Reddit | Hacker News | Lemmy | -|-|-|-| -| Does not take the lifetime of the thread into account, [giving early comments an overwhelming advantage over later ones,](https://minimaxir.com/2016/11/first-comment/) with the effect being even worse in small communities. New comments pool at the bottom of the thread, effectively killing off discussion and making each thread a race to comment early. This lowers the quality of conversation and rewards comments that are repetitive and spammy. | While far superior to Reddit's implementation for its decay of scores over time, [Hacker News' ranking algorithm](https://medium.com/hacking-and-gonzo/how-hacker-news-ranking-algorithm-works-1d9b0cf2c08d) does not use a logarithmic scale for scores. | Counterbalances the snowballing effect of votes over time with a logarithmic scale. Negates the inherent advantage of early comments while still ensuring that votes still matter in the long-term, not nuking older popular comments. | +## Implementations + +### Reddit +Does not take the lifetime of the thread into account, [giving early comments an overwhelming advantage over later ones,](https://minimaxir.com/2016/11/first-comment/) with the effect being even worse in small communities. New comments pool at the bottom of the thread, effectively killing off discussion and making each thread a race to comment early. This lowers the quality of conversation and rewards comments that are repetitive and spammy. + +### Hacker News + +While far superior to Reddit's implementation for its decay of scores over time, [Hacker News' ranking algorithm](https://medium.com/hacking-and-gonzo/how-hacker-news-ranking-algorithm-works-1d9b0cf2c08d) does not use a logarithmic scale for scores. + +### Lemmy + +Counterbalances the snowballing effect of votes over time with a logarithmic scale. Negates the inherent advantage of early comments while still ensuring that votes still matter in the long-term, not nuking older popular comments. -## Additional Details ``` Rank = ScaleFactor * log(Max(1, 3 + Score)) / (Time + 2)^Gravity diff --git a/docs/src/lemmy_council.md b/docs/src/lemmy_council.md index d5dc5a6e..7bcb3089 100644 --- a/docs/src/lemmy_council.md +++ b/docs/src/lemmy_council.md @@ -1,7 +1,6 @@ # Lemmy Council -- A group of lemmy developers and users that use a well-defined democratic process to steer the project in a positive direction, keep it aligned to community goals, and resolve conflicts. -- Council members are also added as administrators to any official Lemmy instances. +- A group of lemmy developers and users that use a well-defined democratic process to steer the project in a positive direction, keep it aligned to community goals, and resolve conflicts. ## 1. What gets voted on @@ -29,7 +28,7 @@ Every week, the council should make a thread on Lemmy that details its activity At the same time, users can give feedback and suggestions in this thread. This should be taken into account by the council. Council members can call for a vote on any controversial issues, if they can't be resolved by discussion. -## 2. Voting Process +## 3. Voting Process Most of the time, we keep each other up to date through the Matrix chat, and take informal decisions on uncontroversial issues. For example, a user clearly violating the site rules could be banned by a single person, or ideally after discussing it with at least one other member. @@ -77,3 +76,4 @@ General Contact [@LemmyDev Mastodon](https://mastodon.social/@LemmyDev) - [AgreeableLandscape](https://lemmy.ml/u/AgreeableLandscape) - [fruechtchen](https://lemmy.ml/u/fruechtchen) - [kixiQu](https://lemmy.ml/u/kixiQu) +- [Karanja](https://baraza.africa/u/mwalimu) diff --git a/lemmy_api/src/version.rs b/lemmy_api/src/version.rs index 450fd957..e44da9fb 100644 --- a/lemmy_api/src/version.rs +++ b/lemmy_api/src/version.rs @@ -1 +1 @@ -pub const VERSION: &str = "v0.8.7"; +pub const VERSION: &str = "v0.8.10"; diff --git a/lemmy_apub/src/inbox/community_inbox.rs b/lemmy_apub/src/inbox/community_inbox.rs index ad6eaffb..4bdad2fa 100644 --- a/lemmy_apub/src/inbox/community_inbox.rs +++ b/lemmy_apub/src/inbox/community_inbox.rs @@ -1,6 +1,7 @@ use crate::{ activities::receive::verify_activity_domains_valid, inbox::{ + assert_activity_not_local, get_activity_id, get_activity_to_and_cc, inbox_verify_http_signature, @@ -86,6 +87,7 @@ pub async fn community_inbox( return Err(anyhow!("Activity delivered to wrong community").into()); } + assert_activity_not_local(&activity)?; insert_activity(&activity_id, activity.clone(), false, true, context.pool()).await?; info!( diff --git a/lemmy_apub/src/inbox/mod.rs b/lemmy_apub/src/inbox/mod.rs index 8b37f5be..e04fdd0f 100644 --- a/lemmy_apub/src/inbox/mod.rs +++ b/lemmy_apub/src/inbox/mod.rs @@ -14,7 +14,7 @@ use actix_web::HttpRequest; use anyhow::{anyhow, Context}; use lemmy_db::{activity::Activity, community::Community, user::User_, ApubObject, DbPool}; use lemmy_structs::blocking; -use lemmy_utils::{location_info, LemmyError}; +use lemmy_utils::{location_info, settings::Settings, LemmyError}; use lemmy_websocket::LemmyContext; use serde::{export::fmt::Debug, Serialize}; use url::Url; @@ -151,3 +151,22 @@ pub(crate) async fn is_addressed_to_community_followers( } Ok(None) } + +pub(in crate::inbox) fn assert_activity_not_local(activity: &T) -> Result<(), LemmyError> +where + T: BaseExt + Debug, +{ + let id = activity.id_unchecked().context(location_info!())?; + let activity_domain = id.domain().context(location_info!())?; + + if activity_domain == Settings::get().hostname { + return Err( + anyhow!( + "Error: received activity which was sent by local instance: {:?}", + activity + ) + .into(), + ); + } + Ok(()) +} diff --git a/lemmy_apub/src/inbox/shared_inbox.rs b/lemmy_apub/src/inbox/shared_inbox.rs index 9b5bdd6f..826038bf 100644 --- a/lemmy_apub/src/inbox/shared_inbox.rs +++ b/lemmy_apub/src/inbox/shared_inbox.rs @@ -1,5 +1,6 @@ use crate::{ inbox::{ + assert_activity_not_local, community_inbox::{community_receive_message, CommunityAcceptedActivities}, get_activity_id, get_activity_to_and_cc, @@ -58,6 +59,7 @@ pub async fn shared_inbox( return Ok(HttpResponse::Ok().finish()); } + assert_activity_not_local(&activity)?; // Log the activity, so we avoid receiving and parsing it twice. Note that this could still happen // if we receive the same activity twice in very quick succession. insert_activity(&activity_id, activity.clone(), false, true, context.pool()).await?; diff --git a/lemmy_apub/src/inbox/user_inbox.rs b/lemmy_apub/src/inbox/user_inbox.rs index 76fa7d62..81b9f185 100644 --- a/lemmy_apub/src/inbox/user_inbox.rs +++ b/lemmy_apub/src/inbox/user_inbox.rs @@ -19,6 +19,7 @@ use crate::{ check_is_apub_id_valid, fetcher::get_or_fetch_and_upsert_community, inbox::{ + assert_activity_not_local, get_activity_id, get_activity_to_and_cc, inbox_verify_http_signature, @@ -107,6 +108,7 @@ pub async fn user_inbox( return Err(anyhow!("Activity delivered to wrong user").into()); } + assert_activity_not_local(&activity)?; insert_activity(&activity_id, activity.clone(), false, true, context.pool()).await?; debug!( diff --git a/lemmy_db/src/post_view.rs b/lemmy_db/src/post_view.rs index 3fb6d2b0..ea03c3a4 100644 --- a/lemmy_db/src/post_view.rs +++ b/lemmy_db/src/post_view.rs @@ -280,7 +280,7 @@ impl<'a> PostQueryBuilder<'a> { if let Some(for_community_name) = self.for_community_name { query = query .filter(community_name.eq(for_community_name)) - .filter(local.eq(true)) + .filter(community_local.eq(true)) .then_order_by(stickied.desc()); } diff --git a/src/routes/images.rs b/src/routes/images.rs index deaf11eb..eb3a773f 100644 --- a/src/routes/images.rs +++ b/src/routes/images.rs @@ -1,6 +1,7 @@ use actix::clock::Duration; use actix_web::{body::BodyStream, http::StatusCode, *}; use awc::Client; +use lemmy_api::claims::Claims; use lemmy_rate_limit::RateLimit; use lemmy_utils::settings::Settings; use serde::{Deserialize, Serialize}; @@ -46,7 +47,14 @@ async fn upload( body: web::Payload, client: web::Data, ) -> Result { - // TODO: check auth and rate limit here + // TODO: check rate limit here + let jwt = req + .cookie("jwt") + .expect("No auth header for picture upload"); + + if Claims::decode(jwt.value()).is_err() { + return Ok(HttpResponse::Unauthorized().finish()); + }; let mut res = client .request_from(format!("{}/image", Settings::get().pictrs_url), req.head())