allow setting referral code if not already set (#141)

This commit is contained in:
Bryan Stitt 2023-06-22 12:41:05 -07:00 committed by GitHub
parent 376b9f474d
commit c79b787e13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -8,7 +8,6 @@ pub mod subuser;
use crate::app::Web3ProxyApp; use crate::app::Web3ProxyApp;
use crate::errors::{Web3ProxyError, Web3ProxyErrorContext, Web3ProxyResponse}; use crate::errors::{Web3ProxyError, Web3ProxyErrorContext, Web3ProxyResponse};
use axum::{ use axum::{
headers::{authorization::Bearer, Authorization}, headers::{authorization::Bearer, Authorization},
response::IntoResponse, response::IntoResponse,
@ -16,9 +15,8 @@ use axum::{
}; };
use axum_macros::debug_handler; use axum_macros::debug_handler;
use check_if_email_exists::{check_email, CheckEmailInput, Reachable}; use check_if_email_exists::{check_email, CheckEmailInput, Reachable};
use entities; use entities::{self, referee, referrer, user};
use entities::user; use migration::sea_orm::{self, ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter};
use migration::sea_orm::{self, ActiveModelTrait};
use serde::Deserialize; use serde::Deserialize;
use std::sync::Arc; use std::sync::Arc;
@ -38,9 +36,11 @@ pub async fn user_get(
} }
/// the JSON input to the `post_user` handler. /// the JSON input to the `post_user` handler.
/// TODO: what else can we update here? password hash? subscription to newsletter?
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct UserPost { pub struct UserPost {
email: Option<String>, email: Option<String>,
referral_code: Option<String>,
} }
/// `POST /user` -- modify the account connected to the bearer token in the `Authentication` header. /// `POST /user` -- modify the account connected to the bearer token in the `Authentication` header.
@ -52,6 +52,8 @@ pub async fn user_post(
) -> Web3ProxyResponse { ) -> Web3ProxyResponse {
let (user, _semaphore) = app.bearer_is_authorized(bearer_token).await?; let (user, _semaphore) = app.bearer_is_authorized(bearer_token).await?;
let user_id = user.id;
let mut user: user::ActiveModel = user.into(); let mut user: user::ActiveModel = user.into();
// update the email address // update the email address
@ -72,24 +74,56 @@ pub async fn user_post(
)); ));
} }
// TODO: do some basic validation // TODO: send a confirmation email first before marking this email address as validated
// TODO: don't set immediatly, send a confirmation email first
// TODO: compare first? or is sea orm smart enough to do that for us?
user.email = sea_orm::Set(Some(x)); user.email = sea_orm::Set(Some(x));
} }
} }
// TODO: what else can we update here? password hash? subscription to newsletter? let txn = app.db_transaction().await?;
// update the referral code IFF they do not already have one set
if let Some(x) = payload.referral_code {
let desired_referral_code = referrer::Entity::find()
.filter(referrer::Column::ReferralCode.like(&x))
.one(&txn)
.await?
.web3_context(format!("posted referral code does not exist"))?;
// make sure the user doesn't already have a referral code set
if let Some(existing_referee) = referee::Entity::find()
.filter(referee::Column::UserId.eq(user_id))
.one(&txn)
.await?
{
if existing_referee.used_referral_code == desired_referral_code.id {
// code was already set this code. nothing to do
} else {
// referral code cannot change! error!
return Err(Web3ProxyError::BadRequest(
"referral code cannot be changed".into(),
));
}
} else {
// no existing referral code. set one now
let new_referee = referee::ActiveModel {
used_referral_code: sea_orm::Set(desired_referral_code.id),
user_id: sea_orm::Set(user_id),
..Default::default()
};
new_referee.save(&txn).await?;
}
}
let user = if user.is_changed() { let user = if user.is_changed() {
let db_conn = app.db_conn().web3_context("Getting database connection")?; user.save(&txn).await?
user.save(&db_conn).await?
} else { } else {
// no changes. no need to touch the database // no changes. no need to touch the database
user user
}; };
txn.commit().await?;
let user: user::Model = user.try_into().web3_context("Returning updated user")?; let user: user::Model = user.try_into().web3_context("Returning updated user")?;
Ok(Json(user).into_response()) Ok(Json(user).into_response())