Add "error" and "error_description" fields to Mastodon API error responses

This commit is contained in:
silverpill 2023-02-25 22:27:07 +00:00
parent 971b541826
commit e4254e7a3d
21 changed files with 240 additions and 143 deletions

View file

@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Set deliverer timeout to 30 seconds.
- Added `federation` parameter group to configuration.
- Add empty `spoiler_text` property to Mastodon API Status object.
- Added `error` and `error_description` fields to Mastodon API error responses.
### Changed
@ -22,6 +23,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Deprecated `proxy_url` configuration parameter (replaced by `federation.proxy_url`).
- Deprecated Atom feeds at `/feeds/{username}`.
- Deprecated `message` field in Mastodon API error response.
### Fixed

View file

@ -39,12 +39,6 @@ pub enum HttpError {
#[error("{0} not found")]
NotFoundError(&'static str),
#[error("operation not supported")]
NotSupported,
#[error("{0}")]
OperationError(&'static str),
#[error("internal error")]
InternalError,
}
@ -80,8 +74,6 @@ impl ResponseError for HttpError {
HttpError::AuthError(_) => StatusCode::UNAUTHORIZED,
HttpError::PermissionError => StatusCode::FORBIDDEN,
HttpError::NotFoundError(_) => StatusCode::NOT_FOUND,
HttpError::NotSupported => StatusCode::IM_A_TEAPOT,
HttpError::OperationError(_) => StatusCode::UNPROCESSABLE_ENTITY,
_ => StatusCode::INTERNAL_SERVER_ERROR,
}
}

View file

@ -6,9 +6,10 @@ use uuid::Uuid;
use mitra_utils::markdown::markdown_basic_to_html;
use crate::errors::{HttpError, ValidationError};
use crate::errors::ValidationError;
use crate::identity::did::Did;
use crate::mastodon_api::{
errors::MastodonError,
pagination::PageSize,
uploads::{save_b64_file, UploadError},
};
@ -315,7 +316,7 @@ impl AccountUpdateData {
self,
profile: &DbActorProfile,
media_dir: &Path,
) -> Result<ProfileUpdateData, HttpError> {
) -> Result<ProfileUpdateData, MastodonError> {
let maybe_bio = if let Some(ref bio_source) = self.note {
let bio = markdown_basic_to_html(bio_source)
.map_err(|_| ValidationError("invalid markdown"))?;

View file

@ -32,7 +32,7 @@ use crate::activitypub::builders::{
},
};
use crate::database::{get_database_client, DatabaseError, DbPool};
use crate::errors::{HttpError, ValidationError};
use crate::errors::ValidationError;
use crate::ethereum::{
contracts::ContractSet,
eip4361::verify_eip4361_signature,
@ -58,6 +58,7 @@ use crate::json_signatures::{
},
};
use crate::mastodon_api::{
errors::MastodonError,
oauth::auth::get_current_user,
pagination::get_paginated_response,
search::helpers::search_profiles_only,
@ -122,7 +123,7 @@ pub async fn create_account(
db_pool: web::Data<DbPool>,
maybe_blockchain: web::Data<Option<ContractSet>>,
account_data: web::Json<AccountCreateData>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &mut **get_database_client(&db_pool).await?;
// Validate
account_data.clean()?;
@ -136,7 +137,7 @@ pub async fn create_account(
let maybe_password_hash = if let Some(password) = account_data.password.as_ref() {
let password_hash = hash_password(password)
.map_err(|_| HttpError::InternalError)?;
.map_err(|_| MastodonError::InternalError)?;
Some(password_hash)
} else {
None
@ -165,7 +166,7 @@ pub async fn create_account(
let wallet_address = maybe_wallet_address.as_ref()
.ok_or(ValidationError("wallet address is required"))?;
let is_allowed = is_allowed_user(gate, wallet_address).await
.map_err(|_| HttpError::InternalError)?;
.map_err(|_| MastodonError::InternalError)?;
if !is_allowed {
return Err(ValidationError("not allowed to sign up").into());
};
@ -175,10 +176,10 @@ pub async fn create_account(
// Generate RSA private key for actor
let private_key = match web::block(generate_rsa_key).await {
Ok(Ok(private_key)) => private_key,
_ => return Err(HttpError::InternalError),
_ => return Err(MastodonError::InternalError),
};
let private_key_pem = serialize_private_key(&private_key)
.map_err(|_| HttpError::InternalError)?;
.map_err(|_| MastodonError::InternalError)?;
let AccountCreateData { username, invite_code, .. } =
account_data.into_inner();
@ -216,7 +217,7 @@ async fn verify_credentials(
connection_info: ConnectionInfo,
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let user = get_current_user(db_client, auth.token()).await?;
let account = Account::from_user(
@ -234,7 +235,7 @@ async fn update_credentials(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
account_data: web::Json<AccountUpdateData>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let mut current_user = get_current_user(db_client, auth.token()).await?;
let mut profile_data = account_data.into_inner()
@ -270,7 +271,7 @@ async fn get_unsigned_update(
auth: BearerAuth,
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let internal_activity_id = generate_ulid();
@ -278,9 +279,9 @@ async fn get_unsigned_update(
&config.instance_url(),
&current_user,
Some(internal_activity_id),
).map_err(|_| HttpError::InternalError)?;
).map_err(|_| MastodonError::InternalError)?;
let canonical_json = canonicalize_object(&activity)
.map_err(|_| HttpError::InternalError)?;
.map_err(|_| MastodonError::InternalError)?;
let data = UnsignedActivity {
params: ActivityParams::Update { internal_activity_id },
message: canonical_json,
@ -295,7 +296,7 @@ async fn send_signed_activity(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
data: web::Json<SignedActivity>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let signer = data.signer.parse::<Did>()
@ -310,11 +311,11 @@ async fn send_signed_activity(
&config.instance(),
&current_user,
Some(*internal_activity_id),
).await.map_err(|_| HttpError::InternalError)?
).await.map_err(|_| MastodonError::InternalError)?
},
};
let canonical_json = canonicalize_object(&outgoing_activity.activity)
.map_err(|_| HttpError::InternalError)?;
.map_err(|_| MastodonError::InternalError)?;
let proof = match signer {
Did::Key(signer) => {
let signature_bin = parse_minisign_signature(&data.signature)
@ -332,7 +333,7 @@ async fn send_signed_activity(
},
};
add_integrity_proof(&mut outgoing_activity.activity, proof)
.map_err(|_| HttpError::InternalError)?;
.map_err(|_| MastodonError::InternalError)?;
outgoing_activity.enqueue(db_client).await?;
@ -350,7 +351,7 @@ async fn get_identity_claim(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
query_params: web::Query<IdentityClaimQueryParams>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let did = match query_params.proof_type.as_str() {
@ -370,7 +371,7 @@ async fn get_identity_claim(
};
let actor_id = current_user.profile.actor_id(&config.instance_url());
let claim = create_identity_claim(&actor_id, &did)
.map_err(|_| HttpError::InternalError)?;
.map_err(|_| MastodonError::InternalError)?;
let response = IdentityClaim { did, claim };
Ok(HttpResponse::Ok().json(response))
}
@ -382,7 +383,7 @@ async fn create_identity_proof(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
proof_data: web::Json<IdentityProofData>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let mut current_user = get_current_user(db_client, auth.token()).await?;
let did = proof_data.did.parse::<Did>()
@ -469,7 +470,7 @@ async fn get_relationships_view(
auth: BearerAuth,
db_pool: web::Data<DbPool>,
query_params: web::Query<RelationshipQueryParams>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let relationship = get_relationship(
@ -486,7 +487,7 @@ async fn lookup_acct(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
query_params: web::Query<LookupAcctQueryParams>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let profile = get_profile_by_acct(db_client, &query_params.acct).await?;
let account = Account::from_profile(
@ -503,7 +504,7 @@ async fn search_by_acct(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
query_params: web::Query<SearchAcctQueryParams>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let profiles = search_profiles_only(
db_client,
@ -528,7 +529,7 @@ async fn search_by_did(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
query_params: web::Query<SearchDidQueryParams>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let did: Did = query_params.did.parse()
.map_err(|_| ValidationError("invalid DID"))?;
@ -551,7 +552,7 @@ async fn get_account(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
account_id: web::Path<Uuid>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let profile = get_profile_by_id(db_client, &account_id).await?;
let account = Account::from_profile(
@ -569,7 +570,7 @@ async fn follow_account(
db_pool: web::Data<DbPool>,
account_id: web::Path<Uuid>,
follow_data: web::Json<FollowData>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let target = get_profile_by_id(db_client, &account_id).await?;
@ -603,7 +604,7 @@ async fn unfollow_account(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
account_id: web::Path<Uuid>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let target = get_profile_by_id(db_client, &account_id).await?;
@ -611,7 +612,7 @@ async fn unfollow_account(
Ok(Some(follow_request_id)) => {
// Remote follow
let remote_actor = target.actor_json
.ok_or(HttpError::InternalError)?;
.ok_or(MastodonError::InternalError)?;
prepare_undo_follow(
&config.instance(),
&current_user,
@ -640,7 +641,7 @@ async fn get_account_statuses(
db_pool: web::Data<DbPool>,
account_id: web::Path<Uuid>,
query_params: web::Query<StatusListQueryParams>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let maybe_current_user = match auth {
Some(auth) => Some(get_current_user(db_client, auth.token()).await?),
@ -681,7 +682,7 @@ async fn get_account_followers(
account_id: web::Path<Uuid>,
query_params: web::Query<FollowListQueryParams>,
request: HttpRequest,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let profile = get_profile_by_id(db_client, &account_id).await?;
@ -725,7 +726,7 @@ async fn get_account_following(
account_id: web::Path<Uuid>,
query_params: web::Query<FollowListQueryParams>,
request: HttpRequest,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let profile = get_profile_by_id(db_client, &account_id).await?;
@ -768,7 +769,7 @@ async fn get_account_subscribers(
db_pool: web::Data<DbPool>,
account_id: web::Path<Uuid>,
query_params: web::Query<FollowListQueryParams>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let profile = get_profile_by_id(db_client, &account_id).await?;

View file

@ -8,8 +8,10 @@ use actix_web::{
use uuid::Uuid;
use crate::database::{get_database_client, DbPool};
use crate::errors::HttpError;
use crate::mastodon_api::oauth::utils::generate_access_token;
use crate::mastodon_api::{
errors::MastodonError,
oauth::utils::generate_access_token,
};
use crate::models::{
oauth::queries::create_oauth_app,
oauth::types::DbOauthAppData,
@ -24,7 +26,7 @@ async fn create_app_view(
web::Json<CreateAppRequest>,
web::Form<CreateAppRequest>,
>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let request_data = match request_data {
Either::Left(json) => json.into_inner(),
Either::Right(form) => form.into_inner(),

View file

@ -7,8 +7,8 @@ use actix_web::{
};
use crate::database::{get_database_client, DbPool};
use crate::errors::HttpError;
use crate::http::get_request_base_url;
use crate::mastodon_api::errors::MastodonError;
use crate::models::emojis::queries::get_local_emojis;
use super::types::CustomEmoji;
@ -17,7 +17,7 @@ use super::types::CustomEmoji;
async fn custom_emoji_list(
connection_info: ConnectionInfo,
db_pool: web::Data<DbPool>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let base_url = get_request_base_url(connection_info);
let emojis: Vec<CustomEmoji> = get_local_emojis(db_client).await?

View file

@ -11,10 +11,10 @@ use actix_web_httpauth::extractors::bearer::BearerAuth;
use mitra_config::Config;
use crate::database::{get_database_client, DbPool};
use crate::errors::HttpError;
use crate::http::get_request_base_url;
use crate::mastodon_api::{
accounts::types::Account,
errors::MastodonError,
oauth::auth::get_current_user,
};
use crate::models::profiles::queries::get_profiles;
@ -27,7 +27,7 @@ async fn profile_directory(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
query_params: web::Query<DirectoryQueryParams>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
get_current_user(db_client, auth.token()).await?;
let profiles = get_profiles(

View file

@ -0,0 +1,89 @@
use actix_web::{
error::ResponseError,
http::StatusCode,
HttpResponse,
HttpResponseBuilder,
};
use serde::Serialize;
use crate::database::DatabaseError;
use crate::errors::ValidationError;
#[derive(thiserror::Error, Debug)]
pub enum MastodonError {
#[error(transparent)]
ActixError(#[from] actix_web::Error),
#[error("database error")]
DatabaseError(#[source] DatabaseError),
#[error("{0}")]
ValidationError(String),
#[error("{0}")]
ValidationErrorAuto(#[from] ValidationError),
#[error("{0}")]
AuthError(&'static str),
#[error("permission error")]
PermissionError,
#[error("{0} not found")]
NotFoundError(&'static str),
#[error("operation not supported")]
NotSupported,
#[error("{0}")]
OperationError(&'static str),
#[error("internal error")]
InternalError,
}
impl From<DatabaseError> for MastodonError {
fn from(error: DatabaseError) -> Self {
match error {
DatabaseError::NotFound(name) => Self::NotFoundError(name),
DatabaseError::AlreadyExists(name) => Self::ValidationError(
format!("{} already exists", name),
),
_ => Self::DatabaseError(error),
}
}
}
/// https://docs.joinmastodon.org/entities/Error/
#[derive(Serialize)]
struct MastodonErrorData {
message: String, // deprecated
error: String,
error_description: Option<String>,
}
impl ResponseError for MastodonError {
fn error_response(&self) -> HttpResponse {
let error_data = MastodonErrorData {
message: self.to_string(),
error: self.to_string(),
error_description: Some(self.to_string()),
};
HttpResponseBuilder::new(self.status_code()).json(error_data)
}
fn status_code(&self) -> StatusCode {
match self {
Self::ActixError(error) =>
error.as_response_error().status_code(),
Self::ValidationError(_) => StatusCode::BAD_REQUEST,
Self::ValidationErrorAuto(_) => StatusCode::BAD_REQUEST,
Self::AuthError(_) => StatusCode::UNAUTHORIZED,
Self::PermissionError => StatusCode::FORBIDDEN,
Self::NotFoundError(_) => StatusCode::NOT_FOUND,
Self::NotSupported => StatusCode::IM_A_TEAPOT,
Self::OperationError(_) => StatusCode::UNPROCESSABLE_ENTITY,
_ => StatusCode::INTERNAL_SERVER_ERROR,
}
}
}

View file

@ -3,8 +3,8 @@ use actix_web::{get, web, HttpResponse, Scope};
use mitra_config::Config;
use crate::database::{get_database_client, DbPool};
use crate::errors::HttpError;
use crate::ethereum::contracts::ContractSet;
use crate::mastodon_api::errors::MastodonError;
use crate::models::{
instances::queries::get_peer_count,
posts::queries::get_local_post_count,
@ -18,7 +18,7 @@ async fn instance_view(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
maybe_blockchain: web::Data<Option<ContractSet>>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let user_count = get_user_count(db_client).await?;
let post_count = get_local_post_count(db_client).await?;

View file

@ -2,8 +2,10 @@ use actix_web::{get, post, web, HttpResponse, Scope};
use actix_web_httpauth::extractors::bearer::BearerAuth;
use crate::database::{get_database_client, DbPool};
use crate::errors::HttpError;
use crate::mastodon_api::oauth::auth::get_current_user;
use crate::mastodon_api::{
errors::MastodonError,
oauth::auth::get_current_user,
};
use crate::models::{
markers::queries::{
create_or_update_marker,
@ -19,7 +21,7 @@ async fn get_marker_view(
auth: BearerAuth,
db_pool: web::Data<DbPool>,
query_params: web::Query<MarkerQueryParams>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let timeline = query_params.to_timeline()?;
@ -35,7 +37,7 @@ async fn update_marker_view(
auth: BearerAuth,
db_pool: web::Data<DbPool>,
marker_data: web::Json<MarkerCreateData>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let db_marker = create_or_update_marker(

View file

@ -5,8 +5,8 @@ use actix_web_httpauth::extractors::bearer::BearerAuth;
use mitra_config::Config;
use crate::database::{get_database_client, DbPool};
use crate::errors::HttpError;
use crate::mastodon_api::{
errors::MastodonError,
oauth::auth::get_current_user,
uploads::save_b64_file,
};
@ -19,7 +19,7 @@ async fn create_attachment_view(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
attachment_data: web::Json<AttachmentCreateData>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let (file_name, file_size, media_type) = save_b64_file(

View file

@ -7,12 +7,14 @@ pub mod markers;
pub mod media;
pub mod notifications;
pub mod oauth;
mod pagination;
pub mod search;
pub mod settings;
pub mod statuses;
pub mod subscriptions;
pub mod timelines;
mod errors;
mod pagination;
mod uploads;
const MASTODON_API_VERSION: &str = "4.0.0";

View file

@ -11,9 +11,9 @@ use actix_web_httpauth::extractors::bearer::BearerAuth;
use mitra_config::Config;
use crate::database::{get_database_client, DbPool};
use crate::errors::HttpError;
use crate::http::get_request_base_url;
use crate::mastodon_api::{
errors::MastodonError,
oauth::auth::get_current_user,
pagination::get_paginated_response,
};
@ -28,7 +28,7 @@ async fn get_notifications_view(
db_pool: web::Data<DbPool>,
query_params: web::Query<NotificationQueryParams>,
request: HttpRequest,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let base_url = get_request_base_url(connection_info);

View file

@ -1,5 +1,5 @@
use crate::database::{DatabaseClient, DatabaseError};
use crate::errors::HttpError;
use crate::mastodon_api::errors::MastodonError;
use crate::models::{
oauth::queries::get_user_by_oauth_token,
users::types::User,
@ -8,13 +8,13 @@ use crate::models::{
pub async fn get_current_user(
db_client: &impl DatabaseClient,
token: &str,
) -> Result<User, HttpError> {
) -> Result<User, MastodonError> {
let user = get_user_by_oauth_token(db_client, token).await.map_err(|err| {
match err {
DatabaseError::NotFound(_) => {
HttpError::AuthError("access token is invalid")
MastodonError::AuthError("access token is invalid")
},
_ => HttpError::InternalError,
_ => MastodonError::InternalError,
}
})?;
Ok(user)

View file

@ -13,12 +13,13 @@ use mitra_config::Config;
use mitra_utils::passwords::verify_password;
use crate::database::{get_database_client, DatabaseError, DbPool};
use crate::errors::{HttpError, ValidationError};
use crate::errors::ValidationError;
use crate::ethereum::{
eip4361::verify_eip4361_signature,
utils::validate_ethereum_address,
};
use crate::http::FormOrJson;
use crate::mastodon_api::errors::MastodonError;
use crate::models::{
oauth::queries::{
create_oauth_authorization,
@ -60,7 +61,7 @@ async fn authorize_view(
db_pool: web::Data<DbPool>,
form_data: web::Form<AuthorizationRequest>,
query_params: web::Query<AuthorizationQueryParams>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let user = get_user_by_name(db_client, &form_data.username).await?;
let password_hash = user.password_hash.as_ref()
@ -68,7 +69,7 @@ async fn authorize_view(
let password_correct = verify_password(
password_hash,
&form_data.password,
).map_err(|_| HttpError::InternalError)?;
).map_err(|_| MastodonError::InternalError)?;
if !password_correct {
return Err(ValidationError("incorrect password").into());
};
@ -116,7 +117,7 @@ async fn token_view(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
request_data: FormOrJson<TokenRequest>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let request_data = request_data.into_inner();
let db_client = &**get_database_client(&db_pool).await?;
let user = match request_data.grant_type.as_str() {
@ -165,7 +166,7 @@ async fn token_view(
let password_correct = verify_password(
password_hash,
password,
).map_err(|_| HttpError::InternalError)?;
).map_err(|_| MastodonError::InternalError)?;
if !password_correct {
return Err(ValidationError("incorrect password").into());
};
@ -193,7 +194,7 @@ async fn revoke_token_view(
auth: BearerAuth,
db_pool: web::Data<DbPool>,
request_data: web::Json<RevocationRequest>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
match delete_oauth_token(
@ -202,7 +203,7 @@ async fn revoke_token_view(
&request_data.token,
).await {
Ok(_) => (),
Err(DatabaseError::NotFound(_)) => return Err(HttpError::PermissionError),
Err(DatabaseError::NotFound(_)) => return Err(MastodonError::PermissionError),
Err(other_error) => return Err(other_error.into()),
};
Ok(HttpResponse::Ok().finish())

View file

@ -11,10 +11,10 @@ use actix_web_httpauth::extractors::bearer::BearerAuth;
use mitra_config::Config;
use crate::database::{get_database_client, DbPool};
use crate::errors::HttpError;
use crate::http::get_request_base_url;
use crate::mastodon_api::{
accounts::types::Account,
errors::MastodonError,
oauth::auth::get_current_user,
statuses::helpers::build_status_list,
statuses::types::Tag,
@ -29,7 +29,7 @@ async fn search_view(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
query_params: web::Query<SearchQueryParams>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let (profiles, posts, tags) = search(

View file

@ -18,10 +18,11 @@ use crate::activitypub::{
},
};
use crate::database::{get_database_client, DatabaseError, DbPool};
use crate::errors::{HttpError, ValidationError};
use crate::errors::ValidationError;
use crate::http::get_request_base_url;
use crate::mastodon_api::{
accounts::types::Account,
errors::MastodonError,
oauth::auth::get_current_user,
};
use crate::models::{
@ -49,11 +50,11 @@ async fn change_password_view(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
request_data: web::Json<PasswordChangeRequest>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let password_hash = hash_password(&request_data.new_password)
.map_err(|_| HttpError::InternalError)?;
.map_err(|_| MastodonError::InternalError)?;
set_user_password(db_client, &current_user.id, password_hash).await?;
let account = Account::from_user(
&get_request_base_url(connection_info),
@ -68,7 +69,7 @@ async fn export_followers_view(
auth: BearerAuth,
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let csv = export_followers(
@ -87,7 +88,7 @@ async fn export_follows_view(
auth: BearerAuth,
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let csv = export_follows(
@ -107,7 +108,7 @@ async fn import_follows_view(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
request_data: web::Json<ImportFollowsRequest>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let address_list = parse_address_list(&request_data.follows_csv)?;
@ -131,7 +132,7 @@ async fn move_followers(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
request_data: web::Json<MoveFollowersRequest>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let instance = config.instance();

View file

@ -27,7 +27,7 @@ use crate::activitypub::builders::{
undo_like::prepare_undo_like,
};
use crate::database::{get_database_client, DatabaseError, DbPool};
use crate::errors::{HttpError, ValidationError};
use crate::errors::ValidationError;
use crate::ethereum::nft::create_mint_signature;
use crate::http::{get_request_base_url, FormOrJson};
use crate::ipfs::{
@ -35,7 +35,10 @@ use crate::ipfs::{
posts::PostMetadata,
utils::get_ipfs_url,
};
use crate::mastodon_api::oauth::auth::get_current_user;
use crate::mastodon_api::{
errors::MastodonError,
oauth::auth::get_current_user,
};
use crate::models::{
posts::helpers::{can_create_post, can_view_post},
posts::queries::{
@ -81,11 +84,11 @@ async fn create_status(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
status_data: FormOrJson<StatusData>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
if !can_create_post(&current_user) {
return Err(HttpError::PermissionError);
return Err(MastodonError::PermissionError);
};
let instance = config.instance();
let status_data = status_data.into_inner();
@ -213,7 +216,7 @@ async fn preview_status(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
status_data: web::Json<StatusPreviewData>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
get_current_user(db_client, auth.token()).await?;
let instance = config.instance();
@ -249,7 +252,7 @@ async fn get_status(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
status_id: web::Path<Uuid>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let maybe_current_user = match auth {
Some(auth) => Some(get_current_user(db_client, auth.token()).await?),
@ -257,7 +260,7 @@ async fn get_status(
};
let post = get_post_by_id(db_client, &status_id).await?;
if !can_view_post(db_client, maybe_current_user.as_ref(), &post).await? {
return Err(HttpError::NotFoundError("post"));
return Err(MastodonError::NotFoundError("post"));
};
let status = build_status(
db_client,
@ -275,12 +278,12 @@ async fn delete_status(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
status_id: web::Path<Uuid>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let post = get_post_by_id(db_client, &status_id).await?;
if post.author.id != current_user.id {
return Err(HttpError::PermissionError);
return Err(MastodonError::PermissionError);
};
let delete_note = prepare_delete_note(
db_client,
@ -304,7 +307,7 @@ async fn get_context(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
status_id: web::Path<Uuid>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let maybe_current_user = match auth {
Some(auth) => Some(get_current_user(db_client, auth.token()).await?),
@ -347,7 +350,7 @@ async fn get_thread_view(
connection_info: ConnectionInfo,
db_pool: web::Data<DbPool>,
status_id: web::Path<Uuid>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let maybe_current_user = match auth {
Some(auth) => Some(get_current_user(db_client, auth.token()).await?),
@ -375,12 +378,12 @@ async fn favourite(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
status_id: web::Path<Uuid>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let mut post = get_post_by_id(db_client, &status_id).await?;
if post.repost_of_id.is_some() {
return Err(HttpError::NotFoundError("post"));
return Err(MastodonError::NotFoundError("post"));
};
let maybe_reaction_created = match create_reaction(
db_client, &current_user.id, &status_id, None,
@ -421,7 +424,7 @@ async fn unfavourite(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
status_id: web::Path<Uuid>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let mut post = get_post_by_id(db_client, &status_id).await?;
@ -464,15 +467,15 @@ async fn reblog(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
status_id: web::Path<Uuid>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
if !can_create_post(&current_user) {
return Err(HttpError::PermissionError);
return Err(MastodonError::PermissionError);
};
let mut post = get_post_by_id(db_client, &status_id).await?;
if !post.is_public() || post.repost_of_id.is_some() {
return Err(HttpError::NotFoundError("post"));
return Err(MastodonError::NotFoundError("post"));
};
let repost_data = PostCreateData::repost(status_id.into_inner(), None);
let mut repost = create_post(db_client, &current_user.id, repost_data).await?;
@ -504,7 +507,7 @@ async fn unreblog(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
status_id: web::Path<Uuid>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let reposts = find_reposts_by_user(
@ -512,7 +515,7 @@ async fn unreblog(
&current_user.id,
&[*status_id],
).await?;
let repost_id = reposts.first().ok_or(HttpError::NotFoundError("post"))?;
let repost_id = reposts.first().ok_or(MastodonError::NotFoundError("post"))?;
// Ignore returned data because reposts don't have attached files
delete_post(db_client, repost_id).await?;
let post = get_post_by_id(db_client, &status_id).await?;
@ -543,28 +546,28 @@ async fn make_permanent(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
status_id: web::Path<Uuid>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &mut **get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let mut post = get_post_by_id(db_client, &status_id).await?;
if post.ipfs_cid.is_some() {
return Err(HttpError::OperationError("post already saved to IPFS"));
return Err(MastodonError::OperationError("post already saved to IPFS"));
};
if post.author.id != current_user.id || !post.is_public() || post.repost_of_id.is_some() {
// Users can only archive their own public posts
return Err(HttpError::PermissionError);
return Err(MastodonError::PermissionError);
};
let ipfs_api_url = config.ipfs_api_url.as_ref()
.ok_or(HttpError::NotSupported)?;
.ok_or(MastodonError::NotSupported)?;
let mut attachments = vec![];
for attachment in post.attachments.iter_mut() {
// Add attachment to IPFS
let image_path = config.media_dir().join(&attachment.file_name);
let image_data = std::fs::read(image_path)
.map_err(|_| HttpError::InternalError)?;
.map_err(|_| MastodonError::InternalError)?;
let image_cid = ipfs_store::add(ipfs_api_url, image_data).await
.map_err(|_| HttpError::InternalError)?;
.map_err(|_| MastodonError::InternalError)?;
attachment.ipfs_cid = Some(image_cid.clone());
attachments.push((attachment.id, image_cid));
};
@ -579,10 +582,10 @@ async fn make_permanent(
maybe_post_image_cid,
);
let post_metadata_json = serde_json::to_string(&post_metadata)
.map_err(|_| HttpError::InternalError)?
.map_err(|_| MastodonError::InternalError)?
.as_bytes().to_vec();
let post_metadata_cid = ipfs_store::add(ipfs_api_url, post_metadata_json).await
.map_err(|_| HttpError::InternalError)?;
.map_err(|_| MastodonError::InternalError)?;
set_post_ipfs_cid(db_client, &post.id, &post_metadata_cid, attachments).await?;
post.ipfs_cid = Some(post_metadata_cid);
@ -603,31 +606,31 @@ async fn get_signature(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
status_id: web::Path<Uuid>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let ethereum_config = config.blockchain()
.ok_or(HttpError::NotSupported)?
.ok_or(MastodonError::NotSupported)?
.ethereum_config()
.ok_or(HttpError::NotSupported)?;
.ok_or(MastodonError::NotSupported)?;
// User must have a public ethereum address
let wallet_address = current_user
.public_wallet_address(&Currency::Ethereum)
.ok_or(HttpError::PermissionError)?;
.ok_or(MastodonError::PermissionError)?;
let post = get_post_by_id(db_client, &status_id).await?;
if post.author.id != current_user.id || !post.is_public() || post.repost_of_id.is_some() {
// Users can only tokenize their own public posts
return Err(HttpError::PermissionError);
return Err(MastodonError::PermissionError);
};
let ipfs_cid = post.ipfs_cid
// Post metadata is not immutable
.ok_or(HttpError::PermissionError)?;
.ok_or(MastodonError::PermissionError)?;
let token_uri = get_ipfs_url(&ipfs_cid);
let signature = create_mint_signature(
ethereum_config,
&wallet_address,
&token_uri,
).map_err(|_| HttpError::InternalError)?;
).map_err(|_| MastodonError::InternalError)?;
Ok(HttpResponse::Ok().json(signature))
}
@ -639,15 +642,15 @@ async fn token_minted(
db_pool: web::Data<DbPool>,
status_id: web::Path<Uuid>,
transaction_data: web::Json<TransactionData>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let mut post = get_post_by_id(db_client, &status_id).await?;
if post.token_tx_id.is_some() {
return Err(HttpError::OperationError("transaction is already registered"));
return Err(MastodonError::OperationError("transaction is already registered"));
};
if post.author.id != current_user.id || !post.is_public() || post.repost_of_id.is_some() {
return Err(HttpError::PermissionError);
return Err(MastodonError::PermissionError);
};
let token_tx_id = transaction_data.into_inner().transaction_id;
set_post_token_tx_id(db_client, &post.id, &token_tx_id).await?;

View file

@ -14,7 +14,7 @@ use mitra_utils::currencies::Currency;
use crate::activitypub::builders::update_person::prepare_update_person;
use crate::database::{get_database_client, DbPool};
use crate::errors::{HttpError, ValidationError};
use crate::errors::ValidationError;
use crate::ethereum::{
contracts::ContractSet,
subscriptions::{
@ -25,6 +25,7 @@ use crate::ethereum::{
use crate::http::get_request_base_url;
use crate::mastodon_api::{
accounts::types::Account,
errors::MastodonError,
oauth::auth::get_current_user,
};
use crate::models::{
@ -62,24 +63,24 @@ pub async fn authorize_subscription(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
query_params: web::Query<SubscriptionAuthorizationQueryParams>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let ethereum_config = config.blockchain()
.ok_or(HttpError::NotSupported)?
.ok_or(MastodonError::NotSupported)?
.ethereum_config()
.ok_or(HttpError::NotSupported)?;
.ok_or(MastodonError::NotSupported)?;
// The user must have a public ethereum address,
// because subscribers should be able
// to verify that payments are actually sent to the recipient.
let wallet_address = current_user
.public_wallet_address(&Currency::Ethereum)
.ok_or(HttpError::PermissionError)?;
.ok_or(MastodonError::PermissionError)?;
let signature = create_subscription_signature(
ethereum_config,
&wallet_address,
query_params.price,
).map_err(|_| HttpError::InternalError)?;
).map_err(|_| MastodonError::InternalError)?;
Ok(HttpResponse::Ok().json(signature))
}
@ -87,7 +88,7 @@ pub async fn authorize_subscription(
async fn get_subscription_options(
auth: BearerAuth,
db_pool: web::Data<DbPool>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let options: Vec<SubscriptionOption> = current_user.profile
@ -105,23 +106,23 @@ pub async fn register_subscription_option(
db_pool: web::Data<DbPool>,
maybe_blockchain: web::Data<Option<ContractSet>>,
subscription_option: web::Json<SubscriptionOption>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let mut current_user = get_current_user(db_client, auth.token()).await?;
if !current_user.role.has_permission(Permission::ManageSubscriptionOptions) {
return Err(HttpError::PermissionError);
return Err(MastodonError::PermissionError);
};
let maybe_payment_option = match subscription_option.into_inner() {
SubscriptionOption::Ethereum => {
let ethereum_config = config.blockchain()
.and_then(|conf| conf.ethereum_config())
.ok_or(HttpError::NotSupported)?;
.ok_or(MastodonError::NotSupported)?;
let contract_set = maybe_blockchain.as_ref().as_ref()
.ok_or(HttpError::NotSupported)?;
.ok_or(MastodonError::NotSupported)?;
let wallet_address = current_user
.public_wallet_address(&Currency::Ethereum)
.ok_or(HttpError::PermissionError)?;
.ok_or(MastodonError::PermissionError)?;
if current_user.profile.payment_options
.any(PaymentType::EthereumSubscription)
{
@ -131,7 +132,7 @@ pub async fn register_subscription_option(
let is_registered = is_registered_recipient(
contract_set,
&wallet_address,
).await.map_err(|_| HttpError::InternalError)?;
).await.map_err(|_| MastodonError::InternalError)?;
if !is_registered {
return Err(ValidationError("recipient is not registered").into());
};
@ -143,7 +144,7 @@ pub async fn register_subscription_option(
SubscriptionOption::Monero { price, payout_address } => {
let monero_config = config.blockchain()
.and_then(|conf| conf.monero_config())
.ok_or(HttpError::NotSupported)?;
.ok_or(MastodonError::NotSupported)?;
if price == 0 {
return Err(ValidationError("price must be greater than 0").into());
};
@ -186,7 +187,7 @@ pub async fn register_subscription_option(
async fn find_subscription(
db_pool: web::Data<DbPool>,
query_params: web::Query<SubscriptionQueryParams>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let subscription = get_subscription_by_participants(
db_client,
@ -205,11 +206,11 @@ async fn create_invoice_view(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
invoice_data: web::Json<InvoiceData>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let monero_config = config.blockchain()
.ok_or(HttpError::NotSupported)?
.ok_or(MastodonError::NotSupported)?
.monero_config()
.ok_or(HttpError::NotSupported)?;
.ok_or(MastodonError::NotSupported)?;
if invoice_data.sender_id == invoice_data.recipient_id {
return Err(ValidationError("sender must be different from recipient").into());
};
@ -225,7 +226,7 @@ async fn create_invoice_view(
};
let payment_address = create_monero_address(monero_config).await
.map_err(|_| HttpError::InternalError)?
.map_err(|_| MastodonError::InternalError)?
.to_string();
let db_invoice = create_invoice(
db_client,
@ -243,7 +244,7 @@ async fn create_invoice_view(
async fn get_invoice(
db_pool: web::Data<DbPool>,
invoice_id: web::Path<Uuid>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let db_invoice = get_invoice_by_id(db_client, &invoice_id).await?;
let invoice = Invoice::from(db_invoice);

View file

@ -11,9 +11,9 @@ use actix_web_httpauth::extractors::bearer::BearerAuth;
use mitra_config::Config;
use crate::database::{get_database_client, DbPool};
use crate::errors::HttpError;
use crate::http::get_request_base_url;
use crate::mastodon_api::{
errors::MastodonError,
oauth::auth::get_current_user,
statuses::helpers::build_status_list,
};
@ -31,7 +31,7 @@ async fn home_timeline(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
query_params: web::Query<TimelineQueryParams>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let posts = get_home_timeline(
@ -58,7 +58,7 @@ async fn public_timeline(
config: web::Data<Config>,
db_pool: web::Data<DbPool>,
query_params: web::Query<TimelineQueryParams>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let current_user = get_current_user(db_client, auth.token()).await?;
let posts = get_local_timeline(
@ -85,7 +85,7 @@ async fn hashtag_timeline(
db_pool: web::Data<DbPool>,
hashtag: web::Path<String>,
query_params: web::Query<TimelineQueryParams>,
) -> Result<HttpResponse, HttpError> {
) -> Result<HttpResponse, MastodonError> {
let db_client = &**get_database_client(&db_pool).await?;
let maybe_current_user = match auth {
Some(auth) => Some(get_current_user(db_client, auth.token()).await?),

View file

@ -2,8 +2,8 @@ use std::path::Path;
use mitra_utils::files::sniff_media_type;
use crate::errors::HttpError;
use crate::media::{save_file, SUPPORTED_MEDIA_TYPES};
use super::errors::MastodonError;
pub const UPLOAD_MAX_SIZE: usize = 1024 * 1024 * 5;
@ -22,12 +22,12 @@ pub enum UploadError {
InvalidMediaType,
}
impl From<UploadError> for HttpError {
impl From<UploadError> for MastodonError {
fn from(error: UploadError) -> Self {
match error {
UploadError::WriteError(_) => HttpError::InternalError,
UploadError::WriteError(_) => MastodonError::InternalError,
other_error => {
HttpError::ValidationError(other_error.to_string())
MastodonError::ValidationError(other_error.to_string())
},
}
}