Skip to content

Commit

Permalink
dev: fix clippy warnings for: src/routes/user.rs
Browse files Browse the repository at this point in the history
  • Loading branch information
da2ce7 committed May 10, 2023
1 parent 33c3218 commit 6d5e2ed
Showing 1 changed file with 59 additions and 10 deletions.
69 changes: 59 additions & 10 deletions src/routes/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub fn init(cfg: &mut web::ServiceConfig) {
.service(web::resource("/register").route(web::post().to(register)))
.service(web::resource("/login").route(web::post().to(login)))
// code-review: should not this be a POST method? We add the user to the blacklist. We do not delete the user.
.service(web::resource("/ban/{user}").route(web::delete().to(ban_user)))
.service(web::resource("/ban/{user}").route(web::delete().to(ban)))
.service(web::resource("/token/verify").route(web::post().to(verify_token)))
.service(web::resource("/token/renew").route(web::post().to(renew_token)))
.service(web::resource("/email/verify/{token}").route(web::get().to(verify_email))),
Expand All @@ -48,6 +48,19 @@ pub struct Token {
pub token: String,
}

/// Register a User in the Index
///
/// # Errors
///
/// This function will return a `ServiceError::EmailMissing` if email is required, but missing.
/// This function will return a `ServiceError::EmailInvalid` if supplied email is badly formatted.
/// This function will return a `ServiceError::PasswordsDontMatch` if the supplied passwords do not match.
/// This function will return a `ServiceError::PasswordTooShort` if the supplied password is too short.
/// This function will return a `ServiceError::PasswordTooLong` if the supplied password is too long.
/// This function will return a `ServiceError::UsernameInvalid` if the supplied username is badly formatted.
/// This function will return an error if unable to successfully hash the password.
/// This function will return an error if unable to insert user into the database.
/// This function will return a `ServiceError::FailedToSendVerificationEmail` if unable to send the required verification email.
pub async fn register(req: HttpRequest, mut payload: web::Json<Register>, app_data: WebAppData) -> ServiceResult<impl Responder> {
info!("registering user: {}", payload.username);

Expand All @@ -60,7 +73,7 @@ pub async fn register(req: HttpRequest, mut payload: web::Json<Register>, app_da
}
}
EmailOnSignup::None => payload.email = None,
_ => {}
EmailOnSignup::Optional => {}
}

if let Some(email) = &payload.email {
Expand Down Expand Up @@ -108,13 +121,13 @@ pub async fn register(req: HttpRequest, mut payload: web::Json<Register>, app_da
let _ = app_data.database.grant_admin_role(user_id).await;
}

let conn_info = req.connection_info();
let conn_info = req.connection_info().clone();

if settings.mail.email_verification_enabled && payload.email.is_some() {
let mail_res = app_data
.mailer
.send_verification_mail(
payload.email.as_ref().unwrap(),
payload.email.as_ref().expect("variable `email` is checked above"),
&payload.username,
user_id,
format!("{}://{}", conn_info.scheme(), conn_info.host()).as_str(),
Expand All @@ -130,6 +143,15 @@ pub async fn register(req: HttpRequest, mut payload: web::Json<Register>, app_da
Ok(HttpResponse::Ok())
}

/// Login user to Index
///
/// # Errors
///
/// This function will return a `ServiceError::WrongPasswordOrUsername` if unable to get user profile.
/// This function will return a `ServiceError::InternalServerError` if unable to get user authentication data from the user id.
/// This function will return an error if unable to verify the password.
/// This function will return a `ServiceError::EmailNotVerified` if the email should be, but is not verified.
/// This function will return an error if unable to get the user data from the database.
pub async fn login(payload: web::Json<Login>, app_data: WebAppData) -> ServiceResult<impl Responder> {
// get the user profile from database
let user_profile = app_data
Expand Down Expand Up @@ -172,6 +194,11 @@ pub async fn login(payload: web::Json<Login>, app_data: WebAppData) -> ServiceRe
}

/// Verify if the user supplied and the database supplied passwords match
///
/// # Errors
///
/// This function will return an error if unable to parse password hash from the stored user authentication value.
/// This function will return a `ServiceError::WrongPasswordOrUsername` if unable to match the password with either `argon2id` or `pbkdf2-sha256`.
pub fn verify_password(password: &[u8], user_authentication: &UserAuthentication) -> Result<(), ServiceError> {
// wrap string of the hashed password into a PasswordHash struct for verification
let parsed_hash = PasswordHash::new(&user_authentication.password_hash)?;
Expand All @@ -195,6 +222,11 @@ pub fn verify_password(password: &[u8], user_authentication: &UserAuthentication
}
}

/// Verify a supplied JWT.
///
/// # Errors
///
/// This function will return an error if unable to verify the supplied payload as a valid jwt.
pub async fn verify_token(payload: web::Json<Token>, app_data: WebAppData) -> ServiceResult<impl Responder> {
// verify if token is valid
let _claims = app_data.auth.verify_jwt(&payload.token).await?;
Expand All @@ -204,14 +236,20 @@ pub async fn verify_token(payload: web::Json<Token>, app_data: WebAppData) -> Se
}))
}

/// Renew a supplied JWT.
///
/// # Errors
///
/// This function will return an error if unable to verify the supplied payload as a valid jwt.
/// This function will return an error if unable to get user data from the database.
pub async fn renew_token(payload: web::Json<Token>, app_data: WebAppData) -> ServiceResult<impl Responder> {
const ONE_WEEK_IN_SECONDS: u64 = 604_800;

// verify if token is valid
let claims = app_data.auth.verify_jwt(&payload.token).await?;

let user_compact = app_data.database.get_user_compact_from_id(claims.user.user_id).await?;

const ONE_WEEK_IN_SECONDS: u64 = 604_800;

// renew token if it is valid for less than one week
let token = match claims.exp - current_time() {
x if x < ONE_WEEK_IN_SECONDS => app_data.auth.sign_jwt(user_compact.clone()).await,
Expand All @@ -229,7 +267,10 @@ pub async fn renew_token(payload: web::Json<Token>, app_data: WebAppData) -> Ser

pub async fn verify_email(req: HttpRequest, app_data: WebAppData) -> String {
let settings = app_data.cfg.settings.read().await;
let token = req.match_info().get("token").unwrap();
let token = match req.match_info().get("token").ok_or(ServiceError::InternalServerError) {
Ok(token) => token,
Err(err) => return err.to_string(),
};

let token_data = match decode::<VerifyClaims>(
token,
Expand All @@ -255,8 +296,16 @@ pub async fn verify_email(req: HttpRequest, app_data: WebAppData) -> String {
String::from("Email verified, you can close this page.")
}

// TODO: add reason and date_expiry parameters to request
pub async fn ban_user(req: HttpRequest, app_data: WebAppData) -> ServiceResult<impl Responder> {
/// Ban a user from the Index
///
/// TODO: add reason and `date_expiry` parameters to request
///
/// # Errors
///
/// This function will return a `ServiceError::InternalServerError` if unable get user from the request.
/// This function will return an error if unable to get user profile from supplied username.
/// This function will return an error if unable to ser the ban of the user in the database.
pub async fn ban(req: HttpRequest, app_data: WebAppData) -> ServiceResult<impl Responder> {
debug!("banning user");

let user = app_data.auth.get_user_compact_from_request(&req).await?;
Expand All @@ -266,7 +315,7 @@ pub async fn ban_user(req: HttpRequest, app_data: WebAppData) -> ServiceResult<i
return Err(ServiceError::Unauthorized);
}

let to_be_banned_username = req.match_info().get("user").unwrap();
let to_be_banned_username = req.match_info().get("user").ok_or(ServiceError::InternalServerError)?;

debug!("user to be banned: {}", to_be_banned_username);

Expand Down

0 comments on commit 6d5e2ed

Please sign in to comment.