All checks were successful
continuous-integration/drone/push Build is passing
130 lines
4.1 KiB
Rust
130 lines
4.1 KiB
Rust
use std::{collections::HashMap, sync::Arc};
|
|
|
|
use argon2::{password_hash::SaltString, Argon2, PasswordHasher};
|
|
use axum::{
|
|
extract::Query,
|
|
http::StatusCode,
|
|
routing::{get, post},
|
|
Extension, Json,
|
|
};
|
|
use rand_core::OsRng;
|
|
use sqlx::SqlitePool;
|
|
|
|
use crate::{
|
|
api::client_server::errors::authentication_error::AuthenticationError,
|
|
models::sessions::Session,
|
|
responses::{
|
|
authentication::{AuthenticationResponse, AuthenticationSuccess},
|
|
registration::RegistrationResponse,
|
|
},
|
|
};
|
|
use crate::{
|
|
models::devices::Device,
|
|
responses::{flow::Flows, registration::RegistrationSuccess},
|
|
};
|
|
use crate::{
|
|
models::users::User,
|
|
requests::registration::RegistrationRequest,
|
|
responses::username_available::UsernameAvailable,
|
|
types::{authentication_data::AuthenticationData, user_id::UserId},
|
|
Config,
|
|
};
|
|
|
|
use super::errors::{api_error::ApiError, registration_error::RegistrationError};
|
|
|
|
pub fn routes() -> axum::Router {
|
|
axum::Router::new()
|
|
.route("/r0/login", get(get_login).post(post_login))
|
|
.route("/r0/register", post(post_register))
|
|
.route("/r0/register/available", get(get_username_available))
|
|
}
|
|
|
|
#[tracing::instrument]
|
|
async fn get_login() -> Result<Json<Flows>, ApiError> {
|
|
Ok(Json(Flows::new()))
|
|
}
|
|
|
|
#[tracing::instrument(skip_all)]
|
|
async fn post_login(
|
|
Extension(config): Extension<Arc<Config>>,
|
|
Extension(db): Extension<SqlitePool>,
|
|
Json(body): Json<AuthenticationData>,
|
|
) -> Result<Json<AuthenticationResponse>, ApiError> {
|
|
let user = UserId::new("name", "server_name")
|
|
.ok()
|
|
.ok_or(AuthenticationError::InvalidUserId)?;
|
|
let resp = AuthenticationSuccess::new("", "", &user);
|
|
|
|
Ok(Json(AuthenticationResponse::Success(resp)))
|
|
}
|
|
|
|
#[tracing::instrument(skip_all)]
|
|
async fn get_username_available(
|
|
Extension(config): Extension<Arc<Config>>,
|
|
Extension(db): Extension<SqlitePool>,
|
|
Query(params): Query<HashMap<String, String>>,
|
|
) -> Result<Json<UsernameAvailable>, ApiError> {
|
|
let username = params
|
|
.get("username")
|
|
.ok_or(RegistrationError::MissingUserId)?;
|
|
let user_id = UserId::new(username, &config.homeserver_name)
|
|
.ok()
|
|
.ok_or(RegistrationError::InvalidUserId)?;
|
|
let exists = User::exists(&db, &user_id).await?;
|
|
|
|
Ok(Json(UsernameAvailable::new(!exists)))
|
|
}
|
|
|
|
#[tracing::instrument(skip_all)]
|
|
async fn post_register(
|
|
Extension(config): Extension<Arc<Config>>,
|
|
Extension(db): Extension<SqlitePool>,
|
|
Json(body): Json<RegistrationRequest>,
|
|
) -> Result<Json<RegistrationResponse>, ApiError> {
|
|
body.auth()
|
|
.ok_or(RegistrationError::AdditionalAuthenticationInformation)?;
|
|
|
|
let (user, device) = match &body.auth().expect("must be Some") {
|
|
AuthenticationData::Password(auth_data) => {
|
|
let username = body.username().ok_or(RegistrationError::MissingUserId)?;
|
|
let user_id = UserId::new(username, &config.homeserver_name)
|
|
.ok()
|
|
.ok_or(RegistrationError::InvalidUserId)?;
|
|
|
|
if User::exists(&db, &user_id).await? {
|
|
return Err(ApiError::from(RegistrationError::UserIdTaken));
|
|
}
|
|
|
|
let display_name = match body.initial_device_display_name() {
|
|
Some(display_name) => display_name.as_ref(),
|
|
None => "Random displayname",
|
|
};
|
|
|
|
let user = User::new(&user_id, &user_id.to_string(), auth_data.password())?
|
|
.create(&db)
|
|
.await?;
|
|
|
|
let device = Device::new(&user, "test", display_name)?
|
|
.create(&db)
|
|
.await?;
|
|
|
|
(user, device)
|
|
}
|
|
};
|
|
|
|
if body.inhibit_login().unwrap_or(false) {
|
|
let resp = RegistrationSuccess::new(None, device.device_id(), &user.user_id().to_string());
|
|
|
|
Ok(Json(RegistrationResponse::Success(resp)))
|
|
} else {
|
|
let session = Session::new(&device)?.create(&db).await?;
|
|
let resp = RegistrationSuccess::new(
|
|
Some(session.key()),
|
|
device.device_id(),
|
|
&user.user_id().to_string(),
|
|
);
|
|
|
|
Ok(Json(RegistrationResponse::Success(resp)))
|
|
}
|
|
}
|