diff --git a/i18n/en.toml b/i18n/en.toml index 25c1ec4..aa2a93c 100644 --- a/i18n/en.toml +++ b/i18n/en.toml @@ -71,6 +71,7 @@ limited = "Limited" list = "List" load_image = "Load Image" lock = "Lock" +login_captcha = "Login Captcha" medium = "Medium" members = "Members" message = "Message" diff --git a/i18n/fr.toml b/i18n/fr.toml index bbfbc50..1db40d5 100644 --- a/i18n/fr.toml +++ b/i18n/fr.toml @@ -71,6 +71,7 @@ limited = "Limité" list = "Liste" load_image = "Charger une image" lock = "Verrouiller" +login_captcha = "Captcha de connexion" medium = "Moyen" members = "Membres" message = "Message" # @TODO diff --git a/i18n/ja.toml b/i18n/ja.toml index 5112a68..8aa6619 100644 --- a/i18n/ja.toml +++ b/i18n/ja.toml @@ -71,6 +71,7 @@ limited = "制限付き" list = "リスト" load_image = "画像を読み込む" lock = "ロック" +login_captcha = "ログインキャプチャ" medium = "中" members = "メンバー" message = "Message" # @TODO diff --git a/i18n/uk.toml b/i18n/uk.toml index c7e0750..66998fe 100644 --- a/i18n/uk.toml +++ b/i18n/uk.toml @@ -72,6 +72,7 @@ list = "Список" load_image = "Відвантажити зображення" lock = "Заблокувати" medium = "Помірно" +login_captcha = "Капча входу" members = "Учасники" message = "Повідомлення" mod = "Модерація" diff --git a/i18n/zh_cn.toml b/i18n/zh_cn.toml index ecbbd3c..77b2c2b 100644 --- a/i18n/zh_cn.toml +++ b/i18n/zh_cn.toml @@ -72,6 +72,7 @@ list = "列表" load_image = "加载图片" lock = "锁定" medium = "中等" +login_captcha = "登录验证码" members = "成员" message = "Message" # @TODO mod = "管理员" diff --git a/src/controller/admin.rs b/src/controller/admin.rs index f120bd1..844b213 100644 --- a/src/controller/admin.rs +++ b/src/controller/admin.rs @@ -381,6 +381,7 @@ impl Default for SiteConfig { lang: "en".into(), tos_link: "https://en.wikipedia.org/wiki/WTFPL".into(), custom_footer_code: None, + login_captcha: None, } } } diff --git a/src/controller/meta_handler.rs b/src/controller/meta_handler.rs index a8207e3..ecc1a40 100644 --- a/src/controller/meta_handler.rs +++ b/src/controller/meta_handler.rs @@ -168,6 +168,7 @@ pub(super) struct PageData<'a> { pub(super) has_unread: bool, pub(super) lang: String, pub(super) custom_footer_code: Option<&'a str>, + pub(super) login_captcha: bool, } impl<'a> PageData<'a> { @@ -194,6 +195,7 @@ impl<'a> PageData<'a> { site_description, site_name: &site_config.site_name, title, + login_captcha: site_config.login_captcha.unwrap_or(false), } } } diff --git a/src/controller/mod.rs b/src/controller/mod.rs index 0f7c53f..3c54ea8 100644 --- a/src/controller/mod.rs +++ b/src/controller/mod.rs @@ -529,6 +529,8 @@ pub(super) struct SiteConfig { tos_link: String, #[validate(skip)] custom_footer_code: Option, + #[validate(skip)] + login_captcha: Option, } impl SiteConfig { diff --git a/src/controller/user.rs b/src/controller/user.rs index c6ce1d4..0127f84 100644 --- a/src/controller/user.rs +++ b/src/controller/user.rs @@ -877,8 +877,8 @@ pub(crate) const COOKIE_NAME: &str = "id"; /// Form data: `/signin` #[derive(Deserialize)] pub(crate) struct FormSignin { - captcha_id: String, - captcha_value: String, + captcha_id: Option, + captcha_value: Option, password: String, remember: String, username: String, @@ -925,12 +925,15 @@ pub(crate) async fn signin( /// `POST /signin` pub(crate) async fn signin_post(Form(input): Form) -> impl IntoResponse { - let captcha_char = DB - .open_partition("captcha", Default::default())? - .take(&input.captcha_id)? - .ok_or(AppError::CaptchaError)?; - if captcha_char != input.captcha_value { - return Err(AppError::CaptchaError); + let site_config = SiteConfig::get(&DB)?; + if site_config.login_captcha == Some(true) { + let captcha_char = DB + .open_partition("captcha", Default::default())? + .take(&input.captcha_id.unwrap_or_default())? + .ok_or(AppError::CaptchaError)?; + if captcha_char != input.captcha_value.unwrap_or_default() { + return Err(AppError::CaptchaError); + } } let uid = match input.username.parse::() { @@ -941,7 +944,6 @@ pub(crate) async fn signin_post(Form(input): Form) -> impl IntoRespo }; let user: User = get_one(&DB, "users", uid)?; if check_password(&input.password, &user.password_hash) { - let site_config = SiteConfig::get(&DB)?; if site_config.read_only && Role::from(user.role) != Role::Admin { return Err(AppError::ReadOnly); } diff --git a/templates/admin.html b/templates/admin.html index 2bda9ca..af61820 100644 --- a/templates/admin.html +++ b/templates/admin.html @@ -283,6 +283,26 @@ +
+
+ +
+
+
+
+ {% match site_config.login_captcha %} + {% when Some(true) %} + + + {% else %} + + + {% endmatch %} +
+
+
+
+
diff --git a/templates/signin.html b/templates/signin.html index 7a1ecd0..930b665 100644 --- a/templates/signin.html +++ b/templates/signin.html @@ -28,6 +28,7 @@
+ {% if page_data.login_captcha %}
captcha
@@ -39,6 +40,7 @@ + {% endif %}