clean up api error and login stub
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
304f82baa4
commit
b0895145de
@ -10,7 +10,7 @@ use axum::{
|
|||||||
use rand_core::OsRng;
|
use rand_core::OsRng;
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
use crate::responses::registration::RegistrationResponse;
|
use crate::{responses::{registration::RegistrationResponse, authentication::{AuthenticationResponse, AuthenticationSuccess}}, api::client_server::errors::authentication_error::AuthenticationError};
|
||||||
use crate::{
|
use crate::{
|
||||||
models::devices::Device,
|
models::devices::Device,
|
||||||
responses::{flow::Flows, registration::RegistrationSuccess},
|
responses::{flow::Flows, registration::RegistrationSuccess},
|
||||||
@ -38,9 +38,16 @@ async fn get_login() -> Result<Json<Flows>, ApiError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
async fn post_login(body: String) -> StatusCode {
|
async fn post_login(
|
||||||
dbg!(body);
|
Extension(config): Extension<Arc<Config>>,
|
||||||
StatusCode::INTERNAL_SERVER_ERROR
|
Extension(db): Extension<SqlitePool>,
|
||||||
|
Json(body): Json<AuthenticationData>
|
||||||
|
) -> Result<Json<AuthenticationResponse>, ApiError> {
|
||||||
|
let user = UserId::new("name", "server_name").ok().ok_or(AuthenticationError::InvalidUserId)?;
|
||||||
|
todo!("Flesh this out more");
|
||||||
|
let resp = AuthenticationSuccess::new("", "", &user);
|
||||||
|
|
||||||
|
Ok(Json(AuthenticationResponse::Success(resp)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
@ -76,17 +83,17 @@ async fn post_register(
|
|||||||
.ok()
|
.ok()
|
||||||
.ok_or(RegistrationError::InvalidUserId)?;
|
.ok_or(RegistrationError::InvalidUserId)?;
|
||||||
|
|
||||||
User::exists(&db, &user_id)
|
if User::exists(&db, &user_id).await? {
|
||||||
.await?
|
return Err(ApiError::from(RegistrationError::UserIdTaken));
|
||||||
.then(|| ())
|
}
|
||||||
.ok_or(RegistrationError::UserIdTaken)?;
|
|
||||||
|
|
||||||
let display_name = match body.initial_device_display_name() {
|
let display_name = match body.initial_device_display_name() {
|
||||||
Some(display_name) => display_name.as_ref(),
|
Some(display_name) => display_name.as_ref(),
|
||||||
None => "Random displayname",
|
None => "Random displayname",
|
||||||
};
|
};
|
||||||
|
|
||||||
let user = User::create(&db, &user_id, &user_id.to_string(), auth_data.password()).await?;
|
let user =
|
||||||
|
User::create(&db, &user_id, &user_id.to_string(), auth_data.password()).await?;
|
||||||
let device = Device::create(&db, &user, "test", display_name).await?;
|
let device = Device::create(&db, &user, "test", display_name).await?;
|
||||||
|
|
||||||
(user, device)
|
(user, device)
|
||||||
|
@ -6,7 +6,9 @@ use sqlx::Statement;
|
|||||||
use crate::responses::registration::RegistrationResponse;
|
use crate::responses::registration::RegistrationResponse;
|
||||||
use crate::types::error_code::ErrorCode;
|
use crate::types::error_code::ErrorCode;
|
||||||
|
|
||||||
|
use super::authentication_error::AuthenticationError;
|
||||||
use super::registration_error::RegistrationError;
|
use super::registration_error::RegistrationError;
|
||||||
|
use super::ErrorResponse;
|
||||||
|
|
||||||
macro_rules! map_err {
|
macro_rules! map_err {
|
||||||
($err:ident, $($type:path => $target:path),+) => {
|
($err:ident, $($type:path => $target:path),+) => {
|
||||||
@ -18,34 +20,19 @@ macro_rules! map_err {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, serde::Serialize)]
|
|
||||||
struct ErrorResponse {
|
|
||||||
errcode: ErrorCode,
|
|
||||||
error: String,
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
retry_after_ms: Option<u64>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ErrorResponse {
|
|
||||||
fn new(errcode: ErrorCode, error: &str, retry_after_ms: Option<u64>) -> Self {
|
|
||||||
Self {
|
|
||||||
errcode,
|
|
||||||
error: error.to_owned(),
|
|
||||||
retry_after_ms,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum ApiError {
|
pub enum ApiError {
|
||||||
#[error("Registration Error")]
|
#[error("Registration Error")]
|
||||||
RegistrationError(#[from] RegistrationError),
|
RegistrationError(#[from] RegistrationError),
|
||||||
|
|
||||||
|
#[error("Authentication Error")]
|
||||||
|
AuthenticationError(#[from] AuthenticationError),
|
||||||
|
|
||||||
#[error("Database Error")]
|
#[error("Database Error")]
|
||||||
DBError(#[from] sqlx::Error),
|
DBError(#[from] sqlx::Error),
|
||||||
|
|
||||||
#[error("Generic Error")]
|
#[error("Generic Error")]
|
||||||
Generic(anyhow::Error)
|
Generic(anyhow::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<anyhow::Error> for ApiError {
|
impl From<anyhow::Error> for ApiError {
|
||||||
@ -62,29 +49,8 @@ impl From<anyhow::Error> for ApiError {
|
|||||||
impl IntoResponse for ApiError {
|
impl IntoResponse for ApiError {
|
||||||
fn into_response(self) -> axum::response::Response {
|
fn into_response(self) -> axum::response::Response {
|
||||||
match self {
|
match self {
|
||||||
ApiError::RegistrationError(registration_error) => match registration_error {
|
ApiError::RegistrationError(e) => e.into_response(),
|
||||||
RegistrationError::AdditionalAuthenticationInformation => (
|
ApiError::AuthenticationError(e) => e.into_response(),
|
||||||
StatusCode::UNAUTHORIZED,
|
|
||||||
Json(RegistrationResponse::user_interactive_authorization_info()),
|
|
||||||
).into_response(),
|
|
||||||
RegistrationError::InvalidUserId | RegistrationError::MissingUserId => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(ErrorResponse::new(
|
|
||||||
ErrorCode::InvalidUsername,
|
|
||||||
®istration_error.to_string(),
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
)).into_response(),
|
|
||||||
RegistrationError::UserIdTaken => (
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
Json(ErrorResponse::new(
|
|
||||||
ErrorCode::UserInUse,
|
|
||||||
®istration_error.to_string(),
|
|
||||||
None,
|
|
||||||
)),
|
|
||||||
)
|
|
||||||
.into_response(),
|
|
||||||
},
|
|
||||||
ApiError::DBError(err) => {
|
ApiError::DBError(err) => {
|
||||||
tracing::error!("{}", err.to_string());
|
tracing::error!("{}", err.to_string());
|
||||||
(
|
(
|
||||||
|
41
src/api/client_server/errors/authentication_error.rs
Normal file
41
src/api/client_server/errors/authentication_error.rs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
use axum::{http::StatusCode, response::IntoResponse, Json};
|
||||||
|
|
||||||
|
use crate::types::error_code::ErrorCode;
|
||||||
|
|
||||||
|
use super::ErrorResponse;
|
||||||
|
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
pub enum AuthenticationError {
|
||||||
|
#[error("UserId is missing")]
|
||||||
|
MissingUserId,
|
||||||
|
#[error("The user ID is not a valid user name")]
|
||||||
|
InvalidUserId,
|
||||||
|
#[error("The provided authentication data was incorrect")]
|
||||||
|
Forbidden,
|
||||||
|
#[error("The user has been deactivated")]
|
||||||
|
UserDeactivated,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoResponse for AuthenticationError {
|
||||||
|
fn into_response(self) -> axum::response::Response {
|
||||||
|
match self {
|
||||||
|
Self::InvalidUserId | Self::MissingUserId => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(ErrorResponse::new(
|
||||||
|
ErrorCode::InvalidUsername,
|
||||||
|
&self.to_string(),
|
||||||
|
None,
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
.into_response(),
|
||||||
|
Self::Forbidden => (
|
||||||
|
StatusCode::FORBIDDEN,
|
||||||
|
Json(ErrorResponse::new(ErrorCode::Forbidden, &self.to_string(), None)),
|
||||||
|
).into_response(),
|
||||||
|
Self::UserDeactivated => (
|
||||||
|
StatusCode::FORBIDDEN,
|
||||||
|
Json(ErrorResponse::new(ErrorCode::UserDeactivated, &self.to_string(), None)),
|
||||||
|
).into_response(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,2 +1,23 @@
|
|||||||
|
use crate::types::error_code::ErrorCode;
|
||||||
|
|
||||||
pub mod api_error;
|
pub mod api_error;
|
||||||
|
pub mod authentication_error;
|
||||||
pub mod registration_error;
|
pub mod registration_error;
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize)]
|
||||||
|
pub struct ErrorResponse {
|
||||||
|
errcode: ErrorCode,
|
||||||
|
error: String,
|
||||||
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
|
retry_after_ms: Option<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ErrorResponse {
|
||||||
|
fn new(errcode: ErrorCode, error: &str, retry_after_ms: Option<u64>) -> Self {
|
||||||
|
Self {
|
||||||
|
errcode,
|
||||||
|
error: error.to_owned(),
|
||||||
|
retry_after_ms,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,9 @@
|
|||||||
|
use axum::{http::StatusCode, response::IntoResponse, Json};
|
||||||
|
|
||||||
|
use crate::{responses::registration::RegistrationResponse, types::error_code::ErrorCode};
|
||||||
|
|
||||||
|
use super::ErrorResponse;
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum RegistrationError {
|
pub enum RegistrationError {
|
||||||
#[error("The homeserver requires additional authentication information")]
|
#[error("The homeserver requires additional authentication information")]
|
||||||
@ -7,5 +13,35 @@ pub enum RegistrationError {
|
|||||||
#[error("The desired user ID is not a valid user name")]
|
#[error("The desired user ID is not a valid user name")]
|
||||||
InvalidUserId,
|
InvalidUserId,
|
||||||
#[error("The desired user ID is already taken")]
|
#[error("The desired user ID is already taken")]
|
||||||
UserIdTaken
|
UserIdTaken,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoResponse for RegistrationError {
|
||||||
|
fn into_response(self) -> axum::response::Response {
|
||||||
|
match self {
|
||||||
|
RegistrationError::AdditionalAuthenticationInformation => (
|
||||||
|
StatusCode::UNAUTHORIZED,
|
||||||
|
Json(RegistrationResponse::user_interactive_authorization_info()),
|
||||||
|
)
|
||||||
|
.into_response(),
|
||||||
|
RegistrationError::InvalidUserId | RegistrationError::MissingUserId => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(ErrorResponse::new(
|
||||||
|
ErrorCode::InvalidUsername,
|
||||||
|
&self.to_string(),
|
||||||
|
None,
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
.into_response(),
|
||||||
|
RegistrationError::UserIdTaken => (
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
Json(ErrorResponse::new(
|
||||||
|
ErrorCode::UserInUse,
|
||||||
|
&self.to_string(),
|
||||||
|
None,
|
||||||
|
)),
|
||||||
|
)
|
||||||
|
.into_response(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,22 +2,11 @@ use crate::types::{authentication_data::AuthenticationData, flow::Flow, identifi
|
|||||||
|
|
||||||
#[derive(Debug, serde::Deserialize)]
|
#[derive(Debug, serde::Deserialize)]
|
||||||
pub struct RegistrationRequest {
|
pub struct RegistrationRequest {
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
auth: Option<AuthenticationData>,
|
auth: Option<AuthenticationData>,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
device_id: Option<String>,
|
device_id: Option<String>,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
inhibit_login: Option<bool>,
|
inhibit_login: Option<bool>,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
initial_device_display_name: Option<String>,
|
initial_device_display_name: Option<String>,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
password: Option<String>,
|
password: Option<String>,
|
||||||
|
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
username: Option<String>,
|
username: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
26
src/responses/authentication.rs
Normal file
26
src/responses/authentication.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
use axum::{response::IntoResponse, Json};
|
||||||
|
|
||||||
|
use crate::types::user_id::UserId;
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum AuthenticationResponse {
|
||||||
|
Success(AuthenticationSuccess)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize)]
|
||||||
|
pub struct AuthenticationSuccess {
|
||||||
|
access_token: String,
|
||||||
|
device_id: String,
|
||||||
|
user_id: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AuthenticationSuccess {
|
||||||
|
pub fn new(access_token: &str, device_id: &str, user_id: &UserId) -> Self {
|
||||||
|
Self {
|
||||||
|
access_token: access_token.to_owned(),
|
||||||
|
device_id: device_id.to_owned(),
|
||||||
|
user_id: user_id.to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,3 +2,4 @@ pub mod flow;
|
|||||||
pub mod registration;
|
pub mod registration;
|
||||||
pub mod username_available;
|
pub mod username_available;
|
||||||
pub mod versions;
|
pub mod versions;
|
||||||
|
pub mod authentication;
|
@ -13,6 +13,8 @@ pub struct AuthenticationPassword {
|
|||||||
identifier: Identifier,
|
identifier: Identifier,
|
||||||
password: String,
|
password: String,
|
||||||
user: Option<String>,
|
user: Option<String>,
|
||||||
|
device_id: Option<String>,
|
||||||
|
initial_device_display_name: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AuthenticationPassword {
|
impl AuthenticationPassword {
|
||||||
@ -33,4 +35,16 @@ impl AuthenticationPassword {
|
|||||||
pub fn user(&self) -> Option<&String> {
|
pub fn user(&self) -> Option<&String> {
|
||||||
self.user.as_ref()
|
self.user.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a reference to the authentication password's device id.
|
||||||
|
#[must_use]
|
||||||
|
pub fn device_id(&self) -> Option<&String> {
|
||||||
|
self.device_id.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a mutable reference to the authentication password's initial device display name.
|
||||||
|
#[must_use]
|
||||||
|
pub fn initial_device_display_name_mut(&self) -> Option<&String> {
|
||||||
|
self.initial_device_display_name.as_ref()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ pub enum ErrorCode {
|
|||||||
UserInUse,
|
UserInUse,
|
||||||
InvalidUsername,
|
InvalidUsername,
|
||||||
Exclusive,
|
Exclusive,
|
||||||
|
UserDeactivated
|
||||||
}
|
}
|
||||||
|
|
||||||
impl serde::Serialize for ErrorCode {
|
impl serde::Serialize for ErrorCode {
|
||||||
@ -31,6 +32,7 @@ impl serde::Serialize for ErrorCode {
|
|||||||
ErrorCode::UserInUse => "M_USER_IN_USE",
|
ErrorCode::UserInUse => "M_USER_IN_USE",
|
||||||
ErrorCode::InvalidUsername => "M_INVALID_USERNAME",
|
ErrorCode::InvalidUsername => "M_INVALID_USERNAME",
|
||||||
ErrorCode::Exclusive => "M_EXCLUSIVE",
|
ErrorCode::Exclusive => "M_EXCLUSIVE",
|
||||||
|
ErrorCode::UserDeactivated => "M_USER_DEACTIVATED",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user