forked from jmug/stoatchat
feat(core/result): add rocket and okapi support
This commit is contained in:
@@ -11,12 +11,20 @@ description = "Revolt Backend: Result and Error types"
|
||||
[features]
|
||||
serde = [ "dep:serde" ]
|
||||
schemas = [ "dep:schemars" ]
|
||||
rocket = [ "dep:rocket", "dep:serde_json" ]
|
||||
okapi = [ "dep:revolt_rocket_okapi", "dep:revolt_okapi" ]
|
||||
|
||||
default = [ "serde" ]
|
||||
|
||||
[dependencies]
|
||||
# Serialisation
|
||||
serde_json = { version = "1", optional = true }
|
||||
serde = { version = "1", features = ["derive"], optional = true }
|
||||
|
||||
# Spec Generation
|
||||
schemars = { version = "0.8.8", optional = true }
|
||||
|
||||
# Rocket
|
||||
rocket = { optional = true, version = "0.5.0-rc.2", default-features = false }
|
||||
revolt_rocket_okapi = { version = "0.9.1", optional = true }
|
||||
revolt_okapi = { version = "0.9.1", optional = true }
|
||||
|
||||
@@ -6,6 +6,12 @@ extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate schemars;
|
||||
|
||||
#[cfg(feature = "rocket")]
|
||||
pub mod rocket;
|
||||
|
||||
#[cfg(feature = "okapi")]
|
||||
pub mod okapi;
|
||||
|
||||
/// Result type with custom Error
|
||||
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
||||
|
||||
|
||||
49
crates/core/result/src/okapi.rs
Normal file
49
crates/core/result/src/okapi.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
use revolt_okapi::openapi3::SchemaObject;
|
||||
use revolt_rocket_okapi::revolt_okapi::openapi3;
|
||||
use schemars::schema::Schema;
|
||||
|
||||
use crate::Error;
|
||||
|
||||
impl revolt_rocket_okapi::response::OpenApiResponderInner for Error {
|
||||
fn responses(
|
||||
gen: &mut revolt_rocket_okapi::gen::OpenApiGenerator,
|
||||
) -> std::result::Result<openapi3::Responses, revolt_rocket_okapi::OpenApiError> {
|
||||
let mut content = revolt_okapi::Map::new();
|
||||
|
||||
let settings = schemars::gen::SchemaSettings::default().with(|s| {
|
||||
s.option_nullable = true;
|
||||
s.option_add_null_type = false;
|
||||
s.definitions_path = "#/components/schemas/".to_string();
|
||||
});
|
||||
|
||||
let mut schema_generator = settings.into_generator();
|
||||
let schema = schema_generator.root_schema_for::<Error>();
|
||||
|
||||
let definitions = gen.schema_generator().definitions_mut();
|
||||
for (key, value) in schema.definitions {
|
||||
definitions.insert(key, value);
|
||||
}
|
||||
|
||||
definitions.insert("Error".to_string(), Schema::Object(schema.schema));
|
||||
|
||||
content.insert(
|
||||
"application/json".to_string(),
|
||||
openapi3::MediaType {
|
||||
schema: Some(SchemaObject {
|
||||
reference: Some("#/components/schemas/Error".to_string()),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
|
||||
Ok(openapi3::Responses {
|
||||
default: Some(openapi3::RefOr::Object(openapi3::Response {
|
||||
content,
|
||||
description: "An error occurred.".to_string(),
|
||||
..Default::default()
|
||||
})),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
87
crates/core/result/src/rocket.rs
Normal file
87
crates/core/result/src/rocket.rs
Normal file
@@ -0,0 +1,87 @@
|
||||
use std::io::Cursor;
|
||||
|
||||
use rocket::{
|
||||
http::{ContentType, Status},
|
||||
response::{self, Responder},
|
||||
Request, Response,
|
||||
};
|
||||
|
||||
use crate::{Error, ErrorType};
|
||||
|
||||
/// HTTP response builder for Error enum
|
||||
impl<'r> Responder<'r, 'static> for Error {
|
||||
fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
|
||||
let status = match self.error_type {
|
||||
ErrorType::LabelMe => Status::InternalServerError,
|
||||
|
||||
ErrorType::AlreadyOnboarded => Status::Forbidden,
|
||||
|
||||
ErrorType::UnknownUser => Status::NotFound,
|
||||
ErrorType::InvalidUsername => Status::BadRequest,
|
||||
ErrorType::UsernameTaken => Status::Conflict,
|
||||
ErrorType::AlreadyFriends => Status::Conflict,
|
||||
ErrorType::AlreadySentRequest => Status::Conflict,
|
||||
ErrorType::Blocked => Status::Conflict,
|
||||
ErrorType::BlockedByOther => Status::Forbidden,
|
||||
ErrorType::NotFriends => Status::Forbidden,
|
||||
|
||||
ErrorType::UnknownChannel => Status::NotFound,
|
||||
ErrorType::UnknownMessage => Status::NotFound,
|
||||
ErrorType::UnknownAttachment => Status::BadRequest,
|
||||
ErrorType::CannotEditMessage => Status::Forbidden,
|
||||
ErrorType::CannotJoinCall => Status::BadRequest,
|
||||
ErrorType::TooManyAttachments { .. } => Status::BadRequest,
|
||||
ErrorType::TooManyReplies { .. } => Status::BadRequest,
|
||||
ErrorType::EmptyMessage => Status::UnprocessableEntity,
|
||||
ErrorType::PayloadTooLarge => Status::UnprocessableEntity,
|
||||
ErrorType::CannotRemoveYourself => Status::BadRequest,
|
||||
ErrorType::GroupTooLarge { .. } => Status::Forbidden,
|
||||
ErrorType::AlreadyInGroup => Status::Conflict,
|
||||
ErrorType::NotInGroup => Status::NotFound,
|
||||
|
||||
ErrorType::UnknownServer => Status::NotFound,
|
||||
ErrorType::InvalidRole => Status::NotFound,
|
||||
ErrorType::Banned => Status::Forbidden,
|
||||
|
||||
ErrorType::TooManyServers { .. } => Status::BadRequest,
|
||||
ErrorType::TooManyEmoji { .. } => Status::BadRequest,
|
||||
ErrorType::TooManyChannels { .. } => Status::BadRequest,
|
||||
ErrorType::TooManyRoles { .. } => Status::BadRequest,
|
||||
|
||||
ErrorType::ReachedMaximumBots => Status::BadRequest,
|
||||
ErrorType::IsBot => Status::BadRequest,
|
||||
ErrorType::BotIsPrivate => Status::Forbidden,
|
||||
|
||||
ErrorType::CannotReportYourself => Status::BadRequest,
|
||||
|
||||
ErrorType::MissingPermission { .. } => Status::Forbidden,
|
||||
ErrorType::MissingUserPermission { .. } => Status::Forbidden,
|
||||
ErrorType::NotElevated => Status::Forbidden,
|
||||
ErrorType::NotPrivileged => Status::Forbidden,
|
||||
ErrorType::CannotGiveMissingPermissions => Status::Forbidden,
|
||||
ErrorType::NotOwner => Status::Forbidden,
|
||||
|
||||
ErrorType::DatabaseError { .. } => Status::InternalServerError,
|
||||
ErrorType::InternalError => Status::InternalServerError,
|
||||
ErrorType::InvalidOperation => Status::BadRequest,
|
||||
ErrorType::InvalidCredentials => Status::Unauthorized,
|
||||
ErrorType::InvalidProperty => Status::BadRequest,
|
||||
ErrorType::InvalidSession => Status::Unauthorized,
|
||||
ErrorType::DuplicateNonce => Status::Conflict,
|
||||
ErrorType::VosoUnavailable => Status::BadRequest,
|
||||
ErrorType::NotFound => Status::NotFound,
|
||||
ErrorType::NoEffect => Status::Ok,
|
||||
ErrorType::FailedValidation { .. } => Status::BadRequest,
|
||||
};
|
||||
|
||||
// Serialize the error data structure into JSON.
|
||||
let string = serde_json::to_string(&self).unwrap();
|
||||
|
||||
// Build and send the request.
|
||||
Response::build()
|
||||
.sized_body(string.len(), Cursor::new(string))
|
||||
.header(ContentType::new("application", "json"))
|
||||
.status(status)
|
||||
.ok()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user