chore(doc): implement remainder of documentation

This commit is contained in:
Paul Makles
2022-03-19 18:19:24 +00:00
parent 43c475eabb
commit 8dd9acdb59
54 changed files with 499 additions and 123 deletions

View File

@@ -4,6 +4,10 @@ use revolt_quark::{Database, Result};
use rocket::serde::json::Json;
use rocket::State;
/// # Send Friend Request / Accept Request
///
/// Send a friend request to another user or accept another user's friend request.
#[openapi(tag = "Relationships")]
#[put("/<username>/friend")]
pub async fn req(db: &State<Database>, user: User, username: String) -> Result<Json<User>> {
let mut target = db.fetch_user_by_username(&username).await?;

View File

@@ -4,6 +4,10 @@ use revolt_quark::{Database, Result};
use rocket::serde::json::Json;
use rocket::State;
/// # Block User
///
/// Block another user by their id.
#[openapi(tag = "Relationships")]
#[put("/<target>/block")]
pub async fn req(db: &State<Database>, user: User, target: String) -> Result<Json<User>> {
let mut target = db.fetch_user(&target).await?;

View File

@@ -5,20 +5,27 @@ use rocket::{serde::json::Json, State};
use serde::{Deserialize, Serialize};
use validator::Validate;
#[derive(Validate, Serialize, Deserialize)]
pub struct Data {
/// # Username Information
#[derive(Validate, Serialize, Deserialize, JsonSchema)]
pub struct DataChangeUsername {
/// New username
#[validate(length(min = 2, max = 32), regex = "RE_USERNAME")]
username: String,
/// Current account password
#[validate(length(min = 8, max = 1024))]
password: String,
}
/// # Change Username
///
/// Change your username.
#[openapi(tag = "User Information")]
#[patch("/@me/username", data = "<data>")]
pub async fn req(
db: &State<Database>,
account: Account,
mut user: User,
data: Json<Data>,
data: Json<DataChangeUsername>,
) -> Result<Json<User>> {
let data = data.into_inner();
account

View File

@@ -1,5 +1,3 @@
//! Edit currently authenticated user.
use revolt_quark::models::user::{FieldsUser, PartialUser, User};
use revolt_quark::models::File;
use revolt_quark::{Database, Error, Result};
@@ -10,30 +8,48 @@ use rocket::State;
use serde::{Deserialize, Serialize};
use validator::Validate;
#[derive(Validate, Serialize, Deserialize, Debug)]
/// # Profile Data
#[derive(Validate, Serialize, Deserialize, Debug, JsonSchema)]
pub struct UserProfileData {
/// Text to set as user profile description
#[validate(length(min = 0, max = 2000))]
#[serde(skip_serializing_if = "Option::is_none")]
content: Option<String>,
/// Attachment Id for background
#[serde(skip_serializing_if = "Option::is_none")]
#[validate(length(min = 1, max = 128))]
background: Option<String>,
}
#[derive(Validate, Serialize, Deserialize)]
pub struct Data {
/// # User Data
#[derive(Validate, Serialize, Deserialize, JsonSchema)]
pub struct DataEditUser {
/// New user status
#[validate]
status: Option<UserStatus>,
/// New user profile data
///
/// This is applied as a partial.
#[validate]
profile: Option<UserProfileData>,
/// Attachment Id for avatar
#[validate(length(min = 1, max = 128))]
avatar: Option<String>,
/// Fields to remove from user object
#[validate(length(min = 1))]
remove: Option<Vec<FieldsUser>>,
}
/// # Edit User
///
/// Edit currently authenticated user.
#[openapi(tag = "User Information")]
#[patch("/@me", data = "<data>")]
pub async fn req(db: &State<Database>, mut user: User, data: Json<Data>) -> Result<Json<User>> {
pub async fn req(
db: &State<Database>,
mut user: User,
data: Json<DataEditUser>,
) -> Result<Json<User>> {
let data = data.into_inner();
data.validate()
.map_err(|error| Error::FailedValidation { error })?;

View File

@@ -1,7 +1,3 @@
//! Fetch direct messages that the current user is involved in
//!
//! This includes group DMs and "active" 1:1 DMs.
use revolt_quark::{
models::{Channel, User},
Database, Result,
@@ -9,6 +5,10 @@ use revolt_quark::{
use rocket::{serde::json::Json, State};
/// # Fetch Direct Message Channels
///
/// This fetches your direct messages, including any DM and group DM conversations.
#[openapi(tag = "Direct Messaging")]
#[get("/dms")]
pub async fn req(db: &State<Database>, user: User) -> Result<Json<Vec<Channel>>> {
db.find_direct_messages(&user.id).await.map(Json)

View File

@@ -1,8 +1,3 @@
//! Fetch another user's profile
//!
//! Will fail if the authenticated user does not
//! have permission to access the other user's profile.
use revolt_quark::{
models::{user::UserProfile, User},
perms, Database, Error, Ref, Result,
@@ -10,6 +5,12 @@ use revolt_quark::{
use rocket::{serde::json::Json, State};
/// # Fetch User Profile
///
/// Retrieve a user's profile data.
///
/// Will fail if you do not have permission to access the other user's profile.
#[openapi(tag = "User Information")]
#[get("/<target>/profile")]
pub async fn req(db: &State<Database>, user: User, target: Ref) -> Result<Json<UserProfile>> {
let target = target.as_user(db).await?;

View File

@@ -1,10 +1,12 @@
//! Fetch the currently authenticated session's user account
use revolt_quark::models::User;
use revolt_quark::Result;
use rocket::serde::json::Json;
/// # Fetch Self
///
/// Retrieve your user information.
#[openapi(tag = "User Information")]
#[get("/@me")]
pub async fn req(user: User) -> Result<Json<User>> {
Ok(Json(user.foreign()))

View File

@@ -1,12 +1,11 @@
//! Fetch another user
//!
//! Will fail if the authenticated user does not
//! have permission to access the other user.
use revolt_quark::{models::User, perms, Database, Error, Ref, Result};
use rocket::{serde::json::Json, State};
/// # Fetch User
///
/// Retrieve a user's information.
#[openapi(tag = "User Information")]
#[get("/<target>")]
pub async fn req(db: &State<Database>, user: User, target: Ref) -> Result<Json<User>> {
let target = target.as_user(db).await?;

View File

@@ -1,12 +1,13 @@
//! Fetch IDs of servers and friends that are mutually shared between the
//! authenticated user and the target user
use revolt_quark::models::User;
use revolt_quark::{perms, Database, Error, Ref, Result};
use rocket::serde::json::Value;
use rocket::State;
/// # Fetch Mutual Friends And Servers
///
/// Retrieve a list of mutual friends and servers with another user.
#[openapi(tag = "Relationships")]
#[get("/<target>/mutual")]
pub async fn req(db: &State<Database>, user: User, target: Ref) -> Result<Value> {
let target = target.as_user(db).await?;

View File

@@ -1,6 +1,8 @@
use rocket::http::ContentType;
use rocket::response::{self, Responder};
use rocket::{Request, Response};
use rocket_okapi::okapi::openapi3::{self, MediaType, RefOr};
use schemars::schema::{InstanceType, SchemaObject, SingleOrVec};
pub struct CachedFile((ContentType, Vec<u8>));
@@ -14,13 +16,51 @@ impl<'r> Responder<'r, 'static> for CachedFile {
}
}
// Charset: 0123456789ABCDEFGHJKMNPQRSTVWXYZ
impl rocket_okapi::response::OpenApiResponderInner for CachedFile {
fn responses(
_gen: &mut rocket_okapi::gen::OpenApiGenerator,
) -> std::result::Result<openapi3::Responses, rocket_okapi::OpenApiError> {
let mut responses = schemars::Map::new();
let mut content = schemars::Map::new();
content.insert(
"image/png".to_owned(),
MediaType {
schema: Some(SchemaObject {
instance_type: Some(SingleOrVec::Single(Box::new(InstanceType::String))),
format: Some("binary".to_owned()),
..Default::default()
}),
..Default::default()
},
);
responses.insert(
"200".to_string(),
RefOr::Object(openapi3::Response {
description: "Default Avatar Picture".to_string(),
content,
..Default::default()
}),
);
Ok(openapi3::Responses {
responses,
..Default::default()
})
}
}
/// # Fetch Default Avatar
///
/// This returns a default avatar based on the given id.
#[openapi(tag = "User Information")]
#[get("/<target>/default_avatar")]
pub async fn req(target: String) -> CachedFile {
CachedFile((
ContentType::PNG,
match target.chars().last().unwrap() {
// 0123456789ABCDEFGHJKMNPQRSTVWXYZ
'0' | '1' | '2' | '3' | 'S' | 'Z' => {
include_bytes!("../../../assets/user/2.png").to_vec()
}

View File

@@ -1,4 +1,5 @@
use rocket::Route;
use rocket_okapi::okapi::openapi3::OpenApi;
mod add_friend;
mod block_user;
@@ -14,8 +15,8 @@ mod open_dm;
mod remove_friend;
mod unblock_user;
pub fn routes() -> Vec<Route> {
routes![
pub fn routes() -> (Vec<Route>, OpenApi) {
openapi_get_routes_spec![
// User Information
fetch_self::req,
fetch_user::req,

View File

@@ -1,5 +1,3 @@
//! Open a direct message with another user
use revolt_quark::{
models::{Channel, User},
perms, Database, Error, Ref, Result, UserPermission,
@@ -8,6 +6,10 @@ use revolt_quark::{
use rocket::{serde::json::Json, State};
use ulid::Ulid;
/// # Open Direct Message
///
/// Open a DM with another user.
#[openapi(tag = "Direct Messaging")]
#[get("/<target>/dm")]
pub async fn req(db: &State<Database>, user: User, target: Ref) -> Result<Json<Channel>> {
let target = target.as_user(db).await?;

View File

@@ -4,6 +4,10 @@ use revolt_quark::{Database, Result};
use rocket::serde::json::Json;
use rocket::State;
/// # Deny Friend Request / Remove Friend
///
/// Denies another user's friend request or removes an existing friend.
#[openapi(tag = "Relationships")]
#[delete("/<target>/friend")]
pub async fn req(db: &State<Database>, user: User, target: String) -> Result<Json<User>> {
let mut target = db.fetch_user(&target).await?;

View File

@@ -4,6 +4,10 @@ use revolt_quark::{Database, Result};
use rocket::serde::json::Json;
use rocket::State;
/// # Unblock User
///
/// Unblock another user by their id.
#[openapi(tag = "Relationships")]
#[delete("/<target>/block")]
pub async fn req(db: &State<Database>, user: User, target: String) -> Result<Json<User>> {
let mut target = db.fetch_user(&target).await?;