Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement email verification (fixes #219) #1956

Closed
wants to merge 2 commits into from
Closed

Conversation

Nutomic
Copy link
Member

@Nutomic Nutomic commented Nov 24, 2021

very much wip

@Nutomic
Copy link
Member Author

Nutomic commented Nov 25, 2021

Updated, works fine now in my testing. It will require some frontend changes though:

  • Create a frontend page for the email verification and send link to that (instead of raw api link). then also change the verify endpoint to POST
  • Add error message for email_not_verified on login
  • When changing email in user settings, the change will only be applied after clicking the verification link, should maybe add a message about that
  • Add admin checkbox to toggle require_email_verification

@Nutomic Nutomic changed the title WIP: Implement email verification (fixes #219) Implement email verification (fixes #219) Nov 25, 2021
@Nutomic Nutomic marked this pull request as ready for review November 25, 2021 17:51
@dessalines
Copy link
Member

Run this to make sure your commit hooks are up to date, it missed an unwrap:

cp .cargo-husky/hooks/pre-commit .git/hooks/

@Nutomic
Copy link
Member Author

Nutomic commented Nov 26, 2021

updated

@@ -0,0 +1,15 @@
-- use defaults from db for local user init
alter table local_user alter column theme set default 'browser';
alter table local_user alter column default_listing_type set default 2;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pub enum ListingType {
  All,
  Local,
  Subscribed,
  Community,
}

I noticed in the DB the default is 1 or Local, but when a new user registers, it uses subscribed. I spose subscribed is the better default here, so this is good.

Comment on lines +50 to 59
// no email verification if the site is not setup yet
let mut email_verification = false;

// Make sure site has open registration
if let Ok(site) = blocking(context.pool(), Site::read_simple).await? {
if !site.open_registration {
return Err(ApiError::err_plain("registration_closed").into());
}
email_verification = site.require_email_verification;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of mut, you could probably do let email_verification = if let ...

Comment on lines +228 to +238
// Log the user in directly if email verification is not required
let jwt = if email_verification {
send_verification_email(
inserted_local_user.id,
// we check at the beginning of this method that email is set
&inserted_local_user.email.expect("email was provided"),
&inserted_person.name,
context,
)
.await?;
None
Copy link
Member

@dessalines dessalines Nov 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, I'll have to remember to create a translation string for "Your application has been sent" or something like that, for when jwt is None on a register.

The other possibility is to add an optional application_sent: bool field to LoginResponse. That might be more clear.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm doing the registration_application stuff, and I also need to add a registration_sent: bool for that too, so you might as well add one here for verify_email_sent.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did this now on my PR, so don't worry about this one.

Ok(LoginResponse {
jwt: data.auth.to_owned(),
})
Ok(LoginResponse { jwt: None })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This never really made sense in the first place, and now we'll get conflicting responses. Could you create DeleteAccountResponse { success: bool } below here.

pub fn read_for_token(conn: &PgConnection, token: &str) -> Result<Self, Error> {
use crate::schema::email_verification::dsl::*;
email_verification
.filter(verification_token.eq(token))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should also add a time filter to protect this... maybe a week? Example: https://github.com/LemmyNet/lemmy/blob/main/crates/db_schema/src/impls/password_reset_request.rs#L57

Comment on lines +33 to +34
pub person_id: Option<PersonId>,
pub password_encrypted: Option<String>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore that above.

Comment on lines +22 to +24
// TODO: link should be replaced with a frontend route once that exists
let verify_link = format!(
"{}/api/v3/user/verify_email?token={}",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Go ahead and make it {}/verify_email?..., I can start adding that front end soon.

create table email_verification (
id serial primary key,
local_user_id int references local_user(id) on update cascade on delete cascade not null,
email text not null,
Copy link
Member

@dessalines dessalines Nov 29, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be removed. There should only be one email field, on the local_user table.

local_user_id int references local_user(id) on update cascade on delete cascade not null,
email text not null,
verification_token text not null

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add published.

.route("/unread_count", web::get().to(route_get::<GetUnreadCount>)),
.route("/unread_count", web::get().to(route_get::<GetUnreadCount>))
// TODO: currently GET for easier testing, but should probably be POST
.route("/verify_email", web::get().to(route_get::<VerifyEmail>)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Go ahead and make POST, I can start working on the front end for this soon.

@dessalines
Copy link
Member

Don't force push to this, because I'll be working off it from another branch.

show_read_posts: Some(true),
show_new_post_notifs: Some(false),
send_notifications_to_email: Some(false),
email_verified: Some(!email_verification),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just noticed this too. If email_verification is false, this will incorrectly get set to true, when no email has been actually verified. This should just be Some(false)

Comment on lines +33 to +34
pub person_id: Option<PersonId>,
pub password_encrypted: Option<String>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ignore that above.

@dessalines
Copy link
Member

I'll close this as I've merged its work and some updates into #1949

@dessalines dessalines closed this Dec 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants