"eslint": "^8.25.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "^27.0.6",
- "lemmy-js-client": "0.17.0-rc.60",
+ "lemmy-js-client": "0.17.0-rc.61",
"node-fetch": "^2.6.1",
"prettier": "^2.7.1",
"ts-jest": "^27.0.3",
GetCommentsResponse,
FeaturePost,
PostFeatureType,
+ RegistrationMode,
} from "lemmy-js-client";
export interface API {
// Registration applications are now enabled by default, need to disable them
let editSiteForm: EditSite = {
- require_application: false,
+ registration_mode: RegistrationMode.Open,
federation_debug: true,
rate_limit_message: 999,
rate_limit_post: 999,
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
-lemmy-js-client@0.17.0-rc.60:
- version "0.17.0-rc.60"
- resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.17.0-rc.60.tgz#6cabac42d842eb1f152d230be018090050476614"
- integrity sha512-Nl+DUBJde0KpKywNkX5wof9PDCmr6RuJlgukVfQRmW5rznYRKYnI1V+awf+9mUx1eNQ8jhnjVO+6XxOzMjloZA==
+lemmy-js-client@0.17.0-rc.61:
+ version "0.17.0-rc.61"
+ resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.17.0-rc.61.tgz#c01e129a3d4c3483ecf337f1e4acf0ad91f9684f"
+ integrity sha512-xauBCD5i4vlUEWqsTMIXLCXeIjAK7ivVIN3C/g+RMAM7mD3CTcRkDZUerwnvLipIfr7V/4iYLWZW0orBaiV1CQ==
dependencies:
node-fetch "2.6.6"
utils::password_length_check,
};
use lemmy_db_schema::source::{
+ local_site::RegistrationMode,
local_user::LocalUser,
password_reset_request::PasswordResetRequest,
};
// Return the jwt if login is allowed
let site_view = SiteView::read_local(context.pool()).await?;
- let jwt =
- if site_view.local_site.require_application && !updated_local_user.accepted_application {
- None
- } else {
- Some(
- Claims::jwt(
- updated_local_user.id.0,
- &context.secret().jwt_secret,
- &context.settings().hostname,
- )?
- .into(),
- )
- };
+ let jwt = if site_view.local_site.registration_mode == RegistrationMode::RequireApplication
+ && !updated_local_user.accepted_application
+ {
+ None
+ } else {
+ Some(
+ Claims::jwt(
+ updated_local_user.id.0,
+ &context.secret().jwt_secret,
+ &context.settings().hostname,
+ )?
+ .into(),
+ )
+ };
Ok(LoginResponse {
jwt,
use crate::sensitive::Sensitive;
use lemmy_db_schema::{
newtypes::{CommentId, CommunityId, LanguageId, PersonId, PostId},
- source::{language::Language, tagline::Tagline},
+ source::{language::Language, local_site::RegistrationMode, tagline::Tagline},
ListingType,
ModlogActionType,
SearchType,
pub icon: Option<String>,
pub banner: Option<String>,
pub enable_downvotes: Option<bool>,
- pub open_registration: Option<bool>,
pub enable_nsfw: Option<bool>,
pub community_creation_admin_only: Option<bool>,
pub require_email_verification: Option<bool>,
- pub require_application: Option<bool>,
pub application_question: Option<String>,
pub private_instance: Option<bool>,
pub default_theme: Option<String>,
pub allowed_instances: Option<Vec<String>>,
pub blocked_instances: Option<Vec<String>>,
pub taglines: Option<Vec<String>>,
+ pub registration_mode: Option<RegistrationMode>,
pub auth: Sensitive<String>,
}
pub icon: Option<String>,
pub banner: Option<String>,
pub enable_downvotes: Option<bool>,
- pub open_registration: Option<bool>,
pub enable_nsfw: Option<bool>,
pub community_creation_admin_only: Option<bool>,
pub require_email_verification: Option<bool>,
- pub require_application: Option<bool>,
pub application_question: Option<String>,
pub private_instance: Option<bool>,
pub default_theme: Option<String>,
pub allowed_instances: Option<Vec<String>>,
pub blocked_instances: Option<Vec<String>>,
pub taglines: Option<Vec<String>>,
+ pub registration_mode: Option<RegistrationMode>,
pub auth: Sensitive<String>,
}
community::{Community, CommunityUpdateForm},
email_verification::{EmailVerification, EmailVerificationForm},
instance::Instance,
- local_site::LocalSite,
+ local_site::{LocalSite, RegistrationMode},
local_site_rate_limit::LocalSiteRateLimit,
password_reset_request::PasswordResetRequest,
person::{Person, PersonUpdateForm},
local_site: &LocalSite,
pool: &DbPool,
) -> Result<(), LemmyError> {
- if local_site.require_application
+ if local_site.registration_mode == RegistrationMode::RequireApplication
&& !local_user_view.local_user.accepted_application
&& !local_user_view.person.admin
{
use actix_web::web::Data;
use lemmy_api_common::context::LemmyContext;
-use lemmy_db_schema::source::local_site::LocalSite;
use lemmy_utils::{error::LemmyError, ConnectionId};
mod comment;
websocket_id: Option<ConnectionId>,
) -> Result<Self::Response, LemmyError>;
}
-
-/// Make sure if applications are required, that there is an application questionnaire
-pub fn check_application_question(
- application_question: &Option<Option<String>>,
- local_site: &LocalSite,
- require_application: &Option<bool>,
-) -> Result<(), LemmyError> {
- if require_application.unwrap_or(false)
- && (application_question == &Some(None)
- || (application_question.is_none() && local_site.application_question.is_none()))
- {
- return Err(LemmyError::from_message("application_question_required"));
- }
- Ok(())
-}
-use crate::{check_application_question, PerformCrud};
+use crate::{site::check_application_question, PerformCrud};
use activitypub_federation::core::signatures::generate_actor_keypair;
use actix_web::web::Data;
use lemmy_api_common::{
let application_question = diesel_option_overwrite(&data.application_question);
check_application_question(
&application_question,
- &local_site,
- &data.require_application,
+ data
+ .registration_mode
+ .unwrap_or(local_site.registration_mode),
)?;
let actor_id: DbUrl = Url::parse(&context.settings().get_protocol_and_hostname())?.into();
// Set the site setup to true
.site_setup(Some(true))
.enable_downvotes(data.enable_downvotes)
- .open_registration(data.open_registration)
+ .registration_mode(data.registration_mode)
.enable_nsfw(data.enable_nsfw)
.community_creation_admin_only(data.community_creation_admin_only)
.require_email_verification(data.require_email_verification)
- .require_application(data.require_application)
.application_question(application_question)
.private_instance(data.private_instance)
.default_theme(data.default_theme.clone())
+use lemmy_db_schema::source::local_site::RegistrationMode;
+use lemmy_utils::error::LemmyError;
+
mod create;
mod read;
mod update;
+
+pub fn check_application_question(
+ application_question: &Option<Option<String>>,
+ registration_mode: RegistrationMode,
+) -> Result<(), LemmyError> {
+ if registration_mode == RegistrationMode::RequireApplication
+ && application_question.as_ref().unwrap_or(&None).is_none()
+ {
+ Err(LemmyError::from_message("application_question_required"))
+ } else {
+ Ok(())
+ }
+}
-use crate::{check_application_question, PerformCrud};
+use crate::{site::check_application_question, PerformCrud};
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
actor_language::SiteLanguage,
federation_allowlist::FederationAllowList,
federation_blocklist::FederationBlockList,
- local_site::{LocalSite, LocalSiteUpdateForm},
+ local_site::{LocalSite, LocalSiteUpdateForm, RegistrationMode},
local_site_rate_limit::{LocalSiteRateLimit, LocalSiteRateLimitUpdateForm},
local_user::LocalUser,
site::{Site, SiteUpdateForm},
let application_question = diesel_option_overwrite(&data.application_question);
check_application_question(
&application_question,
- &local_site,
- &data.require_application,
+ data
+ .registration_mode
+ .unwrap_or(local_site.registration_mode),
)?;
if let Some(default_post_listing_type) = &data.default_post_listing_type {
let local_site_form = LocalSiteUpdateForm::builder()
.enable_downvotes(data.enable_downvotes)
- .open_registration(data.open_registration)
+ .registration_mode(data.registration_mode)
.enable_nsfw(data.enable_nsfw)
.community_creation_admin_only(data.community_creation_admin_only)
.require_email_verification(data.require_email_verification)
- .require_application(data.require_application)
.application_question(application_question)
.private_instance(data.private_instance)
.default_theme(data.default_theme.clone())
// will be able to log in. It really only wants this to be a requirement for NEW signups.
// So if it was set from false, to true, you need to update all current users columns to be verified.
+ let old_require_application =
+ local_site.registration_mode == RegistrationMode::RequireApplication;
let new_require_application = update_local_site
.as_ref()
- .map(|ols| ols.require_application)
+ .map(|ols| ols.registration_mode == RegistrationMode::RequireApplication)
.unwrap_or(false);
- if !local_site.require_application && new_require_application {
+ if !old_require_application && new_require_application {
LocalUser::set_all_users_registration_applications_accepted(context.pool())
.await
.map_err(|e| LemmyError::from_error_message(e, "couldnt_set_all_registrations_accepted"))?;
use lemmy_db_schema::{
aggregates::structs::PersonAggregates,
source::{
+ local_site::RegistrationMode,
local_user::{LocalUser, LocalUserInsertForm},
person::{Person, PersonInsertForm},
registration_application::{RegistrationApplication, RegistrationApplicationInsertForm},
let site_view = SiteView::read_local(context.pool()).await?;
let local_site = site_view.local_site;
+ let require_registration_application =
+ local_site.registration_mode == RegistrationMode::RequireApplication;
- if !local_site.open_registration {
+ if local_site.registration_mode == RegistrationMode::Closed {
return Err(LemmyError::from_message("registration_closed"));
}
return Err(LemmyError::from_message("email_required"));
}
- if local_site.site_setup && local_site.require_application && data.answer.is_none() {
+ if local_site.site_setup && require_registration_application && data.answer.is_none() {
return Err(LemmyError::from_message(
"registration_application_answer_required",
));
}
};
- if local_site.site_setup && local_site.require_application {
+ if local_site.site_setup && require_registration_application {
// Create the registration application
let form = RegistrationApplicationInsertForm {
local_user_id: inserted_local_user.id,
// Log the user in directly if the site is not setup, or email verification and application aren't required
if !local_site.site_setup
- || (!local_site.require_application && !local_site.require_email_verification)
+ || (!require_registration_application && !local_site.require_email_verification)
{
login_response.jwt = Some(
Claims::jwt(
login_response.verify_email_sent = true;
}
- if local_site.require_application {
+ if require_registration_application {
login_response.registration_created = true;
}
}
use crate::{
schema::local_site::dsl::local_site,
- source::local_site::{LocalSite, LocalSiteInsertForm, LocalSiteUpdateForm},
+ source::local_site::{
+ LocalSite,
+ LocalSiteInsertForm,
+ LocalSiteUpdateForm,
+ RegistrationMode,
+ RegistrationModeType,
+ },
utils::{get_conn, DbPool},
};
-use diesel::{dsl::insert_into, result::Error};
+use diesel::{
+ deserialize,
+ deserialize::FromSql,
+ dsl::insert_into,
+ pg::{Pg, PgValue},
+ result::Error,
+ serialize,
+ serialize::{IsNull, Output, ToSql},
+};
use diesel_async::RunQueryDsl;
+use std::io::Write;
impl LocalSite {
pub async fn create(pool: &DbPool, form: &LocalSiteInsertForm) -> Result<Self, Error> {
diesel::delete(local_site).execute(conn).await
}
}
+
+impl ToSql<RegistrationModeType, Pg> for RegistrationMode {
+ fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, Pg>) -> serialize::Result {
+ match *self {
+ RegistrationMode::Closed => out.write_all(b"closed")?,
+ RegistrationMode::RequireApplication => out.write_all(b"require_application")?,
+ RegistrationMode::Open => out.write_all(b"open")?,
+ }
+ Ok(IsNull::No)
+ }
+}
+
+impl FromSql<RegistrationModeType, Pg> for RegistrationMode {
+ fn from_sql(bytes: PgValue<'_>) -> deserialize::Result<Self> {
+ match bytes.as_bytes() {
+ b"closed" => Ok(RegistrationMode::Closed),
+ b"require_application" => Ok(RegistrationMode::RequireApplication),
+ b"open" => Ok(RegistrationMode::Open),
+ _ => Err("Unrecognized enum variant".into()),
+ }
+ }
+}
}
table! {
+ use crate::source::local_site::RegistrationModeType;
+ use diesel::sql_types::*;
+
local_site(id) {
id -> Int4,
site_id -> Int4,
site_setup -> Bool,
enable_downvotes -> Bool,
- open_registration -> Bool,
enable_nsfw -> Bool,
community_creation_admin_only -> Bool,
require_email_verification -> Bool,
- require_application -> Bool,
application_question -> Nullable<Text>,
private_instance -> Bool,
default_theme -> Text,
federation_worker_count -> Int4,
captcha_enabled -> Bool,
captcha_difficulty -> Text,
+ registration_mode -> RegistrationModeType,
published -> Timestamp,
updated -> Nullable<Timestamp>,
}
pub site_id: SiteId,
pub site_setup: bool,
pub enable_downvotes: bool,
- pub open_registration: bool,
pub enable_nsfw: bool,
pub community_creation_admin_only: bool,
pub require_email_verification: bool,
- pub require_application: bool,
pub application_question: Option<String>,
pub private_instance: bool,
pub default_theme: String,
pub federation_worker_count: i32,
pub captcha_enabled: bool,
pub captcha_difficulty: String,
+ pub registration_mode: RegistrationMode,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
}
pub site_id: SiteId,
pub site_setup: Option<bool>,
pub enable_downvotes: Option<bool>,
- pub open_registration: Option<bool>,
pub enable_nsfw: Option<bool>,
pub community_creation_admin_only: Option<bool>,
pub require_email_verification: Option<bool>,
- pub require_application: Option<bool>,
pub application_question: Option<String>,
pub private_instance: Option<bool>,
pub default_theme: Option<String>,
pub federation_worker_count: Option<i32>,
pub captcha_enabled: Option<bool>,
pub captcha_difficulty: Option<String>,
+ pub registration_mode: Option<RegistrationMode>,
}
#[derive(Clone, TypedBuilder)]
pub struct LocalSiteUpdateForm {
pub site_setup: Option<bool>,
pub enable_downvotes: Option<bool>,
- pub open_registration: Option<bool>,
pub enable_nsfw: Option<bool>,
pub community_creation_admin_only: Option<bool>,
pub require_email_verification: Option<bool>,
- pub require_application: Option<bool>,
pub application_question: Option<Option<String>>,
pub private_instance: Option<bool>,
pub default_theme: Option<String>,
pub federation_worker_count: Option<i32>,
pub captcha_enabled: Option<bool>,
pub captcha_difficulty: Option<String>,
+ pub registration_mode: Option<RegistrationMode>,
pub updated: Option<Option<chrono::NaiveDateTime>>,
}
+
+#[cfg(feature = "full")]
+#[derive(SqlType)]
+#[diesel(postgres_type(name = "registration_mode_enum"))]
+pub struct RegistrationModeType;
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
+#[cfg_attr(feature = "full", derive(FromSqlRow, AsExpression))]
+#[cfg_attr(feature = "full", diesel(sql_type = RegistrationModeType))]
+#[serde(rename_all = "lowercase")]
+pub enum RegistrationMode {
+ Closed,
+ RequireApplication,
+ Open,
+}
use actix_web::{error::ErrorBadRequest, web, Error, HttpResponse, Result};
use anyhow::anyhow;
use lemmy_api_common::context::LemmyContext;
+use lemmy_db_schema::source::local_site::RegistrationMode;
use lemmy_db_views::structs::SiteView;
use lemmy_utils::{error::LemmyError, version};
use serde::{Deserialize, Serialize};
} else {
vec![]
};
-
+ let open_registrations = site_view.local_site.registration_mode == RegistrationMode::Open;
let json = NodeInfo {
version: "2.0".to_string(),
software: NodeInfoSoftware {
local_posts: site_view.counts.posts,
local_comments: site_view.counts.comments,
},
- open_registrations: site_view.local_site.open_registration,
+ open_registrations,
};
Ok(HttpResponse::Ok().json(json))
--- /dev/null
+-- add back old registration columns
+alter table local_site add column open_registration boolean not null default true;
+alter table local_site add column require_application boolean not null default true;
+
+-- regenerate their values
+with subquery as (
+ select registration_mode,
+ case
+ when registration_mode='closed' then false
+ else true
+ end
+ from local_site
+)
+update local_site
+set open_registration = subquery.case
+from subquery;
+with subquery as (
+ select registration_mode,
+ case
+ when registration_mode='open' then false
+ else true
+ end
+ from local_site
+)
+update local_site
+set require_application = subquery.case
+from subquery;
+
+-- drop new column and type
+alter table local_site drop column registration_mode;
+drop type registration_mode_enum;
\ No newline at end of file
--- /dev/null
+-- create enum for registration modes
+create type registration_mode_enum as enum
+ ('closed', 'require_application', 'open');
+
+-- use this enum for registration mode setting
+alter table local_site add column
+ registration_mode registration_mode_enum not null default 'require_application';
+
+-- generate registration mode value from previous settings
+with subquery as (
+ select open_registration, require_application,
+ case
+ when open_registration=false then 'closed'::registration_mode_enum
+ when open_registration=true and require_application=true then 'require_application'
+ else 'open'
+ end
+ from local_site
+)
+update local_site
+set registration_mode = subquery.case
+from subquery;
+
+-- drop old registration settings
+alter table local_site drop column open_registration;
+alter table local_site drop column require_application;