mirror of
https://github.com/mCaptcha/mCaptcha.git
synced 2025-06-14 18:26:36 +00:00
refactoring
This commit is contained in:
parent
609bbde7bd
commit
ee548588a8
153
src/api/v1/mcaptcha/domains.rs
Normal file
153
src/api/v1/mcaptcha/domains.rs
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* 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_identity::Identity;
|
||||||
|
use actix_web::{post, web, HttpResponse, Responder};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
use super::is_authenticated;
|
||||||
|
use crate::errors::*;
|
||||||
|
use crate::Data;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct Domain {
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/api/v1/mcaptcha/domain/add")]
|
||||||
|
pub async fn add_domain(
|
||||||
|
payload: web::Json<Domain>,
|
||||||
|
data: web::Data<Data>,
|
||||||
|
id: Identity,
|
||||||
|
) -> ServiceResult<impl Responder> {
|
||||||
|
is_authenticated(&id)?;
|
||||||
|
let url = Url::parse(&payload.name)?;
|
||||||
|
if let Some(host) = url.host_str() {
|
||||||
|
let user = id.identity().unwrap();
|
||||||
|
let res = sqlx::query!(
|
||||||
|
"INSERT INTO mcaptcha_domains (name, ID) VALUES
|
||||||
|
($1, (SELECT ID FROM mcaptcha_users WHERE name = ($2) ));",
|
||||||
|
host,
|
||||||
|
user
|
||||||
|
)
|
||||||
|
.execute(&data.db)
|
||||||
|
.await;
|
||||||
|
match res {
|
||||||
|
Err(e) => Err(dup_error(e, ServiceError::HostnameTaken)),
|
||||||
|
Ok(_) => Ok(HttpResponse::Ok()),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(ServiceError::NotAUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/api/v1/mcaptcha/domain/delete")]
|
||||||
|
pub async fn delete_domain(
|
||||||
|
payload: web::Json<Domain>,
|
||||||
|
data: web::Data<Data>,
|
||||||
|
id: Identity,
|
||||||
|
) -> ServiceResult<impl Responder> {
|
||||||
|
is_authenticated(&id)?;
|
||||||
|
let url = Url::parse(&payload.name)?;
|
||||||
|
if let Some(host) = url.host_str() {
|
||||||
|
sqlx::query!("DELETE FROM mcaptcha_domains WHERE name = ($1)", host,)
|
||||||
|
.execute(&data.db)
|
||||||
|
.await?;
|
||||||
|
Ok(HttpResponse::Ok())
|
||||||
|
} else {
|
||||||
|
Err(ServiceError::NotAUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Workflow:
|
||||||
|
// 1. Sign up
|
||||||
|
// 2. Sign in
|
||||||
|
// 3. Add domain(DNS TXT record verification? / put string at path)
|
||||||
|
// 4. Create token
|
||||||
|
// 5. Add levels
|
||||||
|
// 6. Update duration
|
||||||
|
// 7. Start syatem
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use actix_web::http::{header, StatusCode};
|
||||||
|
use actix_web::test;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use crate::api::v1::services as v1_services;
|
||||||
|
use crate::tests::*;
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn add_domains_work() {
|
||||||
|
const NAME: &str = "testuserdomainn";
|
||||||
|
const PASSWORD: &str = "longpassworddomain";
|
||||||
|
const EMAIL: &str = "testuserdomain@a.com";
|
||||||
|
const DOMAIN: &str = "http://example.com";
|
||||||
|
const ADD_URL: &str = "/api/v1/mcaptcha/domain/add";
|
||||||
|
|
||||||
|
{
|
||||||
|
let data = Data::new().await;
|
||||||
|
delete_user(NAME, &data).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
register_and_signin(NAME, EMAIL, PASSWORD).await;
|
||||||
|
|
||||||
|
// 1. add domain
|
||||||
|
let (data, _, signin_resp) = add_domain_util(NAME, PASSWORD, DOMAIN).await;
|
||||||
|
let cookies = get_cookie!(signin_resp);
|
||||||
|
let mut app = get_app!(data).await;
|
||||||
|
|
||||||
|
let mut domain = Domain {
|
||||||
|
name: DOMAIN.into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// 2. duplicate domain
|
||||||
|
bad_post_req_test(
|
||||||
|
NAME,
|
||||||
|
PASSWORD,
|
||||||
|
ADD_URL,
|
||||||
|
&domain,
|
||||||
|
ServiceError::HostnameTaken,
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// 3. delete domain
|
||||||
|
let del_domain_resp = test::call_service(
|
||||||
|
&mut app,
|
||||||
|
post_request!(&domain, "/api/v1/mcaptcha/domain/delete")
|
||||||
|
.cookie(cookies.clone())
|
||||||
|
.to_request(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert_eq!(del_domain_resp.status(), StatusCode::OK);
|
||||||
|
|
||||||
|
// 4. not a URL test for adding domain
|
||||||
|
domain.name = "testing".into();
|
||||||
|
bad_post_req_test(
|
||||||
|
NAME,
|
||||||
|
PASSWORD,
|
||||||
|
ADD_URL,
|
||||||
|
&domain,
|
||||||
|
ServiceError::NotAUrl,
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
161
src/api/v1/mcaptcha/duration.rs
Normal file
161
src/api/v1/mcaptcha/duration.rs
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
* 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_identity::Identity;
|
||||||
|
use actix_web::{post, web, HttpResponse, Responder};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use super::is_authenticated;
|
||||||
|
use crate::errors::*;
|
||||||
|
use crate::Data;
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct UpdateDuration {
|
||||||
|
pub token_name: String,
|
||||||
|
pub duration: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/api/v1/mcaptcha/domain/token/duration/update")]
|
||||||
|
pub async fn update_duration(
|
||||||
|
payload: web::Json<UpdateDuration>,
|
||||||
|
data: web::Data<Data>,
|
||||||
|
id: Identity,
|
||||||
|
) -> ServiceResult<impl Responder> {
|
||||||
|
is_authenticated(&id)?;
|
||||||
|
|
||||||
|
if payload.duration > 0 {
|
||||||
|
sqlx::query!(
|
||||||
|
"UPDATE mcaptcha_config set duration = $1 WHERE
|
||||||
|
name = $2;",
|
||||||
|
&payload.duration,
|
||||||
|
&payload.token_name,
|
||||||
|
)
|
||||||
|
.execute(&data.db)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok())
|
||||||
|
} else {
|
||||||
|
// when mCaptcha/mCaptcha #2 is fixed, this wont be necessary
|
||||||
|
Err(ServiceError::CaptchaError(
|
||||||
|
m_captcha::errors::CaptchaError::DifficultyFactorZero,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct GetDurationResp {
|
||||||
|
pub duration: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
pub struct GetDuration {
|
||||||
|
pub token: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/api/v1/mcaptcha/domain/token/duration/get")]
|
||||||
|
pub async fn get_duration(
|
||||||
|
payload: web::Json<GetDuration>,
|
||||||
|
data: web::Data<Data>,
|
||||||
|
id: Identity,
|
||||||
|
) -> ServiceResult<impl Responder> {
|
||||||
|
is_authenticated(&id)?;
|
||||||
|
|
||||||
|
let duration = sqlx::query_as!(
|
||||||
|
GetDurationResp,
|
||||||
|
"SELECT duration FROM mcaptcha_config WHERE
|
||||||
|
name = $1;",
|
||||||
|
&payload.token,
|
||||||
|
)
|
||||||
|
.fetch_one(&data.db)
|
||||||
|
.await?;
|
||||||
|
Ok(HttpResponse::Ok().json(duration))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use actix_web::http::{header, StatusCode};
|
||||||
|
use actix_web::test;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use crate::api::v1::services as v1_services;
|
||||||
|
use crate::tests::*;
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn update_duration() {
|
||||||
|
const NAME: &str = "testuserduration";
|
||||||
|
const PASSWORD: &str = "longpassworddomain";
|
||||||
|
const EMAIL: &str = "testuserduration@a.com";
|
||||||
|
const DOMAIN: &str = "http://duration.example.com";
|
||||||
|
const TOKEN_NAME: &str = "duration_routes_token";
|
||||||
|
const GET_URL: &str = "/api/v1/mcaptcha/domain/token/duration/get";
|
||||||
|
const UPDATE_URL: &str = "/api/v1/mcaptcha/domain/token/duration/update";
|
||||||
|
|
||||||
|
{
|
||||||
|
let data = Data::new().await;
|
||||||
|
delete_user(NAME, &data).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
register_and_signin(NAME, EMAIL, PASSWORD).await;
|
||||||
|
let (data, _, signin_resp) = add_token_util(NAME, PASSWORD, DOMAIN, TOKEN_NAME).await;
|
||||||
|
let cookies = get_cookie!(signin_resp);
|
||||||
|
let mut app = get_app!(data).await;
|
||||||
|
|
||||||
|
let update = UpdateDuration {
|
||||||
|
token_name: TOKEN_NAME.into(),
|
||||||
|
duration: 40,
|
||||||
|
};
|
||||||
|
|
||||||
|
let get = GetDuration {
|
||||||
|
token: TOKEN_NAME.into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// check default
|
||||||
|
|
||||||
|
let get_level_resp = test::call_service(
|
||||||
|
&mut app,
|
||||||
|
post_request!(&get, GET_URL)
|
||||||
|
.cookie(cookies.clone())
|
||||||
|
.to_request(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert_eq!(get_level_resp.status(), StatusCode::OK);
|
||||||
|
let res_levels: GetDurationResp = test::read_body_json(get_level_resp).await;
|
||||||
|
assert_eq!(res_levels.duration, 30);
|
||||||
|
|
||||||
|
// update and check changes
|
||||||
|
|
||||||
|
let update_duration = test::call_service(
|
||||||
|
&mut app,
|
||||||
|
post_request!(&update, UPDATE_URL)
|
||||||
|
.cookie(cookies.clone())
|
||||||
|
.to_request(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert_eq!(update_duration.status(), StatusCode::OK);
|
||||||
|
let get_level_resp = test::call_service(
|
||||||
|
&mut app,
|
||||||
|
post_request!(&get, GET_URL)
|
||||||
|
.cookie(cookies.clone())
|
||||||
|
.to_request(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert_eq!(get_level_resp.status(), StatusCode::OK);
|
||||||
|
let res_levels: GetDurationResp = test::read_body_json(get_level_resp).await;
|
||||||
|
assert_eq!(res_levels.duration, 40);
|
||||||
|
}
|
||||||
|
}
|
@ -19,143 +19,11 @@ use actix_identity::Identity;
|
|||||||
use actix_web::{post, web, HttpResponse, Responder};
|
use actix_web::{post, web, HttpResponse, Responder};
|
||||||
use m_captcha::{defense::Level, DefenseBuilder};
|
use m_captcha::{defense::Level, DefenseBuilder};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
use super::auth::is_authenticated;
|
use super::is_authenticated;
|
||||||
use crate::errors::*;
|
use crate::errors::*;
|
||||||
use crate::Data;
|
use crate::Data;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
||||||
pub struct Domain {
|
|
||||||
pub name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[post("/api/v1/mcaptcha/domain/add")]
|
|
||||||
pub async fn add_domain(
|
|
||||||
payload: web::Json<Domain>,
|
|
||||||
data: web::Data<Data>,
|
|
||||||
id: Identity,
|
|
||||||
) -> ServiceResult<impl Responder> {
|
|
||||||
is_authenticated(&id)?;
|
|
||||||
let url = Url::parse(&payload.name)?;
|
|
||||||
if let Some(host) = url.host_str() {
|
|
||||||
let user = id.identity().unwrap();
|
|
||||||
let res = sqlx::query!(
|
|
||||||
"INSERT INTO mcaptcha_domains (name, ID) VALUES
|
|
||||||
($1, (SELECT ID FROM mcaptcha_users WHERE name = ($2) ));",
|
|
||||||
host,
|
|
||||||
user
|
|
||||||
)
|
|
||||||
.execute(&data.db)
|
|
||||||
.await;
|
|
||||||
match res {
|
|
||||||
Err(e) => Err(dup_error(e, ServiceError::HostnameTaken)),
|
|
||||||
Ok(_) => Ok(HttpResponse::Ok()),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(ServiceError::NotAUrl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[post("/api/v1/mcaptcha/domain/delete")]
|
|
||||||
pub async fn delete_domain(
|
|
||||||
payload: web::Json<Domain>,
|
|
||||||
data: web::Data<Data>,
|
|
||||||
id: Identity,
|
|
||||||
) -> ServiceResult<impl Responder> {
|
|
||||||
is_authenticated(&id)?;
|
|
||||||
let url = Url::parse(&payload.name)?;
|
|
||||||
if let Some(host) = url.host_str() {
|
|
||||||
sqlx::query!("DELETE FROM mcaptcha_domains WHERE name = ($1)", host,)
|
|
||||||
.execute(&data.db)
|
|
||||||
.await?;
|
|
||||||
Ok(HttpResponse::Ok())
|
|
||||||
} else {
|
|
||||||
Err(ServiceError::NotAUrl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
||||||
pub struct CreateToken {
|
|
||||||
pub name: String,
|
|
||||||
pub domain: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
|
||||||
pub struct TokenKeyPair {
|
|
||||||
pub name: String,
|
|
||||||
pub key: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[post("/api/v1/mcaptcha/domain/token/add")]
|
|
||||||
pub async fn add_mcaptcha(
|
|
||||||
payload: web::Json<CreateToken>,
|
|
||||||
data: web::Data<Data>,
|
|
||||||
id: Identity,
|
|
||||||
) -> ServiceResult<impl Responder> {
|
|
||||||
is_authenticated(&id)?;
|
|
||||||
let key = get_random(32);
|
|
||||||
let url = Url::parse(&payload.domain)?;
|
|
||||||
println!("got req");
|
|
||||||
if let Some(host) = url.host_str() {
|
|
||||||
let res = sqlx::query!(
|
|
||||||
"INSERT INTO mcaptcha_config
|
|
||||||
(name, key, domain_name)
|
|
||||||
VALUES ($1, $2, (
|
|
||||||
SELECT name FROM mcaptcha_domains WHERE name = ($3)))",
|
|
||||||
&payload.name,
|
|
||||||
&key,
|
|
||||||
&host,
|
|
||||||
)
|
|
||||||
.execute(&data.db)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
match res {
|
|
||||||
Err(e) => Err(dup_error(e, ServiceError::TokenNameTaken)),
|
|
||||||
Ok(_) => {
|
|
||||||
let resp = TokenKeyPair {
|
|
||||||
key,
|
|
||||||
name: payload.into_inner().name,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(HttpResponse::Ok().json(resp))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(ServiceError::NotAUrl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[post("/api/v1/mcaptcha/domain/token/delete")]
|
|
||||||
pub async fn delete_mcaptcha(
|
|
||||||
payload: web::Json<CreateToken>,
|
|
||||||
data: web::Data<Data>,
|
|
||||||
id: Identity,
|
|
||||||
) -> ServiceResult<impl Responder> {
|
|
||||||
is_authenticated(&id)?;
|
|
||||||
sqlx::query!(
|
|
||||||
"DELETE FROM mcaptcha_config WHERE name = ($1)",
|
|
||||||
&payload.name,
|
|
||||||
)
|
|
||||||
.execute(&data.db)
|
|
||||||
.await?;
|
|
||||||
Ok(HttpResponse::Ok())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_random(len: usize) -> String {
|
|
||||||
use std::iter;
|
|
||||||
|
|
||||||
use rand::{distributions::Alphanumeric, rngs::ThreadRng, thread_rng, Rng};
|
|
||||||
|
|
||||||
let mut rng: ThreadRng = thread_rng();
|
|
||||||
|
|
||||||
iter::repeat(())
|
|
||||||
.map(|()| rng.sample(Alphanumeric))
|
|
||||||
.map(char::from)
|
|
||||||
.take(len)
|
|
||||||
.collect::<String>()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct AddLevels {
|
pub struct AddLevels {
|
||||||
pub levels: Vec<Level>,
|
pub levels: Vec<Level>,
|
||||||
@ -287,63 +155,6 @@ pub async fn get_levels(
|
|||||||
Ok(HttpResponse::Ok().json(levels))
|
Ok(HttpResponse::Ok().json(levels))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
|
||||||
pub struct Duration {
|
|
||||||
pub token_name: String,
|
|
||||||
pub duration: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[post("/api/v1/mcaptcha/domain/token/duration/update")]
|
|
||||||
pub async fn update_duration(
|
|
||||||
payload: web::Json<Duration>,
|
|
||||||
data: web::Data<Data>,
|
|
||||||
id: Identity,
|
|
||||||
) -> ServiceResult<impl Responder> {
|
|
||||||
is_authenticated(&id)?;
|
|
||||||
|
|
||||||
if payload.duration > 0 {
|
|
||||||
sqlx::query!(
|
|
||||||
"UPDATE mcaptcha_config set duration = $1 WHERE
|
|
||||||
name = $2;",
|
|
||||||
&payload.duration,
|
|
||||||
&payload.token_name,
|
|
||||||
)
|
|
||||||
.execute(&data.db)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(HttpResponse::Ok())
|
|
||||||
} else {
|
|
||||||
// when mCaptcha/mCaptcha #2 is fixed, this wont be necessary
|
|
||||||
Err(ServiceError::CaptchaError(
|
|
||||||
m_captcha::errors::CaptchaError::DifficultyFactorZero,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
|
||||||
pub struct GetDuration {
|
|
||||||
pub duration: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[post("/api/v1/mcaptcha/domain/token/duration/get")]
|
|
||||||
pub async fn get_duration(
|
|
||||||
payload: web::Json<GetLevels>,
|
|
||||||
data: web::Data<Data>,
|
|
||||||
id: Identity,
|
|
||||||
) -> ServiceResult<impl Responder> {
|
|
||||||
is_authenticated(&id)?;
|
|
||||||
|
|
||||||
let duration = sqlx::query_as!(
|
|
||||||
GetDuration,
|
|
||||||
"SELECT duration FROM mcaptcha_config WHERE
|
|
||||||
name = $1;",
|
|
||||||
&payload.token,
|
|
||||||
)
|
|
||||||
.fetch_one(&data.db)
|
|
||||||
.await?;
|
|
||||||
Ok(HttpResponse::Ok().json(duration))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct Levels {
|
pub struct Levels {
|
||||||
levels: I32Levels,
|
levels: I32Levels,
|
||||||
@ -370,11 +181,143 @@ async fn get_levels_util(name: &str, data: &Data) -> ServiceResult<Vec<I32Levels
|
|||||||
Ok(levels)
|
Ok(levels)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Workflow:
|
#[cfg(test)]
|
||||||
// 1. Sign up
|
mod tests {
|
||||||
// 2. Sign in
|
use actix_web::http::{header, StatusCode};
|
||||||
// 3. Add domain(DNS TXT record verification? / put string at path)
|
use actix_web::test;
|
||||||
// 4. Create token
|
|
||||||
// 5. Add levels
|
use super::*;
|
||||||
// 6. Update duration
|
use crate::api::v1::services as v1_services;
|
||||||
// 7. Start syatem
|
use crate::tests::*;
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn level_routes_work() {
|
||||||
|
const NAME: &str = "testuserlevelroutes";
|
||||||
|
const PASSWORD: &str = "longpassworddomain";
|
||||||
|
const EMAIL: &str = "testuserlevelrouts@a.com";
|
||||||
|
const DOMAIN: &str = "http://level.example.com";
|
||||||
|
const TOKEN_NAME: &str = "level_routes_work";
|
||||||
|
const ADD_URL: &str = "/api/v1/mcaptcha/domain/token/levels/add";
|
||||||
|
const UPDATE_URL: &str = "/api/v1/mcaptcha/domain/token/levels/update";
|
||||||
|
const DEL_URL: &str = "/api/v1/mcaptcha/domain/token/levels/delete";
|
||||||
|
const GET_URL: &str = "/api/v1/mcaptcha/domain/token/levels/get";
|
||||||
|
|
||||||
|
let l1 = Level {
|
||||||
|
difficulty_factor: 50,
|
||||||
|
visitor_threshold: 50,
|
||||||
|
};
|
||||||
|
let l2 = Level {
|
||||||
|
difficulty_factor: 500,
|
||||||
|
visitor_threshold: 500,
|
||||||
|
};
|
||||||
|
let levels = vec![l1, l2];
|
||||||
|
let add_level = AddLevels {
|
||||||
|
levels: levels.clone(),
|
||||||
|
name: TOKEN_NAME.into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let get_level = GetLevels {
|
||||||
|
token: TOKEN_NAME.into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
let data = Data::new().await;
|
||||||
|
delete_user(NAME, &data).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
register_and_signin(NAME, EMAIL, PASSWORD).await;
|
||||||
|
let (data, _, signin_resp) = add_token_util(NAME, PASSWORD, DOMAIN, TOKEN_NAME).await;
|
||||||
|
let cookies = get_cookie!(signin_resp);
|
||||||
|
let mut app = get_app!(data).await;
|
||||||
|
|
||||||
|
// 1. add level
|
||||||
|
let add_token_resp = test::call_service(
|
||||||
|
&mut app,
|
||||||
|
post_request!(&add_level, ADD_URL)
|
||||||
|
.cookie(cookies.clone())
|
||||||
|
.to_request(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert_eq!(add_token_resp.status(), StatusCode::OK);
|
||||||
|
|
||||||
|
// 2. get level
|
||||||
|
let get_level_resp = test::call_service(
|
||||||
|
&mut app,
|
||||||
|
post_request!(&get_level, GET_URL)
|
||||||
|
.cookie(cookies.clone())
|
||||||
|
.to_request(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert_eq!(get_level_resp.status(), StatusCode::OK);
|
||||||
|
let res_levels: Vec<Level> = test::read_body_json(get_level_resp).await;
|
||||||
|
assert_eq!(res_levels, levels);
|
||||||
|
|
||||||
|
// 3. update level
|
||||||
|
|
||||||
|
let l1 = Level {
|
||||||
|
difficulty_factor: 10,
|
||||||
|
visitor_threshold: 10,
|
||||||
|
};
|
||||||
|
let l2 = Level {
|
||||||
|
difficulty_factor: 5000,
|
||||||
|
visitor_threshold: 5000,
|
||||||
|
};
|
||||||
|
let levels = vec![l1, l2];
|
||||||
|
let add_level = AddLevels {
|
||||||
|
levels: levels.clone(),
|
||||||
|
name: TOKEN_NAME.into(),
|
||||||
|
};
|
||||||
|
let add_token_resp = test::call_service(
|
||||||
|
&mut app,
|
||||||
|
post_request!(&add_level, UPDATE_URL)
|
||||||
|
.cookie(cookies.clone())
|
||||||
|
.to_request(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert_eq!(add_token_resp.status(), StatusCode::OK);
|
||||||
|
let get_level_resp = test::call_service(
|
||||||
|
&mut app,
|
||||||
|
post_request!(&get_level, GET_URL)
|
||||||
|
.cookie(cookies.clone())
|
||||||
|
.to_request(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert_eq!(get_level_resp.status(), StatusCode::OK);
|
||||||
|
let res_levels: Vec<Level> = test::read_body_json(get_level_resp).await;
|
||||||
|
assert_eq!(res_levels, levels);
|
||||||
|
|
||||||
|
// 4. delete level
|
||||||
|
let l1 = Level {
|
||||||
|
difficulty_factor: 10,
|
||||||
|
visitor_threshold: 10,
|
||||||
|
};
|
||||||
|
let l2 = Level {
|
||||||
|
difficulty_factor: 5000,
|
||||||
|
visitor_threshold: 5000,
|
||||||
|
};
|
||||||
|
let levels = vec![l1, l2];
|
||||||
|
let add_level = AddLevels {
|
||||||
|
levels: levels.clone(),
|
||||||
|
name: TOKEN_NAME.into(),
|
||||||
|
};
|
||||||
|
let add_token_resp = test::call_service(
|
||||||
|
&mut app,
|
||||||
|
post_request!(&add_level, DEL_URL)
|
||||||
|
.cookie(cookies.clone())
|
||||||
|
.to_request(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert_eq!(add_token_resp.status(), StatusCode::OK);
|
||||||
|
let get_level_resp = test::call_service(
|
||||||
|
&mut app,
|
||||||
|
post_request!(&get_level, GET_URL)
|
||||||
|
.cookie(cookies.clone())
|
||||||
|
.to_request(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert_eq!(get_level_resp.status(), StatusCode::OK);
|
||||||
|
let res_levels: Vec<Level> = test::read_body_json(get_level_resp).await;
|
||||||
|
assert_eq!(res_levels, Vec::new());
|
||||||
|
}
|
||||||
|
}
|
186
src/api/v1/mcaptcha/mcaptcha.rs
Normal file
186
src/api/v1/mcaptcha/mcaptcha.rs
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* 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_identity::Identity;
|
||||||
|
use actix_web::{post, web, HttpResponse, Responder};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
use super::is_authenticated;
|
||||||
|
use crate::errors::*;
|
||||||
|
use crate::Data;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct MCaptchaID {
|
||||||
|
pub name: String,
|
||||||
|
pub domain: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct MCaptchaDetails {
|
||||||
|
pub name: String,
|
||||||
|
pub key: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/api/v1/mcaptcha/domain/token/add")]
|
||||||
|
pub async fn add_mcaptcha(
|
||||||
|
payload: web::Json<MCaptchaID>,
|
||||||
|
data: web::Data<Data>,
|
||||||
|
id: Identity,
|
||||||
|
) -> ServiceResult<impl Responder> {
|
||||||
|
is_authenticated(&id)?;
|
||||||
|
let key = get_random(32);
|
||||||
|
let url = Url::parse(&payload.domain)?;
|
||||||
|
println!("got req");
|
||||||
|
if let Some(host) = url.host_str() {
|
||||||
|
let res = sqlx::query!(
|
||||||
|
"INSERT INTO mcaptcha_config
|
||||||
|
(name, key, domain_name)
|
||||||
|
VALUES ($1, $2, (
|
||||||
|
SELECT name FROM mcaptcha_domains WHERE name = ($3)))",
|
||||||
|
&payload.name,
|
||||||
|
&key,
|
||||||
|
&host,
|
||||||
|
)
|
||||||
|
.execute(&data.db)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
match res {
|
||||||
|
Err(e) => Err(dup_error(e, ServiceError::TokenNameTaken)),
|
||||||
|
Ok(_) => {
|
||||||
|
let resp = MCaptchaDetails {
|
||||||
|
key,
|
||||||
|
name: payload.into_inner().name,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(HttpResponse::Ok().json(resp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(ServiceError::NotAUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/api/v1/mcaptcha/domain/token/delete")]
|
||||||
|
pub async fn delete_mcaptcha(
|
||||||
|
payload: web::Json<MCaptchaID>,
|
||||||
|
data: web::Data<Data>,
|
||||||
|
id: Identity,
|
||||||
|
) -> ServiceResult<impl Responder> {
|
||||||
|
is_authenticated(&id)?;
|
||||||
|
sqlx::query!(
|
||||||
|
"DELETE FROM mcaptcha_config WHERE name = ($1)",
|
||||||
|
&payload.name,
|
||||||
|
)
|
||||||
|
.execute(&data.db)
|
||||||
|
.await?;
|
||||||
|
Ok(HttpResponse::Ok())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_random(len: usize) -> String {
|
||||||
|
use std::iter;
|
||||||
|
|
||||||
|
use rand::{distributions::Alphanumeric, rngs::ThreadRng, thread_rng, Rng};
|
||||||
|
|
||||||
|
let mut rng: ThreadRng = thread_rng();
|
||||||
|
|
||||||
|
iter::repeat(())
|
||||||
|
.map(|()| rng.sample(Alphanumeric))
|
||||||
|
.map(char::from)
|
||||||
|
.take(len)
|
||||||
|
.collect::<String>()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Workflow:
|
||||||
|
// 1. Sign up
|
||||||
|
// 2. Sign in
|
||||||
|
// 3. Add domain(DNS TXT record verification? / put string at path)
|
||||||
|
// 4. Create token
|
||||||
|
// 5. Add levels
|
||||||
|
// 6. Update duration
|
||||||
|
// 7. Start syatem
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use actix_web::http::{header, StatusCode};
|
||||||
|
use actix_web::test;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use crate::api::v1::services as v1_services;
|
||||||
|
use crate::tests::*;
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn add_mcaptcha_works() {
|
||||||
|
const NAME: &str = "testusermcaptcha";
|
||||||
|
const PASSWORD: &str = "longpassworddomain";
|
||||||
|
const EMAIL: &str = "testusermcaptcha@a.com";
|
||||||
|
const DOMAIN: &str = "http://mcaptcha.example.com";
|
||||||
|
const TOKEN_NAME: &str = "add_mcaptcha_works_token";
|
||||||
|
const ADD_URL: &str = "/api/v1/mcaptcha/domain/token/add";
|
||||||
|
const DEL_URL: &str = "/api/v1/mcaptcha/domain/token/delete";
|
||||||
|
|
||||||
|
{
|
||||||
|
let data = Data::new().await;
|
||||||
|
delete_user(NAME, &data).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. add mcaptcha token
|
||||||
|
register_and_signin(NAME, EMAIL, PASSWORD).await;
|
||||||
|
let (data, _, signin_resp) = add_token_util(NAME, PASSWORD, DOMAIN, TOKEN_NAME).await;
|
||||||
|
let cookies = get_cookie!(signin_resp);
|
||||||
|
let mut app = get_app!(data).await;
|
||||||
|
|
||||||
|
let mut domain = MCaptchaID {
|
||||||
|
domain: DOMAIN.into(),
|
||||||
|
name: TOKEN_NAME.into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// 2. add duplicate mcaptha
|
||||||
|
bad_post_req_test(
|
||||||
|
NAME,
|
||||||
|
PASSWORD,
|
||||||
|
ADD_URL,
|
||||||
|
&domain,
|
||||||
|
ServiceError::TokenNameTaken,
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// 4. not a URL test for adding domain
|
||||||
|
domain.domain = "testing".into();
|
||||||
|
bad_post_req_test(
|
||||||
|
NAME,
|
||||||
|
PASSWORD,
|
||||||
|
ADD_URL,
|
||||||
|
&domain,
|
||||||
|
ServiceError::NotAUrl,
|
||||||
|
StatusCode::BAD_REQUEST,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// 4. delete token
|
||||||
|
let del_token = test::call_service(
|
||||||
|
&mut app,
|
||||||
|
post_request!(&domain, DEL_URL)
|
||||||
|
.cookie(cookies.clone())
|
||||||
|
.to_request(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
assert_eq!(del_token.status(), StatusCode::OK);
|
||||||
|
}
|
||||||
|
}
|
23
src/api/v1/mcaptcha/mod.rs
Normal file
23
src/api/v1/mcaptcha/mod.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub mod domains;
|
||||||
|
pub mod duration;
|
||||||
|
pub mod levels;
|
||||||
|
pub mod mcaptcha;
|
||||||
|
|
||||||
|
pub use super::auth::is_authenticated;
|
@ -29,19 +29,23 @@ pub fn services(cfg: &mut ServiceConfig) {
|
|||||||
cfg.service(auth::delete_account);
|
cfg.service(auth::delete_account);
|
||||||
|
|
||||||
// mcaptcha
|
// mcaptcha
|
||||||
// 1. domain and mcaptcha
|
// domain
|
||||||
cfg.service(mcaptcha::add_domain);
|
cfg.service(mcaptcha::domains::add_domain);
|
||||||
cfg.service(mcaptcha::delete_domain);
|
cfg.service(mcaptcha::domains::delete_domain);
|
||||||
cfg.service(mcaptcha::add_mcaptcha);
|
|
||||||
cfg.service(mcaptcha::delete_mcaptcha);
|
// mcaptcha
|
||||||
|
cfg.service(mcaptcha::mcaptcha::add_mcaptcha);
|
||||||
|
cfg.service(mcaptcha::mcaptcha::delete_mcaptcha);
|
||||||
|
|
||||||
// levels
|
// levels
|
||||||
cfg.service(mcaptcha::add_levels);
|
cfg.service(mcaptcha::levels::add_levels);
|
||||||
cfg.service(mcaptcha::update_levels);
|
cfg.service(mcaptcha::levels::update_levels);
|
||||||
cfg.service(mcaptcha::delete_levels);
|
cfg.service(mcaptcha::levels::delete_levels);
|
||||||
cfg.service(mcaptcha::get_levels);
|
cfg.service(mcaptcha::levels::get_levels);
|
||||||
|
|
||||||
// duration
|
// duration
|
||||||
cfg.service(mcaptcha::update_duration);
|
cfg.service(mcaptcha::duration::update_duration);
|
||||||
cfg.service(mcaptcha::get_duration);
|
cfg.service(mcaptcha::duration::get_duration);
|
||||||
|
|
||||||
// meta
|
// meta
|
||||||
cfg.service(meta::build_details);
|
cfg.service(meta::build_details);
|
||||||
|
@ -1,338 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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::http::{header, StatusCode};
|
|
||||||
use actix_web::test;
|
|
||||||
use m_captcha::defense::Level;
|
|
||||||
|
|
||||||
use crate::api::v1::mcaptcha::*;
|
|
||||||
use crate::api::v1::services as v1_services;
|
|
||||||
use crate::errors::*;
|
|
||||||
use crate::tests::*;
|
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
#[actix_rt::test]
|
|
||||||
async fn add_domains_work() {
|
|
||||||
const NAME: &str = "testuserdomainn";
|
|
||||||
const PASSWORD: &str = "longpassworddomain";
|
|
||||||
const EMAIL: &str = "testuserdomain@a.com";
|
|
||||||
const DOMAIN: &str = "http://example.com";
|
|
||||||
const ADD_URL: &str = "/api/v1/mcaptcha/domain/add";
|
|
||||||
|
|
||||||
{
|
|
||||||
let data = Data::new().await;
|
|
||||||
delete_user(NAME, &data).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
register_and_signin(NAME, EMAIL, PASSWORD).await;
|
|
||||||
|
|
||||||
// 1. add domain
|
|
||||||
let (data, _, signin_resp) = add_domain_util(NAME, PASSWORD, DOMAIN).await;
|
|
||||||
let cookies = get_cookie!(signin_resp);
|
|
||||||
let mut app = get_app!(data).await;
|
|
||||||
|
|
||||||
let mut domain = Domain {
|
|
||||||
name: DOMAIN.into(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// 2. duplicate domain
|
|
||||||
bad_post_req_test(
|
|
||||||
NAME,
|
|
||||||
PASSWORD,
|
|
||||||
ADD_URL,
|
|
||||||
&domain,
|
|
||||||
ServiceError::HostnameTaken,
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
// 3. delete domain
|
|
||||||
let del_domain_resp = test::call_service(
|
|
||||||
&mut app,
|
|
||||||
post_request!(&domain, "/api/v1/mcaptcha/domain/delete")
|
|
||||||
.cookie(cookies.clone())
|
|
||||||
.to_request(),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
assert_eq!(del_domain_resp.status(), StatusCode::OK);
|
|
||||||
|
|
||||||
// 4. not a URL test for adding domain
|
|
||||||
domain.name = "testing".into();
|
|
||||||
bad_post_req_test(
|
|
||||||
NAME,
|
|
||||||
PASSWORD,
|
|
||||||
ADD_URL,
|
|
||||||
&domain,
|
|
||||||
ServiceError::NotAUrl,
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[actix_rt::test]
|
|
||||||
async fn add_mcaptcha_works() {
|
|
||||||
const NAME: &str = "testusermcaptcha";
|
|
||||||
const PASSWORD: &str = "longpassworddomain";
|
|
||||||
const EMAIL: &str = "testusermcaptcha@a.com";
|
|
||||||
const DOMAIN: &str = "http://mcaptcha.example.com";
|
|
||||||
const TOKEN_NAME: &str = "add_mcaptcha_works_token";
|
|
||||||
const ADD_URL: &str = "/api/v1/mcaptcha/domain/token/add";
|
|
||||||
const DEL_URL: &str = "/api/v1/mcaptcha/domain/token/delete";
|
|
||||||
|
|
||||||
{
|
|
||||||
let data = Data::new().await;
|
|
||||||
delete_user(NAME, &data).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. add mcaptcha token
|
|
||||||
register_and_signin(NAME, EMAIL, PASSWORD).await;
|
|
||||||
let (data, _, signin_resp) = add_token_util(NAME, PASSWORD, DOMAIN, TOKEN_NAME).await;
|
|
||||||
let cookies = get_cookie!(signin_resp);
|
|
||||||
let mut app = get_app!(data).await;
|
|
||||||
|
|
||||||
let mut domain = CreateToken {
|
|
||||||
domain: DOMAIN.into(),
|
|
||||||
name: TOKEN_NAME.into(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// 2. add duplicate mcaptha
|
|
||||||
bad_post_req_test(
|
|
||||||
NAME,
|
|
||||||
PASSWORD,
|
|
||||||
ADD_URL,
|
|
||||||
&domain,
|
|
||||||
ServiceError::TokenNameTaken,
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
// 4. not a URL test for adding domain
|
|
||||||
domain.domain = "testing".into();
|
|
||||||
bad_post_req_test(
|
|
||||||
NAME,
|
|
||||||
PASSWORD,
|
|
||||||
ADD_URL,
|
|
||||||
&domain,
|
|
||||||
ServiceError::NotAUrl,
|
|
||||||
StatusCode::BAD_REQUEST,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
// 4. delete token
|
|
||||||
let del_token = test::call_service(
|
|
||||||
&mut app,
|
|
||||||
post_request!(&domain, DEL_URL)
|
|
||||||
.cookie(cookies.clone())
|
|
||||||
.to_request(),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
assert_eq!(del_token.status(), StatusCode::OK);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[actix_rt::test]
|
|
||||||
async fn level_routes_work() {
|
|
||||||
const NAME: &str = "testuserlevelroutes";
|
|
||||||
const PASSWORD: &str = "longpassworddomain";
|
|
||||||
const EMAIL: &str = "testuserlevelrouts@a.com";
|
|
||||||
const DOMAIN: &str = "http://level.example.com";
|
|
||||||
const TOKEN_NAME: &str = "level_routes_work";
|
|
||||||
const ADD_URL: &str = "/api/v1/mcaptcha/domain/token/levels/add";
|
|
||||||
const UPDATE_URL: &str = "/api/v1/mcaptcha/domain/token/levels/update";
|
|
||||||
const DEL_URL: &str = "/api/v1/mcaptcha/domain/token/levels/delete";
|
|
||||||
const GET_URL: &str = "/api/v1/mcaptcha/domain/token/levels/get";
|
|
||||||
|
|
||||||
let l1 = Level {
|
|
||||||
difficulty_factor: 50,
|
|
||||||
visitor_threshold: 50,
|
|
||||||
};
|
|
||||||
let l2 = Level {
|
|
||||||
difficulty_factor: 500,
|
|
||||||
visitor_threshold: 500,
|
|
||||||
};
|
|
||||||
let levels = vec![l1, l2];
|
|
||||||
let add_level = AddLevels {
|
|
||||||
levels: levels.clone(),
|
|
||||||
name: TOKEN_NAME.into(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let get_level = GetLevels {
|
|
||||||
token: TOKEN_NAME.into(),
|
|
||||||
};
|
|
||||||
|
|
||||||
{
|
|
||||||
let data = Data::new().await;
|
|
||||||
delete_user(NAME, &data).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
register_and_signin(NAME, EMAIL, PASSWORD).await;
|
|
||||||
let (data, _, signin_resp) = add_token_util(NAME, PASSWORD, DOMAIN, TOKEN_NAME).await;
|
|
||||||
let cookies = get_cookie!(signin_resp);
|
|
||||||
let mut app = get_app!(data).await;
|
|
||||||
|
|
||||||
// 1. add level
|
|
||||||
let add_token_resp = test::call_service(
|
|
||||||
&mut app,
|
|
||||||
post_request!(&add_level, ADD_URL)
|
|
||||||
.cookie(cookies.clone())
|
|
||||||
.to_request(),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
assert_eq!(add_token_resp.status(), StatusCode::OK);
|
|
||||||
|
|
||||||
// 2. get level
|
|
||||||
let get_level_resp = test::call_service(
|
|
||||||
&mut app,
|
|
||||||
post_request!(&get_level, GET_URL)
|
|
||||||
.cookie(cookies.clone())
|
|
||||||
.to_request(),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
assert_eq!(get_level_resp.status(), StatusCode::OK);
|
|
||||||
let res_levels: Vec<Level> = test::read_body_json(get_level_resp).await;
|
|
||||||
assert_eq!(res_levels, levels);
|
|
||||||
|
|
||||||
// 3. update level
|
|
||||||
|
|
||||||
let l1 = Level {
|
|
||||||
difficulty_factor: 10,
|
|
||||||
visitor_threshold: 10,
|
|
||||||
};
|
|
||||||
let l2 = Level {
|
|
||||||
difficulty_factor: 5000,
|
|
||||||
visitor_threshold: 5000,
|
|
||||||
};
|
|
||||||
let levels = vec![l1, l2];
|
|
||||||
let add_level = AddLevels {
|
|
||||||
levels: levels.clone(),
|
|
||||||
name: TOKEN_NAME.into(),
|
|
||||||
};
|
|
||||||
let add_token_resp = test::call_service(
|
|
||||||
&mut app,
|
|
||||||
post_request!(&add_level, UPDATE_URL)
|
|
||||||
.cookie(cookies.clone())
|
|
||||||
.to_request(),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
assert_eq!(add_token_resp.status(), StatusCode::OK);
|
|
||||||
let get_level_resp = test::call_service(
|
|
||||||
&mut app,
|
|
||||||
post_request!(&get_level, GET_URL)
|
|
||||||
.cookie(cookies.clone())
|
|
||||||
.to_request(),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
assert_eq!(get_level_resp.status(), StatusCode::OK);
|
|
||||||
let res_levels: Vec<Level> = test::read_body_json(get_level_resp).await;
|
|
||||||
assert_eq!(res_levels, levels);
|
|
||||||
|
|
||||||
// 4. delete level
|
|
||||||
let l1 = Level {
|
|
||||||
difficulty_factor: 10,
|
|
||||||
visitor_threshold: 10,
|
|
||||||
};
|
|
||||||
let l2 = Level {
|
|
||||||
difficulty_factor: 5000,
|
|
||||||
visitor_threshold: 5000,
|
|
||||||
};
|
|
||||||
let levels = vec![l1, l2];
|
|
||||||
let add_level = AddLevels {
|
|
||||||
levels: levels.clone(),
|
|
||||||
name: TOKEN_NAME.into(),
|
|
||||||
};
|
|
||||||
let add_token_resp = test::call_service(
|
|
||||||
&mut app,
|
|
||||||
post_request!(&add_level, DEL_URL)
|
|
||||||
.cookie(cookies.clone())
|
|
||||||
.to_request(),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
assert_eq!(add_token_resp.status(), StatusCode::OK);
|
|
||||||
let get_level_resp = test::call_service(
|
|
||||||
&mut app,
|
|
||||||
post_request!(&get_level, GET_URL)
|
|
||||||
.cookie(cookies.clone())
|
|
||||||
.to_request(),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
assert_eq!(get_level_resp.status(), StatusCode::OK);
|
|
||||||
let res_levels: Vec<Level> = test::read_body_json(get_level_resp).await;
|
|
||||||
assert_eq!(res_levels, Vec::new());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[actix_rt::test]
|
|
||||||
async fn update_duration() {
|
|
||||||
const NAME: &str = "testuserduration";
|
|
||||||
const PASSWORD: &str = "longpassworddomain";
|
|
||||||
const EMAIL: &str = "testuserduration@a.com";
|
|
||||||
const DOMAIN: &str = "http://duration.example.com";
|
|
||||||
const TOKEN_NAME: &str = "duration_routes_token";
|
|
||||||
const GET_URL: &str = "/api/v1/mcaptcha/domain/token/duration/get";
|
|
||||||
const UPDATE_URL: &str = "/api/v1/mcaptcha/domain/token/duration/update";
|
|
||||||
|
|
||||||
{
|
|
||||||
let data = Data::new().await;
|
|
||||||
delete_user(NAME, &data).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
register_and_signin(NAME, EMAIL, PASSWORD).await;
|
|
||||||
let (data, _, signin_resp) = add_token_util(NAME, PASSWORD, DOMAIN, TOKEN_NAME).await;
|
|
||||||
let cookies = get_cookie!(signin_resp);
|
|
||||||
let mut app = get_app!(data).await;
|
|
||||||
|
|
||||||
let update = Duration {
|
|
||||||
token_name: TOKEN_NAME.into(),
|
|
||||||
duration: 40,
|
|
||||||
};
|
|
||||||
|
|
||||||
let get = GetLevels {
|
|
||||||
token: TOKEN_NAME.into(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// check default
|
|
||||||
|
|
||||||
let get_level_resp = test::call_service(
|
|
||||||
&mut app,
|
|
||||||
post_request!(&get, GET_URL)
|
|
||||||
.cookie(cookies.clone())
|
|
||||||
.to_request(),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
assert_eq!(get_level_resp.status(), StatusCode::OK);
|
|
||||||
let res_levels: GetDuration = test::read_body_json(get_level_resp).await;
|
|
||||||
assert_eq!(res_levels.duration, 30);
|
|
||||||
|
|
||||||
// update and check changes
|
|
||||||
|
|
||||||
let update_duration = test::call_service(
|
|
||||||
&mut app,
|
|
||||||
post_request!(&update, UPDATE_URL)
|
|
||||||
.cookie(cookies.clone())
|
|
||||||
.to_request(),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
assert_eq!(update_duration.status(), StatusCode::OK);
|
|
||||||
let get_level_resp = test::call_service(
|
|
||||||
&mut app,
|
|
||||||
post_request!(&get, GET_URL)
|
|
||||||
.cookie(cookies.clone())
|
|
||||||
.to_request(),
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
assert_eq!(get_level_resp.status(), StatusCode::OK);
|
|
||||||
let res_levels: GetDuration = test::read_body_json(get_level_resp).await;
|
|
||||||
assert_eq!(res_levels.duration, 40);
|
|
||||||
}
|
|
@ -16,4 +16,3 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
mod auth;
|
mod auth;
|
||||||
mod mcaptcha;
|
|
||||||
|
@ -102,7 +102,7 @@ pub async fn add_domain_util(
|
|||||||
password: &str,
|
password: &str,
|
||||||
domain: &str,
|
domain: &str,
|
||||||
) -> (data::Data, Login, ServiceResponse) {
|
) -> (data::Data, Login, ServiceResponse) {
|
||||||
use crate::api::v1::mcaptcha::Domain;
|
use crate::api::v1::mcaptcha::domains::Domain;
|
||||||
|
|
||||||
let (data, creds, signin_resp) = signin(name, password).await;
|
let (data, creds, signin_resp) = signin(name, password).await;
|
||||||
let cookies = get_cookie!(signin_resp);
|
let cookies = get_cookie!(signin_resp);
|
||||||
@ -131,7 +131,7 @@ pub async fn add_token_util(
|
|||||||
domain: &str,
|
domain: &str,
|
||||||
token_name: &str,
|
token_name: &str,
|
||||||
) -> (data::Data, Login, ServiceResponse) {
|
) -> (data::Data, Login, ServiceResponse) {
|
||||||
use crate::api::v1::mcaptcha::CreateToken;
|
use crate::api::v1::mcaptcha::mcaptcha::MCaptchaID;
|
||||||
|
|
||||||
const ADD_URL: &str = "/api/v1/mcaptcha/domain/token/add";
|
const ADD_URL: &str = "/api/v1/mcaptcha/domain/token/add";
|
||||||
|
|
||||||
@ -140,7 +140,7 @@ pub async fn add_token_util(
|
|||||||
let mut app = get_app!(data).await;
|
let mut app = get_app!(data).await;
|
||||||
|
|
||||||
// 1. add mcaptcha token
|
// 1. add mcaptcha token
|
||||||
let domain = CreateToken {
|
let domain = MCaptchaID {
|
||||||
domain: domain.into(),
|
domain: domain.into(),
|
||||||
name: token_name.into(),
|
name: token_name.into(),
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user