Add web site settings
authorGreg Burri <greg.burri@gmail.com>
Sun, 19 Jan 2025 20:05:46 +0000 (21:05 +0100)
committerGreg Burri <greg.burri@gmail.com>
Sun, 19 Jan 2025 20:05:46 +0000 (21:05 +0100)
Cargo.lock
backend/sql/version_1.sql
backend/src/data/db/mod.rs
backend/src/data/db/settings.rs [new file with mode: 0644]
backend/src/main.rs
backend/src/services/user.rs
backend/src/translation.rs
backend/translation.ron

index c9a4177..06c8034 100644 (file)
@@ -353,9 +353,9 @@ checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
 
 [[package]]
 name = "cc"
-version = "1.2.9"
+version = "1.2.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b"
+checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229"
 dependencies = [
  "shlex",
 ]
@@ -2202,9 +2202,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.135"
+version = "1.0.136"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9"
+checksum = "336a0c23cf42a38d9eaa7cd22c7040d04e1228a19a933890805ffd00a16437d2"
 dependencies = [
  "itoa",
  "memchr",
@@ -3020,9 +3020,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
 
 [[package]]
 name = "valuable"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
+checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
 
 [[package]]
 name = "vcpkg"
index be6ae95..46cbd1d 100644 (file)
@@ -159,3 +159,11 @@ CREATE TABLE [Ingredient] (
 ) STRICT;
 
 CREATE INDEX [Ingredient_order_index] ON [Ingredient]([order]);
+
+-- Table not strict because [value] can story any type of data.
+CREATE TABLE [Settings] (
+    [name] TEXT NOT NULL PRIMARY KEY,
+    [value] TEXT NOT NULL
+);
+
+INSERT INTO [Settings] ([name], [value]) VALUES ('new_user_registration_enabled', TRUE);
index 7f55fd6..23b7ccb 100644 (file)
@@ -16,6 +16,7 @@ use tracing::{event, Level};
 use crate::consts;
 
 pub mod recipe;
+pub mod settings;
 pub mod user;
 
 const CURRENT_DB_VERSION: u32 = 1;
diff --git a/backend/src/data/db/settings.rs b/backend/src/data/db/settings.rs
new file mode 100644 (file)
index 0000000..edbf351
--- /dev/null
@@ -0,0 +1,26 @@
+use std::str::FromStr;
+
+use super::{Connection, DBError, Result};
+
+impl Connection {
+    pub async fn get_new_user_registration_enabled(&self) -> Result<bool> {
+        self.get("new_user_registration_enabled").await
+    }
+
+    async fn get<T>(&self, name: &str) -> Result<T>
+    where
+        T: FromStr,
+    {
+        let v: String = sqlx::query_scalar("SELECT [value] FROM [Settings] WHERE [name] = $1")
+            .bind(name)
+            .fetch_one(&self.pool)
+            .await?;
+
+        T::from_str(&v).map_err(|_| {
+            DBError::Other(format!(
+                "Can't convert string value \"{}\" when reading setting {}",
+                v, name
+            ))
+        })
+    }
+}
index 092c2b3..c5bcb30 100644 (file)
@@ -68,7 +68,7 @@ type Result<T> = std::result::Result<T, AppError>;
 
 impl axum::response::IntoResponse for AppError {
     fn into_response(self) -> Response {
-        (StatusCode::INTERNAL_SERVER_ERROR, "Template error").into_response()
+        (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()).into_response()
     }
 }
 
index d01a422..985dc7b 100644 (file)
@@ -32,20 +32,29 @@ use crate::{
 
 #[debug_handler]
 pub async fn sign_up_get(
+    State(connection): State<db::Connection>,
     Extension(user): Extension<Option<model::User>>,
     Extension(tr): Extension<translation::Tr>,
-) -> Result<impl IntoResponse> {
-    Ok(Html(
-        SignUpFormTemplate {
-            user,
-            tr,
-            email: String::new(),
-            message: "",
-            message_email: "",
-            message_password: "",
-        }
-        .render()?,
-    ))
+) -> Result<Response> {
+    if connection.get_new_user_registration_enabled().await? {
+        Ok(Html(
+            SignUpFormTemplate {
+                user,
+                tr,
+                email: String::new(),
+                message: "",
+                message_email: "",
+                message_password: "",
+            }
+            .render()?,
+        )
+        .into_response())
+    } else {
+        Ok(
+            Html(MessageTemplate::new_with_user(tr.t(Sentence::SignUpClosed), tr, user).render()?)
+                .into_response(),
+        )
+    }
 }
 
 #[derive(Deserialize, Debug)]
@@ -109,6 +118,13 @@ pub async fn sign_up_post(
         .into_response())
     }
 
+    if !connection.get_new_user_registration_enabled().await? {
+        return Ok(Html(
+            MessageTemplate::new_with_user(tr.t(Sentence::SignUpClosed), tr, user).render()?,
+        )
+        .into_response());
+    }
+
     // Validation of email and password.
     if form_data.email.parse::<Address>().is_err() {
         return error_response(SignUpError::InvalidEmail, &form_data, user, tr);
index 157a707..7fa8053 100644 (file)
@@ -41,8 +41,10 @@ pub enum Sentence {
     SignUpEmailValidationSuccess,
     SignUpValidationExpired,
     SignUpValidationErrorTryAgain,
+    SignUpClosed,
     ChooseAPassword,
     ReEnterPassword,
+
     AccountMustBeValidatedFirst,
     InvalidEmail,
     PasswordDontMatch,
index dc02b19..cf79c8f 100644 (file)
@@ -44,6 +44,7 @@
             (SignUpEmailValidationSuccess, "Email validation successful, your account has been created"),
             (SignUpValidationExpired, "The validation has expired. Try to sign up again"),
             (SignUpValidationErrorTryAgain, "Validation error. Try to sign up again"),
+            (SignUpClosed, "New registration are closed"),
             (ChooseAPassword, "Choose a password (minimum {} characters)"),
             (ReEnterPassword, "Re-enter password"),
 
             (SignUpEmailValidationSuccess, "La validation de votre email s'est déroulée avec succès, votre compte a été créé"),
             (SignUpValidationExpired, "La validation a expiré. Essayez de vous inscrire à nouveau"),
             (SignUpValidationErrorTryAgain, "Erreur de validation. Essayez de vous inscrire à nouveau"),
+            (SignUpClosed, "Les inscriptions sont actuellement fermées"),
             (ChooseAPassword, "Choisir un mot de passe (minimum {} caractères)"),
             (ReEnterPassword, "Entrez à nouveau le mot de passe"),