mirror of
https://github.com/mCaptcha/mCaptcha.git
synced 2026-02-12 02:25:41 +00:00
swagger ui
This commit is contained in:
@@ -36,8 +36,9 @@ pub struct Login {
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
struct Password {
|
||||
password: String,
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct Password {
|
||||
pub password: String,
|
||||
}
|
||||
|
||||
#[post("/api/v1/signup")]
|
||||
@@ -114,7 +115,7 @@ pub fn is_authenticated(id: &Identity) -> ServiceResult<()> {
|
||||
#[post("/api/v1/account/delete")]
|
||||
pub async fn delete_account(
|
||||
id: Identity,
|
||||
payload: web::Json<Login>,
|
||||
payload: web::Json<Password>,
|
||||
data: web::Data<Data>,
|
||||
) -> ServiceResult<impl Responder> {
|
||||
use argon2_creds::Config;
|
||||
@@ -122,10 +123,12 @@ pub async fn delete_account(
|
||||
|
||||
is_authenticated(&id)?;
|
||||
|
||||
let username = id.identity().unwrap();
|
||||
|
||||
let rec = sqlx::query_as!(
|
||||
Password,
|
||||
r#"SELECT password FROM mcaptcha_users WHERE name = ($1)"#,
|
||||
&payload.username,
|
||||
&username,
|
||||
)
|
||||
.fetch_one(&data.db)
|
||||
.await;
|
||||
@@ -135,12 +138,9 @@ pub async fn delete_account(
|
||||
match rec {
|
||||
Ok(s) => {
|
||||
if Config::verify(&s.password, &payload.password)? {
|
||||
sqlx::query!(
|
||||
"DELETE FROM mcaptcha_users WHERE name = ($1)",
|
||||
&payload.username,
|
||||
)
|
||||
.execute(&data.db)
|
||||
.await?;
|
||||
sqlx::query!("DELETE FROM mcaptcha_users WHERE name = ($1)", &username)
|
||||
.execute(&data.db)
|
||||
.await?;
|
||||
Ok(HttpResponse::Ok())
|
||||
} else {
|
||||
Err(ServiceError::WrongPassword)
|
||||
@@ -153,7 +153,7 @@ pub async fn delete_account(
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct AccountCheckPayload {
|
||||
pub field: String,
|
||||
pub val: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
@@ -168,7 +168,7 @@ pub async fn username_exists(
|
||||
) -> ServiceResult<impl Responder> {
|
||||
let res = sqlx::query!(
|
||||
"SELECT EXISTS (SELECT 1 from mcaptcha_users WHERE name = $1)",
|
||||
&payload.field,
|
||||
&payload.val,
|
||||
)
|
||||
.fetch_one(&data.db)
|
||||
.await?;
|
||||
@@ -191,7 +191,7 @@ pub async fn email_exists(
|
||||
) -> ServiceResult<impl Responder> {
|
||||
let res = sqlx::query!(
|
||||
"SELECT EXISTS (SELECT 1 from mcaptcha_users WHERE email = $1)",
|
||||
&payload.field,
|
||||
&payload.val,
|
||||
)
|
||||
.fetch_one(&data.db)
|
||||
.await?;
|
||||
|
||||
@@ -70,7 +70,7 @@ async fn auth_works() {
|
||||
SIGNIN,
|
||||
&login,
|
||||
ServiceError::UsernameNotFound,
|
||||
StatusCode::UNAUTHORIZED,
|
||||
StatusCode::NOT_FOUND,
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -115,9 +115,13 @@ async fn del_userworks() {
|
||||
let cookies = get_cookie!(signin_resp);
|
||||
let mut app = get_app!(data).await;
|
||||
|
||||
let payload = Password {
|
||||
password: creds.password,
|
||||
};
|
||||
|
||||
let delete_user_resp = test::call_service(
|
||||
&mut app,
|
||||
post_request!(&creds, "/api/v1/account/delete")
|
||||
post_request!(&payload, "/api/v1/account/delete")
|
||||
.cookie(cookies)
|
||||
.to_request(),
|
||||
)
|
||||
@@ -143,7 +147,7 @@ async fn uname_email_exists_works() {
|
||||
let cookies = get_cookie!(signin_resp);
|
||||
let mut app = get_app!(data).await;
|
||||
|
||||
let mut payload = AccountCheckPayload { field: NAME.into() };
|
||||
let mut payload = AccountCheckPayload { val: NAME.into() };
|
||||
|
||||
let user_exists_resp = test::call_service(
|
||||
&mut app,
|
||||
@@ -156,7 +160,7 @@ async fn uname_email_exists_works() {
|
||||
let mut resp: AccountCheckResp = test::read_body_json(user_exists_resp).await;
|
||||
assert!(resp.exists);
|
||||
|
||||
payload.field = PASSWORD.into();
|
||||
payload.val = PASSWORD.into();
|
||||
|
||||
let user_doesnt_exist = test::call_service(
|
||||
&mut app,
|
||||
@@ -180,7 +184,7 @@ async fn uname_email_exists_works() {
|
||||
resp = test::read_body_json(email_doesnt_exist).await;
|
||||
assert!(!resp.exists);
|
||||
|
||||
payload.field = EMAIL.into();
|
||||
payload.val = EMAIL.into();
|
||||
|
||||
let email_exist = test::call_service(
|
||||
&mut app,
|
||||
|
||||
82
src/docs.rs
Normal file
82
src/docs.rs
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2021 Aravinth Manivannan <realaravinth@batsense.net>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use actix_web::body::Body;
|
||||
use actix_web::{get, web, HttpResponse, Responder};
|
||||
use mime_guess::from_path;
|
||||
use rust_embed::RustEmbed;
|
||||
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "docs/"]
|
||||
struct Asset;
|
||||
|
||||
pub fn handle_embedded_file(path: &str) -> HttpResponse {
|
||||
match Asset::get(path) {
|
||||
Some(content) => {
|
||||
let body: Body = match content {
|
||||
Cow::Borrowed(bytes) => bytes.into(),
|
||||
Cow::Owned(bytes) => bytes.into(),
|
||||
};
|
||||
HttpResponse::Ok()
|
||||
.content_type(from_path(path).first_or_octet_stream().as_ref())
|
||||
.body(body)
|
||||
}
|
||||
None => HttpResponse::NotFound().body("404 Not Found"),
|
||||
}
|
||||
}
|
||||
|
||||
#[get("/docs/{_:.*}")]
|
||||
async fn dist(path: web::Path<String>) -> impl Responder {
|
||||
handle_embedded_file(&path.0)
|
||||
}
|
||||
|
||||
#[get("/docs")]
|
||||
async fn index() -> HttpResponse {
|
||||
handle_embedded_file("index.html")
|
||||
}
|
||||
|
||||
pub fn services(cfg: &mut web::ServiceConfig) {
|
||||
cfg.service(index);
|
||||
cfg.service(dist);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::test;
|
||||
|
||||
use super::*;
|
||||
use crate::*;
|
||||
|
||||
#[actix_rt::test]
|
||||
async fn docs_work() {
|
||||
const INDEX: &str = "/docs";
|
||||
const FILE: &str = "/docs/swagger.json";
|
||||
|
||||
let mut app = test::init_service(App::new().configure(services)).await;
|
||||
|
||||
let resp =
|
||||
test::call_service(&mut app, test::TestRequest::get().uri(INDEX).to_request()).await;
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
|
||||
let resp =
|
||||
test::call_service(&mut app, test::TestRequest::get().uri(FILE).to_request()).await;
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
}
|
||||
}
|
||||
@@ -118,14 +118,18 @@ impl ResponseError for ServiceError {
|
||||
ServiceError::NotAnEmail => StatusCode::BAD_REQUEST,
|
||||
ServiceError::NotAUrl => StatusCode::BAD_REQUEST,
|
||||
ServiceError::WrongPassword => StatusCode::UNAUTHORIZED,
|
||||
ServiceError::UsernameNotFound => StatusCode::UNAUTHORIZED,
|
||||
ServiceError::UsernameNotFound => StatusCode::NOT_FOUND,
|
||||
ServiceError::AuthorizationRequired => StatusCode::UNAUTHORIZED,
|
||||
|
||||
ServiceError::ProfainityError => StatusCode::BAD_REQUEST,
|
||||
ServiceError::BlacklistError => StatusCode::BAD_REQUEST,
|
||||
ServiceError::UsernameCaseMappedError => StatusCode::BAD_REQUEST,
|
||||
|
||||
ServiceError::PasswordTooShort => StatusCode::BAD_REQUEST,
|
||||
ServiceError::PasswordTooLong => StatusCode::BAD_REQUEST,
|
||||
ServiceError::UsernameCaseMappedError => StatusCode::BAD_REQUEST,
|
||||
|
||||
ServiceError::UsernameTaken => StatusCode::BAD_REQUEST,
|
||||
|
||||
ServiceError::TokenNameTaken => StatusCode::BAD_REQUEST,
|
||||
ServiceError::TokenNotFound => StatusCode::NOT_FOUND,
|
||||
ServiceError::HostnameTaken => StatusCode::BAD_REQUEST,
|
||||
|
||||
@@ -30,6 +30,7 @@ mod data;
|
||||
mod errors;
|
||||
//mod routes;
|
||||
mod api;
|
||||
mod docs;
|
||||
mod settings;
|
||||
//mod templates;
|
||||
#[cfg(test)]
|
||||
@@ -54,7 +55,9 @@ pub static VERIFICATION_PATH: &str = "mcaptchaVerificationChallenge.json";
|
||||
#[cfg(not(tarpaulin_include))]
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
use api::v1::services as v1_services;
|
||||
use actix_web::web;
|
||||
use api::v1;
|
||||
use docs;
|
||||
pretty_env_logger::init();
|
||||
info!(
|
||||
"{}: {}.\nFor more information, see: {}\nBuild info:\nVersion: {} commit: {}",
|
||||
@@ -67,7 +70,9 @@ async fn main() -> std::io::Result<()> {
|
||||
HttpServer::new(move || {
|
||||
let client = Client::default();
|
||||
App::new()
|
||||
.configure(v1_services)
|
||||
.configure(v1::services)
|
||||
.configure(docs::services)
|
||||
//.service(web::resource("/dist/{_:.*}").route(web::get().to(docs::dist)))
|
||||
.wrap(middleware::Logger::default())
|
||||
.wrap(get_identity_service())
|
||||
.wrap(middleware::Compress::default())
|
||||
|
||||
Reference in New Issue
Block a user