]> Untitled Git - lemmy.git/commitdiff
Merge pull request #1537 from LemmyNet/add_users_active_monthly_community_sort
authorNutomic <me@nutomic.com>
Tue, 6 Apr 2021 12:03:11 +0000 (12:03 +0000)
committerGitHub <noreply@github.com>
Tue, 6 Apr 2021 12:03:11 +0000 (12:03 +0000)
Adding users active monthly for community sort. Fixes #1527

38 files changed:
.drone.yml
RELEASES.md
ansible/VERSION
ansible/templates/config.hjson
api_tests/package.json
api_tests/src/user.spec.ts
api_tests/yarn.lock
config/config.hjson
config/defaults.hjson [deleted file]
crates/api/src/lib.rs
crates/api/src/local_user.rs
crates/api_common/src/person.rs
crates/api_crud/src/user/create.rs
crates/apub/src/objects/person.rs
crates/db_queries/src/source/local_user.rs
crates/db_queries/src/source/person.rs
crates/db_schema/src/schema.rs
crates/db_schema/src/source/local_user.rs
crates/db_schema/src/source/person.rs
crates/db_views/src/comment_view.rs
crates/db_views/src/post_view.rs
crates/utils/src/settings/mod.rs
crates/utils/src/test.rs
crates/utils/src/utils.rs
crates/utils/src/version.rs
docker/dev/Dockerfile
docker/dev/docker-compose.yml
docker/dev/volume_mount.dockerfile
docker/federation/docker-compose.yml
docker/prod/Dockerfile
docker/prod/Dockerfile.arm
docker/prod/deploy.sh
docker/prod/docker-compose.yml
migrations/2021-03-31-103917_add_show_score_setting/down.sql [new file with mode: 0644]
migrations/2021-03-31-103917_add_show_score_setting/up.sql [new file with mode: 0644]
migrations/2021-04-01-173552_rename_preferred_username_to_display_name/down.sql [new file with mode: 0644]
migrations/2021-04-01-173552_rename_preferred_username_to_display_name/up.sql [new file with mode: 0644]
scripts/test.sh

index bb27984f904515424f6fb179a30fb9b082cc2e5c..7dd4d3e79e23eec5bb4d3b581788d07dabd2cb91 100644 (file)
@@ -29,6 +29,7 @@ steps:
     image: ekidd/rust-musl-builder:1.50.0
     environment:
       LEMMY_DATABASE_URL: postgres://lemmy:password@database:5432/lemmy
+      LEMMY_CONFIG_LOCATION: ../../config/config.hjson
       RUST_BACKTRACE: 1
       RUST_TEST_THREADS: 1
     commands:
@@ -107,6 +108,7 @@ steps:
     image: rust:1.50-slim-buster
     environment:
       LEMMY_DATABASE_URL: postgres://lemmy:password@database:5432/lemmy
+      LEMMY_CONFIG_LOCATION: ../../config/config.hjson
       RUST_BACKTRACE: 1
       RUST_TEST_THREADS: 1
     commands:
index e64c7e92a8f73a029fd0bc2243eba3873b66234c..95b458240e081c542506bfdebcdbbd39214ec59f 100644 (file)
@@ -1,3 +1,95 @@
+# Lemmy v0.10.2 Release (2021-04-05)
+
+- Forcing a crash if config.hjson fails to load. Should show errors easier.
+
+# Lemmy v0.10.0 Release (2021-04-05)
+
+## Changes
+
+Since our last release in February, we've had [~150](https://github.com/LemmyNet/lemmy/compare/0.9.9...main) commits to Lemmy. The biggest changes, as we'll outline below, are a split of Lemmy's user tables into federated and local tables, necessitating a `v3` of Lemmy's API, federated moderation, i18n support in join.lemmy.ml, and lots of back-end cleanup.
+
+### Lemmy Server
+
+#### General
+
+- Rewrote config implementation, finally allowing us to use newer Rust versions.
+- Removed categories. 
+- Various refactors.
+
+#### API
+
+- A full list of the API changes can be seen on this diff of [lemmy-js-client: 0.9.9 -> 0.10.0](https://github.com/LemmyNet/lemmy-js-client/compare/0.9.9...0.10.0-rc.13) .
+- Login invalidation on password change, thanks to @Mart-Bogdan
+
+#### Federation
+
+- It is now possible to add users from other instances as community mods.
+- Federating Matrix ID.
+- Many changes for better compatibility with ActivityPub standard.
+
+#### Database 
+
+- Split the `user_` into `person` and `local_user` tables.
+- Strictly typed commonly used ID columns, to prevent DB errors using `i32` as ids.
+- Strictly typed URL fields, thanks to ajyoon.
+- Created default DB forms, now used in all the unit tests.
+
+### Lemmy UI
+
+- Now using utf-8 emojis.
+- Support for all the above changes to Lemmy.
+- Typescript-safe i18n strings, thanks to @shilangyu.
+- Added expandable post text (click on open book icon).
+- Prettier cross-posting, which does smart quoting.
+- Bugfixes for restoring scroll position on post page, custom site favicons, and autocomplete for login fields.
+
+### Lemmy Docs
+
+- Gazconroy built an [Async API spec for Lemmy](https://join.lemmy.ml/api/index.html), that now serves as our main API docs.
+
+### join.lemmy.ml
+
+- Rewrote in inferno isomorphic, added i18n support via [weblate](https://weblate.yerbamate.ml/projects/lemmy/joinlemmy/).
+- Added a section on the support page thanking contributors.
+- Changed some page urls / titles
+
+## Upgrade notes
+
+**Important**: there are multiple breaking changes:
+
+- Configuration via environment variables is not supported anymore, you must have all your config in the [lemmy.hjson](https://github.com/LemmyNet/lemmy/blob/main/ansible/templates/config.hjson) file ( except for `LEMMY_CONFIG_LOCATION` ).
+- The config format for `allowed_instances` and `blocked_instances` has changed, and you need to adjust your config file manually:
+    - before: `allowed_instances: ds9.lemmy.ml,enterprise.lemmy.ml`
+    - now: `allowed_instances: ["ds9.lemmy.ml", "enterprise.lemmy.ml"]` , and only one of the `allowed_instances` or `blocked_instances` blocks can be set.
+- The API has been upgraded from `v2` to `v3`, so all clients need to be updated: [lemmy-js-client: 0.9.9 -> 0.10.0](https://github.com/LemmyNet/lemmy-js-client/compare/0.9.9...0.10.0-rc.13) .
+
+If you'd like to make a DB backup before upgrading, follow [this guide](https://join.lemmy.ml/docs/en/administration/backup_and_restore.html).
+
+To upgrade your instance to `v0.10.0`, simply follow the instructions in the documentation:
+
+- [Upgrade with manual Docker installation](https://join.lemmy.ml/docs/en/administration/install_docker.html#updating)
+- [Upgrade with Ansible installation](https://join.lemmy.ml/docs/en/administration/install_ansible.html)
+
+
+## Compilation time
+
+|| v0.9.0 (Rust 1.47) | v0.10.0 (Rust 1.47) | v0.10.0 (Rust 1.51) |
+|-| -------- | -------- | -------- |
+|Clean | 140s     | 146s     | 119s     |
+| Incremental | 28s | 22s | 19s |
+
+Despite ongoing efforts to speed up compilation, it has actually gotten slower when comparing with the same Rust version. Only thanks to improvements in newer Rust versions has our build process gotten faster. This could be simply because we added more code, while Lemmy v0.9.0 had 22.4k lines of Rust, v0.10.0 has 23.8k (an increase of 6%).
+
+v0.9.0 build graph:
+![](https://lemmy.ml/pictrs/image/GVBqFnrLqG.jpg)
+
+v0.10.0 build graph:
+![](https://lemmy.ml/pictrs/image/NllzjVEyNK.jpg)
+
+We extracted the crates `lemmy_api_crud` and `lemmy_apub_receive` from `lemmy_api` and `lemmy_apub`, respectively, and renamed `lemmy_structs` to `lemmy_api_common`. In the second graph you can see how parts of the api and apub crates are now built nicely in parallel, speeding up builds on multi-core systems.
+
+On the other hand, some crates have gotten much slower to compile, in particular `lemmy_db_queries` (6.5s slower), `lemmy_apub` (6.5s slower if we include `lemmy_apub_receive`). And `lemmy_db_views` is quite slow, just as before.
+
 # Lemmy v0.9.9 Release (2021-02-19)
 
 ## Changes
index 7e310bae19960a3c44b9f9095f1f95b1e4c49ad9..5eef0f10e8cd5cac36342fc9b6dc9855e024361f 100644 (file)
@@ -1 +1 @@
-0.9.9
+0.10.2
index 55537ca50ca944114ab2d2b8b30b69f6c7b9ec59..51d25e77f8cb6340bcc51221f924497a9dc574e8 100644 (file)
@@ -4,15 +4,22 @@
 
   # settings related to the postgresql database
   database: {
+    database: lemmy
+    user: lemmy
+    host: postgres
+    port: 5432
+    pool_size: 5
     # password to connect to postgres
     password: "{{ postgres_password }}"
-    # host where postgres is running
-    host: "postgres"
   }
   # the domain name of your instance (eg "lemmy.ml")
   hostname: "{{ domain }}"
+  # the port where lemmy should listen for incoming requests
+  port: 8536
   # json web token for authorization between server and client
   jwt_secret: "{{ jwt_password }}"
+  # whether tls is required for activitypub. only disable this for debugging, never for producion.
+  tls_enabled: true
   # email sending configuration
   email: {
     # hostname of the smtp server
index 7cb949594f859be7e72f96395926ab5e2a7780bf..1b0583c4f5537da9a2fec638dcc12c67a8da7876 100644 (file)
@@ -16,7 +16,7 @@
     "eslint": "^7.18.0",
     "eslint-plugin-jane": "^9.0.3",
     "jest": "^26.6.3",
-    "lemmy-js-client": "0.10.0-rc.13",
+    "lemmy-js-client": "0.11.0-rc.1",
     "node-fetch": "^2.6.1",
     "prettier": "^2.1.2",
     "ts-jest": "^26.4.4",
index a10876cf5e435ad346b2dd45390a14b931189244..5d10fd04382d59b71f4154befd5505f117626c4e 100644 (file)
@@ -19,7 +19,7 @@ let apShortname: string;
 
 function assertUserFederation(userOne: PersonViewSafe, userTwo: PersonViewSafe) {
   expect(userOne.person.name).toBe(userTwo.person.name);
-  expect(userOne.person.preferred_username).toBe(userTwo.person.preferred_username);
+  expect(userOne.person.display_name).toBe(userTwo.person.display_name);
   expect(userOne.person.bio).toBe(userTwo.person.bio);
   expect(userOne.person.actor_id).toBe(userTwo.person.actor_id);
   expect(userOne.person.avatar).toBe(userTwo.person.avatar);
@@ -49,7 +49,7 @@ test('Set some user settings, check that they are federated', async () => {
     lang: '',
     avatar,
     banner,
-    preferred_username: 'user321',
+    display_name: 'user321',
     show_avatars: false,
     send_notifications_to_email: false,
     bio,
index 8f8abf87346e519c5616735044c0d2a2b4faa376..f3b8e603f9e8eda335a0b685e00c511b87a58676 100644 (file)
@@ -3233,10 +3233,10 @@ language-tags@^1.0.5:
   dependencies:
     language-subtag-registry "~0.3.2"
 
-lemmy-js-client@0.10.0-rc.13:
-  version "0.10.0-rc.13"
-  resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.10.0-rc.13.tgz#ea2e88857243374d7fbd49ee6b4bb94c34359d85"
-  integrity sha512-zodvYkwBYR7iP27ah6L/QPUphUUdq38kCH7QF2CUYBrsSAEkGmq2kdz+iusnQ1Ht7Ad80GtYycFprsZBveV5eQ==
+lemmy-js-client@0.11.0-rc.1:
+  version "0.11.0-rc.1"
+  resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.11.0-rc.1.tgz#0031676be9fc787157a21dd3f5095dd1ee9e6a57"
+  integrity sha512-dtpxe/hHTbYEv2WnfGkAieOB9jyKUVED+y4DosUp/FcaatjPcMTiKOvCdMNjlvvG/9GyclWEoyNitPEsvJwjmg==
 
 leven@^3.1.0:
   version "3.1.0"
index 286b1c031b1c89cb378bad04ecd6604c7f2813a3..1ab231c2ff1288c2ff120333407d4da95d6b2f7c 100644 (file)
@@ -1,3 +1,91 @@
 {
-  hostname: "localhost:8536"
+#  # optional: parameters for automatic configuration of new instance (only used at first start)
+#  setup: {
+#    # username for the admin user
+#    admin_username: ""
+#    # password for the admin user
+#    admin_password: ""
+#    # optional: email for the admin user (can be omitted and set later through the website)
+#    admin_email: ""
+#    # name of the site (can be changed later)
+#    site_name: ""
+#  }
+  # settings related to the postgresql database
+  database: {
+    # username to connect to postgres
+    user: "lemmy"
+    # password to connect to postgres
+    password: "password"
+    # host where postgres is running
+    host: "localhost"
+    # port where postgres can be accessed
+    port: 5432
+    # name of the postgres database for lemmy
+    database: "lemmy"
+    # maximum number of active sql connections
+    pool_size: 5
+  }
+  # the domain name of your instance (eg "lemmy.ml")
+  hostname: lemmy-alpha
+  # address where lemmy should listen for incoming requests
+  bind: "0.0.0.0"
+  # port where lemmy should listen for incoming requests
+  port: 8536
+  # whether tls is required for activitypub. only disable this for debugging, never for producion.
+  tls_enabled: true
+  # json web token for authorization between server and client
+  jwt_secret: "changeme"
+  # address where pictrs is available
+  pictrs_url: "http://pictrs:8080"
+  # address where iframely is available
+  iframely_url: "http://iframely"
+  # rate limits for various user actions, by user ip
+  rate_limit: {
+    # maximum number of messages created in interval
+    message: 180
+    # interval length for message limit
+    message_per_second: 60
+    # maximum number of posts created in interval
+    post: 6
+    # interval length for post limit
+    post_per_second: 600
+    # maximum number of registrations in interval
+    register: 3
+    # interval length for registration limit
+    register_per_second: 3600
+    # maximum number of image uploads in interval
+    image: 6
+    # interval length for image uploads
+    image_per_second: 3600
+  }
+  # settings related to activitypub federation
+  federation: {
+    # whether to enable activitypub federation.
+    enabled: false
+    # Allows and blocks are described here:
+    # https://join.lemmy.ml/docs/en/federation/administration.html#instance-allowlist-and-blocklist
+    #
+    # comma separated list of instances with which federation is allowed
+    # Only one of these blocks should be uncommented
+    # allowed_instances: ["instance1.tld","instance2.tld"]
+    # comma separated list of instances which are blocked from federating
+    # blocked_instances: []
+  }
+  captcha: {
+    enabled: true
+    difficulty: medium # Can be easy, medium, or hard
+  }
+#  # email sending configuration
+#  email: {
+#    # hostname and port of the smtp server
+#    smtp_server: ""
+#    # login name for smtp server
+#    smtp_login: ""
+#    # password to login to the smtp server
+#    smtp_password: ""
+#    # address to send emails from, eg "noreply@your-instance.com"
+#    smtp_from_address: ""
+#    # whether or not smtp connections should use tls
+#    use_tls: true
+#  }
 }
diff --git a/config/defaults.hjson b/config/defaults.hjson
deleted file mode 100644 (file)
index c3eaba6..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-{
-#  # optional: parameters for automatic configuration of new instance (only used at first start)
-#  setup: {
-#    # username for the admin user
-#    admin_username: ""
-#    # password for the admin user
-#    admin_password: ""
-#    # optional: email for the admin user (can be omitted and set later through the website)
-#    admin_email: ""
-#    # name of the site (can be changed later)
-#    site_name: ""
-#  }
-  # settings related to the postgresql database
-  database: {
-    # username to connect to postgres
-    user: "lemmy"
-    # password to connect to postgres
-    password: "password"
-    # host where postgres is running
-    host: "localhost"
-    # port where postgres can be accessed
-    port: 5432
-    # name of the postgres database for lemmy
-    database: "lemmy"
-    # maximum number of active sql connections
-    pool_size: 5
-  }
-  # the domain name of your instance (eg "lemmy.ml")
-  hostname: null
-  # address where lemmy should listen for incoming requests
-  bind: "0.0.0.0"
-  # port where lemmy should listen for incoming requests
-  port: 8536
-  # whether tls is required for activitypub. only disable this for debugging, never for producion.
-  tls_enabled: true
-  # json web token for authorization between server and client
-  jwt_secret: "changeme"
-  # address where pictrs is available
-  pictrs_url: "http://pictrs:8080"
-  # address where iframely is available
-  iframely_url: "http://iframely"
-  # rate limits for various user actions, by user ip
-  rate_limit: {
-    # maximum number of messages created in interval
-    message: 180
-    # interval length for message limit
-    message_per_second: 60
-    # maximum number of posts created in interval
-    post: 6
-    # interval length for post limit
-    post_per_second: 600
-    # maximum number of registrations in interval
-    register: 3
-    # interval length for registration limit
-    register_per_second: 3600
-    # maximum number of image uploads in interval
-    image: 6
-    # interval length for image uploads
-    image_per_second: 3600
-  }
-  # settings related to activitypub federation
-  federation: {
-    # whether to enable activitypub federation. 
-    enabled: false
-    # Allows and blocks are described here:
-    # https://join.lemmy.ml/docs/en/federation/administration.html#instance-allowlist-and-blocklist
-    #
-    # comma separated list of instances with which federation is allowed
-    # Only one of these blocks should be uncommented
-    # allowed_instances: ["instance1.tld","instance2.tld"]
-    # comma separated list of instances which are blocked from federating
-    # blocked_instances: []
-  }
-  captcha: {
-    enabled: true
-    difficulty: medium # Can be easy, medium, or hard
-  }
-#  # email sending configuration
-#  email: {
-#    # hostname and port of the smtp server
-#    smtp_server: ""
-#    # login name for smtp server
-#    smtp_login: ""
-#    # password to login to the smtp server
-#    smtp_password: ""
-#    # address to send emails from, eg "noreply@your-instance.com"
-#    smtp_from_address: ""
-#    # whether or not smtp connections should use tls
-#    use_tls: true
-#  }
-}
index 5dc678be66d7ff0ce3aa6f9236fefba23050843a..c9de749ef36e9a9999392b99738b3b57cc912372 100644 (file)
@@ -1,9 +1,9 @@
 use actix_web::{web, web::Data};
+use captcha::Captcha;
 use lemmy_api_common::{comment::*, community::*, person::*, post::*, site::*, websocket::*};
 use lemmy_utils::{ConnectionId, LemmyError};
 use lemmy_websocket::{serialize_websocket_message, LemmyContext, UserOperation};
 use serde::Deserialize;
-use std::{env, process::Command};
 
 mod comment;
 mod comment_report;
@@ -158,60 +158,23 @@ where
   serialize_websocket_message(&op, &res)
 }
 
-pub(crate) fn captcha_espeak_wav_base64(captcha: &str) -> Result<String, LemmyError> {
-  let mut built_text = String::new();
+/// Converts the captcha to a base64 encoded wav audio file
+pub(crate) fn captcha_as_wav_base64(captcha: &Captcha) -> String {
+  let letters = captcha.as_wav();
 
-  // Building proper speech text for espeak
-  for mut c in captcha.chars() {
-    let new_str = if c.is_alphabetic() {
-      if c.is_lowercase() {
-        c.make_ascii_uppercase();
-        format!("lower case {} ... ", c)
-      } else {
-        c.make_ascii_uppercase();
-        format!("capital {} ... ", c)
-      }
-    } else {
-      format!("{} ...", c)
-    };
+  let mut concat_letters: Vec<u8> = Vec::new();
 
-    built_text.push_str(&new_str);
+  for letter in letters {
+    let bytes = letter.unwrap_or_default();
+    concat_letters.extend(bytes);
   }
 
-  espeak_wav_base64(&built_text)
-}
-
-pub(crate) fn espeak_wav_base64(text: &str) -> Result<String, LemmyError> {
-  // Make a temp file path
-  let uuid = uuid::Uuid::new_v4().to_string();
-  let file_path = format!(
-    "{}/lemmy_espeak_{}.wav",
-    env::temp_dir().to_string_lossy(),
-    &uuid
-  );
-
-  // Write the wav file
-  Command::new("espeak")
-    .arg("-w")
-    .arg(&file_path)
-    .arg(text)
-    .status()?;
-
-  // Read the wav file bytes
-  let bytes = std::fs::read(&file_path)?;
-
-  // Delete the file
-  std::fs::remove_file(file_path)?;
-
   // Convert to base64
-  let base64 = base64::encode(bytes);
-
-  Ok(base64)
+  base64::encode(concat_letters)
 }
 
 #[cfg(test)]
 mod tests {
-  use crate::captcha_espeak_wav_base64;
   use lemmy_api_common::check_validator_time;
   use lemmy_db_queries::{establish_unpooled_connection, source::local_user::LocalUser_, Crud};
   use lemmy_db_schema::source::{
@@ -253,9 +216,4 @@ mod tests {
     let num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
     assert_eq!(1, num_deleted);
   }
-
-  #[test]
-  fn test_espeak() {
-    assert!(captcha_espeak_wav_base64("WxRt2l").is_ok())
-  }
 }
index 656ddf9719fec29b859659f04cae6be112228143..6a319dcd5741494ac1bf4ad5e036ed82a34003e7 100644 (file)
@@ -1,4 +1,4 @@
-use crate::{captcha_espeak_wav_base64, Perform};
+use crate::{captcha_as_wav_base64, Perform};
 use actix_web::web::Data;
 use anyhow::Context;
 use bcrypt::verify;
@@ -60,7 +60,7 @@ use lemmy_utils::{
   email::send_email,
   location_info,
   settings::structs::Settings,
-  utils::{generate_random_string, is_valid_preferred_username, naive_from_unix},
+  utils::{generate_random_string, is_valid_display_name, naive_from_unix},
   ApiError,
   ConnectionId,
   LemmyError,
@@ -135,13 +135,11 @@ impl Perform for GetCaptcha {
 
     let answer = captcha.chars_as_string();
 
-    let png_byte_array = captcha.as_png().expect("failed to generate captcha");
-
-    let png = base64::encode(png_byte_array);
+    let png = captcha.as_base64().expect("failed to generate captcha");
 
     let uuid = uuid::Uuid::new_v4().to_string();
 
-    let wav = captcha_espeak_wav_base64(&answer).ok();
+    let wav = captcha_as_wav_base64(&captcha);
 
     let captcha_item = CaptchaItem {
       answer,
@@ -174,7 +172,7 @@ impl Perform for SaveUserSettings {
     let banner = diesel_option_overwrite_to_url(&data.banner)?;
     let email = diesel_option_overwrite(&data.email);
     let bio = diesel_option_overwrite(&data.bio);
-    let preferred_username = diesel_option_overwrite(&data.preferred_username);
+    let display_name = diesel_option_overwrite(&data.display_name);
     let matrix_user_id = diesel_option_overwrite(&data.matrix_user_id);
 
     if let Some(Some(bio)) = &bio {
@@ -183,8 +181,8 @@ impl Perform for SaveUserSettings {
       }
     }
 
-    if let Some(Some(preferred_username)) = &preferred_username {
-      if !is_valid_preferred_username(preferred_username.trim()) {
+    if let Some(Some(display_name)) = &display_name {
+      if !is_valid_display_name(display_name.trim()) {
         return Err(ApiError::err("invalid_username").into());
       }
     }
@@ -235,7 +233,7 @@ impl Perform for SaveUserSettings {
       avatar,
       banner,
       inbox_url: None,
-      preferred_username,
+      display_name,
       published: None,
       updated: Some(naive_now()),
       banned: None,
@@ -267,6 +265,7 @@ impl Perform for SaveUserSettings {
       email,
       password_encrypted,
       show_nsfw: data.show_nsfw,
+      show_scores: data.show_scores,
       theme: data.theme.to_owned(),
       default_sort_type,
       default_listing_type,
index 7767da460d82e118f7b21c51774eb0fcf6e2aad9..21fa1c778e5fe0393c6ef57368cd436e77ff055a 100644 (file)
@@ -39,28 +39,29 @@ pub struct GetCaptchaResponse {
 
 #[derive(Serialize)]
 pub struct CaptchaResponse {
-  pub png: String,         // A Base64 encoded png
-  pub wav: Option<String>, // A Base64 encoded wav audio
+  pub png: String, // A Base64 encoded png
+  pub wav: String, // A Base64 encoded wav audio
   pub uuid: String,
 }
 
 #[derive(Deserialize)]
 pub struct SaveUserSettings {
   pub show_nsfw: Option<bool>,
+  pub show_scores: Option<bool>,
+  pub show_avatars: Option<bool>,
   pub theme: Option<String>,
   pub default_sort_type: Option<i16>,
   pub default_listing_type: Option<i16>,
   pub lang: Option<String>,
   pub avatar: Option<String>,
   pub banner: Option<String>,
-  pub preferred_username: Option<String>,
+  pub display_name: Option<String>,
   pub email: Option<String>,
   pub bio: Option<String>,
   pub matrix_user_id: Option<String>,
   pub new_password: Option<String>,
   pub new_password_verify: Option<String>,
   pub old_password: Option<String>,
-  pub show_avatars: Option<bool>,
   pub send_notifications_to_email: Option<bool>,
   pub auth: String,
 }
index 63a6474d62484b4a312ed8287992a8cd36211b3d..c61c1e79a6663b63626194d5b84e2bf92fb73d39 100644 (file)
@@ -133,6 +133,7 @@ impl PerformCrud for Register {
       default_listing_type: Some(ListingType::Subscribed as i16),
       lang: Some("browser".into()),
       show_avatars: Some(true),
+      show_scores: Some(true),
       send_notifications_to_email: Some(false),
     };
 
index 25c785d84b464a3051ba64b1681214135ea3ddeb..3e468d5c81bc7991b78b8013114f262a057f2d53 100644 (file)
@@ -64,7 +64,8 @@ impl ToApub for DbPerson {
       set_content_and_source(&mut person, bio)?;
     }
 
-    if let Some(i) = self.preferred_username.to_owned() {
+    // In apub, the "name" is a display name
+    if let Some(i) = self.display_name.to_owned() {
       person.set_name(i);
     }
 
@@ -161,7 +162,7 @@ impl FromApubToForm<PersonExt> for PersonForm {
       .preferred_username()
       .context(location_info!())?
       .to_string();
-    let preferred_username: Option<String> = person
+    let display_name: Option<String> = person
       .name()
       .map(|n| n.one())
       .flatten()
@@ -176,12 +177,12 @@ impl FromApubToForm<PersonExt> for PersonForm {
       .map(|s| s.to_owned().into());
 
     check_slurs(&name)?;
-    check_slurs_opt(&preferred_username)?;
+    check_slurs_opt(&display_name)?;
     check_slurs_opt(&bio)?;
 
     Ok(PersonForm {
       name,
-      preferred_username: Some(preferred_username),
+      display_name: Some(display_name),
       banned: None,
       deleted: None,
       avatar: avatar.map(|o| o.map(|i| i.into())),
index 18720ceba3c0a95469955558a9d271817c5e86d7..d1fad2e8523ff8c8566c49ee0ff6497a29ff2bd8 100644 (file)
@@ -24,6 +24,7 @@ mod safe_settings_type {
     show_avatars,
     send_notifications_to_email,
     validator_time,
+    show_scores,
   );
 
   impl ToSafeSettings for LocalUser {
@@ -43,6 +44,7 @@ mod safe_settings_type {
         show_avatars,
         send_notifications_to_email,
         validator_time,
+        show_scores,
       )
     }
   }
index 35ed540c0fc4f51846cbc8f3d5937707c5d5df93..2d332bd01eccd5d866283263ccb59ff66157603c 100644 (file)
@@ -15,7 +15,7 @@ mod safe_type {
   type Columns = (
     id,
     name,
-    preferred_username,
+    display_name,
     avatar,
     banned,
     published,
@@ -37,7 +37,7 @@ mod safe_type {
       (
         id,
         name,
-        preferred_username,
+        display_name,
         avatar,
         banned,
         published,
@@ -63,7 +63,7 @@ mod safe_type_alias_1 {
   type Columns = (
     id,
     name,
-    preferred_username,
+    display_name,
     avatar,
     banned,
     published,
@@ -85,7 +85,7 @@ mod safe_type_alias_1 {
       (
         id,
         name,
-        preferred_username,
+        display_name,
         avatar,
         banned,
         published,
@@ -111,7 +111,7 @@ mod safe_type_alias_2 {
   type Columns = (
     id,
     name,
-    preferred_username,
+    display_name,
     avatar,
     banned,
     published,
@@ -133,7 +133,7 @@ mod safe_type_alias_2 {
       (
         id,
         name,
-        preferred_username,
+        display_name,
         avatar,
         banned,
         published,
@@ -236,7 +236,7 @@ impl Person_ for Person {
 
     diesel::update(person.find(person_id))
       .set((
-        preferred_username.eq::<Option<String>>(None),
+        display_name.eq::<Option<String>>(None),
         bio.eq::<Option<String>>(None),
         matrix_user_id.eq::<Option<String>>(None),
         deleted.eq(true),
@@ -264,7 +264,7 @@ mod tests {
     let expected_person = Person {
       id: inserted_person.id,
       name: "holly".into(),
-      preferred_username: None,
+      display_name: None,
       avatar: None,
       banner: None,
       banned: false,
index 5bc55f529bc6a63fb620d545e93c4640959990c8..32fd3de1889d74cf066267c718f5a42ccdf39109 100644 (file)
@@ -154,6 +154,7 @@ table! {
         show_avatars -> Bool,
         send_notifications_to_email -> Bool,
         validator_time -> Timestamp,
+        show_scores -> Bool,
     }
 }
 
@@ -270,7 +271,7 @@ table! {
     person (id) {
         id -> Int4,
         name -> Varchar,
-        preferred_username -> Nullable<Varchar>,
+        display_name -> Nullable<Varchar>,
         avatar -> Nullable<Varchar>,
         banned -> Bool,
         published -> Timestamp,
@@ -470,7 +471,7 @@ table! {
     person_alias_1 (id) {
         id -> Int4,
         name -> Varchar,
-        preferred_username -> Nullable<Varchar>,
+        display_name -> Nullable<Varchar>,
         avatar -> Nullable<Varchar>,
         banned -> Bool,
         published -> Timestamp,
@@ -494,7 +495,7 @@ table! {
     person_alias_2 (id) {
         id -> Int4,
         name -> Varchar,
-        preferred_username -> Nullable<Varchar>,
+        display_name -> Nullable<Varchar>,
         avatar -> Nullable<Varchar>,
         banned -> Bool,
         published -> Timestamp,
index 6f28a8fbcdba6e4e1c44d0f1696ec0684291aaa7..0a7181fdbef57d36bade01a67d46c8808d9e1dd4 100644 (file)
@@ -16,6 +16,7 @@ pub struct LocalUser {
   pub show_avatars: bool,
   pub send_notifications_to_email: bool,
   pub validator_time: chrono::NaiveDateTime,
+  pub show_scores: bool,
 }
 
 // TODO redo these, check table defaults
@@ -32,6 +33,7 @@ pub struct LocalUserForm {
   pub lang: Option<String>,
   pub show_avatars: Option<bool>,
   pub send_notifications_to_email: Option<bool>,
+  pub show_scores: Option<bool>,
 }
 
 /// A local user view that removes password encrypted
@@ -49,4 +51,5 @@ pub struct LocalUserSettings {
   pub show_avatars: bool,
   pub send_notifications_to_email: bool,
   pub validator_time: chrono::NaiveDateTime,
+  pub show_scores: bool,
 }
index 2c0e7e8b790238b7c5a6c4b9fa6c45576b44da24..be1ce268f7d5bc4f4bc525ca4851cb2c1850b480 100644 (file)
@@ -10,7 +10,7 @@ use serde::Serialize;
 pub struct Person {
   pub id: PersonId,
   pub name: String,
-  pub preferred_username: Option<String>,
+  pub display_name: Option<String>,
   pub avatar: Option<DbUrl>,
   pub banned: bool,
   pub published: chrono::NaiveDateTime,
@@ -35,7 +35,7 @@ pub struct Person {
 pub struct PersonSafe {
   pub id: PersonId,
   pub name: String,
-  pub preferred_username: Option<String>,
+  pub display_name: Option<String>,
   pub avatar: Option<DbUrl>,
   pub banned: bool,
   pub published: chrono::NaiveDateTime,
@@ -56,7 +56,7 @@ pub struct PersonSafe {
 pub struct PersonAlias1 {
   pub id: PersonId,
   pub name: String,
-  pub preferred_username: Option<String>,
+  pub display_name: Option<String>,
   pub avatar: Option<DbUrl>,
   pub banned: bool,
   pub published: chrono::NaiveDateTime,
@@ -80,7 +80,7 @@ pub struct PersonAlias1 {
 pub struct PersonSafeAlias1 {
   pub id: PersonId,
   pub name: String,
-  pub preferred_username: Option<String>,
+  pub display_name: Option<String>,
   pub avatar: Option<DbUrl>,
   pub banned: bool,
   pub published: chrono::NaiveDateTime,
@@ -101,7 +101,7 @@ pub struct PersonSafeAlias1 {
 pub struct PersonAlias2 {
   pub id: PersonId,
   pub name: String,
-  pub preferred_username: Option<String>,
+  pub display_name: Option<String>,
   pub avatar: Option<DbUrl>,
   pub banned: bool,
   pub published: chrono::NaiveDateTime,
@@ -125,7 +125,7 @@ pub struct PersonAlias2 {
 pub struct PersonSafeAlias2 {
   pub id: PersonId,
   pub name: String,
-  pub preferred_username: Option<String>,
+  pub display_name: Option<String>,
   pub avatar: Option<DbUrl>,
   pub banned: bool,
   pub published: chrono::NaiveDateTime,
@@ -145,7 +145,7 @@ pub struct PersonSafeAlias2 {
 #[table_name = "person"]
 pub struct PersonForm {
   pub name: String,
-  pub preferred_username: Option<Option<String>>,
+  pub display_name: Option<Option<String>>,
   pub avatar: Option<Option<DbUrl>>,
   pub banned: Option<bool>,
   pub published: Option<chrono::NaiveDateTime>,
index 6b13103c0eb19b06f7db3c165b6ac389fcedcecc..ff5b6debfc4515f4d744b2a93d353a6b38b307bc 100644 (file)
@@ -519,7 +519,7 @@ mod tests {
       creator: PersonSafe {
         id: inserted_person.id,
         name: "timmy".into(),
-        preferred_username: None,
+        display_name: None,
         published: inserted_person.published,
         avatar: None,
         actor_id: inserted_person.actor_id.to_owned(),
index df67d36933376becf7cfad72d85b9dc77887898f..64f261aadbb0ac94f53562362d0a696630d6daca 100644 (file)
@@ -541,7 +541,7 @@ mod tests {
       creator: PersonSafe {
         id: inserted_person.id,
         name: person_name,
-        preferred_username: None,
+        display_name: None,
         published: inserted_person.published,
         avatar: None,
         actor_id: inserted_person.actor_id.to_owned(),
index 0990a43ded26e66d9713a6d6d22a7e0c7f914abf..d052fec6c665c5db8dbef5c0eb9eca9f7041e6e8 100644 (file)
@@ -13,7 +13,6 @@ use crate::{
 };
 use anyhow::{anyhow, Context};
 use deser_hjson::from_str;
-use log::warn;
 use merge::Merge;
 use std::{env, fs, io::Error, net::IpAddr, sync::RwLock};
 
@@ -23,16 +22,8 @@ pub mod structs;
 static CONFIG_FILE: &str = "config/config.hjson";
 
 lazy_static! {
-  static ref SETTINGS: RwLock<Settings> = RwLock::new(match Settings::init() {
-    Ok(c) => c,
-    Err(e) => {
-      warn!(
-        "Couldn't load settings file, using default settings.\n{}",
-        e
-      );
-      Settings::default()
-    }
-  });
+  static ref SETTINGS: RwLock<Settings> =
+    RwLock::new(Settings::init().expect("Failed to load settings file"));
 }
 
 impl Settings {
index aaa59bfa7aefcc6b0a0b229184e01080eb9b1541..754aa8c3a8befda82b79dcbc424979233c274821 100644 (file)
@@ -1,7 +1,7 @@
 use crate::utils::{
   is_valid_community_name,
+  is_valid_display_name,
   is_valid_post_title,
-  is_valid_preferred_username,
   is_valid_username,
   remove_slurs,
   scrape_text_for_mentions,
@@ -29,9 +29,15 @@ fn test_valid_register_username() {
 }
 
 #[test]
-fn test_valid_preferred_username() {
-  assert!(is_valid_preferred_username("hello @there"));
-  assert!(!is_valid_preferred_username("@hello there"));
+fn test_valid_display_name() {
+  assert!(is_valid_display_name("hello @there"));
+  assert!(!is_valid_display_name("@hello there"));
+
+  // Make sure zero-space with an @ doesn't work
+  assert!(!is_valid_display_name(&format!(
+    "{}@my name is",
+    '\u{200b}'
+  )));
 }
 
 #[test]
index c53d6c7c2c8bfe894b0f82ea50fac09a3cde5698..732ac2c8d85c5104d811e6eaf3e773e9d190dd3b 100644 (file)
@@ -108,10 +108,11 @@ pub fn is_valid_username(name: &str) -> bool {
 }
 
 // Can't do a regex here, reverse lookarounds not supported
-pub fn is_valid_preferred_username(preferred_username: &str) -> bool {
-  !preferred_username.starts_with('@')
-    && preferred_username.chars().count() >= 3
-    && preferred_username.chars().count() <= 20
+pub fn is_valid_display_name(name: &str) -> bool {
+  !name.starts_with('@')
+    && !name.starts_with('\u{200b}')
+    && name.chars().count() >= 3
+    && name.chars().count() <= 20
 }
 
 pub fn is_valid_community_name(name: &str) -> bool {
index 133ba6080028c6cbf4225b47b00911c4cbc8756b..476a14bd49cdae5460c762548ead8d4a6630d6b4 100644 (file)
@@ -1 +1 @@
-pub const VERSION: &str = "0.10.0-rc.13";
+pub const VERSION: &str = "0.10.2";
index 954c85c84bfa531a874ab2b2754455a4afbf5173..5d2acec7faf9a1192de816c803ad5307cd668e1c 100644 (file)
@@ -49,9 +49,6 @@ FROM alpine:3.12 as lemmy
 # Install libpq for postgres
 RUN apk add libpq
 
-# Install Espeak for captchas
-RUN apk add espeak
-
 RUN addgroup -g 1000 lemmy
 RUN adduser -D -s /bin/sh -u 1000 -G lemmy lemmy
 
index d16a9331c7c84e09f31ae87331dbe737d2fe422c..2df7f28cf10990e99205c99fc218a51e1cc7e089 100644 (file)
@@ -17,7 +17,7 @@ services:
       - iframely
 
   lemmy-ui:
-    image: dessalines/lemmy-ui:0.10.0-rc.13
+    image: dessalines/lemmy-ui:0.10.2
     ports:
       - "1235:1234"
     restart: always
index 0cb036247186a2a9d86750bd10a19dd3dfbcb0b5..d848e0ea6cf7e08eccd1de8c1108add9fa049f89 100644 (file)
@@ -19,9 +19,9 @@ RUN --mount=type=cache,target=/app/target \
 
 FROM ubuntu:20.10
 
-# Install libpq for postgres and espeak
+# Install libpq for postgres
 RUN apt-get update -y
-RUN apt-get install -y libpq-dev espeak 
+RUN apt-get install -y libpq-dev
 
 # Copy resources
 COPY config/defaults.hjson /config/defaults.hjson
index d683f7764db5a03e926c49faede9956ad6c2a3aa..ee6e2d27d41fdf4ee79d3a0e9f6a238fa270287c 100644 (file)
@@ -29,7 +29,7 @@ services:
       - ./volumes/pictrs_alpha:/mnt
 
   lemmy-alpha-ui:
-    image: dessalines/lemmy-ui:0.10.0-rc.13
+    image: dessalines/lemmy-ui:0.10.2
     environment:
       - LEMMY_INTERNAL_HOST=lemmy-alpha:8541
       - LEMMY_EXTERNAL_HOST=localhost:8541
@@ -58,7 +58,7 @@ services:
       - ./volumes/postgres_alpha:/var/lib/postgresql/data
 
   lemmy-beta-ui:
-    image: dessalines/lemmy-ui:0.10.0-rc.13
+    image: dessalines/lemmy-ui:0.10.2
     environment:
       - LEMMY_INTERNAL_HOST=lemmy-beta:8551
       - LEMMY_EXTERNAL_HOST=localhost:8551
@@ -87,7 +87,7 @@ services:
       - ./volumes/postgres_beta:/var/lib/postgresql/data
 
   lemmy-gamma-ui:
-    image: dessalines/lemmy-ui:0.10.0-rc.13
+    image: dessalines/lemmy-ui:0.10.2
     environment:
       - LEMMY_INTERNAL_HOST=lemmy-gamma:8561
       - LEMMY_EXTERNAL_HOST=localhost:8561
@@ -117,7 +117,7 @@ services:
 
   # An instance with only an allowlist for beta
   lemmy-delta-ui:
-    image: dessalines/lemmy-ui:0.10.0-rc.13
+    image: dessalines/lemmy-ui:0.10.2
     environment:
       - LEMMY_INTERNAL_HOST=lemmy-delta:8571
       - LEMMY_EXTERNAL_HOST=localhost:8571
@@ -147,7 +147,7 @@ services:
 
   # An instance who has a blocklist, with lemmy-alpha blocked
   lemmy-epsilon-ui:
-    image: dessalines/lemmy-ui:0.10.0-rc.13
+    image: dessalines/lemmy-ui:0.10.2
     environment:
       - LEMMY_INTERNAL_HOST=lemmy-epsilon:8581
       - LEMMY_EXTERNAL_HOST=localhost:8581
index 2ad601aec1d3dab663b58c864248aafa79cf71fb..88a05fb269acc89fb7bf55933be625e833a1b88f 100644 (file)
@@ -49,9 +49,6 @@ FROM alpine:3.12 as lemmy
 # Install libpq for postgres
 RUN apk add libpq
 
-# Install Espeak for captchas
-RUN apk add espeak
-
 RUN addgroup -g 1000 lemmy
 RUN adduser -D -s /bin/sh -u 1000 -G lemmy lemmy
 
index 61d1f86c9c2bbc6695c3e90675231ee31a669353..b3eacb4f9f41ea6d29eb5849dc019747ede67dfe 100644 (file)
@@ -22,9 +22,9 @@ RUN cp ./target/release/lemmy_server /app/lemmy_server
 # The Debian runner
 FROM debian:buster-slim as lemmy
 
-# Install libpq for postgres and espeak for captchas
+# Install libpq for postgres
 RUN apt-get update \
- && apt-get -y install --no-install-recommends espeak postgresql-client libc6 libssl1.1 \
+ && apt-get -y install --no-install-recommends postgresql-client libc6 libssl1.1 \
  && rm -rf /var/lib/apt/lists/*
 
 RUN addgroup --gid 1000 lemmy
index bd99fdb09ced98db2b4b2ff58faa89c52459517d..b2ee16635d095bbd86af9c31054179f7610fae9a 100755 (executable)
@@ -13,7 +13,9 @@ git add "crates/utils/src/version.rs"
 popd
 
 # Changing various references to the Lemmy version
+sed -i "s/dessalines\/lemmy:.*/dessalines\/lemmy:$new_tag/" ../dev/docker-compose.yml
 sed -i "s/dessalines\/lemmy-ui:.*/dessalines\/lemmy-ui:$new_tag/" ../dev/docker-compose.yml
+sed -i "s/dessalines\/lemmy:.*/dessalines\/lemmy:$new_tag/" ../federation/docker-compose.yml
 sed -i "s/dessalines\/lemmy-ui:.*/dessalines\/lemmy-ui:$new_tag/" ../federation/docker-compose.yml
 git add ../dev/docker-compose.yml
 git add ../federation/docker-compose.yml
@@ -22,6 +24,7 @@ git add ../federation/docker-compose.yml
 # IE, when the third semver is a number, not '2-rc'
 if [ ! -z "${third_semver##*[!0-9]*}" ]; then
   sed -i "s/dessalines\/lemmy:.*/dessalines\/lemmy:$new_tag/" ../prod/docker-compose.yml
+  sed -i "s/dessalines\/lemmy-ui:.*/dessalines\/lemmy-ui:$new_tag/" ../prod/docker-compose.yml
   git add ../prod/docker-compose.yml
 
   # Setting the version for Ansible
index a508269a5e72ac6731247af5efe3091f39e953af..5e617c6cc941981f8f25352f0db7410acd23551c 100644 (file)
@@ -12,7 +12,7 @@ services:
     restart: always
 
   lemmy:
-    image: dessalines/lemmy:0.9.9
+    image: dessalines/lemmy:0.10.2
     ports:
       - "127.0.0.1:8536:8536"
     restart: always
@@ -26,7 +26,7 @@ services:
       - iframely
 
   lemmy-ui:
-    image: dessalines/lemmy-ui:0.9.9
+    image: dessalines/lemmy-ui:0.10.2
     ports:
       - "127.0.0.1:1235:1234"
     restart: always
diff --git a/migrations/2021-03-31-103917_add_show_score_setting/down.sql b/migrations/2021-03-31-103917_add_show_score_setting/down.sql
new file mode 100644 (file)
index 0000000..9d35b56
--- /dev/null
@@ -0,0 +1 @@
+alter table local_user drop column show_scores;
diff --git a/migrations/2021-03-31-103917_add_show_score_setting/up.sql b/migrations/2021-03-31-103917_add_show_score_setting/up.sql
new file mode 100644 (file)
index 0000000..7960886
--- /dev/null
@@ -0,0 +1 @@
+alter table local_user add column show_scores boolean default true not null;
diff --git a/migrations/2021-04-01-173552_rename_preferred_username_to_display_name/down.sql b/migrations/2021-04-01-173552_rename_preferred_username_to_display_name/down.sql
new file mode 100644 (file)
index 0000000..844c02d
--- /dev/null
@@ -0,0 +1,6 @@
+alter table person rename display_name to preferred_username;
+
+-- Regenerate the person_alias views
+drop view person_alias_1, person_alias_2;
+create view person_alias_1 as select * from person;
+create view person_alias_2 as select * from person;
diff --git a/migrations/2021-04-01-173552_rename_preferred_username_to_display_name/up.sql b/migrations/2021-04-01-173552_rename_preferred_username_to_display_name/up.sql
new file mode 100644 (file)
index 0000000..f4b9729
--- /dev/null
@@ -0,0 +1,6 @@
+alter table person rename preferred_username to display_name;
+
+-- Regenerate the person_alias views
+drop view person_alias_1, person_alias_2;
+create view person_alias_1 as select * from person;
+create view person_alias_2 as select * from person;
index 251e6a74a70e9ac05a2f2ad5502cbb6741ccb520..0a3fa90fc6ce383d00ebe568063afd32d5478eb7 100755 (executable)
@@ -5,5 +5,8 @@ psql -U lemmy -d postgres -c "DROP DATABASE lemmy;"
 psql -U lemmy -d postgres -c "CREATE DATABASE lemmy;"
 
 export LEMMY_DATABASE_URL=postgres://lemmy:password@localhost:5432/lemmy
+# tests are executed in working directory crates/api (or similar),
+# so to load the config we need to traverse to the repo root
+export LEMMY_CONFIG_LOCATION=../../config/config.hjson
 RUST_BACKTRACE=1 \
   cargo test --workspace --no-fail-fast