diff options
Diffstat (limited to 'src/api')
-rw-r--r-- | src/api/admin.rs | 75 | ||||
-rw-r--r-- | src/api/auth.rs | 57 | ||||
-rw-r--r-- | src/api/mod.rs | 8 | ||||
-rw-r--r-- | src/api/posts.rs | 97 | ||||
-rw-r--r-- | src/api/users.rs | 82 |
5 files changed, 308 insertions, 11 deletions
diff --git a/src/api/admin.rs b/src/api/admin.rs index a23d20f..8db3032 100644 --- a/src/api/admin.rs +++ b/src/api/admin.rs @@ -6,13 +6,29 @@ use tower_cookies::{Cookie, Cookies}; use crate::{ database, - public::admin, + public::{admin, docs::{EndpointDocumentation, EndpointMethod}}, types::{ extract::{AdminUser, Check, CheckResult, Json}, http::ResponseCode, }, }; +pub const ADMIN_AUTH: EndpointDocumentation = EndpointDocumentation { + uri: "/api/admin/auth", + method: EndpointMethod::Post, + description: "Authenticates on the admin panel", + body: Some(r#" + { + "secret" : "admin" + } + "#), + responses: &[ + (200, "Successfully executed SQL query"), + (400, " Successfully authed, admin cookie returned") + ], + cookie: None, +}; + #[derive(Deserialize)] struct AdminAuthRequest { secret: String, @@ -40,6 +56,24 @@ async fn auth(cookies: Cookies, Json(body): Json<AdminAuthRequest>) -> Response ResponseCode::Success.text("Successfully logged in") } +pub const ADMIN_QUERY: EndpointDocumentation = EndpointDocumentation { + uri: "/api/admin/query", + method: EndpointMethod::Post, + description: "Run a SQL query on the database", + body: Some(r#" + { + "query" : "DROP TABLE users;" + } + "#), + responses: &[ + (200, "Successfully executed SQL query"), + (400, "Body does not match parameters"), + (401, "Unauthorized"), + (500, "SQL query ran into an error") + ], + cookie: Some("admin"), +}; + #[derive(Deserialize)] struct QueryRequest { query: String, @@ -60,14 +94,53 @@ async fn query(_: AdminUser, Json(body): Json<QueryRequest>) -> Response { } } +pub const ADMIN_POSTS: EndpointDocumentation = EndpointDocumentation { + uri: "/api/admin/posts", + method: EndpointMethod::Post, + description: "Returns the entire posts table", + body: None, + responses: &[ + (200, "Returns sql table in <span>text/html</span>"), + (401, "Unauthorized"), + (500, "Failed to fetch data") + ], + cookie: Some("admin"), +}; + async fn posts(_: AdminUser) -> Response { admin::generate_posts() } +pub const ADMIN_USERS: EndpointDocumentation = EndpointDocumentation { + uri: "/api/admin/users", + method: EndpointMethod::Post, + description: "Returns the entire users table", + body: None, + responses: &[ + (200, "Returns sql table in <span>text/html</span>"), + (401, "Unauthorized"), + (500, "Failed to fetch data") + ], + cookie: Some("admin"), +}; + async fn users(_: AdminUser) -> Response { admin::generate_users() } +pub const ADMIN_SESSIONS: EndpointDocumentation = EndpointDocumentation { + uri: "/api/admin/sessions", + method: EndpointMethod::Post, + description: "Returns the entire sessions table", + body: None, + responses: &[ + (200, "Returns sql table in <span>text/html</span>"), + (401, "Unauthorized"), + (500, "Failed to fetch data") + ], + cookie: Some("admin"), +}; + async fn sessions(_: AdminUser) -> Response { admin::generate_sessions() } diff --git a/src/api/auth.rs b/src/api/auth.rs index 7f7cf9e..0ff180e 100644 --- a/src/api/auth.rs +++ b/src/api/auth.rs @@ -3,11 +3,34 @@ use serde::Deserialize; use time::{Duration, OffsetDateTime}; use tower_cookies::{Cookie, Cookies}; -use crate::types::{ +use crate::{types::{ extract::{AuthorizedUser, Check, CheckResult, Json, Log}, http::ResponseCode, session::Session, user::User, +}, public::docs::{EndpointDocumentation, EndpointMethod}}; + +pub const AUTH_REGISTER: EndpointDocumentation = EndpointDocumentation { + uri: "/api/auth/register", + method: EndpointMethod::Post, + description: "Registeres a new account", + body: Some(r#" + { + "firstname": "[Object]", + "lastname": "object]", + "email": "object@object.object", + "password": "i love js", + "gender": "object", + "day": 1, + "month": 1, + "year": 1970 + } + "#), + responses: &[ + (201, "Successfully registered new user"), + (400, "Body does not match parameters"), + ], + cookie: None, }; #[derive(Deserialize, Debug)] @@ -93,9 +116,26 @@ async fn register(cookies: Cookies, Json(body): Json<RegistrationRequet>) -> Res cookies.add(cookie); - ResponseCode::Created.text("Successfully created new user") + ResponseCode::Created.text("Successfully created new user, auth cookie is returned") } +pub const AUTH_LOGIN: EndpointDocumentation = EndpointDocumentation { + uri: "/api/auth/login", + method: EndpointMethod::Post, + description: "Logs into an existing account", + body: Some(r#" + { + "email": "object@object.object", + "password": "i love js" + } + "#), + responses: &[ + (200, "Successfully logged in, auth cookie is returned"), + (400, "Body does not match parameters, or invalid email password combination"), + ], + cookie: None, +}; + #[derive(Deserialize)] struct LoginRequest { email: String, @@ -136,6 +176,19 @@ async fn login(cookies: Cookies, Json(body): Json<LoginRequest>) -> Response { ResponseCode::Success.text("Successfully logged in") } +pub const AUTH_LOGOUT: EndpointDocumentation = EndpointDocumentation { + uri: "/api/auth/logout", + method: EndpointMethod::Post, + description: "Logs out of a logged in account", + body: None, + responses: &[ + (200, "Successfully logged out"), + (401, "Unauthorized"), + (500, "Failed to log out user") + ], + cookie: None, +}; + async fn logout(cookies: Cookies, AuthorizedUser(user): AuthorizedUser, _: Log) -> Response { cookies.remove(Cookie::new("auth", "")); diff --git a/src/api/mod.rs b/src/api/mod.rs index 9efcefc..12563e3 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -6,10 +6,10 @@ use tower_governor::{ GovernorLayer, }; -mod admin; -mod auth; -mod posts; -mod users; +pub mod admin; +pub mod auth; +pub mod posts; +pub mod users; pub use auth::RegistrationRequet; diff --git a/src/api/posts.rs b/src/api/posts.rs index 6aa074f..f1cdab3 100644 --- a/src/api/posts.rs +++ b/src/api/posts.rs @@ -5,10 +5,28 @@ use axum::{ }; use serde::Deserialize; -use crate::types::{ +use crate::{types::{ extract::{AuthorizedUser, Check, CheckResult, Json}, http::ResponseCode, post::Post, +}, public::docs::{EndpointDocumentation, EndpointMethod}}; + +pub const POSTS_CREATE: EndpointDocumentation = EndpointDocumentation { + uri: "/api/posts/create", + method: EndpointMethod::Post, + description: "Creates a new post", + body: Some(r#" + { + "content" : "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." + } + "#), + responses: &[ + (201, "Successfully created post"), + (400, "Body does not match parameters"), + (401, "Unauthorized"), + (500, "Failed to create post") + ], + cookie: Some("auth"), }; #[derive(Deserialize)] @@ -43,6 +61,24 @@ async fn create( ResponseCode::Created.json(&json) } +pub const POSTS_PAGE: EndpointDocumentation = EndpointDocumentation { + uri: "/api/posts/page", + method: EndpointMethod::Post, + description: "Load a section of posts from newest to oldest", + body: Some(r#" + { + "page": 0 + } + "#), + responses: &[ + (200, "Returns posts in <span>application/json<span>"), + (400, "Body does not match parameters"), + (401, "Unauthorized"), + (500, "Failed to fetch posts") + ], + cookie: Some("auth"), +}; + #[derive(Deserialize)] struct PostPageRequest { page: u64, @@ -69,10 +105,29 @@ async fn page( ResponseCode::Success.json(&json) } +pub const POSTS_USER: EndpointDocumentation = EndpointDocumentation { + uri: "/api/posts/user", + method: EndpointMethod::Post, + description: "Load a section of posts from newest to oldest from a specific user", + body: Some(r#" + { + "user_id": 3, + "page": 0 + } + "#), + responses: &[ + (200, "Returns posts in <span>application/json<span>"), + (400, "Body does not match parameters"), + (401, "Unauthorized"), + (500, "Failed to fetch posts") + ], + cookie: Some("auth"), +}; + #[derive(Deserialize)] struct UsersPostsRequest { user_id: u64, - page: u64 + page: u64, } impl Check for UsersPostsRequest { @@ -96,6 +151,25 @@ async fn user( ResponseCode::Success.json(&json) } +pub const POSTS_COMMENT: EndpointDocumentation = EndpointDocumentation { + uri: "/api/posts/comment", + method: EndpointMethod::Patch, + description: "Add a comment to a post", + body: Some(r#" + { + "content": "This is a very cool comment", + "post_id": 0 + } + "#), + responses: &[ + (200, "Successfully added comment"), + (400, "Body does not match parameters"), + (401, "Unauthorized"), + (500, "Failed to add comment") + ], + cookie: Some("auth"), +}; + #[derive(Deserialize)] struct PostCommentRequest { content: String, @@ -129,6 +203,25 @@ async fn comment( ResponseCode::Success.text("Successfully commented on post") } +pub const POSTS_LIKE: EndpointDocumentation = EndpointDocumentation { + uri: "/api/posts/like", + method: EndpointMethod::Patch, + description: "Set like status on a post", + body: Some(r#" + { + "post_id" : 0, + "status" : true + } + "#), + responses: &[ + (200, "Successfully set like status"), + (400, "Body does not match parameters"), + (401, "Unauthorized"), + (500, "Failed to set like status") + ], + cookie: Some("auth"), +}; + #[derive(Deserialize)] struct PostLikeRequest { state: bool, diff --git a/src/api/users.rs b/src/api/users.rs index e3c992b..7d1f006 100644 --- a/src/api/users.rs +++ b/src/api/users.rs @@ -1,8 +1,8 @@ -use crate::types::{ +use crate::{types::{ extract::{AuthorizedUser, Check, CheckResult, Json, Png}, http::ResponseCode, user::User, -}; +}, public::docs::{EndpointDocumentation, EndpointMethod}}; use axum::{ response::Response, routing::{post, put}, @@ -10,6 +10,24 @@ use axum::{ }; use serde::Deserialize; +pub const USERS_LOAD: EndpointDocumentation = EndpointDocumentation { + uri: "/api/users/load", + method: EndpointMethod::Post, + description: "Loads a requested set of users", + body: Some(r#" + { + "ids": [0, 3, 7] + } + "#), + responses: &[ + (200, "Returns users in <span>application/json</span>"), + (400, "Body does not match parameters"), + (401, "Unauthorized"), + (500, "Failed to fetch users") + ], + cookie: Some("auth"), +}; + #[derive(Deserialize)] struct UserLoadRequest { ids: Vec<u64>, @@ -33,6 +51,25 @@ async fn load_batch( ResponseCode::Success.json(&json) } +pub const USERS_PAGE: EndpointDocumentation = EndpointDocumentation { + uri: "/api/users/page", + method: EndpointMethod::Post, + description: "Load a section of users from newest to oldest", + body: Some(r#" + { + "user_id": 3, + "page": 0 + } + "#), + responses: &[ + (200, "Returns users in <span>application/json</span>"), + (400, "Body does not match parameters"), + (401, "Unauthorized"), + (500, "Failed to fetch users") + ], + cookie: Some("auth"), +}; + #[derive(Deserialize)] struct UserPageReqiest { page: u64, @@ -59,6 +96,19 @@ async fn load_page( ResponseCode::Success.json(&json) } +pub const USERS_SELF: EndpointDocumentation = EndpointDocumentation { + uri: "/api/users/self", + method: EndpointMethod::Post, + description: "Returns current authenticated user (whoami)", + body: None, + responses: &[ + (200, "Successfully executed SQL query"), + (401, "Unauthorized"), + (500, "Failed to fetch user") + ], + cookie: Some("auth"), +}; + async fn load_self(AuthorizedUser(user): AuthorizedUser) -> Response { let Ok(json) = serde_json::to_string(&user) else { return ResponseCode::InternalServerError.text("Failed to fetch user") @@ -67,6 +117,20 @@ async fn load_self(AuthorizedUser(user): AuthorizedUser) -> Response { ResponseCode::Success.json(&json) } +pub const USERS_AVATAR: EndpointDocumentation = EndpointDocumentation { + uri: "/api/users/avatar", + method: EndpointMethod::Put, + description: "Set your current profile avatar", + body: Some("PNG sent as a binary blob"), + responses: &[ + (200, "Successfully updated avatar"), + (400, "Invalid PNG or disallowed size"), + (401, "Unauthorized"), + (500, "Failed to update avatar") + ], + cookie: Some("auth"), +}; + async fn avatar(AuthorizedUser(user): AuthorizedUser, Png(img): Png) -> Response { let path = format!("./public/image/custom/avatar/{}.png", user.user_id); @@ -77,6 +141,20 @@ async fn avatar(AuthorizedUser(user): AuthorizedUser, Png(img): Png) -> Response ResponseCode::Success.text("Successfully updated avatar") } +pub const USERS_BANNER: EndpointDocumentation = EndpointDocumentation { + uri: "/api/users/banner", + method: EndpointMethod::Put, + description: "Set your current profile banner", + body: Some("PNG sent as a binary blob"), + responses: &[ + (200, "Successfully updated banner"), + (400, "Invalid PNG or disallowed size"), + (401, "Unauthorized"), + (500, "Failed to update banner") + ], + cookie: Some("auth"), +}; + async fn banner(AuthorizedUser(user): AuthorizedUser, Png(img): Png) -> Response { let path = format!("./public/image/custom/banner/{}.png", user.user_id); |