2021-03-25 19:19:40 +00:00
|
|
|
use crate::PerformCrud;
|
2023-03-21 15:03:05 +00:00
|
|
|
use activitypub_federation::http_signatures::generate_actor_keypair;
|
2021-03-25 19:19:40 +00:00
|
|
|
use actix_web::web::Data;
|
2021-12-15 19:49:59 +00:00
|
|
|
use lemmy_api_common::{
|
2022-11-28 14:29:33 +00:00
|
|
|
context::LemmyContext,
|
2022-05-03 17:44:13 +00:00
|
|
|
person::{LoginResponse, Register},
|
2022-09-27 16:48:44 +00:00
|
|
|
utils::{
|
2022-11-28 14:29:33 +00:00
|
|
|
generate_inbox_url,
|
|
|
|
generate_local_apub_endpoint,
|
|
|
|
generate_shared_inbox_url,
|
2022-09-27 16:48:44 +00:00
|
|
|
honeypot_check,
|
2022-10-27 09:24:07 +00:00
|
|
|
local_site_to_slur_regex,
|
2022-09-27 16:48:44 +00:00
|
|
|
password_length_check,
|
|
|
|
send_new_applicant_email_to_admins,
|
|
|
|
send_verification_email,
|
2022-11-28 14:29:33 +00:00
|
|
|
EndpointType,
|
2022-09-27 16:48:44 +00:00
|
|
|
},
|
2023-04-13 10:53:55 +00:00
|
|
|
websocket::handlers::captcha::CheckCaptcha,
|
2021-03-25 19:19:40 +00:00
|
|
|
};
|
|
|
|
use lemmy_db_schema::{
|
2022-05-03 17:44:13 +00:00
|
|
|
aggregates::structs::PersonAggregates,
|
2021-03-25 19:19:40 +00:00
|
|
|
source::{
|
2022-10-27 09:24:07 +00:00
|
|
|
local_user::{LocalUser, LocalUserInsertForm},
|
|
|
|
person::{Person, PersonInsertForm},
|
|
|
|
registration_application::{RegistrationApplication, RegistrationApplicationInsertForm},
|
2021-03-25 19:19:40 +00:00
|
|
|
},
|
2022-06-22 19:38:27 +00:00
|
|
|
traits::Crud,
|
2023-04-17 19:19:51 +00:00
|
|
|
RegistrationMode,
|
2021-03-25 19:19:40 +00:00
|
|
|
};
|
2022-10-27 09:24:07 +00:00
|
|
|
use lemmy_db_views::structs::{LocalUserView, SiteView};
|
2021-03-25 19:19:40 +00:00
|
|
|
use lemmy_utils::{
|
|
|
|
claims::Claims,
|
2022-06-02 14:33:41 +00:00
|
|
|
error::LemmyError,
|
2023-02-16 04:05:14 +00:00
|
|
|
utils::{
|
|
|
|
slurs::{check_slurs, check_slurs_opt},
|
|
|
|
validation::is_valid_actor_name,
|
|
|
|
},
|
2021-03-25 19:19:40 +00:00
|
|
|
ConnectionId,
|
|
|
|
};
|
|
|
|
|
|
|
|
#[async_trait::async_trait(?Send)]
|
|
|
|
impl PerformCrud for Register {
|
|
|
|
type Response = LoginResponse;
|
|
|
|
|
2021-12-06 14:54:47 +00:00
|
|
|
#[tracing::instrument(skip(self, context, _websocket_id))]
|
2021-03-25 19:19:40 +00:00
|
|
|
async fn perform(
|
|
|
|
&self,
|
|
|
|
context: &Data<LemmyContext>,
|
|
|
|
_websocket_id: Option<ConnectionId>,
|
|
|
|
) -> Result<LoginResponse, LemmyError> {
|
2021-07-05 16:07:26 +00:00
|
|
|
let data: &Register = self;
|
2021-03-25 19:19:40 +00:00
|
|
|
|
2022-11-09 10:05:00 +00:00
|
|
|
let site_view = SiteView::read_local(context.pool()).await?;
|
2022-10-27 09:24:07 +00:00
|
|
|
let local_site = site_view.local_site;
|
2023-01-05 01:42:30 +00:00
|
|
|
let require_registration_application =
|
|
|
|
local_site.registration_mode == RegistrationMode::RequireApplication;
|
2021-12-15 19:49:59 +00:00
|
|
|
|
2023-01-05 01:42:30 +00:00
|
|
|
if local_site.registration_mode == RegistrationMode::Closed {
|
2022-10-27 09:24:07 +00:00
|
|
|
return Err(LemmyError::from_message("registration_closed"));
|
2021-03-25 19:19:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
password_length_check(&data.password)?;
|
2021-10-01 11:37:39 +00:00
|
|
|
honeypot_check(&data.honeypot)?;
|
2021-03-25 19:19:40 +00:00
|
|
|
|
2022-10-27 09:24:07 +00:00
|
|
|
if local_site.require_email_verification && data.email.is_none() {
|
2021-12-15 19:49:59 +00:00
|
|
|
return Err(LemmyError::from_message("email_required"));
|
|
|
|
}
|
|
|
|
|
2023-01-05 01:42:30 +00:00
|
|
|
if local_site.site_setup && require_registration_application && data.answer.is_none() {
|
2021-12-15 19:49:59 +00:00
|
|
|
return Err(LemmyError::from_message(
|
|
|
|
"registration_application_answer_required",
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2021-03-25 19:19:40 +00:00
|
|
|
// Make sure passwords match
|
|
|
|
if data.password != data.password_verify {
|
2021-12-06 14:54:47 +00:00
|
|
|
return Err(LemmyError::from_message("passwords_dont_match"));
|
2021-03-25 19:19:40 +00:00
|
|
|
}
|
|
|
|
|
2022-11-09 10:05:00 +00:00
|
|
|
// If the site is set up, check the captcha
|
|
|
|
if local_site.site_setup && local_site.captcha_enabled {
|
2023-04-13 10:53:55 +00:00
|
|
|
let check = context
|
|
|
|
.chat_server()
|
|
|
|
.send(CheckCaptcha {
|
|
|
|
uuid: data.captcha_uuid.clone().unwrap_or_default(),
|
|
|
|
answer: data.captcha_answer.clone().unwrap_or_default(),
|
|
|
|
})
|
|
|
|
.await?;
|
2021-03-25 19:19:40 +00:00
|
|
|
if !check {
|
2021-12-06 14:54:47 +00:00
|
|
|
return Err(LemmyError::from_message("captcha_incorrect"));
|
2021-03-25 19:19:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-27 09:24:07 +00:00
|
|
|
let slur_regex = local_site_to_slur_regex(&local_site);
|
|
|
|
check_slurs(&data.username, &slur_regex)?;
|
|
|
|
check_slurs_opt(&data.answer, &slur_regex)?;
|
2021-03-25 19:19:40 +00:00
|
|
|
|
|
|
|
let actor_keypair = generate_actor_keypair()?;
|
2023-04-15 14:45:11 +00:00
|
|
|
is_valid_actor_name(&data.username, local_site.actor_name_max_length as usize)?;
|
2021-10-25 16:09:21 +00:00
|
|
|
let actor_id = generate_local_apub_endpoint(
|
2021-09-22 15:57:09 +00:00
|
|
|
EndpointType::Person,
|
|
|
|
&data.username,
|
|
|
|
&context.settings().get_protocol_and_hostname(),
|
|
|
|
)?;
|
2021-03-25 19:19:40 +00:00
|
|
|
|
|
|
|
// We have to create both a person, and local_user
|
|
|
|
|
|
|
|
// Register the new person
|
2022-10-27 09:24:07 +00:00
|
|
|
let person_form = PersonInsertForm::builder()
|
2022-11-19 04:33:54 +00:00
|
|
|
.name(data.username.clone())
|
2022-10-27 09:24:07 +00:00
|
|
|
.actor_id(Some(actor_id.clone()))
|
|
|
|
.private_key(Some(actor_keypair.private_key))
|
|
|
|
.public_key(actor_keypair.public_key)
|
|
|
|
.inbox_url(Some(generate_inbox_url(&actor_id)?))
|
|
|
|
.shared_inbox_url(Some(generate_shared_inbox_url(&actor_id)?))
|
2022-11-09 10:05:00 +00:00
|
|
|
// If its the initial site setup, they are an admin
|
|
|
|
.admin(Some(!local_site.site_setup))
|
2022-10-27 09:24:07 +00:00
|
|
|
.instance_id(site_view.site.instance_id)
|
|
|
|
.build();
|
2021-03-25 19:19:40 +00:00
|
|
|
|
|
|
|
// insert the person
|
2022-11-09 10:05:00 +00:00
|
|
|
let inserted_person = Person::create(context.pool(), &person_form)
|
|
|
|
.await
|
|
|
|
.map_err(|e| LemmyError::from_error_message(e, "user_already_exists"))?;
|
2021-03-25 19:19:40 +00:00
|
|
|
|
|
|
|
// Create the local user
|
2022-10-27 09:24:07 +00:00
|
|
|
let local_user_form = LocalUserInsertForm::builder()
|
|
|
|
.person_id(inserted_person.id)
|
2022-11-19 04:33:54 +00:00
|
|
|
.email(data.email.as_deref().map(str::to_lowercase))
|
2022-10-27 09:24:07 +00:00
|
|
|
.password_encrypted(data.password.to_string())
|
|
|
|
.show_nsfw(Some(data.show_nsfw))
|
|
|
|
.build();
|
2021-03-25 19:19:40 +00:00
|
|
|
|
2022-11-09 10:05:00 +00:00
|
|
|
let inserted_local_user = match LocalUser::create(context.pool(), &local_user_form).await {
|
2021-03-25 19:19:40 +00:00
|
|
|
Ok(lu) => lu,
|
|
|
|
Err(e) => {
|
|
|
|
let err_type = if e.to_string()
|
|
|
|
== "duplicate key value violates unique constraint \"local_user_email_key\""
|
|
|
|
{
|
|
|
|
"email_already_exists"
|
|
|
|
} else {
|
|
|
|
"user_already_exists"
|
|
|
|
};
|
|
|
|
|
|
|
|
// If the local user creation errored, then delete that person
|
2022-11-09 10:05:00 +00:00
|
|
|
Person::delete(context.pool(), inserted_person.id).await?;
|
2021-03-25 19:19:40 +00:00
|
|
|
|
2022-03-16 20:11:49 +00:00
|
|
|
return Err(LemmyError::from_error_message(e, err_type));
|
2021-03-25 19:19:40 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-01-05 01:42:30 +00:00
|
|
|
if local_site.site_setup && require_registration_application {
|
2021-12-15 19:49:59 +00:00
|
|
|
// Create the registration application
|
2022-10-27 09:24:07 +00:00
|
|
|
let form = RegistrationApplicationInsertForm {
|
|
|
|
local_user_id: inserted_local_user.id,
|
2021-12-15 19:49:59 +00:00
|
|
|
// We already made sure answer was not null above
|
2022-11-19 04:33:54 +00:00
|
|
|
answer: data.answer.clone().expect("must have an answer"),
|
2021-12-15 19:49:59 +00:00
|
|
|
};
|
|
|
|
|
2022-11-09 10:05:00 +00:00
|
|
|
RegistrationApplication::create(context.pool(), &form).await?;
|
2021-12-15 19:49:59 +00:00
|
|
|
}
|
|
|
|
|
2022-09-27 16:48:44 +00:00
|
|
|
// Email the admins
|
2022-10-27 09:24:07 +00:00
|
|
|
if local_site.application_email_admins {
|
2022-09-27 16:48:44 +00:00
|
|
|
send_new_applicant_email_to_admins(&data.username, context.pool(), context.settings())
|
|
|
|
.await?;
|
|
|
|
}
|
|
|
|
|
2021-12-15 19:49:59 +00:00
|
|
|
let mut login_response = LoginResponse {
|
|
|
|
jwt: None,
|
|
|
|
registration_created: false,
|
|
|
|
verify_email_sent: false,
|
|
|
|
};
|
|
|
|
|
2022-11-09 10:05:00 +00:00
|
|
|
// Log the user in directly if the site is not setup, or email verification and application aren't required
|
|
|
|
if !local_site.site_setup
|
2023-01-05 01:42:30 +00:00
|
|
|
|| (!require_registration_application && !local_site.require_email_verification)
|
2022-11-09 10:05:00 +00:00
|
|
|
{
|
2021-12-15 19:49:59 +00:00
|
|
|
login_response.jwt = Some(
|
|
|
|
Claims::jwt(
|
|
|
|
inserted_local_user.id.0,
|
|
|
|
&context.secret().jwt_secret,
|
|
|
|
&context.settings().hostname,
|
|
|
|
)?
|
|
|
|
.into(),
|
|
|
|
);
|
|
|
|
} else {
|
2022-10-27 09:24:07 +00:00
|
|
|
if local_site.require_email_verification {
|
2022-03-24 15:25:51 +00:00
|
|
|
let local_user_view = LocalUserView {
|
|
|
|
local_user: inserted_local_user,
|
|
|
|
person: inserted_person,
|
|
|
|
counts: PersonAggregates::default(),
|
|
|
|
};
|
|
|
|
// we check at the beginning of this method that email is set
|
|
|
|
let email = local_user_view
|
|
|
|
.local_user
|
|
|
|
.email
|
|
|
|
.clone()
|
|
|
|
.expect("email was provided");
|
2022-10-27 09:24:07 +00:00
|
|
|
|
2022-06-22 20:24:54 +00:00
|
|
|
send_verification_email(&local_user_view, &email, context.pool(), context.settings())
|
|
|
|
.await?;
|
2021-12-15 19:49:59 +00:00
|
|
|
login_response.verify_email_sent = true;
|
|
|
|
}
|
|
|
|
|
2023-01-05 01:42:30 +00:00
|
|
|
if require_registration_application {
|
2021-12-15 19:49:59 +00:00
|
|
|
login_response.registration_created = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(login_response)
|
2021-03-25 19:19:40 +00:00
|
|
|
}
|
|
|
|
}
|