Disable login captcha if backend has no captcha secret (#5288)
* Add /_internal/globals route * Don't show login captcha if backend claims it's disabled * try to re-add tombi * typos * Assume captcha enabled if globals route is unreachable * Prepare frontend fixes
This commit is contained in:
20
.github/workflows/check-generic.yml
vendored
20
.github/workflows/check-generic.yml
vendored
@@ -13,13 +13,15 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: crate-ci/typos@master
|
- uses: crate-ci/typos@v1.43.1
|
||||||
|
|
||||||
# broken: <https://github.com/SchemaStore/schemastore/issues/5108>
|
# see <https://github.com/influxdata/datafusion-udf-wasm/pull/275>
|
||||||
# tombi:
|
tombi:
|
||||||
# runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
# steps:
|
steps:
|
||||||
# - uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
# - uses: tombi-toml/setup-tombi@v1
|
- uses: taiki-e/install-action@v2
|
||||||
# - run: tombi lint
|
with:
|
||||||
# - run: tombi fmt --check
|
tool: tombi
|
||||||
|
- run: tombi lint
|
||||||
|
- run: tombi fmt --check
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ const_format = "0.2.34"
|
|||||||
daedalus = { path = "packages/daedalus" }
|
daedalus = { path = "packages/daedalus" }
|
||||||
dashmap = "6.1.0"
|
dashmap = "6.1.0"
|
||||||
data-url = "0.3.2"
|
data-url = "0.3.2"
|
||||||
deadpool-redis = { version = "0.22.1", git = "https://github.com/modrinth/deadpool", rev = "db5fb00b036ecc8fe5f18853c559b745ffe47bde" }
|
deadpool-redis = { git = "https://github.com/modrinth/deadpool", rev = "db5fb00b036ecc8fe5f18853c559b745ffe47bde", version = "0.22.1" }
|
||||||
derive_more = "2.0.1"
|
derive_more = "2.0.1"
|
||||||
directories = "6.0.0"
|
directories = "6.0.0"
|
||||||
dirs = "6.0.0"
|
dirs = "6.0.0"
|
||||||
|
|||||||
@@ -22,9 +22,13 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<HCaptcha ref="captcha" v-model="token" />
|
<HCaptcha v-if="globals?.captcha_enabled" ref="captcha" v-model="token" />
|
||||||
|
|
||||||
<button class="btn btn-primary centered-btn" :disabled="!token" @click="recovery">
|
<button
|
||||||
|
class="btn btn-primary centered-btn"
|
||||||
|
:disabled="globals?.captcha_enabled ? !token : false"
|
||||||
|
@click="recovery"
|
||||||
|
>
|
||||||
<SendIcon /> {{ formatMessage(methodChoiceMessages.action) }}
|
<SendIcon /> {{ formatMessage(methodChoiceMessages.action) }}
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
@@ -158,6 +162,15 @@ if (route.query.flow) {
|
|||||||
|
|
||||||
const captcha = ref()
|
const captcha = ref()
|
||||||
|
|
||||||
|
const { data: globals } = await useAsyncData('auth-globals', async () => {
|
||||||
|
try {
|
||||||
|
return await useBaseFetch('globals', { internal: true })
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error fetching globals:', err)
|
||||||
|
return { captcha_enabled: true }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const email = ref('')
|
const email = ref('')
|
||||||
const token = ref('')
|
const token = ref('')
|
||||||
|
|
||||||
|
|||||||
@@ -89,11 +89,11 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<HCaptcha ref="captcha" v-model="token" />
|
<HCaptcha v-if="globals?.captcha_enabled" ref="captcha" v-model="token" />
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="btn btn-primary continue-btn centered-btn"
|
class="btn btn-primary continue-btn centered-btn"
|
||||||
:disabled="!token"
|
:disabled="globals?.captcha_enabled ? !token : false"
|
||||||
@click="beginPasswordSignIn()"
|
@click="beginPasswordSignIn()"
|
||||||
>
|
>
|
||||||
{{ formatMessage(commonMessages.signInButton) }} <RightArrowIcon />
|
{{ formatMessage(commonMessages.signInButton) }} <RightArrowIcon />
|
||||||
@@ -210,6 +210,15 @@ if (auth.value.user) {
|
|||||||
|
|
||||||
const captcha = ref()
|
const captcha = ref()
|
||||||
|
|
||||||
|
const { data: globals } = await useAsyncData('auth-globals', async () => {
|
||||||
|
try {
|
||||||
|
return await useBaseFetch('globals', { internal: true })
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error fetching globals:', err)
|
||||||
|
return { captcha_enabled: true }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const email = ref('')
|
const email = ref('')
|
||||||
const password = ref('')
|
const password = ref('')
|
||||||
const token = ref('')
|
const token = ref('')
|
||||||
|
|||||||
@@ -108,11 +108,11 @@
|
|||||||
</IntlFormatted>
|
</IntlFormatted>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<HCaptcha ref="captcha" v-model="token" />
|
<HCaptcha v-if="globals?.captcha_enabled" ref="captcha" v-model="token" />
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="btn btn-primary continue-btn centered-btn"
|
class="btn btn-primary continue-btn centered-btn"
|
||||||
:disabled="!token"
|
:disabled="globals?.captcha_enabled ? !token : false"
|
||||||
@click="createAccount"
|
@click="createAccount"
|
||||||
>
|
>
|
||||||
{{ formatMessage(messages.createAccountButton) }} <RightArrowIcon />
|
{{ formatMessage(messages.createAccountButton) }} <RightArrowIcon />
|
||||||
@@ -209,6 +209,15 @@ if (auth.value.user) {
|
|||||||
|
|
||||||
const captcha = ref()
|
const captcha = ref()
|
||||||
|
|
||||||
|
const { data: globals } = await useAsyncData('auth-globals', async () => {
|
||||||
|
try {
|
||||||
|
return await useBaseFetch('globals', { internal: true })
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error fetching globals:', err)
|
||||||
|
return { captcha_enabled: true }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
const email = ref('')
|
const email = ref('')
|
||||||
const username = ref('')
|
const username = ref('')
|
||||||
const password = ref('')
|
const password = ref('')
|
||||||
|
|||||||
39
apps/labrinth/src/routes/internal/globals.rs
Normal file
39
apps/labrinth/src/routes/internal/globals.rs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
use std::{collections::HashMap, sync::LazyLock};
|
||||||
|
|
||||||
|
use actix_web::{get, web};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
pub fn config(cfg: &mut utoipa_actix_web::service_config::ServiceConfig) {
|
||||||
|
cfg.service(get_globals);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See [`get`].
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
|
||||||
|
pub struct Globals {
|
||||||
|
/// Map of years to how much a creator can withdraw in that year, in USD,
|
||||||
|
/// before they must fill in a tax compliance form.
|
||||||
|
///
|
||||||
|
/// If the current year is not contained in this map:
|
||||||
|
/// - if the year is before the first year in the map, the threshold is the first year's.
|
||||||
|
/// - if the year is after the last year in the map, the threshold is the last year's threshold.
|
||||||
|
pub tax_compliance_thresholds: HashMap<u16, u64>,
|
||||||
|
/// If this backend instance has a Captcha enabled for password login.
|
||||||
|
///
|
||||||
|
/// In production, this will always be true. On local testing builds, this
|
||||||
|
/// will always be false.
|
||||||
|
pub captcha_enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLOBALS: LazyLock<Globals> = LazyLock::new(|| Globals {
|
||||||
|
tax_compliance_thresholds: [(2025, 600), (2026, 2000)]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
captcha_enabled: dotenvy::var("HCAPTCHA_SECRET").is_ok_and(|x| x != "none"),
|
||||||
|
});
|
||||||
|
|
||||||
|
/// Gets configured global non-secret variables for this backend instance.
|
||||||
|
#[utoipa::path]
|
||||||
|
#[get("")]
|
||||||
|
pub async fn get_globals() -> web::Json<Globals> {
|
||||||
|
web::Json(GLOBALS.clone())
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ pub mod delphi;
|
|||||||
pub mod external_notifications;
|
pub mod external_notifications;
|
||||||
pub mod flows;
|
pub mod flows;
|
||||||
pub mod gdpr;
|
pub mod gdpr;
|
||||||
|
pub mod globals;
|
||||||
pub mod gotenberg;
|
pub mod gotenberg;
|
||||||
pub mod medal;
|
pub mod medal;
|
||||||
pub mod moderation;
|
pub mod moderation;
|
||||||
@@ -55,5 +56,10 @@ pub fn utoipa_config(
|
|||||||
utoipa_actix_web::scope("/_internal/search-management")
|
utoipa_actix_web::scope("/_internal/search-management")
|
||||||
.wrap(default_cors())
|
.wrap(default_cors())
|
||||||
.configure(search::config),
|
.configure(search::config),
|
||||||
|
)
|
||||||
|
.service(
|
||||||
|
utoipa_actix_web::scope("/_internal/globals")
|
||||||
|
.wrap(default_cors())
|
||||||
|
.configure(globals::config),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user