feat(backend): move open signups configuration to db settings

This commit is contained in:
FrenchGithubUser
2025-12-14 20:23:24 +01:00
parent eeb822cc45
commit 264852aa6c
23 changed files with 75 additions and 239 deletions

View File

@@ -16,7 +16,6 @@ SQLX_OFFLINE=true
# arcadia config
ARCADIA_OPEN_SIGNUPS=true
ARCADIA_TRACKER_NAME=Arcadia
ARCADIA_FRONTEND_URL=https://site.com
ARCADIA_TRACKER_URL=https://site.com

View File

@@ -33,8 +33,6 @@ DATABASE_URL=postgresql://arcadia:password@localhost:4321/arcadia
## Arcadia Configuration
# Enable or disable open signups.
ARCADIA_OPEN_SIGNUPS=true
# Name of the tracker.
ARCADIA_TRACKER_NAME=Arcadia
# URL for the frontend application.

View File

@@ -1,4 +1,3 @@
use crate::OpenSignups;
use envconfig::Envconfig;
use reqwest::Url;
@@ -10,8 +9,6 @@ pub struct Env {
pub database_url: String,
#[envconfig(from = "JWT_SECRET")]
pub jwt_secret: String,
#[envconfig(from = "ARCADIA_OPEN_SIGNUPS")]
pub open_signups: OpenSignups,
#[envconfig(from = "ARCADIA_USER_CLASS_NAME_ON_SIGNUP")]
pub user_class_name_on_signup: String,
#[envconfig(from = "ARCADIA_FRONTEND_URL")]

View File

@@ -47,7 +47,7 @@ pub async fn exec<R: RedisPoolInterface + 'static>(
query: web::Query<RegisterQuery>,
) -> Result<HttpResponse> {
let invitation: Invitation;
if !arc.is_open_signups() {
if !arc.settings.lock().unwrap().open_signups {
let invitation_key = query
.invitation_key
.as_ref()
@@ -88,6 +88,7 @@ pub async fn exec<R: RedisPoolInterface + 'static>(
.unwrap()
.to_string();
let arcadia_settings = arc.settings.lock().unwrap().clone();
let user = arc
.pool
.create_user(
@@ -95,9 +96,7 @@ pub async fn exec<R: RedisPoolInterface + 'static>(
client_ip,
&password_hash,
&invitation,
&arc.is_open_signups(),
&arc.env.user_class_name_on_signup,
&arc.settings.lock().unwrap().default_css_sheet_name,
&arcadia_settings,
)
.await?;

View File

@@ -4,7 +4,6 @@ use arcadia_storage::{
};
use std::{
ops::Deref,
str::FromStr,
sync::{Arc, Mutex},
};
@@ -17,26 +16,6 @@ pub mod middlewares;
pub mod routes;
pub mod services;
#[derive(PartialEq, Debug, Copy, Clone)]
pub enum OpenSignups {
Disabled,
Enabled,
}
impl FromStr for OpenSignups {
type Err = env::Error;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
match s {
"true" => Ok(Self::Enabled),
"false" => Ok(Self::Disabled),
_ => Err(env::Error::EnvVariableParseError(
"ARCADIA_OPEN_SIGNUPS".to_string(),
)),
}
}
}
pub struct Arcadia<R: RedisPoolInterface> {
pub pool: Arc<ConnectionPool>,
pub redis_pool: Arc<R>,
@@ -68,8 +47,4 @@ impl<R: RedisPoolInterface> Arcadia<R> {
env,
}
}
#[inline]
pub fn is_open_signups(&self) -> bool {
Into::<OpenSignups>::into(self.env.open_signups) == OpenSignups::Enabled
}
}

View File

@@ -8,7 +8,7 @@ use actix_web::{
},
test, web, App, Error,
};
use arcadia_api::{env::Env, Arcadia, OpenSignups};
use arcadia_api::{env::Env, Arcadia};
use arcadia_storage::models::user::Login;
use arcadia_storage::{
connection_pool::ConnectionPool,
@@ -27,12 +27,10 @@ pub struct Profile {
pub async fn create_test_app<R: RedisPoolInterface + 'static>(
pool: Arc<ConnectionPool>,
redis_pool: R,
open_signups: OpenSignups,
global_upload_factor: i16,
global_download_factor: i16,
) -> impl Service<Request, Response = ServiceResponse, Error = Error> {
let mut env = Env::init_from_env().unwrap();
env.open_signups = open_signups;
env.global_upload_factor = global_upload_factor;
env.global_download_factor = global_download_factor;
@@ -128,7 +126,6 @@ pub async fn create_test_app_and_login<R: RedisPoolInterface + 'static>(
let service = create_test_app(
pool,
redis_pool,
OpenSignups::Disabled,
global_upload_factor,
global_download_factor,
)

View File

@@ -1,3 +1,6 @@
UPDATE arcadia_settings
SET open_signups = FALSE;
INSERT INTO
invitations (
expires_at,

View File

@@ -1,3 +1,6 @@
UPDATE arcadia_settings
SET open_signups = FALSE;
INSERT INTO
invitations (
expires_at,

View File

@@ -2,7 +2,6 @@ pub mod common;
pub mod mocks;
use actix_web::{http::StatusCode, test};
use arcadia_api::OpenSignups;
use arcadia_storage::{connection_pool::ConnectionPool, models::arcadia_settings::ArcadiaSettings};
use common::{
auth_header, call_and_read_body_json, create_test_app, create_test_app_and_login, TestUser,
@@ -33,6 +32,7 @@ async fn test_staff_can_get_arcadia_settings(pool: PgPool) {
assert_eq!(settings.user_class_name_on_signup, "newbie");
assert_eq!(settings.default_css_sheet_name, "arcadia");
assert!(settings.open_signups);
}
#[sqlx::test(fixtures("with_test_users"), migrations = "../storage/migrations")]
@@ -55,14 +55,7 @@ async fn test_regular_user_cannot_get_arcadia_settings(pool: PgPool) {
#[sqlx::test(fixtures("with_test_users"), migrations = "../storage/migrations")]
async fn test_get_arcadia_settings_requires_auth(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = create_test_app(
pool,
MockRedisPool::default(),
OpenSignups::Disabled,
100,
100,
)
.await;
let service = create_test_app(pool, MockRedisPool::default(), 100, 100).await;
let req = test::TestRequest::get()
.insert_header(("X-Forwarded-For", "10.10.4.88"))
@@ -88,6 +81,7 @@ async fn test_staff_can_update_arcadia_settings(pool: PgPool) {
let updated_settings = ArcadiaSettings {
user_class_name_on_signup: "newbie".to_string(),
default_css_sheet_name: "arcadia".to_string(),
open_signups: false,
};
let req = test::TestRequest::put()
@@ -101,11 +95,13 @@ async fn test_staff_can_update_arcadia_settings(pool: PgPool) {
assert_eq!(settings.user_class_name_on_signup, "newbie");
assert_eq!(settings.default_css_sheet_name, "arcadia");
assert!(!settings.open_signups);
// Verify the settings were actually updated in the database
let db_settings = pool.get_arcadia_settings().await.unwrap();
assert_eq!(db_settings.user_class_name_on_signup, "newbie");
assert_eq!(db_settings.default_css_sheet_name, "arcadia");
assert!(!db_settings.open_signups);
}
#[sqlx::test(fixtures("with_test_users"), migrations = "../storage/migrations")]
@@ -118,6 +114,7 @@ async fn test_regular_user_cannot_update_arcadia_settings(pool: PgPool) {
let updated_settings = ArcadiaSettings {
user_class_name_on_signup: "newbie".to_string(),
default_css_sheet_name: "arcadia".to_string(),
open_signups: true,
};
let req = test::TestRequest::put()
@@ -134,18 +131,12 @@ async fn test_regular_user_cannot_update_arcadia_settings(pool: PgPool) {
#[sqlx::test(fixtures("with_test_users"), migrations = "../storage/migrations")]
async fn test_update_arcadia_settings_requires_auth(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = create_test_app(
pool,
MockRedisPool::default(),
OpenSignups::Disabled,
100,
100,
)
.await;
let service = create_test_app(pool, MockRedisPool::default(), 100, 100).await;
let updated_settings = ArcadiaSettings {
user_class_name_on_signup: "newbie".to_string(),
default_css_sheet_name: "arcadia".to_string(),
open_signups: true,
};
let req = test::TestRequest::put()
@@ -184,6 +175,7 @@ async fn test_update_arcadia_settings_updates_in_memory_cache(pool: PgPool) {
let updated_settings = ArcadiaSettings {
user_class_name_on_signup: "newbie".to_string(),
default_css_sheet_name: "arcadia".to_string(),
open_signups: false,
};
let update_req = test::TestRequest::put()
@@ -195,6 +187,7 @@ async fn test_update_arcadia_settings_updates_in_memory_cache(pool: PgPool) {
let updated = call_and_read_body_json::<ArcadiaSettings, _>(&service, update_req).await;
assert_eq!(updated.user_class_name_on_signup, "newbie");
assert!(!updated.open_signups);
// Get the settings again to verify the in-memory cache was updated
let get_req_after = test::TestRequest::get()
@@ -207,4 +200,5 @@ async fn test_update_arcadia_settings_updates_in_memory_cache(pool: PgPool) {
call_and_read_body_json::<ArcadiaSettings, _>(&service, get_req_after).await;
assert_eq!(final_settings.user_class_name_on_signup, "newbie");
assert_eq!(final_settings.default_css_sheet_name, "arcadia");
assert!(!final_settings.open_signups);
}

View File

@@ -5,7 +5,7 @@ use actix_web::{
http::{header::HeaderValue, StatusCode},
test::{call_service, read_body, read_body_json, TestRequest},
};
use arcadia_api::{services::auth::InvalidationEntry, OpenSignups};
use arcadia_api::services::auth::InvalidationEntry;
use arcadia_storage::{
connection_pool::ConnectionPool, models::user::RefreshToken, redis::RedisInterface,
};
@@ -41,14 +41,7 @@ struct RegisterResponse {
#[sqlx::test(migrations = "../storage/migrations")]
async fn test_open_registration(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = create_test_app(
pool,
MockRedisPool::default(),
OpenSignups::Enabled,
100,
100,
)
.await;
let service = create_test_app(pool, MockRedisPool::default(), 100, 100).await;
let req = TestRequest::post()
.insert_header(("X-Forwarded-For", "10.10.4.88"))
@@ -85,14 +78,7 @@ async fn test_open_registration(pool: PgPool) {
#[sqlx::test(migrations = "../storage/migrations")]
async fn test_duplicate_username_registration(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = create_test_app(
pool,
MockRedisPool::default(),
OpenSignups::Enabled,
100,
100,
)
.await;
let service = create_test_app(pool, MockRedisPool::default(), 100, 100).await;
// Register first user
let req = TestRequest::post()
@@ -138,14 +124,7 @@ async fn test_duplicate_username_registration(pool: PgPool) {
)]
async fn test_closed_registration_failures(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = create_test_app(
pool,
MockRedisPool::default(),
OpenSignups::Disabled,
100,
100,
)
.await;
let service = create_test_app(pool, MockRedisPool::default(), 100, 100).await;
// No key specified. Should fail.
let req = TestRequest::post()
@@ -196,14 +175,7 @@ async fn test_closed_registration_failures(pool: PgPool) {
)]
async fn test_closed_registration_success(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = create_test_app(
pool,
MockRedisPool::default(),
OpenSignups::Disabled,
100,
100,
)
.await;
let service = create_test_app(pool, MockRedisPool::default(), 100, 100).await;
let req = TestRequest::post()
.insert_header(("X-Forwarded-For", "10.10.4.88"))
@@ -260,14 +232,7 @@ async fn test_closed_registration_success(pool: PgPool) {
)]
async fn test_closed_registration_expired_failure(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = create_test_app(
pool,
MockRedisPool::default(),
OpenSignups::Disabled,
100,
100,
)
.await;
let service = create_test_app(pool, MockRedisPool::default(), 100, 100).await;
let req = TestRequest::post()
.insert_header(("X-Forwarded-For", "10.10.4.88"))
@@ -325,7 +290,6 @@ async fn test_login_with_banned_user(pool: PgPool) {
let service = create_test_app(
Arc::new(ConnectionPool::with_pg_pool(pool)),
MockRedisPool::default(),
OpenSignups::Disabled,
100,
100,
)

View File

@@ -2,7 +2,6 @@ pub mod common;
pub mod mocks;
use actix_web::{http::StatusCode, test};
use arcadia_api::OpenSignups;
use arcadia_storage::{
connection_pool::ConnectionPool,
models::css_sheet::{CssSheet, CssSheetsEnriched, EditedCssSheet, UserCreatedCssSheet},
@@ -209,14 +208,7 @@ async fn test_regular_user_cannot_edit_css_sheet(pool: PgPool) {
)]
async fn test_get_css_sheet_content_public(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = create_test_app(
pool,
MockRedisPool::default(),
OpenSignups::Disabled,
100,
100,
)
.await;
let service = create_test_app(pool, MockRedisPool::default(), 100, 100).await;
// Get CSS content (public endpoint, no auth required)
let req = test::TestRequest::get()
@@ -235,14 +227,7 @@ async fn test_get_css_sheet_content_public(pool: PgPool) {
#[sqlx::test(fixtures("with_test_users"), migrations = "../storage/migrations")]
async fn test_get_nonexistent_css_sheet_content(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = create_test_app(
pool,
MockRedisPool::default(),
OpenSignups::Disabled,
100,
100,
)
.await;
let service = create_test_app(pool, MockRedisPool::default(), 100, 100).await;
let req = test::TestRequest::get()
.insert_header(("X-Forwarded-For", "10.10.4.88"))
@@ -256,14 +241,7 @@ async fn test_get_nonexistent_css_sheet_content(pool: PgPool) {
#[sqlx::test(fixtures("with_test_users"), migrations = "../storage/migrations")]
async fn test_css_sheet_endpoints_require_auth(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = create_test_app(
pool,
MockRedisPool::default(),
OpenSignups::Disabled,
100,
100,
)
.await;
let service = create_test_app(pool, MockRedisPool::default(), 100, 100).await;
// Test GET /api/css-sheets requires auth
let req = test::TestRequest::get()

View File

@@ -71,14 +71,7 @@ async fn test_non_staff_cannot_create_category(pool: PgPool) {
#[sqlx::test(fixtures("with_test_users"), migrations = "../storage/migrations")]
async fn test_create_category_without_auth(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = common::create_test_app(
pool,
MockRedisPool::default(),
arcadia_api::OpenSignups::Disabled,
100,
100,
)
.await;
let service = common::create_test_app(pool, MockRedisPool::default(), 100, 100).await;
let create_body = UserCreatedForumCategory {
name: "New Category".into(),
@@ -214,14 +207,7 @@ async fn test_non_staff_cannot_edit_category(pool: PgPool) {
)]
async fn test_edit_category_without_auth(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = common::create_test_app(
pool,
MockRedisPool::default(),
arcadia_api::OpenSignups::Disabled,
100,
100,
)
.await;
let service = common::create_test_app(pool, MockRedisPool::default(), 100, 100).await;
let edit_body = EditedForumCategory {
id: 100,

View File

@@ -83,14 +83,7 @@ async fn test_non_staff_cannot_create_sub_category(pool: PgPool) {
)]
async fn test_create_sub_category_without_auth(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = common::create_test_app(
pool,
MockRedisPool::default(),
arcadia_api::OpenSignups::Disabled,
100,
100,
)
.await;
let service = common::create_test_app(pool, MockRedisPool::default(), 100, 100).await;
let create_body = UserCreatedForumSubCategory {
forum_category_id: 100,
@@ -251,14 +244,7 @@ async fn test_non_staff_cannot_edit_sub_category(pool: PgPool) {
)]
async fn test_edit_sub_category_without_auth(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = common::create_test_app(
pool,
MockRedisPool::default(),
arcadia_api::OpenSignups::Disabled,
100,
100,
)
.await;
let service = common::create_test_app(pool, MockRedisPool::default(), 100, 100).await;
let edit_body = EditedForumSubCategory {
id: 100,

View File

@@ -69,14 +69,7 @@ async fn test_create_thread_success(pool: PgPool) {
)]
async fn test_create_thread_without_auth(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = common::create_test_app(
pool,
MockRedisPool::default(),
arcadia_api::OpenSignups::Disabled,
100,
100,
)
.await;
let service = common::create_test_app(pool, MockRedisPool::default(), 100, 100).await;
let create_body = UserCreatedForumThread {
forum_sub_category_id: 100,
@@ -247,14 +240,7 @@ async fn test_get_thread_success(pool: PgPool) {
)]
async fn test_get_thread_without_auth(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = common::create_test_app(
pool,
MockRedisPool::default(),
arcadia_api::OpenSignups::Disabled,
100,
100,
)
.await;
let service = common::create_test_app(pool, MockRedisPool::default(), 100, 100).await;
let req = test::TestRequest::get()
.uri("/api/forum/thread?id=100")
@@ -562,14 +548,7 @@ async fn test_staff_can_edit_any_thread(pool: PgPool) {
)]
async fn test_edit_thread_without_auth(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = common::create_test_app(
pool,
MockRedisPool::default(),
arcadia_api::OpenSignups::Disabled,
100,
100,
)
.await;
let service = common::create_test_app(pool, MockRedisPool::default(), 100, 100).await;
let edit_body = EditedForumThread {
id: 100,
@@ -1043,14 +1022,7 @@ async fn test_get_thread_posts_with_multiple_posts_pagination(pool: PgPool) {
)]
async fn test_get_thread_posts_without_auth(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = common::create_test_app(
pool,
MockRedisPool::default(),
arcadia_api::OpenSignups::Disabled,
100,
100,
)
.await;
let service = common::create_test_app(pool, MockRedisPool::default(), 100, 100).await;
let req = test::TestRequest::get()
.uri("/api/forum/thread/posts?thread_id=100&page_size=10")
@@ -1195,14 +1167,7 @@ async fn test_sub_category_threads_show_locked_threads(pool: PgPool) {
)]
async fn test_get_sub_category_threads_without_auth(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = common::create_test_app(
pool,
MockRedisPool::default(),
arcadia_api::OpenSignups::Disabled,
100,
100,
)
.await;
let service = common::create_test_app(pool, MockRedisPool::default(), 100, 100).await;
let req = test::TestRequest::get()
.uri("/api/forum/sub-category?id=100")

View File

@@ -2,7 +2,6 @@ pub mod common;
pub mod mocks;
use actix_web::{http::StatusCode, test};
use arcadia_api::OpenSignups;
use arcadia_storage::{
connection_pool::ConnectionPool,
models::user::{
@@ -82,14 +81,7 @@ async fn test_regular_user_cannot_create_user_class(pool: PgPool) {
#[sqlx::test(fixtures("with_test_users"), migrations = "../storage/migrations")]
async fn test_create_user_class_requires_auth(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = create_test_app(
pool,
MockRedisPool::default(),
OpenSignups::Disabled,
100,
100,
)
.await;
let service = create_test_app(pool, MockRedisPool::default(), 100, 100).await;
let user_class = UserCreatedUserClass {
name: "power_user".into(),

View File

@@ -2,7 +2,6 @@ pub mod common;
pub mod mocks;
use actix_web::{http::StatusCode, test};
use arcadia_api::OpenSignups;
use arcadia_storage::{connection_pool::ConnectionPool, models::user::UserPermission};
use common::{
auth_header, call_and_read_body_json, create_test_app, create_test_app_and_login, TestUser,
@@ -55,14 +54,7 @@ async fn test_regular_user_cannot_get_user_permissions(pool: PgPool) {
#[sqlx::test(fixtures("with_test_users"), migrations = "../storage/migrations")]
async fn test_get_user_permissions_requires_auth(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = create_test_app(
pool,
MockRedisPool::default(),
OpenSignups::Disabled,
100,
100,
)
.await;
let service = create_test_app(pool, MockRedisPool::default(), 100, 100).await;
let req = test::TestRequest::get()
.insert_header(("X-Forwarded-For", "10.10.4.88"))

View File

@@ -2,7 +2,6 @@ pub mod common;
pub mod mocks;
use actix_web::{http::StatusCode, test};
use arcadia_api::OpenSignups;
use arcadia_storage::{
connection_pool::ConnectionPool, models::css_sheet::UserCreatedCssSheet,
models::user::UserSettings,
@@ -92,14 +91,7 @@ async fn test_update_user_settings(pool: PgPool) {
#[sqlx::test(fixtures("with_test_users"), migrations = "../storage/migrations")]
async fn test_get_user_settings_requires_auth(pool: PgPool) {
let pool = Arc::new(ConnectionPool::with_pg_pool(pool));
let service = create_test_app(
pool,
MockRedisPool::default(),
OpenSignups::Disabled,
100,
100,
)
.await;
let service = create_test_app(pool, MockRedisPool::default(), 100, 100).await;
let req = test::TestRequest::get()
.insert_header(("X-Forwarded-For", "10.10.4.88"))

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "\n SELECT user_class_name_on_signup, default_css_sheet_name\n FROM arcadia_settings\n LIMIT 1\n ",
"query": "\n SELECT user_class_name_on_signup, default_css_sheet_name, open_signups\n FROM arcadia_settings\n LIMIT 1\n ",
"describe": {
"columns": [
{
@@ -12,15 +12,21 @@
"ordinal": 1,
"name": "default_css_sheet_name",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "open_signups",
"type_info": "Bool"
}
],
"parameters": {
"Left": []
},
"nullable": [
false,
false,
false
]
},
"hash": "0ce494c056dbc6166b9a68fd0ddf6e0319adf7db044ea27e1c391c1d5a29f230"
"hash": "98e680f38faf1889f65078dda373391d927ec50aa6a37c3a7bdbfc3e8494de3b"
}

View File

@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
"query": "\n UPDATE arcadia_settings\n SET user_class_name_on_signup = $1,\n default_css_sheet_name = $2\n RETURNING *\n ",
"query": "\n UPDATE arcadia_settings\n SET user_class_name_on_signup = $1,\n default_css_sheet_name = $2,\n open_signups = $3\n RETURNING *\n ",
"describe": {
"columns": [
{
@@ -12,18 +12,25 @@
"ordinal": 1,
"name": "default_css_sheet_name",
"type_info": "Varchar"
},
{
"ordinal": 2,
"name": "open_signups",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Varchar",
"Varchar"
"Varchar",
"Bool"
]
},
"nullable": [
false,
false,
false
]
},
"hash": "8a8c1264be51c4286ad8a85a2abb158ee499582e3212920d741cbd8b4494ee2b"
"hash": "d2e5725bc4b937da8b9ef576592d5e00c7bbaa0cde578e78f35c180e40d4b105"
}

View File

@@ -115,10 +115,11 @@ REFERENCES css_sheets(name)
ON UPDATE CASCADE;
CREATE TABLE arcadia_settings (
user_class_name_on_signup VARCHAR(30) NOT NULL REFERENCES user_classes(name) ON UPDATE CASCADE,
default_css_sheet_name VARCHAR(30) NOT NULL REFERENCES css_sheets(name) ON UPDATE CASCADE
default_css_sheet_name VARCHAR(30) NOT NULL REFERENCES css_sheets(name) ON UPDATE CASCADE,
open_signups BOOLEAN NOT NULL
);
INSERT INTO arcadia_settings (user_class_name_on_signup, default_css_sheet_name)
VALUES ('newbie', 'arcadia');
INSERT INTO arcadia_settings (user_class_name_on_signup, default_css_sheet_name, open_signups)
VALUES ('newbie', 'arcadia', TRUE);
CREATE TABLE api_keys (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),

View File

@@ -6,4 +6,5 @@ use utoipa::ToSchema;
pub struct ArcadiaSettings {
pub user_class_name_on_signup: String,
pub default_css_sheet_name: String,
pub open_signups: bool,
}

View File

@@ -7,7 +7,7 @@ impl ConnectionPool {
let settings = sqlx::query_as!(
ArcadiaSettings,
r#"
SELECT user_class_name_on_signup, default_css_sheet_name
SELECT user_class_name_on_signup, default_css_sheet_name, open_signups
FROM arcadia_settings
LIMIT 1
"#,
@@ -28,11 +28,13 @@ impl ConnectionPool {
r#"
UPDATE arcadia_settings
SET user_class_name_on_signup = $1,
default_css_sheet_name = $2
default_css_sheet_name = $2,
open_signups = $3
RETURNING *
"#,
settings.user_class_name_on_signup,
settings.default_css_sheet_name
settings.default_css_sheet_name,
settings.open_signups
)
.fetch_one(self.borrow())
.await

View File

@@ -1,6 +1,7 @@
use crate::{
connection_pool::ConnectionPool,
models::{
arcadia_settings::ArcadiaSettings,
invitation::Invitation,
user::{APIKey, Login, Register, User, UserCreatedAPIKey, UserPermission},
},
@@ -35,9 +36,7 @@ impl ConnectionPool {
from_ip: IpNetwork,
password_hash: &str,
invitation: &Invitation,
open_signups: &bool,
user_class_name: &str,
css_sheet_name: &str,
arcadia_settings: &ArcadiaSettings,
) -> Result<User> {
let rng = rand::rng();
@@ -65,14 +64,14 @@ impl ConnectionPool {
password_hash,
from_ip,
passkey,
user_class_name,
css_sheet_name
arcadia_settings.user_class_name_on_signup,
arcadia_settings.default_css_sheet_name
)
.fetch_one(self.borrow())
.await
.map_err(Error::CouldNotCreateUser)?;
if !*open_signups {
if !arcadia_settings.open_signups {
// TODO: check this properly
let _ = sqlx::query!(
r#"