use crate::ayb_db::db_interfaces::AybDb;
use crate::ayb_db::models::{AuthenticationMethodType, EntityType};
use crate::email::{backend::EmailBackends, send_registration_email};
use crate::error::AybError;
use crate::http::structs::{AuthenticationDetails, EmptyResponse};
use crate::server::config::AybConfig;
use crate::server::tokens::encrypt_auth_token;
use crate::server::username_validation::validate_username;
use crate::server::utils::{get_lowercased_header, get_required_header};
use crate::server::web_frontend::WebFrontendDetails;
use actix_web::{post, web, HttpRequest, HttpResponse};
use std::str::FromStr;
#[post("/v1/register")]
async fn register(
req: HttpRequest,
ayb_db: web::Data<Box<dyn AybDb>>,
ayb_config: web::Data<AybConfig>,
web_info: web::Data<Option<WebFrontendDetails>>,
email_backends: web::Data<EmailBackends>,
) -> Result<HttpResponse, AybError> {
let entity = get_lowercased_header(&req, "entity")?;
let email_address = get_lowercased_header(&req, "email-address")?;
let entity_type = get_required_header(&req, "entity-type")?;
validate_username(&entity)?;
let desired_entity = ayb_db.get_entity_by_slug(&entity).await;
let mut already_verified = false;
if let Ok(instantiated_entity) = desired_entity {
let auth_methods = ayb_db
.list_authentication_methods(&instantiated_entity)
.await?;
for method in auth_methods {
if AuthenticationMethodType::try_from(method.method_type)?
!= AuthenticationMethodType::Email
|| method.email_address != email_address
{
already_verified = true;
break;
}
}
}
if already_verified {
return Err(AybError::Other {
message: format!("{entity} has already been registered"),
});
}
let token = encrypt_auth_token(
&AuthenticationDetails {
version: 1,
entity: entity.clone(),
entity_type: EntityType::from_str(&entity_type)? as i16,
email_address: email_address.to_owned(),
},
&ayb_config.authentication,
)?;
send_registration_email(
&email_backends,
&ayb_config.email,
&email_address,
&token,
web_info.get_ref(),
)
.await?;
Ok(HttpResponse::Ok().json(EmptyResponse {}))
}